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;
});