jui.defineUI("ui.combo", [ "jquery", "util.base" ], function($, _) { var hideAll = function() { var call_list = jui.get("ui.combo"); for(var i = 0; i < call_list.length; i++) { var ui_list = call_list[i]; for(var j = 0; j < ui_list.length; j++) { if(ui_list[j].type == "open") ui_list[j].fold(); } } } $(function() { document.addEventListener("click", function(e) { hideAll(); }); }); /** * @class ui.combo * @extends core * @alias Combo Box * @requires jquery * @requires util.base */ var UI = function() { var ui_list = null, ui_data = null; var index = -1; function load(type, data) { var $combo_root = ui_list["root"], $combo_text = ui_list["text"], $combo_drop = ui_list["drop"], $combo_list = $combo_drop.children("li"); $combo_list.each(function(i) { var elem = getElement(this), value = $(elem).attr("value"), text = $(elem).text(); if(!value) { value = text; $(elem).attr("value", value); } if((type == "index" && data == i) || (type == "value" && data == value)) { ui_data = { index: i, value: value, text: text }; $combo_root.attr("value", value); $combo_text.html(text); if ($combo_root.select && $combo_root.select[0] ) { $combo_root.select[0].selectedIndex = i; } } }); if($combo_list.length == 0) { ui_data = null; } } function getElement(target) { // 드롭다운 메뉴 타겟 return ($(target).children("a").length > 0) ? $(target).children("a")[0] : target; } function setEventKeydown(self) { if(!self.options.keydown) return; // 기본 상태 처리 index = self.options.index; selectItem(self); self.addEvent(window, "keydown", function(e) { if(self.type == "fold") return; var $list = ui_list["drop"].children("li"); if(e.which == 38) { // up if(index < 1) index = $list.length - 1; else index--; selectItem(self, function() { index--; selectItem(self); }); return false; } if(e.which == 40) { // down if(index < $list.length - 1) index++; else index = 0; selectItem(self, function() { index++; selectItem(self); }); return false; } if(e.which == 13) { // enter $list.eq(index).trigger("click"); } }); } function selectItem(self, callback) { var $list = ui_list["drop"].children("li"), $target = $list.eq(index); $list.removeClass("active"); if($target.val() != "" || $target.html() != "") { $target.addClass("active"); if(self.options.height > 0) { ui_list["drop"].scrollTop(index * $target.outerHeight()); } } else { if(typeof(callback) == "function") { callback(); } } } function makeSelectTouch(self) { if(!_.isTouch) return; var $combo_root = ui_list["root"]; if ($combo_root.select && $combo_root.select[0]) { var $select = $combo_root.select; $select.empty(); } else { var $select = $("<select></select>").css({ position: "absolute", opacity : 0.01 }); $combo_root.find("ul").after($select); self.addEvent($select, "change", function(e) { var elem = $(e.currentTarget).find("option:selected").data("elem"); self.addTrigger(elem, "touchstart"); }); $combo_root.select = $select; } $combo_root.find("ul > li").each(function(i, elem) { var value = $(elem).data('value'); var text = $(elem).text(); $select.append($("<option></option>").val(value).text(text).data("elem", elem)); }); } function getMaxListWidth() { var maxValue = 0; ui_list["drop"].children("li").each(function(i) { var elem = getElement(this); maxValue = Math.max(maxValue, $(elem).outerWidth()); }); return maxValue; } this.init = function() { var self = this, opts = this.options; var $combo_root = $(this.root), $combo_text = $combo_root.children(".btn").not(".toggle"), $combo_toggle = $combo_root.children(".toggle"), $combo_click = $combo_root.children(".btn"), $combo_drop = $combo_root.children("ul"); //-- 드롭다운은 중앙으로 위치 (그룹 스타일 좌/우 라운드 효과) $combo_drop.insertAfter($combo_text); // Width if(opts.width > 0) { $combo_text.outerWidth(opts.width - $combo_toggle.outerWidth() + 1); $combo_text.css({ "overflow-x": "hidden", "overflow-y": "hidden", "white-space": "nowrap" }); } // Height if(opts.height > 0) { $combo_drop.css({ "overflow-x": "hidden", "overflow-y": "auto", "max-height": opts.height }); } // Show this.addEvent($combo_click, "click", function(e) { if (_.isTouch) { $combo_root.select.focus(); } else { if(self.type == "open") return; hideAll(); self.open(e); } return false; }); // Select this.addEvent($combo_drop, "click", "li:not(.divider)", function(e) { hideAll(); var elem = getElement(this), value = $(elem).attr("value"), text = $(elem).text(); ui_data = { value: value, text: text, element: elem }; $combo_text.html(text); $combo_root.attr("value", value); self.emit("click", [ ui_data, e ]); self.emit("change", [ ui_data, e ]); e.preventDefault(); }); // Init ui_list = { root: $combo_root, text: $combo_text, drop: $combo_drop, toggle: $combo_toggle }; this.type = "fold"; // 기본 타입 설정 this.reload(); // Key up/down event setEventKeydown(this); } /** * @method setIndex * Selects a button of a specified index * * @param {Number} index */ this.setIndex = function(index) { load("index", index); this.emit("change", [ ui_data ]); } /** * @method setValue * Selects a button having a specified value * * @param {Mixed} value */ this.setValue = function(value) { load("value", value); this.emit("change", [ ui_data ]); } /** * @method getData * Gets the data of the button currently selected * * @return {Object} */ this.getData = function() { return ui_data; } /** * @method getValue * Gets the value of the button currently selected * * @return {Mixed} */ this.getValue = function() { return (ui_data != null) ? ui_data["value"] : null; } /** * @method getText * Gets the markup text of the button currently selected * * @return {String} */ this.getText = function() { return (ui_data != null) ? ui_data["text"] : null; } /** * @method open * Shows the element list of a combo box */ this.open = function(e) { ui_list["toggle"].addClass("active"); ui_list["drop"].outerWidth(ui_list["root"].outerWidth() - 1); if(this.options.position == "top") { var h = ui_list["drop"].outerHeight(); ui_list["drop"].animate({ top: "-" + h, height: "toggle" }, 100); } else { ui_list["drop"].slideDown(100); } if(this.options.flex) { var maxWidth = getMaxListWidth(); if(maxWidth > ui_list["drop"].outerWidth()) { ui_list["drop"].outerWidth(getMaxListWidth() + 50); } } this.emit("open", e); this.type = "open"; } /** * @method fold * Hides the element list of a combo box */ this.fold = function() { ui_list["drop"].hide(); ui_list["toggle"].removeClass("active"); if(this.options.position == "top") { ui_list["drop"].css("top", 0); } this.emit("fold"); this.type = "fold"; } /** * @method reload * Re-defines a combo box */ this.reload = function() { if(this.options.value != "") { load("value", this.options.value); } else { load("index", this.options.index); } makeSelectTouch(this); this.emit("reload", ui_data); } } UI.setup = function() { return { /** * @cfg {Integer} [index=0] * Determines an initial selection button with a specified index */ index: 0, /** * @cfg {String} [value=0] * Determines an initial selection button with a specified value */ value: "", /** * @cfg {Integer} [width=0] * Determines the horizontal size of a combo box */ width: 0, /** * @cfg {Integer} [height=100] * Determines an initial selection button with a specified value */ height: 100, /** * @cfg {Boolean} [keydown=false] * It is possible to select a node using the keyboard */ keydown: false, /** * @cfg {"top"/"bottom"} [position="bottom"] * It is possible to determine an initial selection button with a specified value */ position: "bottom", /** * @cfg {Boolean} [flex=true] * Drop-down menu is varied by changing the width function */ flex: true } } /** * @event change * Event which occurs when selecting a combo box * * @param {Object} data changed data * @param {EventObject} e The event object */ /** * @event click * Event which occurs when selecting a combo box * * @param {Object} data changed data * @param {EventObject} e The event object */ /** * @event open * Event which occurs when opening a combo box */ /** * @event fold * Event which occurs when folding a combo box */ return UI; });