/** * Библиотека Glib * @author geni * @version 0.1 */ Glib = {}; Glib.Settings = {}; Glib.Settings.webEncoding = 'koi8-r'; Glib.Settings.setWebEncoding = function (newEncoding) { Glib.Settings.webEncoding = newEncoding; } Glib.Settings.getWebEncoding = function () { return Glib.Settings.webEncoding; } function showMessage(sText, sTarget) { var d = new Date(); var sDatePref = "[" + d.toLocaleString() + "] "; if(typeof(sTarget) == "undefined") { sTarget = "debugbox"; } //if (!$(sTarget)) { // var debugConsole = document.createElement("div"); // debugConsole.id = sTarget; // document.appendChild(debugConsole); //} //var obNewMessage = document.createElement("p"); //obNewMessage.innerHTML = sDatePref + sText; //$(sTarget).appendChild(obNewMessage); if ($(sTarget)) { $(sTarget).innerHTML += "
" + sDatePref + sText + "
"; touchFooter(); } } function handleErr(msg,url,l) { var txt=""; txt="There was an error on this page.\n\n" txt+="Error: " + msg + "\n" txt+="URL: " + url + "\n" txt+="Line: " + l + "\n\n" txt+="Click OK to continue.\n\n" showMessage(txt) return false } onerror=handleErr; function alertExeption(e) { showMessage("Exeption " + e.name + "(" + e.message + ")"); } /** * Возвращает элемент по его ID * @param {Object} sID */ function $(sID) { return document.getElementById(sID); } /** * Расширения класса Array */ /** * Функция поиска элемента в массиве * Если obValue содержится в массиве возвращает его индекс, иначе число -1 * * @param {Object} obValue * @return {Integer} */ if ('undefined' == typeof Array.prototype.indexOf) { Array.prototype.indexOf = function (obValue) { for(var i = 0; i < this.length; i++) { if (this[i] == obValue) return i; } return -1; } } if ('undefined' == typeof String.prototype.ltrim) { String.prototype.ltrim = function() { return this.replace(/^\s+/, ''); } } if ('undefined' == typeof String.prototype.rtrim) { String.prototype.rtrim = function() { return this.replace(/\s+$/, ''); } } if ('undefined' == typeof String.prototype.trim) { String.prototype.trim = function() { return this.replace(/^\s+/, '').replace(/\s+$/, ''); } } Glib.Dom = {}; Glib.Dom.insertAfter = function(newElement, targetElement) { var parent = targetElement.parentNode; if (parent.lastChild == targetElement) { parent.appendChild(newElement); } else { parent.insertBefore(newElement,targetElement.nextSibling); } } Glib.Dom.removeChildren = function (el) { while (el.hasChildNodes()) { el.removeChild(el.lastChild); } } Glib.Dom.findPosX = function(obj) { var curleft = 0; if (obj.offsetParent) { while (obj.offsetParent) { curleft += obj.offsetLeft; obj = obj.offsetParent; } } else if (obj.x) { curleft += obj.x; } return curleft; } Glib.Dom.findPosY = function(obj) { var curtop = 0; if (obj.offsetParent) { while (obj.offsetParent) { curtop += obj.offsetTop; obj = obj.offsetParent; } } else if (obj.y) { curtop += obj.y; } return curtop; } Glib.Dom.getClientSize = function() { var nWidth = 0, nHeight = 0, arResult = {}; if (typeof(window.innerWidth) == 'number' ) { nWidth = window.innerWidth; nHeight = window.innerHeight; } else if (document.documentElement && (document.documentElement.clientWidth || document.documentElement.clientHeight)) { nWidth = document.documentElement.clientWidth; nHeight = document.documentElement.clientHeight; } else if (document.body && (document.body.clientWidth || document.body.clientHeight)) { nWidth = document.body.clientWidth; nHeight = document.body.clientHeight; } arResult.nWidth = nWidth; arResult.nHeight = nHeight; return arResult; } /** * Добавляет класс sClassName к классам элемента * @param {Object} sClassName */ Glib.Dom.addClassName = function(elElement, sClassName) { if(!Glib.Dom.hasClassName(elElement, sClassName)) elElement.className += " " + sClassName; } /** * Удаляет класс sClassName из списка классов элемента * @param {Object} sClassName */ Glib.Dom.removeClassName = function(elElement, sClassName) { // var arClassNames = elElement.className.split(" "); // var i = -1; // if((i = arClassNames.indexOf(sClassName)) >= 0) { // arClassNames.splice(i, 1); // elElement.className = arClassNames.join(" "); // } elElement.className = (" " + elElement.className + " ").replace(" " + sClassName + " ", " ").trim(); } /** * Проверяет наличие класса sClassName у элемента. * @param {Object} sClassName * @return {Bool} true если класс есть, иначе false. */ Glib.Dom.hasClassName = function(elElement, sClassName) { return (" " + elElement.className + " ").indexOf(" " + sClassName + " ") != -1; //return elElement.className.split(" ").indexOf(sClassName) >= 0; } /** * Устанавливает класс sClassName для элемента elElement. * @param {Object} sClassName * @return {Bool} true если класс есть, иначе false. */ Glib.Dom.setClassName = function(elElement, sClassName) { elElement.className = sClassName; return elElement.className; } Glib.Dom.getElementWidth = function(sID) { var nWidth; if (document.layers) { nWidth = document.layers[sID].clip.width; } else if (document.all && !document.getElementById) { nWidth = document.all[sID].offsetWidth; } else if(document.getElementById) { nWidth = document.getElementById(sID).offsetWidth; } return nWidth; } Glib.Dom.getElementHeight = function(sID) { var nHeight; if (document.layers) { nHeight = document.layers[sID].clip.height; } else if (document.all && !document.getElementById) { nHeight = document.all[sID].offsetHeight; } else if(document.getElementById) { nHeight = document.getElementById(sID).offsetHeight; } return nHeight; } Glib.Utils = {}; Glib.Utils.swapArrayKeysAndValues = function(arSource) { var arResult = {}; for (var key in arSource) { arResult[arSource[key]] = key; } return arResult; } Glib.Utils.quoteMeta = function(sSource) { return sSource.replace(/([^A-Za-z0-9])/g, "\\$1"); } Glib.Utils.uniqueArray = function(arSource) { var l = arSource.length; var arUnique = {}; for (var i = 0; i < l; i++) { arUnique[arSource[i]] = arSource[i]; } var arResult = new Array(); for (var key in arUnique) { arResult.push(arUnique[key]); } return arResult; } Glib.Utils.checkIntValueInRange = function(sValue, nLowRange, nHighRange, nDefaultValue) { var nResult = isNaN(sValue) ? nDefaultValue : parseInt(sValue); if ((nResult < nLowRange) || (nResult > nHighRange)) { nResult = nDefaultValue; } return nResult; } Glib.Utils.addLeadZero = function(nValue) { return (nValue < 10) ? '0' + nValue : nValue; } Glib.Utils.trimString = function (stringToTrim) { return stringToTrim.replace(/^\s+|\s+$/g,""); } Glib.Debug = {}; Glib.Debug.dumpVar = function(obj) { var sRes = ""; for (var el in obj) { sRes = el + " = " + obj[el] + "
";
var sRequest = "elementid=" + Glib.Net.escapeString(sID) + "&newvalue=" + Glib.Net.escapeString(sNewValue);
Glib.Net.doQuery({
sMethod : "post",
bAsync : true,
sUrl : InlineEditor.sActionUrl,
sRequestBody : sRequest,
fHandler : InlineEditor.responseChangeAction,
arHandlerParams : {"elSource" : elSource}
});
}
InlineEditor.onBlur = function(elInput, sSourceID) {
var elSource = $(sSourceID);
InlineEditor.doChangeAction(elSource.id, elInput.value, elSource);
return false;
}
InlineEditor.onEnter = function(elInput, event, sSourceID) {
event = (event) ? event : window.event;
if (event.keyCode == 13) {
var elSource = $(sSourceID);
InlineEditor.doChangeAction(elSource.id, elInput.value, elSource);
return false;
} else {
return true;
}
}
/**
* Smartselectcontrol
*/
SmartselectControl = function() {}
/**
* Адрес скрипта, через который получаем данные
*/
SmartselectControl.sActionUrl = '/new_dropdown/async_gateway.htms';
/**
* Количиство вызовов unobtrusiveInit
*/
SmartselectControl.nInits = 0;
SmartselectControl.prototype.numPages = 0;
SmartselectControl.prototype.selectedPage = 0;
SmartselectControl.prototype.numShowedPages = 2;
SmartselectControl.prototype.initPagesBox = function() {
this.elPagesBox = document.createElement('div');
this.elPagesBox.obControl = this;
Glib.Dom.insertAfter(this.elPagesBox, this.elSelect);
this.elPagesBox.style.fontSize = "11px";
this.elPagesBox.style.lineHeight = "1.4em";
}
SmartselectControl.prototype.fillPagesBox = function(numPages, selectedPage) {
this.numPages = parseInt(numPages);
this.selectedPage = parseInt(selectedPage);
var pagesBoxHTML = "";
if (numPages > 1) {
var bDotsAdded = false;
for (var i = 1; i <= this.numPages; i++) {
if ((i <= this.numShowedPages) || (i > this.numPages - this.numShowedPages)
|| ((i >= this.selectedPage - this.numShowedPages) && (i <= this.selectedPage + this.numShowedPages))) {
if (i == this.selectedPage) {
pagesBoxHTML += " " + i;
} else {
pagesBoxHTML += " " + '' + i + '';
}
bDotsAdded = false;
} else {
if (!bDotsAdded) {
pagesBoxHTML += " ... ";
bDotsAdded = true;
}
}
}
}
this.elPagesBox.innerHTML = pagesBoxHTML;
}
SmartselectControl.prototype.changePage= function(selectedPage) {
if (selectedPage < 1 || selectedPage > this.numPages) return false;
this.selectedPage = selectedPage;
this.fillPagesBox(this.numPages, this.selectedPage);
this.runSearch();
}
SmartselectControl.prototype.nextPage= function() {
this.changePage(this.selectedPage + 1);
}
SmartselectControl.prototype.prevPage= function() {
this.changePage(this.selectedPage - 1);
}
/**
* Инициализирует контрол для всех select на странице с классом sClassname
* @param string sClassname имя класса, для которого производить инициализацию
*/
SmartselectControl.unobtrusiveInit = function(sClassname) {
SmartselectControl.nInits++;
// Получаем все select на странице
arSelects = document.getElementsByTagName('select');
// Проходим по всем селектам
for (var i in arSelects) {
// Текущий селект
var elSelect = arSelects[i];
// Если имя класса селекта, совпадает с искомым именем класса,
// и на селект ещё не повесили контрол - вешаем контрол на селект
if (Glib.Dom.hasClassName(elSelect, sClassname) && (typeof elSelect.obControl == 'undefined')) {
obControl = new SmartselectControl();
elSelect.obControl = obControl;
obControl.elSelect = elSelect;
obControl.elSelect.onchange = function(){this.obControl.onChange();} //onControl.onChange();
// Вешаем событие, получающее список опций
elSelect.onmousedown = obControl.onGetOptionsAsync;
elSelect.onkeydown = obControl.onGetOptionsAsync;
// Рисуем окошко со страницами
obControl.initPagesBox();
// Рисуем окошко поиска
obControl.elSearchBox = document.createElement('div');
obControl.elSearchBox.innerHTML = '';
obControl.elSearchBoxTextbox = obControl.elSearchBox.firstChild;
obControl.elSearchBoxButtonGo = obControl.elSearchBox.lastChild;
//obControl.elSearchBox.firstChild.obSelf = obControl;
//obControl.elSearchBox.firstChild.onclick = obControl.showSearchBox;
obControl.elSearchBoxButtonGo.obControl = obControl;
obControl.elSearchBoxButtonGo.onclick = obControl.doSearch;
obControl.elSearchBox.style.display = 'none';
Glib.Dom.insertAfter(obControl.elSearchBox, elSelect);
// Рисуем кнопку поиска
obControl.elSearchButton = document.createElement('span');
obControl.elSearchButton.innerHTML = '
';
obControl.elSearchButton.firstChild.obControl = obControl;
obControl.elSearchButton.firstChild.onclick = obControl.showSearchBox;
Glib.Dom.insertAfter(obControl.elSearchButton, elSelect);
// Создаём индикатор прогресса и помещаем его сразу после контрола
elSelect.elProgressIndicator = document.createElement('span');
elSelect.elProgressIndicator.innerHTML = '
';
elSelect.elProgressIndicator.style.display = 'none';
Glib.Dom.insertAfter(elSelect.elProgressIndicator, elSelect);
// Сохраняем информацию о текущей опции
// var nCurrentOptionIndex = elSelect.selectedIndex;
// var elCurrentOption = elSelect.options[nCurrentOptionIndex];
// obControl.currentOption = new Object();
// obControl.currentOption.text = elCurrentOption.text;
// obControl.currentOption.value = elCurrentOption.value;
// obControl.currentOption.isError = elCurrentOption.className == 'error';
// obControl.currentOption.haveFocus = true;
obControl.updateCurrentOption();
var elDummyField = document.createElement('span');
//elDummyField.style = 'border:1px solid black;padding:2px;';
elDummyField.style.width = '100px';
elDummyField.style.border = '1px solid black';
elDummyField.style.background = 'white';
elDummyField.style.padding = '2px';
elDummyField.innerHTML = obControl.currentOption.text;
//elDummyField.disabled = true;
Glib.Dom.insertAfter(elDummyField, elSelect);
obControl.elDummyField = elDummyField;
var elDummyButton = document.createElement('button');
elDummyButton.innerHTML = 'Получить все опции';
elDummyButton.obControl = obControl;
obControl.elDummyButton = elDummyButton;
elDummyButton.onclick = function (event) {Glib.Event.stopEvent(event);this.obControl.getOptionsAsync(); return false;};
Glib.Dom.insertAfter(elDummyButton, elDummyField);
elSelect.style.display = 'none';
}
}
}
SmartselectControl.prototype.updateCurrentOption = function() {
var obControl = this;
var elSelect = obControl.elSelect;
var nCurrentOptionIndex = elSelect.selectedIndex;
var elCurrentOption = elSelect.options[nCurrentOptionIndex];
obControl.currentOption = new Object();
obControl.currentOption.text = elCurrentOption.text;
obControl.currentOption.value = elCurrentOption.value;
obControl.currentOption.isError = elCurrentOption.className == 'error';
obControl.currentOption.haveFocus = true;
}
SmartselectControl.prototype.showSearchBox = function() {
this.obControl.elSearchBox.style.display =
(this.obControl.elSearchBox.style.display == 'none') ? 'block' : 'none';
}
/**
* Происходит ли сейчас получение данных
*/
SmartselectControl.prototype.bDataGetStarted = false;
/**
* Получены ли данные контрола (произведено ли заполнение контрола опциями
*/
SmartselectControl.prototype.bAllDataRecived = false;
/**
* Проверяет датастамп, получены ли данные,
* и если данных нет и корректный датастамп - запускает асинхронный запрос.
* Является обработчиком события onclick и onkeydown для селектбокса
*/
SmartselectControl.prototype.onGetOptionsAsync = function() {
this.obControl.getOptionsAsync();
}
SmartselectControl.prototype.getOptionsAsync = function() {
var obControl = this;
var elSelect = obControl.elSelect;
if (!obControl.bAllDataRecived && (obControl.bDataGetStarted == false)) {
obControl.bDataGetStarted = true;
var sDatastamp = null;
if (!(sDatastamp = elSelect.getAttribute('datastamp'))) {
// @todo add normal error handling
alert('No datastamp!');
return false;
}
obControl.doGetOptionsAsync(sDatastamp, elSelect, null);
return false;
}
}
SmartselectControl.prototype.getDatastamp = function() {
var sDatastamp = null;
if (!(sDatastamp = this.obControl.elSelect.getAttribute('datastamp'))) {
// @todo add normal error handling
alert('No datastamp!');
return null;
}
return sDatastamp;
}
SmartselectControl.prototype.onChange = function() {
var obControl = this;
obControl.updateCurrentOption();
var elSelect = obControl.elSelect;
var selectedOption = elSelect.options[elSelect.selectedIndex];
var navAction = selectedOption.getAttribute('navAction');
if (navAction) {
if (navAction == 'prev') {
obControl.prevPage();
} else if (navAction == 'next') {
obControl.nextPage();
}
}
}
SmartselectControl.prototype.doSearch = function() {
return this.obControl.runSearch();
}
SmartselectControl.prototype.runSearch = function() {
if (this.bDataGetStarted == false) {
this.bDataGetStarted = true;
var sDatastamp = null;
if (!(sDatastamp = this.elSelect.getAttribute('datastamp'))) {
// @todo add normal error handling
alert('No datastamp!');
return false;
}
var searchQuery = this.elSearchBoxTextbox.value;
this.doGetOptionsAsync(sDatastamp, this.elSelect, searchQuery);
return false;
}
}
/**
* Делает асинхронный запрос, получающий опции селекта
* @param string sDatastamp
* @param {Element} elSelect
*/
SmartselectControl.prototype.doGetOptionsAsync = function(sDatastamp, elSelect, searchQuery, pageNumber) {
elSelect.elProgressIndicator.style.display = 'inline';
var sAsyncComponent = 'smartselectcontrol';
var sRequest = 'component=' + sAsyncComponent + '&datastamp=' + sDatastamp;
var arParams = {'elSelect' : elSelect};
arParams['search'] = false;
if (searchQuery !== null) {
sRequest += '&search=' + Glib.Net.escapeString(searchQuery);
arParams['search'] = true;
}
sRequest += '&page=' + this.selectedPage;
Glib.Net.doQuery({
sMethod : 'post',
bAsync : true,
sUrl : SmartselectControl.sActionUrl,
sRequestBody : sRequest,
fHandler : this.responseGetOptionsAsync,
arHandlerParams : arParams
});
}
Glib.Dom.addSelectOptionQuick = function(elSelect, name, value) {
var elOption = document.createElement("option");
elOption.value = value;
elOption.text = name;
try {
elSelect.add(elOption, null);
} catch (ex) {
elSelect.add(elOption);
}
return elOption;
}
Glib.Dom.SelectUtils = {
}
SmartselectControl.prototype.switchSelectBox = function(oldSelect, newSelect) {
Glib.Dom.insertAfter(newSelect, oldSelect);
this.elSelect = newSelect;
newSelect.obControl = this;
newSelect.setAttribute('datastamp', oldSelect.getAttribute('datastamp'));
newSelect.elProgressIndicator = oldSelect.elProgressIndicator;
newSelect.onchange = oldSelect.onchange;
newSelect.name = oldSelect.name;
oldSelect.parentNode.removeChild(oldSelect);
}
SmartselectControl.prototype.createOption = function(elSelect, text, value) {
var elOption = document.createElement("option");
elOption.value = value;
elOption.innerHTML = text;
elSelect.appendChild(elOption);
return elOption;
}
function ord(mixed_var) {
// Переменная, получает ASCII-значение первого символа строки
var result = "";
// Получение скан-кода
if(mixed_var.length != 0) {
result = mixed_var.charCodeAt(0);
}
// Если пришёл пустой символ строки, тогда выдаём просто ошибку
if(result == "") {
result = "None";
}
// Возвращаем результат
return result;
}
SmartselectControl.prototype.responseGetOptionsAsync2 = function(arResponse, arParams, bStatus) {
// Прячем индикатор прогресса
var elSelect = arParams['elSelect'];
var obControl = elSelect.obControl;
elSelect.elProgressIndicator.style.display = 'none';
if (!bStatus) {
// Делаем что-нибудь при ошибке
alert('При попытке получения значений возникла ошибка связи с сервером.');
} else {
// Количество опций в ответе
var numOptions = arResponse['newdata'].length;
var newSelect = document.createElement("select");
//var dataOptGroup = document.createElement("optgroup");
dataOptGroup = newSelect;
//while (elSelect.length > 0) {
// elSelect.remove(elSelect.length-1);
//}
if (obControl.currentOption.isError) {
var errorOption = obControl.createOption(dataOptGroup, obControl.currentOption.text, obControl.currentOption.value);
errorOption.className = "error";
} else if (obControl.currentOption.haveFocus) {
var currentOptionInResponse = false;
for (var ix = 0; ix < numOptions; ix++) {
if (arResponse['newdata'][ix]["id"] == obControl.currentOption.value) {
currentOptionInResponse = true;
break;
}
}
if (!currentOptionInResponse) {
var currentOption = obControl.createOption(dataOptGroup, obControl.currentOption.text, obControl.currentOption.value);
currentOption.style.fontWeight = "bold";
}
//obControl.currentOption.haveFocus = false;
}
// Количество опций в ответе
//
// Если у текущей опции установлен класс error, то это означает,
// что когда рисовался этот контрол, значение этого поле ссылалось на
// несуществующую запись, и поэтому считаем, что текущего значения у контрола нет
//var bValueExists = elCurrentOption.className != 'error';
//var bHaveErrorOption= elCurrentOption.className == 'error';
// Добавляем пустую опцию, если у нас нет текущей пустой опции в фокусе,
// если такая опция есть - снимаем с неё фокус
// При проверке опции на пустоту обрезаем пустые символы по бокам
//alert("+" + Glib.Utils.trimString(obControl.currentOption.text) + "+");
//alert(ord(Glib.Utils.trimString(obControl.currentOption.text)));
//alert(ord(' '));
//alert(Glib.Utils.trimString(obControl.currentOption.value) == '');
//alert(Glib.Utils.trimString(obControl.currentOption.text) == '');
//alert(Glib.Utils.trimString(obControl.currentOption.text) == String.fromCharCode(160));
//alert(obControl.currentOption.haveFocus == true);
if (!((obControl.currentOption.haveFocus == true)
&& (Glib.Utils.trimString(obControl.currentOption.value) == '')
&& (Glib.Utils.trimString(obControl.currentOption.text) == '')
|| Glib.Utils.trimString(obControl.currentOption.text) == String.fromCharCode(160))) {
var dummyOption = obControl.createOption(dataOptGroup, '', '');
} else {
//---obControl.currentOption.haveFocus = false;
}
if (obControl.currentOption.haveFocus && !obControl.currentOption.isError) {
//obControl.currentOption.haveFocus = false;
}
for (var ix = 0; ix < numOptions; ix++) {
// Получаем данные очередной опции из ответа сервера
arOption = arResponse['newdata'][ix];
// Если текущего значения у контрола нет (но при этом у нас всё равно
// есть id ссылающееся на несуществующую запись), но в ответе вдруг появляется
// запись с этим id, то мы пропускаем добавление этой записи.
// Зачем так сделано - не очень понятно, думаю, это можно опустить
//if (!bValueExists && (elCurrentOption.value == arOption["id"])) {
// continue;
//}
//sNewData += '';
// Добавляем новую опцию к списку
elOption = obControl.createOption(dataOptGroup, arOption["name"], arOption["id"]);
elOption.style.whiteSpace = 'pre';
// Если у нас установлено текущее значение,
// и мы добавляем новую опцию с этим же значением,
// убираем текущую опцию и делаем выбранной добавленную
//if (bValueExists && (elCurrentOption.value == arOption["id"])) {
// //arParams['elSelect'].remove(nCurrentOptionIndex);
// bValueExists = false;
// elOption.selected = true;
//}
if (obControl.currentOption.value == arOption["id"]) {
elOption.selected = true;
}
}
//if (!bHaveErrorOption) {
// elSelect.remove(nCurrentOptionIndex);
//}
//elSelect.style.whiteSpace = 'pre';
obControl.fillPagesBox(arResponse["numPages"], arResponse["page"]);
var bShowPrevPageLink = obControl.selectedPage > 1;
var bShowNextPageLink = obControl.selectedPage < obControl.numPages;
if (bShowPrevPageLink || bShowNextPageLink) {
//var navGroup = document.createElement("optgroup");
//navGroup.label = "Навигация";
//elSelect.appendChild(navGroup);
if (bShowPrevPageLink) {
var prevOption = obControl.createOption(dataOptGroup, 'Предыдущая страница', '');
prevOption.className = 'nav';
//prevOption.style.fontWeight = 'bold';
prevOption.obControl = obControl;
prevOption.setAttribute('navAction', 'prev');
//prevOption.onclick = function() {this.obControl.prevPage()}
}
if (bShowNextPageLink) {
var nextOption = obControl.createOption(dataOptGroup, 'Следующая страница', '');
nextOption.className = 'nav';
//nextOption.style.fontWeight = 'bold';
nextOption.obControl = obControl;
nextOption.setAttribute('navAction', 'next');
//nextOption.onclick = function() {this.obControl.nextPage()}
}
}
this.switchSelectBox(elSelect, newSelect);
//for (var ix in elSelect.childNodes) {
// elSelect.removeChild(elSelect.childNodes[0]);
//}
//elSelect.appendChild(dataOptGroup);
//newSelect.click();
newSelect.focus();
//newSelect.size=5;
if (!obControl.bAllDataRecived) {
obControl.elDummyField.style.display = 'none';
obControl.elDummyButton.style.display = 'none';
}
obControl.bAllDataRecived = true;
}
obControl.bDataGetStarted = false;
}
/**
* Обрабатывает ответ асинхронного запроса на опции и добавляет опции в контрол
* @param {Object} arResponse
* @param {Object} arParams
* @param {Object} bStatus
*/
SmartselectControl.prototype.responseGetOptionsAsync = function(arResponse, arParams, bStatus) {
var elSelect = arParams['elSelect'];
var obControl = elSelect.obControl;
obControl.responseGetOptionsAsync2(arResponse, arParams, bStatus);
return;
// Прячем индикатор прогресса
elSelect.elProgressIndicator.style.display = 'none';
if (!bStatus) {
// Делаем что-нибудь при ошибке
alert('При попытке получения значений возникла ошибка связи с сервером.');
} else {
// Количество опций в ответе
var numOptions = arResponse['newdata'].length;
// Генерим список опций из данных ответа
//var sNewData = "";
// Индекс текущей выбранной опции
//var nCurrentOptionIndex = elSelect.selectedIndex;
// Получаем элемент текущей опции по её индексу
//var elCurrentOption = elSelect.options[nCurrentOptionIndex];
//var currentOptionValue = elCurrentOption.value;
//var currentOptionText = elCurrentOption.text;
//if (arParams["search"]) {
while (elSelect.length > 0) {
elSelect.remove(elSelect.length-1);
}
//var elOption = document.createElement("option");
//elOption.value = currentOptionValue;
//elOption.text = currentOptionText;
//elOption.style.whiteSpace = 'pre';
// В ие у add один параметр, так что в случае ошибки
// пробуем вызвать add с одним параметром
//try {
// elSelect.add(elOption, null);
//} catch (ex) {
// elSelect.add(elOption);
//}
//}
if (obControl.currentOption.isError) {
var errorOption = Glib.Dom.addSelectOptionQuick(elSelect, obControl.currentOption.text, obControl.currentOption.value);
errorOption.className = "error";
} else if (obControl.currentOption.haveFocus) {
var currentOptionInResponse = false;
for (var ix = 0; ix < numOptions; ix++) {
if (arResponse['newdata'][ix]["id"] == obControl.currentOption.value) {
currentOptionInResponse = true;
break;
}
}
if (!currentOptionInResponse) {
var currentOption = Glib.Dom.addSelectOptionQuick(elSelect, obControl.currentOption.text, obControl.currentOption.value);
currentOption.style.fontWeight = "bold";
}
//obControl.currentOption.haveFocus = false;
}
// Количество опций в ответе
//
// Если у текущей опции установлен класс error, то это означает,
// что когда рисовался этот контрол, значение этого поле ссылалось на
// несуществующую запись, и поэтому считаем, что текущего значения у контрола нет
//var bValueExists = elCurrentOption.className != 'error';
//var bHaveErrorOption= elCurrentOption.className == 'error';
// Добавляем пустую опцию, если у нас нет текущей пустой опции в фокусе,
// если такая опция есть - снимаем с неё фокус
// При проверке опции на пустоту обрезаем пустые символы по бокам
//alert("+" + Glib.Utils.trimString(obControl.currentOption.text) + "+");
//alert(Glib.Utils.trimString(obControl.currentOption.value) == '');
//alert(Glib.Utils.trimString(obControl.currentOption.text) == '');
//alert(obControl.currentOption.haveFocus == true);
if (!((obControl.currentOption.haveFocus == true)
&& (Glib.Utils.trimString(obControl.currentOption.value) == '')
&& (Glib.Utils.trimString(obControl.currentOption.text) == ''))) {
var dummyOption = Glib.Dom.addSelectOptionQuick(elSelect, '', '');
} else {
//obControl.currentOption.haveFocus = false;
}
if (obControl.currentOption.haveFocus && !obControl.currentOption.isError) {
obControl.currentOption.haveFocus = false;
}
for (var ix = 0; ix < numOptions; ix++) {
// Получаем данные очередной опции из ответа сервера
arOption = arResponse['newdata'][ix];
// Если текущего значения у контрола нет (но при этом у нас всё равно
// есть id ссылающееся на несуществующую запись), но в ответе вдруг появляется
// запись с этим id, то мы пропускаем добавление этой записи.
// Зачем так сделано - не очень понятно, думаю, это можно опустить
//if (!bValueExists && (elCurrentOption.value == arOption["id"])) {
// continue;
//}
//sNewData += '';
// Добавляем новую опцию к списку
elOption = document.createElement("option");
elOption.value = arOption["id"];
elOption.text = arOption["name"];
elOption.style.whiteSpace = 'pre';
// В ие у add один параметр, так что в случае ошибки
// пробуем вызвать add с одним параметром
try {
elSelect.add(elOption, null);
} catch (ex) {
elSelect.add(elOption);
}
// Если у нас установлено текущее значение,
// и мы добавляем новую опцию с этим же значением,
// убираем текущую опцию и делаем выбранной добавленную
//if (bValueExists && (elCurrentOption.value == arOption["id"])) {
// //arParams['elSelect'].remove(nCurrentOptionIndex);
// bValueExists = false;
// elOption.selected = true;
//}
if (obControl.currentOption.value == arOption["id"]) {
elOption.selected = true;
}
}
//if (!bHaveErrorOption) {
// elSelect.remove(nCurrentOptionIndex);
//}
//elSelect.style.whiteSpace = 'pre';
obControl.fillPagesBox(arResponse["numPages"], arResponse["page"]);
var bShowPrevPageLink = obControl.selectedPage > 1;
var bShowNextPageLink = obControl.selectedPage < obControl.numPages;
if (bShowPrevPageLink || bShowNextPageLink) {
//var navGroup = document.createElement("optgroup");
//navGroup.label = "Навигация";
//elSelect.appendChild(navGroup);
if (bShowPrevPageLink) {
var prevOption = Glib.Dom.addSelectOptionQuick(elSelect, 'Предыдущая страница', '');
prevOption.className = 'nav';
//prevOption.style.fontWeight = 'bold';
prevOption.obControl = obControl;
prevOption.setAttribute('navAction') = 'prev';
prevOption.onclick = function() {this.obControl.prevPage()}
}
if (bShowNextPageLink) {
var nextOption = Glib.Dom.addSelectOptionQuick(elSelect, 'Следующая страница', '');
nextOption.className = 'nav';
//nextOption.style.fontWeight = 'bold';
nextOption.obControl = obControl;
nextOption.setAttribute('navAction') = 'next';
nextOption.onclick = function() {this.obControl.nextPage()}
}
}
obControl.bAllDataRecived = true;
}
obControl.bDataGetStarted = false;
}
/*
Glib.LoadManager = function() {}
Glib.LoadManager.arHandlers = new Array();
Glib.LoadManager.addOnReadyHandler = function (newHandlerFunction) {
Glib.LoadManager.arHandlers.push(newHandlerFunction);
}
Glib.LoadManager.doOnReady = function() {
//alert("ready");
for (var ix in Glib.LoadManager.arHandlers) {
var fn = Glib.LoadManager.arHandlers[ix];
fn();
}
}*/
/*
if (window.onload) {
Glib.LoadManager.addOnReadyHandler(window.onload);
}
window.onload = Glib.LoadManager.doOnReady;
*/
//Glib.LoadManager.addOnReadyHandler(function() {SmartselectControl.unobtrusiveInit('smartselectcontrol')});
//Glib.LoadManager.addOnReadyHandler(Ext.onReady);
function touchFooter() {
if($("footer")) {
$("footer").style.position="relative";
$("footer").style.position="absolute";
}
}
//************
if (typeof Ext != 'undefined') {
Ext.BLANK_IMAGE_URL = '/core/media/images/s.gif';
Ext.namespace('Ext.ox');
Ext.ox.SmartPagingToolbar = function(config) {
// call parent constructor
this.noAllPages = false;
Ext.ox.SmartPagingToolbar.superclass.constructor.call(this, config);
}
// extend
Ext.extend(Ext.ox.SmartPagingToolbar, Ext.PagingToolbar, {
onRender : function(ct, position){
Ext.PagingToolbar.superclass.onRender.call(this, ct, position);
this.first = this.addButton({
tooltip: this.firstText,
iconCls: "x-tbar-page-first",
disabled: true,
handler: this.onClick.createDelegate(this, ["first"])
});
this.prev = this.addButton({
tooltip: this.prevText,
iconCls: "x-tbar-page-prev",
disabled: true,
handler: this.onClick.createDelegate(this, ["prev"])
});
if (!this.noAllPages) {
this.addSeparator();
this.add(this.beforePageText);
}
this.field = Ext.get(this.addDom({
tag: "input",
type: "text",
size: "3",
value: "1",
cls: "x-tbar-page-number"
}).el);
if (this.noAllPages) {
this.field.hide();
} else {
this.field.on("keydown", this.onPagingKeydown, this);
this.field.on("focus", function(){this.dom.select();});
}
this.afterTextEl = this.addText(String.format(this.afterPageText, 1));
if (this.noAllPages) {
this.afterTextEl.hide();
} else {
this.field.setHeight(18);
this.addSeparator();
}
this.next = this.addButton({
tooltip: this.nextText,
iconCls: "x-tbar-page-next",
disabled: true,
handler: this.onClick.createDelegate(this, ["next"])
});
this.last = this.addButton({
tooltip: this.lastText,
iconCls: "x-tbar-page-last",
disabled: true,
handler: this.onClick.createDelegate(this, ["last"])
});
if (this.noAllPages) {
this.last.hide();
}
this.addSeparator();
this.loading = this.addButton({
tooltip: this.refreshText,
iconCls: "x-tbar-loading",
handler: this.onClick.createDelegate(this, ["refresh"])
});
if(this.displayInfo){
this.displayEl = Ext.fly(this.el.dom).createChild({cls:'x-paging-info'});
}
if(this.dsLoaded){
this.onLoad.apply(this, this.dsLoaded);
}
}
});
Ext.ox.SmartCombo = function(config) {
// call parent constructor
this.noAllPages = false;
this.oldStyle = 'normal';
this.curStyle = 'normal';
Ext.ox.SmartCombo.superclass.constructor.call(this, config);
this.on({
render:{scope:this, fn:function() {
var wrap = this.el.up('div.x-form-field-wrap');
this.wrap.applyStyles({position:'relative'});
this.el.addClass('x-icon-combo-input');
this.flag = Ext.DomHelper.append(wrap, {
tag: 'div', style:'position:absolute'
});
}}
});
} // end of Ext.ux.IconCombo constructor
// extend
Ext.extend(Ext.ox.SmartCombo, Ext.form.ComboBox, {
setErrorStyle : function() {
this.oldStyle = 'error';
this.setInputStyle('error');
},
setSearchStyle : function() {
//alert(this.curStyle);
//this.oldStyle = this.curStyle;
this.setInputStyle('search');
},
setNormalStyle : function() {
this.oldStyle = 'normal';
this.setInputStyle('normal');
},
restoreStyleAfterSearch : function() {
//alert(this.oldStyle);
this.setInputStyle(this.oldStyle);
},
setInputStyle : function(style) {
switch (style) {
case 'error':
this.curStyle = 'error';
this.el.applyStyles({color:'#f33', 'font-style':'normal'});
break;
case 'search':
this.curStyle = 'search';
this.el.applyStyles({color:'#333', 'font-style':'italic'});
break;
case 'normal':
default:
this.curStyle = 'normal';
this.el.applyStyles({color:'#333', 'font-style':'normal'});
}
},
setValue : function(v){
var text = v;
if(this.valueField){
var r = this.findRecord(this.valueField, v);
if(r){
text = r.data[this.displayField];
// Remove from string and trim it
text = text.replace(/ /g, ' ').trim();
}else if(this.valueNotFoundText !== undefined){
text = this.valueNotFoundText;
}
}
this.lastSelectionText = text;
if(this.hiddenField){
this.hiddenField.value = v;
}
this.setNormalStyle();
Ext.form.ComboBox.superclass.setValue.call(this, text);
this.value = v;
},
// private
onKeyUp : function(e){
if(this.editable !== false && !e.isSpecialKey()){
this.lastKey = e.getKey();
this.dqTask.delay(this.queryDelay);
this.setSearchStyle();
}
},
doForce : function(){
if(this.el.dom.value.length > 0){
this.el.dom.value =
this.lastSelectionText === undefined ? '' : this.lastSelectionText;
this.applyEmptyText();
this.restoreStyleAfterSearch();
}
},
setDefaultValue : function(v, displayValue, isError){
if (typeof isError == 'undefined') isError = false;
var text = displayValue;
this.lastSelectionText = text;
if(this.hiddenField){
this.hiddenField.value = v;
}
Ext.form.ComboBox.superclass.setValue.call(this, text);
this.value = v;
if (isError) {
this.setErrorStyle();
} else {
this.setNormalStyle();
}
},
doQuery : function(q, forceAll){
if(q === undefined || q === null){
q = '';
}
var qe = {
query: q,
forceAll: forceAll,
combo: this,
cancel:false
};
if(this.fireEvent('beforequery', qe)===false || qe.cancel){
return false;
}
q = qe.query;
forceAll = qe.forceAll;
if(forceAll === true || (q.length >= this.minChars)){
if(this.lastQuery !== q){
this.lastQuery = q;
if(this.mode == 'local'){
this.selectedIndex = -1;
if(forceAll){
this.store.clearFilter();
}else{
// Filter loacal store with *query*
this.store.filter(this.displayField, q, true);
}
this.onLoad();
}else{
this.store.baseParams[this.queryParam] = q;
this.store.load({
params: this.getParams(q)
});
this.expand();
}
}else{
this.selectedIndex = -1;
this.onLoad();
}
}
},
initList : function(){
if(!this.list){
var cls = 'x-combo-list';
this.list = new Ext.Layer({
shadow: this.shadow, cls: [cls, this.listClass].join(' '), constrain:false
});
var lw = this.listWidth || Math.max(this.wrap.getWidth(), this.minListWidth);
this.list.setWidth(lw);
this.list.swallowEvent('mousewheel');
this.assetHeight = 0;
if(this.title){
this.header = this.list.createChild({cls:cls+'-hd', html: this.title});
this.assetHeight += this.header.getHeight();
}
this.innerList = this.list.createChild({cls:cls+'-inner'});
this.innerList.on('mouseover', this.onViewOver, this);
this.innerList.on('mousemove', this.onViewMove, this);
this.innerList.setWidth(lw - this.list.getFrameWidth('lr'))
if(this.pageSize){
this.footer = this.list.createChild({cls:cls+'-ft'});
this.pageTb = new Ext.ox.SmartPagingToolbar({
store:this.store,
pageSize: this.pageSize,
renderTo:this.footer,
noAllPages:this.noAllPages
});
this.assetHeight += this.footer.getHeight();
}
if(!this.tpl){
/**
* @cfg {String/Ext.XTemplate} tpl The template string, or {@link Ext.XTemplate}
* instance to use to display each item in the dropdown list. Use
* this to create custom UI layouts for items in the list.
* * If you wish to preserve the default visual look of list items, add the CSS * class name
x-combo-list-itemto the template's container element. *
* The template must contain one or more substitution parameters using field * names from the Combo's {@link #store Store}. An example of a custom template * would be adding an
ext:qtipattribute which might display other fields * from the Store. *
* The dropdown list is displayed in a DataView. See {@link Ext.DataView} for details.
*/
this.tpl = '