jui.defineUI("ui.tab", [ "jquery", "util.base", "ui.dropdown" ], function($, _, dropdown) { /** * @class ui.tab * @extends core * @alias Tab * @requires jquery * @requires util.base * @requires ui.dropdown */ var UI = function() { var ui_menu = null, $anchor = null; var menuIndex = -1, // menu index activeIndex = 0; function hideAll(self) { var $list = $(self.root).children("li"); $list.removeClass("active"); } function showMenu(self, elem) { var pos = $(elem).offset(); $(elem).addClass("checked"); ui_menu.show(pos.left, pos.top + $(self.root).height()); } function hideMenu(self) { var $list = $(self.root).children("li"), $menuTab = $list.eq(menuIndex); $menuTab.removeClass("checked"); } function changeTab(self, index) { hideAll(self); var $list = $(self.root).children("li"), $tab = $list.eq(index).addClass("active"); $anchor.appendTo($tab); showTarget(self.options.target, $tab[0]); } function showTarget(target, elem, isInit) { var hash = $(elem).find("[href*=\#]").attr("href"); $(target).children("*").each(function(i) { var self = this; if(("#" + self.id) == hash) { $(self).show(); } else { $(self).hide(); } }); } function setEventNodes(self) { $(self.root).children("li").each(function(i) { // 메뉴 설정 if($(this).hasClass("menu")) { menuIndex = i; } // 이벤트 설정 self.addEvent(this, [ "click", "contextmenu" ], function(e) { if($(this).hasClass("disabled")) { return false; } var text = $.trim($(this).text()), value = $(this).val(); if(i != menuIndex) { if(i != activeIndex) { var args = [ { index: i, text: text, value: value }, e ]; if(self.options.target != "") { showTarget(self.options.target, this); } // 엑티브 인덱스 변경 activeIndex = i; self.emit("change", args); self.emit("click", args); changeTab(self, i); } } else { self.emit("menu", [ { index: i, text: text }, e ]); if(ui_menu.type != "show") showMenu(self, this); } return false; }); }); setActiveNode(self); setEventDragNodes(self); } function setEventDragNodes(self) { if(!self.options.drag) return; var $tabs = $(self.root).children("li"), $origin = null, $clone = null; var index = null, targetIndex = null; $tabs.each(function(i) { self.addEvent(this, "mousedown", function(e) { $origin = $(this); $clone = $origin.clone().css("opacity", "0.5"); index = i; self.emit("dragstart", [ index, e ]); return false; }); self.addEvent(this, "mousemove", function(e) { if(index == null) return; targetIndex = i; if(index > targetIndex) { // move 로직과 동일 if(targetIndex == 0) { $clone.insertBefore($tabs.eq(0)); } else { $clone.insertAfter($tabs.eq(targetIndex - 1)); } } else { if(targetIndex == $tabs.length - 1) { $clone.insertAfter($tabs.eq(targetIndex)); } else { $clone.insertBefore($tabs.eq(targetIndex + 1)); } } $origin.hide(); }); }); self.addEvent(self.root, "mouseup", function(e) { if($origin != null) $origin.show(); if($clone != null) $clone.remove(); if(index != null && targetIndex != null) { self.move(index, targetIndex); self.emit("dragend", [ targetIndex, e ]); } index = null; targetIndex = null; }); } function setActiveNode(self) { var $list = $(self.root).children("li"), $markupNode = $list.filter(".active"), $indexNode = $list.eq(activeIndex), $node = ($markupNode.length == 1) ? $markupNode : $indexNode; // 노드가 없거나 disabled 상태일 때, 맨 첫번째 노드를 활성화 if($node.hasClass("disabled") || $node.length == 0) { $node = $list.eq(0); activeIndex = 0; } $anchor.appendTo($node); changeTab(self, $list.index($node)); } this.init = function() { var self = this, opts = this.options; // 활성화 인덱스 설정 activeIndex = opts.index; // 컴포넌트 요소 세팅 $anchor = $("<div class='anchor'></div>"); // 탭 목록 갱신 및 이벤트 설정 if(opts.nodes.length > 0) { this.update(opts.nodes); } else { setEventNodes(this); } // 드롭다운 메뉴 if(this.tpl.menu) { var $menu = $(this.tpl.menu()); $("body").append($menu); ui_menu = dropdown($menu, { event: { change: function(data, e) { hideMenu(self); self.emit("changemenu", [ data, e ]); }, hide: function() { hideMenu(self); } } }); } return this; } /** * @method update * Changes the tab list * * @param {Array} nodes */ this.update = function(nodes) { if(!this.tpl.node) return; $(this.root).empty(); for(var i = 0; i < nodes.length; i++) { $(this.root).append(this.tpl.node(nodes[i])); } setEventNodes(this); } /** * @method insert * Adds a tab at a specified index * * @param {Integer} index * @param {Object} node */ this.insert = function(index, node) { if(!this.tpl.node) return; var html = this.tpl.node(node), $list = $(this.root).children("li"); if(index == $list.length) { $(html).insertAfter($list.eq(index - 1)); } else { $(html).insertBefore($list.eq(index)); } setEventNodes(this); } /** * @method append * Adds a tab to the last node * * @param {Object} node */ this.append = function(node) { if(!this.tpl.node) return; var html = this.tpl.node(node); if(menuIndex != -1) { $(html).insertBefore($(this.root).find(".menu")); menuIndex++; } else { $(this.root).append(html); } setEventNodes(this); } /** * @method prepend * Adds a tab to the first node * * @param {Object} node */ this.prepend = function(node) { if(!this.tpl.node) return; $(this.root).prepend(this.tpl.node(node)); setEventNodes(this); } /** * @method remove * Removes a tab at a specified index * * @param {Integer} index */ this.remove = function(index) { $(this.root).children("li").eq(index).remove(); setEventNodes(this); } /** * @method move * Changes a specified tab to a tab at a target index * * @param {Integer} index * @param {Integer} targetIndex */ this.move = function(index, targetIndex) { if(index == targetIndex) return; var $tabs = $(this.root).children("li"), $target = $tabs.eq(index); if(index > targetIndex) { if(targetIndex == 0) { $target.insertBefore($tabs.eq(0)); } else { $target.insertAfter($tabs.eq(targetIndex - 1)); } } else { if(targetIndex == $tabs.length - 1) { $target.insertAfter($tabs.eq(targetIndex)); } else { $target.insertBefore($tabs.eq(targetIndex + 1)); } } activeIndex = targetIndex; setEventNodes(this); } /** * @method show * Enables the tab at a specified index * * @param {Integer} index */ this.show = function(index) { if(index == menuIndex || index == activeIndex) return; var $target = $(this.root).children("li").eq(index); if($target.hasClass("disabled")) return; activeIndex = index; this.emit("change", [{ index: index, text: $.trim($target.text()), value: $target.val() }]); changeTab(this, index); } /** * @method enable * Enables the tab at a specified index * * @param {Integer} index */ this.enable = function(index) { if(index == menuIndex || index == activeIndex) return; var $target = $(this.root).children("li").eq(index); $target.removeClass("disabled"); } /** * @method disable * Disables the tab at a specified index * * @param {Integer} index */ this.disable = function(index) { if(index == menuIndex || index == activeIndex) return; var $target = $(this.root).children("li").eq(index); $target.addClass("disabled"); } /** * @method activeIndex * Gets the index of the currently enabled tab * * @return {Integer} */ this.activeIndex = function() { return activeIndex; } } UI.setup = function() { return { /** * @cfg {String/DOMElement} [target=""] * Determines a selector in the area to become the content of a tab */ target: "", /** * @cfg {Integer} [index=0] * Sets an enabled tab */ index: 0, /** * @cfg {Boolean} [drag=false] * Changes the tab location through dragging */ drag: false, /** * @cfg {Array} nodes * Sets a tab list to data rather than markup */ nodes: [] } } /** * @event change * Event that occurs when a tab is enabled * * @param {Object} data changed data * @param {EventObject} e The event object */ /** * @event click * Event that occurs when a tab is mouse clicked * * @param {Object} data changed data * @param {EventObject} e The event object */ * @event menu * Event which occurs when tab menu shown * * @param {Object} data changed data * @param {EventObject} e The event object */ * @event changemenu * Event that occurs when a dropdown is selected * * @param {Object} data changed data * @param {EventObject} e The event object */ /** * @event dragstart * Event that occurs when a tab starts to move * * @param {Integer} index * @param {EventObject} e The event object */ /** * @event dragend * Event that occurs when the movement of a tab is completed * * @param {Integer} index * @param {EventObject} e The event object */ return UI; });