UNPKG

ax5ui-autocomplete

Version:

A autocomplete plugin that works with Bootstrap & jQuery

994 lines (902 loc) 66.8 kB
// ax5.ui.autocomplete (function () { const UI = ax5.ui; const U = ax5.util; let AUTOCOMPLETE; UI.addClass({ className: "autocomplete" }, (function () { /** * @class ax5autocomplete * @classdesc * @author tom@axisj.com * @example * ```js * var options = []; * options.push({value: "1", text: "string"}); * options.push({value: "2", text: "number"}); * options.push({value: "3", text: "substr"}); * options.push({value: "4", text: "substring"}); * options.push({value: "5", text: "search"}); * options.push({value: "6", text: "parseInt"}); * options.push({value: "7", text: "toFixed"}); * options.push({value: "8", text: "min"}); * options.push({value: "9", text: "max"}); * options.push({value: "10", text: "장기영"}); * options.push({value: "11", text: "장서우"}); * options.push({value: "12", text: "이영희"}); * options.push({value: "13", text: "황인서"}); * options.push({value: "14", text: "황세진"}); * options.push({value: "15", text: "이서연"}); * options.push({value: "16", text: "액시스제이"}); * options.push({value: "17", text: "ax5"}); * options.push({value: "18", text: "ax5grid"}); * options.push({value: "19", text: "ax5combobox"}); * options.push({value: "20", text: "ax5autocomplete"}); * options.push({value: "21", text: "ax5binder"}); * options.push({value: "22", text: "ax5select"}); * options.push({value: "23", text: "ax5mask"}); * options.push({value: "24", text: "ax5toast"}); * options.push({value: "25", text: "ax5dialog"}); * options.push({value: "26", text: "ax5modal"}); * var myUI = new ax5.ui.autocomplete({ * theme: "danger", * removeIcon: '<i class="fa fa-times" aria-hidden="true"></i>' * }); * ``` */ return function () { var self = this, cfg; this.instanceId = ax5.getGuid(); this.config = { theme: 'default', animateTime: 250, removeIcon: 'X', lang: { noSelected: '', noOptions: 'no options', loading: 'Now Processing' }, columnKeys: { optionValue: 'value', optionText: 'text', optionSelected: 'selected' } }; this.queue = []; this.activeautocompleteOptionGroup = null; this.activeautocompleteQueueIndex = -1; this.openTimer = null; this.closeTimer = null; this.waitOptionsCallback = null; this.keyUpTimer = null; cfg = this.config; var $window = jQuery(window); var ctrlKeys = { "18": "KEY_ALT", //"8": "KEY_BACKSPACE", "17": "KEY_CONTROL", "46": "KEY_DELETE", "40": "KEY_DOWN", "35": "KEY_END", "187": "KEY_EQUAL", //"27": "KEY_ESC", "36": "KEY_HOME", "45": "KEY_INSERT", "37": "KEY_LEFT", "189": "KEY_MINUS", "34": "KEY_PAGEDOWN", "33": "KEY_PAGEUP", // "190": "KEY_PERIOD", //"13": "KEY_RETURN", "39": "KEY_RIGHT", "16": "KEY_SHIFT", // "32": "KEY_SPACE", "9": "KEY_TAB", "38": "KEY_UP", "91": "KEY_WINDOW" //"107" : "NUMPAD_ADD", //"194" : "NUMPAD_COMMA", //"110" : "NUMPAD_DECIMAL", //"111" : "NUMPAD_DIVIDE", //"12" : "NUMPAD_EQUAL", //"106" : "NUMPAD_MULTIPLY", //"109" : "NUMPAD_SUBTRACT" }, onStateChanged = function (item, that) { if (item && item.onStateChanged) { item.onStateChanged.call(that, that); } else if (this.onStateChanged) { this.onStateChanged.call(that, that); } if (that.state == "changeValue") { if (item && item.onChange) { item.onChange.call(that, that); } else if (this.onChange) { this.onChange.call(that, that); } } item = null; that = null; return true; }, alignAutocompleteDisplay = function () { var i = this.queue.length, w; while (i--) { var item = this.queue[i]; if (item.$display) { w = Math.max(item.$select.outerWidth(), U.number(item.minWidth)); item.$display.css({ "min-width": w }); if (item.reset) { item.$display.find(".addon-icon-reset").css({ "line-height": this.queue[i].$display.height() + "px" }); } // 높이조절 처리 if (item.multiple) { var displayTableHeightAdjust = (function () { return U.number(item.$display.css("border-top-width")) + U.number(item.$display.css("border-bottom-width")); }).call(this); item.$target.height(''); item.$display.height(''); var displayTableHeight = item.$displayTable.outerHeight(); //debugger; if (Math.abs(displayTableHeight - item.$target.height()) >= displayTableHeightAdjust) { item.$target.css({height: displayTableHeight + displayTableHeightAdjust + 4}); item.$display.css({height: displayTableHeight + displayTableHeightAdjust + 4}); } } } } i = null; w = null; return this; }, alignAutocompleteOptionGroup = function (append) { if (append && !this.activeautocompleteOptionGroup) return this; var item = this.queue[this.activeautocompleteQueueIndex], pos = {}, positionMargin = 0, dim = {}, pickerDim = {}, pickerDirection; if (!item) return this; if (append) jQuery(document.body).append(this.activeautocompleteOptionGroup); pos = item.$target.offset(); dim = { width: item.$target.outerWidth(), height: item.$target.outerHeight() }; pickerDim = { winWidth: Math.max($window.width(), jQuery(document.body).width()), winHeight: Math.max($window.height(), jQuery(document.body).height()), width: this.activeautocompleteOptionGroup.outerWidth(), height: this.activeautocompleteOptionGroup.outerHeight() }; // picker css(width, left, top) & direction 결정 if (!item.direction || item.direction === "" || item.direction === "auto") { // set direction pickerDirection = "top"; if (pos.top - pickerDim.height - positionMargin < 0) { pickerDirection = "top"; } else if (pos.top + dim.height + pickerDim.height + positionMargin > pickerDim.winHeight) { pickerDirection = "bottom"; } } else { pickerDirection = item.direction; } if (append) { this.activeautocompleteOptionGroup .addClass("direction-" + pickerDirection); } this.activeautocompleteOptionGroup .css((function () { if (pickerDirection == "top") { if (pos.top + dim.height + pickerDim.height + positionMargin > pickerDim.winHeight) { var newTop = pos.top + pickerDim.height; if (newTop + pickerDim.height + positionMargin > pickerDim.winHeight) { newTop = 0; } if (newTop < 0) { newTop = 0; } return { left: pos.left, top: newTop, width: dim.width } } return { left: pos.left, top: pos.top + dim.height + 1, width: dim.width } } else if (pickerDirection == "bottom") { return { left: pos.left, top: pos.top - pickerDim.height - 1, width: dim.width } } }).call(this)); }, onBodyClick = function (e, target) { if (!this.activeautocompleteOptionGroup) return this; var item = this.queue[this.activeautocompleteQueueIndex], clickEl = "display" ; target = U.findParentNode(e.target, function (target) { if (target.getAttribute("data-option-value")) { clickEl = "optionItem"; return true; } else if (item.$target.get(0) == target) { clickEl = "display"; return true; } }); if (!target) { this.close(); return this; } else if (clickEl === "optionItem") { setSelected.call(this, item.id, { optionIndex: { index: target.getAttribute("data-option-index") } }, undefined, "optionItemClick"); alignAutocompleteDisplay.call(this); alignAutocompleteOptionGroup.call(this); if (!item.multiple) { this.close(); } } else { } return this; }, getLabel = function (queIdx) { var item = this.queue[queIdx]; // 템플릿에 전달 해야할 데이터 선언 var data = {}; data.id = item.id; data.theme = item.theme; data.size = "ax5autocomplete-option-group-" + item.size; data.multiple = item.multiple; data.lang = item.lang; data.options = item.options; data.selected = item.selected; data.hasSelected = (data.selected && data.selected.length > 0); data.removeIcon = item.removeIcon; return AUTOCOMPLETE.tmpl.get.call(this, "label", data, item.columnKeys); }, syncLabel = function (queIdx) { var item = this.queue[queIdx]; if (!item.multiple && item.selected && item.selected.length > 0) { item.selected = [].concat(item.selected[item.selected.length - 1]); } item.selected.forEach(function (n, nindex) { n["@index"] = nindex; }); item.$select.html(AUTOCOMPLETE.tmpl.get.call(this, "formSelectOptions", { selected: item.selected }, item.columnKeys)); }, printLabel = function (queIdx) { var item = this.queue[queIdx]; item.$displayLabel.find('[data-ax5autocomplete-selected-label]').remove(); item.$displayLabelInput.before(getLabel.call(this, queIdx)); }, focusLabel = function (queIdx) { if (this.queue[queIdx].disabled) return this; this.queue[queIdx].$displayLabel.trigger("focus"); this.queue[queIdx].$displayLabelInput.focus(); }, clearLabel = function (queIdx) { this.queue[queIdx].$displayLabelInput.val(''); }, blurLabel = function (queIdx) { this.queue[queIdx].$displayLabel.trigger("blur"); }, onSearch = function (queIdx, searchWord) { if (this.activeautocompleteQueueIndex == -1) return this; // 옵션박스가 닫힌상태이면 진행안함. var regExp = /[\{\}\[\]\/?.,;:|\)*~`!^\-_+<>@\#$%&\\\=\(\'\"]/gi; searchWord = searchWord.replace(regExp, ""); this.queue[queIdx].waitOptions = true; this.queue[queIdx].onSearch.call({ self: this, item: this.queue[queIdx], searchWord: searchWord }, (function (O) { var data = {}; var item = this.queue[this.activeautocompleteQueueIndex]; if (!item) return false; /// 현재 selected 검증후 처리 (function (item, O) { var optionsMap = {}; O.options.forEach(function (_O, _OIndex) { _O["@index"] = _OIndex; _O["@findex"] = _OIndex; optionsMap[_O[item.columnKeys.optionValue]] = _O; }); if (U.isArray(item.selected)) { item.selected.forEach(function (_O) { if (optionsMap[_O[item.columnKeys.optionValue]]) { O.options[optionsMap[_O[item.columnKeys.optionValue]]["@index"]][item.columnKeys.optionSelected] = true; } }); } })(item, O); item.options = O.options; alignAutocompleteDisplay.call(this); /// 템플릿에 전달할 오브젝트 선언 data.id = item.id; data.theme = item.theme; data.size = "ax5autocomplete-option-group-" + item.size; data.multiple = item.multiple; data.lang = item.lang; data.options = item.options; this.activeautocompleteOptionGroup.find('[data-els="content"]').html(AUTOCOMPLETE.tmpl.get.call(this, "options", data, item.columnKeys)); focusWord.call(this, this.activeautocompleteQueueIndex, searchWord); alignAutocompleteOptionGroup.call(this); setTimeout((function () { alignAutocompleteOptionGroup.call(this); }).bind(this)); }).bind(this)); }, focusWord = function (queIdx, searchWord) { if (this.activeautocompleteQueueIndex == -1) return this; // 옵션박스가 닫힌상태이면 진행안함. var collect_options = [], i = -1, l = this.queue[queIdx].options.length - 1, n; if (searchWord != "") { while (l - i++) { n = this.queue[queIdx].options[i]; if (('' + n.text).toLowerCase() == searchWord.toLowerCase()) { collect_options = [{'@findex': n['@findex'], optionsSort: 0}]; break; } else { var sort = ('' + n.text).toLowerCase().search(searchWord.toLowerCase()); if (sort > -1) { collect_options.push({'@findex': n['@findex'], optionsSort: sort}); if (collect_options.length > 2) break; } sort = null; } } collect_options.sort(function (a, b) { return a.optionsSort - b.optionsSort; }); } if (collect_options && collect_options.length > 0) { focusMove.call(this, queIdx, undefined, collect_options[0]['@findex']); } else { focusClear.call(this, queIdx); } }, focusClear = function (queIdx) { if (this.activeautocompleteOptionGroup) { this.activeautocompleteOptionGroup .find('[data-option-focus-index]') .removeClass("hover") .removeAttr("data-option-selected"); } this.queue[queIdx].optionFocusIndex = -1; }, focusMove = function (queIdx, direction, findex) { var _focusIndex, _prevFocusIndex, focusOptionEl, optionGroupScrollContainer; var item = this.queue[queIdx]; if (this.activeautocompleteOptionGroup && item.options && item.options.length > 0) { if (typeof findex !== "undefined") { _focusIndex = findex } else { _prevFocusIndex = (item.optionFocusIndex == -1) ? item.optionSelectedIndex || -1 : item.optionFocusIndex; if (_prevFocusIndex == -1) { _focusIndex = 0; //_focusIndex = (direction > 0) ? 0 : item.optionItemLength - 1; // 맨 끝으로 보낼것인가 말 것인가. } else { _focusIndex = _prevFocusIndex + direction; if (_focusIndex < 0) _focusIndex = 0; else if (_focusIndex > item.optionItemLength - 1) _focusIndex = item.optionItemLength - 1; } } item.optionFocusIndex = _focusIndex; // 포커스 인덱스가 hide아이템을 만나면 hide 아이템이 안나올 때까지 루프를 순회 합니다. if (item.options[_focusIndex] && item.options[_focusIndex].hide) { // 옵션이 없는 값이 선택된 경우 if (typeof direction === "undefined") { return this; } else { var isStrop = false; while (item.options[_focusIndex].hide) { _focusIndex = _focusIndex + direction; if (_focusIndex < 0) { _focusIndex = 0; break; } else if (_focusIndex > item.optionItemLength - 1) { _focusIndex = item.optionItemLength - 1; break; } } } } if (typeof _focusIndex !== "undefined") { this.activeautocompleteOptionGroup .find('[data-option-focus-index]') .removeClass("hover"); focusOptionEl = this.activeautocompleteOptionGroup .find('[data-option-focus-index="' + _focusIndex + '"]') .addClass("hover"); optionGroupScrollContainer = this.activeautocompleteOptionGroup.find('[data-els="content"]'); if (focusOptionEl.get(0)) { let focusOptionElHeight = focusOptionEl.outerHeight(), optionGroupScrollContainerHeight = optionGroupScrollContainer.innerHeight(), optionGroupScrollContainerScrollTop = optionGroupScrollContainer.scrollTop(), focusOptionElTop = focusOptionEl.position().top + optionGroupScrollContainer.scrollTop(); if (optionGroupScrollContainerHeight + optionGroupScrollContainerScrollTop < focusOptionElTop + focusOptionElHeight) { optionGroupScrollContainer.scrollTop(focusOptionElTop + focusOptionElHeight - optionGroupScrollContainerHeight); } else if (optionGroupScrollContainerScrollTop > focusOptionElTop) { optionGroupScrollContainer.scrollTop(focusOptionElTop); } // optionGroup scroll check if (typeof direction !== "undefined") { item.$displayLabelInput.val(item.options[_focusIndex].text); } } } } }, getQueIdx = function (boundID) { if (boundID instanceof jQuery) { boundID = boundID.data("data-ax5autocomplete-id"); } else if (!U.isString(boundID)) { boundID = jQuery(boundID).data("data-ax5autocomplete-id"); } if (!U.isString(boundID)) { console.log(ax5.info.getError("ax5autocomplete", "402", "getQueIdx")); return; } return U.search(this.queue, function () { return this.id == boundID; }); }, getSelected = function (_item, o, selected) { if (typeof selected === "undefined") { return (_item.multiple) ? !o : true; } else { return selected; } }, clearSelected = function (queIdx) { this.queue[queIdx].options.forEach(function (n) { if (n.optgroup) { n.options.forEach(function (nn) { nn.selected = false; }); } else { n.selected = false; } }); this.queue[queIdx].selected = []; this.queue[queIdx].$select.html(AUTOCOMPLETE.tmpl.get.call(this, "formSelectOptions", { selected: this.queue[queIdx].selected }, this.queue[queIdx].columnKeys)); }, setSelected = (function () { var processor = { 'selectedIndex': function (queIdx, value, selected, setValueType) { }, 'removeSelectedIndex': function (queIdx, value, selected, setValueType) { var item = this.queue[queIdx], addOptions = {}; var newSelectedArray = [], optionIndex = 0; for (var i = 0; i < item.selected.length; i++) { if (item.selected[i]['@index'] != value.removeSelectedIndex.index) { addOptions = {'@index': optionIndex, '@findex': optionIndex}; addOptions[item.columnKeys.optionValue] = item.selected[i][item.columnKeys.optionValue]; addOptions[item.columnKeys.optionText] = item.selected[i][item.columnKeys.optionText]; newSelectedArray.push(addOptions); optionIndex++; } } item.selected = newSelectedArray; }, 'optionIndex': function (queIdx, value, selected, setValueType) { var item = this.queue[queIdx], addOptions = {}; var optionIndex = item.selected.length; var pushOk = true; addOptions = { '@index': optionIndex, '@findex': optionIndex }; addOptions[item.columnKeys.optionValue] = item.options[value.optionIndex.index][item.columnKeys.optionValue]; addOptions[item.columnKeys.optionText] = item.options[value.optionIndex.index][item.columnKeys.optionText]; for (var i = 0; i < item.selected.length; i++) { if (item.selected[i][item.columnKeys.optionValue] == addOptions[item.columnKeys.optionValue]) { pushOk = false; } } if (pushOk) item.selected.push(addOptions); }, 'arr': function (queIdx, values, selected, setValueType) { values.forEach(function (value) { if (U.isString(value) || U.isNumber(value)) { processor.text.call(self, queIdx, value, selected, "justSetValue"); } else { for (var key in processor) { if (value[key]) { processor[key].call(self, queIdx, value, selected, "justSetValue"); break; } } } }); }, 'value': function (queIdx, value, selected, setValueType) { var item = this.queue[queIdx]; var addOptions; var optionIndex = U.search(item.options, function () { return this[item.columnKeys.optionValue] == value.value[item.columnKeys.optionValue]; }); if (optionIndex > -1) { item.options[optionIndex][item.columnKeys.optionSelected] = getSelected(item, item.options[optionIndex][item.columnKeys.optionSelected], selected); if (item.options[optionIndex][item.columnKeys.optionSelected]) { var appendOk = true; for (var i = 0; i < item.selected.length; i++) { if (item.selected[i][cfg.columnKeys.optionValue] == item.options[optionIndex][cfg.columnKeys.optionValue]) { appendOk = false; break; } } if (appendOk) { addOptions = {}; addOptions[item.columnKeys.optionValue] = item.options[optionIndex][item.columnKeys.optionValue]; addOptions[item.columnKeys.optionText] = item.options[optionIndex][item.columnKeys.optionText]; item.selected.push(addOptions); } } else { var newSelectedArray = []; for (var i = 0; i < item.selected.length; i++) { if (item.selected[i][cfg.columnKeys.optionValue] == item.options[optionIndex][cfg.columnKeys.optionValue]) { } else { addOptions = {}; addOptions[item.columnKeys.optionValue] = item.selected[i][item.columnKeys.optionValue]; addOptions[item.columnKeys.optionText] = item.selected[i][item.columnKeys.optionText]; newSelectedArray.push(addOptions); } } item.selected = newSelectedArray; } } else { // 새로운 값 추가 var appendOk = true; for (var i = 0; i < item.selected.length; i++) { if (item.selected[i][cfg.columnKeys.optionValue] == value.value[cfg.columnKeys.optionValue]) { appendOk = false; break; } } if (appendOk) { addOptions = {}; addOptions[item.columnKeys.optionValue] = value.value[cfg.columnKeys.optionValue]; addOptions[item.columnKeys.optionText] = value.value[cfg.columnKeys.optionText]; item.selected.push(addOptions); } } }, 'text': function (queIdx, value, selected, setValueType) { var item = this.queue[queIdx]; var addOptions; var optionIndex = U.search(item.options, function () { return this[item.columnKeys.optionText] == value; }); if (optionIndex > -1) { item.options[optionIndex][item.columnKeys.optionSelected] = getSelected(item, item.options[optionIndex][item.columnKeys.optionSelected], selected); if (item.options[optionIndex][item.columnKeys.optionSelected]) { var appendOk = true; for (var i = 0; i < item.selected.length; i++) { if (item.selected[i][cfg.columnKeys.optionText] == item.options[optionIndex][cfg.columnKeys.optionText]) { appendOk = false; break; } } if (appendOk) { addOptions = {}; addOptions[item.columnKeys.optionValue] = item.options[optionIndex][item.columnKeys.optionValue]; addOptions[item.columnKeys.optionText] = item.options[optionIndex][item.columnKeys.optionText]; item.selected.push(addOptions); } } else { var newSelectedArray = []; for (var i = 0; i < item.selected.length; i++) { if (item.selected[i][cfg.columnKeys.optionText] == item.options[optionIndex][cfg.columnKeys.optionText]) { } else { addOptions = {}; addOptions[item.columnKeys.optionValue] = item.selected[i][item.columnKeys.optionValue]; addOptions[item.columnKeys.optionText] = item.selected[i][item.columnKeys.optionText]; newSelectedArray.push(addOptions); } } item.selected = newSelectedArray; } } else { // 새로운 값 추가 var appendOk = true; for (var i = 0; i < item.selected.length; i++) { if (item.selected[i][cfg.columnKeys.optionText] == value) { appendOk = false; break; } } if (appendOk) { addOptions = {}; addOptions[item.columnKeys.optionValue] = value; addOptions[item.columnKeys.optionText] = value; item.selected.push(addOptions); } } }, 'clear': function (queIdx) { clearSelected.call(this, queIdx); focusClear.call(this, queIdx); if (this.activeautocompleteOptionGroup) { this.activeautocompleteOptionGroup .find('[data-option-index]') .attr("data-option-Selected", "false"); } this.queue[queIdx].optionSelectedIndex = -1; } }; return function (boundID, value, selected, _option) { var queIdx = (U.isNumber(boundID)) ? boundID : getQueIdx.call(this, boundID); if (queIdx === -1) { console.log(ax5.info.getError("ax5autocomplete", "402", "val")); return; } if (typeof value == "undefined") { throw "error not found value"; } else if (U.isArray(value)) { processor.clear.call(this, queIdx); processor.arr.call(this, queIdx, (this.queue[queIdx].multiple || value.length == 0) ? value : [value[value.length - 1]], selected); } else if (U.isString(value) || U.isNumber(value)) { if (typeof value !== "undefined" && value !== null && !this.queue[queIdx].multiple) { clearSelected.call(this, queIdx); } processor.text.call(this, queIdx, value, selected); } else { if (value === null) { processor.clear.call(this, queIdx); } else { if (!this.queue[queIdx].multiple) { clearSelected.call(this, queIdx); } for (var key in processor) { if (value[key]) { processor[key].call(this, queIdx, value, selected); break; } } } } syncLabel.call(this, queIdx); printLabel.call(this, queIdx); focusLabel.call(this, queIdx); alignAutocompleteOptionGroup.call(this); if (typeof value !== "undefined") { if (_option && !_option.noStateChange) { onStateChanged.call(this, this.queue[queIdx], { self: this, item: this.queue[queIdx], state: "changeValue", value: this.queue[queIdx].selected }); } } boundID = null; return this; }; })(); /// private end /** * Preferences of autocomplete UI * @method ax5autocomplete.setConfig * @param {Object} config - 클래스 속성값 * @returns {ax5autocomplete} * @example * ``` * ``` */ this.init = function () { this.onStateChanged = cfg.onStateChanged; this.onChange = cfg.onChange; jQuery(window).on("resize.ax5autocomplete-display-" + this.instanceId, (function () { alignAutocompleteDisplay.call(this); }).bind(this)); }; /** * bind autocomplete * @method ax5autocomplete.bind * @param {Object} item * @param {String} [item.id] * @param {String} [item.theme] * @param {Boolean} [item.multiple] * @param {Element} item.target * @returns {ax5autocomplete} */ this.bind = function (item) { var bindAutocompleteTarget = (function () { var debouncedFocusWord = U.debounce(function (queIdx) { if (this.activeautocompleteQueueIndex == -1) return this; // 옵션박스가 닫힌상태이면 진행안함. onSearch.call(self, queIdx, this.queue[queIdx].$displayLabelInput.val()); }, 150); var blurLabel = function (queIdx) { clearLabel.call(this, queIdx); }; var autocompleteEvent = { 'click': function (queIdx, e) { var clickEl; var target = U.findParentNode(e.target, function (target) { if (target.getAttribute("data-ax5autocomplete-remove")) { clickEl = "optionItemRemove"; return true; } else if (target.getAttribute("data-selected-clear")) { clickEl = "clear"; return true; } }); if (target) { if (clickEl === "optionItemRemove") { var removeIndex = target.getAttribute("data-ax5autocomplete-remove-index"); this.queue[queIdx].selected.splice(removeIndex, 1); syncLabel.call(this, queIdx); printLabel.call(this, queIdx); focusLabel.call(this, queIdx); alignAutocompleteDisplay.call(this); alignAutocompleteOptionGroup.call(this); U.stopEvent(e); return this; } else if (clickEl === "clear") { setSelected.call(this, queIdx, {clear: true}); alignAutocompleteDisplay.call(this); alignAutocompleteOptionGroup.call(this); } } else { if (self.activeautocompleteQueueIndex == queIdx) { if (this.queue[queIdx].optionFocusIndex == -1) { // 아이템에 포커스가 활성화 된 후, 마우스 이벤트 이면 무시 self.close(); } } else { focusLabel.call(this, queIdx); } } }, 'keyUp': function (queIdx, e) { /// 약속된 키 이벤트가 발생하면 stopEvent를 통해 keyUp 이벤트가 발생되지 않도록 막아주는 센스 if (e.which == ax5.info.eventKeys.ESC && this.activeautocompleteQueueIndex === -1) { // ESC키를 누르고 옵션그룹이 열려있지 않은 경우 U.stopEvent(e); return this; } if (e.which == ax5.info.eventKeys.TAB) { // nothing this.close(); return this; } if (this.activeautocompleteQueueIndex != queIdx) { // 닫힌 상태 인경우 this.open(queIdx); // open and align } if (ctrlKeys[e.which]) { U.stopEvent(e); } else { // backspace 감지 하여 input 값이 없으면 스탑이벤트 처리 할 것 if (e.which == ax5.info.eventKeys.BACKSPACE && this.queue[queIdx].$displayLabelInput.val() == "") { // 마지막 아이템을 제거. this.queue[queIdx].selected.pop(); syncLabel.call(this, queIdx); printLabel.call(this, queIdx); focusLabel.call(this, queIdx); alignAutocompleteDisplay.call(this); alignAutocompleteOptionGroup.call(this); U.stopEvent(e); } else { debouncedFocusWord.call(this, queIdx); } } }, 'keyDown': function (queIdx, e) { if (e.which == ax5.info.eventKeys.ESC) { clearLabel.call(this, queIdx); this.close(); U.stopEvent(e); } else if (e.which == ax5.info.eventKeys.RETURN) { var inputValue = this.queue[queIdx].$displayLabelInput.val(); if(item.optionFocusIndex > -1) { setSelected.call(this, item.id, { optionIndex: { index: item.optionFocusIndex } }, undefined, "optionItemClick"); }else if(inputValue != ""){ setSelected.call(this, queIdx, inputValue, true); } clearLabel.call(this, queIdx); alignAutocompleteDisplay.call(this); this.close(); U.stopEvent(e); } else if (e.which == ax5.info.eventKeys.DOWN) { focusMove.call(this, queIdx, 1); U.stopEvent(e); } else if (e.which == ax5.info.eventKeys.UP) { focusMove.call(this, queIdx, -1); U.stopEvent(e); } }, 'focus': function (queIdx, e) { // console.log(e); }, 'blur': function (queIdx, e) { blurLabel.call(this, queIdx); U.stopEvent(e); }, 'selectChange': function (queIdx, e) { setSelected.call(this, queIdx, {value: this.queue[queIdx].$select.val()}, true); } }; return function (queIdx) { var item = this.queue[queIdx]; var data = {}; if (!item.$display) { /// 템플릿에 전달할 오브젝트 선언 data.instanceId = this.instanceId; data.id = item.id; data.name = item.name; data.theme = item.theme; data.tabIndex = item.tabIndex; data.multiple = item.multiple; data.reset = item.reset; data.label = getLabel.call(this, queIdx); data.formSize = (function () { return (item.size) ? "input-" + item.size : ""; })(); item.$display = jQuery(AUTOCOMPLETE.tmpl.get.call(this, "autocompleteDisplay", data, item.columnKeys)); item.$displayTable = item.$display.find('[data-els="display-table"]'); item.$displayLabel = item.$display.find('[data-ax5autocomplete-display="label"]'); item.$displayLabelInput = item.$display.find('[data-ax5autocomplete-display="input"]'); if (item.$target.find("select").get(0)) { item.$select = item.$target.find("select"); item.$select .attr("tabindex", "-1") .attr("class", "form-control " + data.formSize); if (data.name) { item.$select.attr("name", "name"); } item.$select.attr("multiple", "multiple");