You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
633 lines
16 KiB
Plaintext
633 lines
16 KiB
Plaintext
/**
|
|
* tabs - jQuery EasyUI
|
|
*
|
|
* Licensed under the GPL terms
|
|
* To use it on other terms please contact us
|
|
*
|
|
* Copyright(c) 2009-2012 stworthy [ stworthy@gmail.com ]
|
|
*
|
|
* Dependencies:
|
|
* panel
|
|
* linkbutton
|
|
*
|
|
*/
|
|
(function($){
|
|
|
|
/**
|
|
* get the max tabs scroll width(scope)
|
|
*/
|
|
function getMaxScrollWidth(container) {
|
|
var header = $(container).children('div.tabs-header');
|
|
var tabsWidth = 0; // all tabs width
|
|
$('ul.tabs li', header).each(function(){
|
|
tabsWidth += $(this).outerWidth(true);
|
|
});
|
|
var wrapWidth = header.children('div.tabs-wrap').width();
|
|
var padding = parseInt(header.find('ul.tabs').css('padding-left'));
|
|
|
|
return tabsWidth - wrapWidth + padding;
|
|
}
|
|
|
|
/**
|
|
* set the tabs scrollers to show or not,
|
|
* dependent on the tabs count and width
|
|
*/
|
|
function setScrollers(container) {
|
|
var opts = $.data(container, 'tabs').options;
|
|
var header = $(container).children('div.tabs-header');
|
|
var tool = header.children('div.tabs-tool');
|
|
var sLeft = header.children('div.tabs-scroller-left');
|
|
var sRight = header.children('div.tabs-scroller-right');
|
|
var wrap = header.children('div.tabs-wrap');
|
|
|
|
// set the tool height
|
|
tool._outerHeight(header.outerHeight() - (opts.plain ? 2 : 0));
|
|
|
|
var tabsWidth = 0;
|
|
$('ul.tabs li', header).each(function(){
|
|
tabsWidth += $(this).outerWidth(true);
|
|
});
|
|
var cWidth = header.width() - tool._outerWidth();
|
|
|
|
if (tabsWidth > cWidth) {
|
|
sLeft.show();
|
|
sRight.show();
|
|
tool.css('right', sRight.outerWidth());
|
|
wrap.css({
|
|
marginLeft: sLeft.outerWidth(),
|
|
marginRight: sRight.outerWidth() + tool._outerWidth(),
|
|
left: 0,
|
|
width: cWidth - sLeft.outerWidth() - sRight.outerWidth()
|
|
});
|
|
} else {
|
|
sLeft.hide();
|
|
sRight.hide();
|
|
tool.css('right', 0);
|
|
wrap.css({
|
|
marginLeft:0,
|
|
marginRight:tool._outerWidth(),
|
|
left: 0,
|
|
width: cWidth
|
|
});
|
|
wrap.scrollLeft(0);
|
|
}
|
|
}
|
|
|
|
function addTools(container){
|
|
var opts = $.data(container, 'tabs').options;
|
|
var header = $(container).children('div.tabs-header');
|
|
if (opts.tools) {
|
|
if (typeof opts.tools == 'string'){
|
|
$(opts.tools).addClass('tabs-tool').appendTo(header);
|
|
$(opts.tools).show();
|
|
} else {
|
|
header.children('div.tabs-tool').remove();
|
|
var tools = $('<div class="tabs-tool"></div>').appendTo(header);
|
|
for(var i=0; i<opts.tools.length; i++){
|
|
var tool = $('<a href="javascript:void(0);"></a>').appendTo(tools);
|
|
tool[0].onclick = eval(opts.tools[i].handler || function(){});
|
|
tool.linkbutton($.extend({}, opts.tools[i], {
|
|
plain: true
|
|
}));
|
|
}
|
|
}
|
|
} else {
|
|
header.children('div.tabs-tool').remove();
|
|
}
|
|
}
|
|
|
|
function setSize(container) {
|
|
var opts = $.data(container, 'tabs').options;
|
|
var cc = $(container);
|
|
if (opts.fit == true){
|
|
var p = cc.parent();
|
|
p.addClass('panel-noscroll');
|
|
if (p[0].tagName == 'BODY') $('html').addClass('panel-fit');
|
|
opts.width = p.width();
|
|
opts.height = p.height();
|
|
}
|
|
cc.width(opts.width).height(opts.height);
|
|
|
|
var header = $(container).children('div.tabs-header');
|
|
header._outerWidth(opts.width);
|
|
|
|
setScrollers(container);
|
|
|
|
var panels = $(container).children('div.tabs-panels');
|
|
var height = opts.height;
|
|
if (!isNaN(height)) {
|
|
panels._outerHeight(height - header.outerHeight());
|
|
} else {
|
|
panels.height('auto');
|
|
}
|
|
var width = opts.width;
|
|
if (!isNaN(width)){
|
|
panels._outerWidth(width);
|
|
} else {
|
|
panels.width('auto');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* set selected tab panel size
|
|
*/
|
|
function setSelectedSize(container){
|
|
var opts = $.data(container, 'tabs').options;
|
|
var tab = getSelectedTab(container);
|
|
if (tab){
|
|
var panels = $(container).children('div.tabs-panels');
|
|
var width = opts.width=='auto' ? 'auto' : panels.width();
|
|
var height = opts.height=='auto' ? 'auto' : panels.height();
|
|
tab.panel('resize', {
|
|
width: width,
|
|
height: height
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* wrap the tabs header and body
|
|
*/
|
|
function wrapTabs(container) {
|
|
var tabs = $.data(container, 'tabs').tabs;
|
|
var cc = $(container);
|
|
cc.addClass('tabs-container');
|
|
cc.wrapInner('<div class="tabs-panels"/>');
|
|
$('<div class="tabs-header">'
|
|
+ '<div class="tabs-scroller-left"></div>'
|
|
+ '<div class="tabs-scroller-right"></div>'
|
|
+ '<div class="tabs-wrap">'
|
|
+ '<ul class="tabs"></ul>'
|
|
+ '</div>'
|
|
+ '</div>').prependTo(container);
|
|
|
|
cc.children('div.tabs-panels').children('div').each(function(i){
|
|
var opts = $.extend({}, $.parser.parseOptions(this), {
|
|
selected: ($(this).attr('selected') ? true : undefined)
|
|
});
|
|
var pp = $(this);
|
|
tabs.push(pp);
|
|
createTab(container, pp, opts);
|
|
});
|
|
|
|
cc.children('div.tabs-header').find('.tabs-scroller-left, .tabs-scroller-right').hover(
|
|
function(){$(this).addClass('tabs-scroller-over');},
|
|
function(){$(this).removeClass('tabs-scroller-over');}
|
|
);
|
|
cc.bind('_resize', function(e,force){
|
|
var opts = $.data(container, 'tabs').options;
|
|
if (opts.fit == true || force){
|
|
setSize(container);
|
|
setSelectedSize(container);
|
|
}
|
|
return false;
|
|
});
|
|
}
|
|
|
|
function setProperties(container){
|
|
var opts = $.data(container, 'tabs').options;
|
|
var header = $(container).children('div.tabs-header');
|
|
var panels = $(container).children('div.tabs-panels');
|
|
|
|
if (opts.plain == true) {
|
|
header.addClass('tabs-header-plain');
|
|
} else {
|
|
header.removeClass('tabs-header-plain');
|
|
}
|
|
if (opts.border == true){
|
|
header.removeClass('tabs-header-noborder');
|
|
panels.removeClass('tabs-panels-noborder');
|
|
} else {
|
|
header.addClass('tabs-header-noborder');
|
|
panels.addClass('tabs-panels-noborder');
|
|
}
|
|
|
|
$('.tabs-scroller-left', header).unbind('.tabs').bind('click.tabs', function(){
|
|
var wrap = $('.tabs-wrap', header);
|
|
var pos = wrap.scrollLeft() - opts.scrollIncrement;
|
|
wrap.animate({scrollLeft:pos}, opts.scrollDuration);
|
|
});
|
|
|
|
$('.tabs-scroller-right', header).unbind('.tabs').bind('click.tabs', function(){
|
|
var wrap = $('.tabs-wrap', header);
|
|
var pos = Math.min(
|
|
wrap.scrollLeft() + opts.scrollIncrement,
|
|
getMaxScrollWidth(container)
|
|
);
|
|
wrap.animate({scrollLeft:pos}, opts.scrollDuration);
|
|
});
|
|
}
|
|
|
|
function createTab(container, pp, options) {
|
|
var state = $.data(container, 'tabs');
|
|
options = options || {};
|
|
|
|
// create panel
|
|
pp.panel($.extend({}, options, {
|
|
border: false,
|
|
noheader: true,
|
|
closed: true,
|
|
doSize: false,
|
|
iconCls: (options.icon ? options.icon : undefined),
|
|
onLoad: function(){
|
|
if (options.onLoad){
|
|
options.onLoad.call(this, arguments);
|
|
}
|
|
state.options.onLoad.call(container, $(this));
|
|
}
|
|
}));
|
|
|
|
var opts = pp.panel('options');
|
|
|
|
var tabs = $(container).children('div.tabs-header').find('ul.tabs');
|
|
|
|
opts.tab = $('<li></li>').appendTo(tabs); // set the tab object in panel options
|
|
opts.tab.append(
|
|
'<a href="javascript:void(0)" class="tabs-inner">' +
|
|
'<span class="tabs-title"></span>' +
|
|
'<span class="tabs-icon"></span>' +
|
|
'</a>'
|
|
);
|
|
opts.tab.unbind('.tabs').bind('click.tabs', {p:pp}, function(e){
|
|
if ($(this).hasClass('tabs-disabled')){return;}
|
|
selectTab(container, getTabIndex(container, e.data.p));
|
|
}).bind('contextmenu.tabs', {p:pp}, function(e){
|
|
if ($(this).hasClass('tabs-disabled')){return;}
|
|
state.options.onContextMenu.call(container, e, $(this).find('span.tabs-title').html(), getTabIndex(container, e.data.p));
|
|
});
|
|
|
|
updateTab(container, {
|
|
tab: pp,
|
|
options: opts
|
|
});
|
|
}
|
|
|
|
function addTab(container, options) {
|
|
var opts = $.data(container, 'tabs').options;
|
|
var tabs = $.data(container, 'tabs').tabs;
|
|
if (options.selected == undefined) options.selected = true;
|
|
|
|
var pp = $('<div></div>').appendTo($(container).children('div.tabs-panels'));
|
|
tabs.push(pp);
|
|
createTab(container, pp, options);
|
|
|
|
opts.onAdd.call(container, options.title, tabs.length-1);
|
|
|
|
setScrollers(container);
|
|
if (options.selected){
|
|
selectTab(container, tabs.length-1); // select the added tab panel
|
|
}
|
|
}
|
|
|
|
/**
|
|
* update tab panel, param has following properties:
|
|
* tab: the tab panel to be updated
|
|
* options: the tab panel options
|
|
*/
|
|
function updateTab(container, param){
|
|
var selectHis = $.data(container, 'tabs').selectHis;
|
|
var pp = param.tab; // the tab panel
|
|
var oldTitle = pp.panel('options').title;
|
|
pp.panel($.extend({}, param.options, {
|
|
iconCls: (param.options.icon ? param.options.icon : undefined)
|
|
}));
|
|
|
|
var opts = pp.panel('options'); // get the tab panel options
|
|
var tab = opts.tab;
|
|
|
|
var s_title = tab.find('span.tabs-title');
|
|
var s_icon = tab.find('span.tabs-icon');
|
|
s_title.html(opts.title);
|
|
s_icon.attr('class', 'tabs-icon');
|
|
|
|
tab.find('a.tabs-close').remove();
|
|
if (opts.closable){
|
|
s_title.addClass('tabs-closable');
|
|
var a_close = $('<a href="javascript:void(0)" class="tabs-close"></a>').appendTo(tab);
|
|
a_close.bind('click.tabs', {p:pp}, function(e){
|
|
if ($(this).parent().hasClass('tabs-disabled')){return;}
|
|
closeTab(container, getTabIndex(container, e.data.p));
|
|
return false;
|
|
});
|
|
} else{
|
|
s_title.removeClass('tabs-closable');
|
|
}
|
|
if (opts.iconCls){
|
|
s_title.addClass('tabs-with-icon');
|
|
s_icon.addClass(opts.iconCls);
|
|
} else {
|
|
s_title.removeClass('tabs-with-icon');
|
|
}
|
|
|
|
if (oldTitle != opts.title){
|
|
for(var i=0; i<selectHis.length; i++){
|
|
if (selectHis[i] == oldTitle){
|
|
selectHis[i] = opts.title;
|
|
}
|
|
}
|
|
}
|
|
|
|
tab.find('span.tabs-p-tool').remove();
|
|
if (opts.tools){
|
|
var p_tool = $('<span class="tabs-p-tool"></span>').insertAfter(tab.find('a.tabs-inner'));
|
|
if (typeof opts.tools == 'string'){
|
|
$(opts.tools).children().appendTo(p_tool);
|
|
} else {
|
|
for(var i=0; i<opts.tools.length; i++){
|
|
var t = $('<a href="javascript:void(0)"></a>').appendTo(p_tool);
|
|
t.addClass(opts.tools[i].iconCls);
|
|
if (opts.tools[i].handler){
|
|
// t.bind('click', eval(opts.tools[i].handler));
|
|
t.bind('click', {handler:opts.tools[i].handler}, function(e){
|
|
if ($(this).parents('li').hasClass('tabs-disabled')){return;}
|
|
e.data.handler.call(this);
|
|
});
|
|
}
|
|
}
|
|
}
|
|
var pr = p_tool.children().length * 12;
|
|
if (opts.closable) {
|
|
pr += 8;
|
|
} else {
|
|
pr -= 3;
|
|
p_tool.css('right','5px');
|
|
}
|
|
s_title.css('padding-right', pr+'px');
|
|
}
|
|
|
|
// setProperties(container);
|
|
setScrollers(container);
|
|
|
|
$.data(container, 'tabs').options.onUpdate.call(container, opts.title, getTabIndex(container, pp));
|
|
}
|
|
|
|
/**
|
|
* close a tab with specified index or title
|
|
*/
|
|
function closeTab(container, which) {
|
|
var opts = $.data(container, 'tabs').options;
|
|
var tabs = $.data(container, 'tabs').tabs;
|
|
var selectHis = $.data(container, 'tabs').selectHis;
|
|
|
|
if (!exists(container, which)) return;
|
|
|
|
var tab = getTab(container, which);
|
|
var title = tab.panel('options').title;
|
|
var index = getTabIndex(container, tab);
|
|
|
|
if (opts.onBeforeClose.call(container, title, index) == false) return;
|
|
|
|
var tab = getTab(container, which, true);
|
|
tab.panel('options').tab.remove();
|
|
tab.panel('destroy');
|
|
|
|
opts.onClose.call(container, title, index);
|
|
|
|
setScrollers(container);
|
|
|
|
// remove the select history item
|
|
for(var i=0; i<selectHis.length; i++){
|
|
if (selectHis[i] == title){
|
|
selectHis.splice(i, 1);
|
|
i --;
|
|
}
|
|
}
|
|
|
|
// select the nearest tab panel
|
|
var hisTitle = selectHis.pop();
|
|
if (hisTitle){
|
|
selectTab(container, hisTitle);
|
|
} else if (tabs.length){
|
|
selectTab(container, 0);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* get the specified tab panel
|
|
*/
|
|
function getTab(container, which, removeit){
|
|
var tabs = $.data(container, 'tabs').tabs;
|
|
if (typeof which == 'number'){
|
|
if (which < 0 || which >= tabs.length){
|
|
return null;
|
|
} else {
|
|
var tab = tabs[which];
|
|
if (removeit) {
|
|
tabs.splice(which, 1);
|
|
}
|
|
return tab;
|
|
}
|
|
}
|
|
for(var i=0; i<tabs.length; i++){
|
|
var tab = tabs[i];
|
|
if (tab.panel('options').title == which){
|
|
if (removeit){
|
|
tabs.splice(i, 1);
|
|
}
|
|
return tab;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
function getTabIndex(container, tab){
|
|
var tabs = $.data(container, 'tabs').tabs;
|
|
for(var i=0; i<tabs.length; i++){
|
|
if (tabs[i][0] == $(tab)[0]){
|
|
return i;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
function getSelectedTab(container){
|
|
var tabs = $.data(container, 'tabs').tabs;
|
|
for(var i=0; i<tabs.length; i++){
|
|
var tab = tabs[i];
|
|
if (tab.panel('options').closed == false){
|
|
return tab;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* do first select action, if no tab is setted the first tab will be selected.
|
|
*/
|
|
function doFirstSelect(container){
|
|
var tabs = $.data(container, 'tabs').tabs;
|
|
for(var i=0; i<tabs.length; i++){
|
|
if (tabs[i].panel('options').selected){
|
|
selectTab(container, i);
|
|
return;
|
|
}
|
|
}
|
|
if (tabs.length){
|
|
selectTab(container, 0);
|
|
}
|
|
}
|
|
|
|
function selectTab(container, which){
|
|
var opts = $.data(container, 'tabs').options;
|
|
var tabs = $.data(container, 'tabs').tabs;
|
|
var selectHis = $.data(container, 'tabs').selectHis;
|
|
|
|
if (tabs.length == 0) return;
|
|
|
|
var panel = getTab(container, which); // get the panel to be activated
|
|
if (!panel) return;
|
|
|
|
var selected = getSelectedTab(container);
|
|
if (selected){
|
|
selected.panel('close');
|
|
selected.panel('options').tab.removeClass('tabs-selected');
|
|
}
|
|
|
|
panel.panel('open');
|
|
var title = panel.panel('options').title; // the panel title
|
|
selectHis.push(title); // push select history
|
|
|
|
var tab = panel.panel('options').tab; // get the tab object
|
|
tab.addClass('tabs-selected');
|
|
|
|
// scroll the tab to center position if required.
|
|
var wrap = $(container).find('>div.tabs-header div.tabs-wrap');
|
|
var leftPos = tab.position().left + wrap.scrollLeft();
|
|
var left = leftPos - wrap.scrollLeft();
|
|
var right = left + tab.outerWidth();
|
|
if (left < 0 || right > wrap.innerWidth()) {
|
|
var pos = Math.min(
|
|
leftPos - (wrap.width()-tab.width()) / 2,
|
|
getMaxScrollWidth(container)
|
|
);
|
|
wrap.animate({scrollLeft:pos}, opts.scrollDuration);
|
|
} else {
|
|
var pos = Math.min(
|
|
wrap.scrollLeft(),
|
|
getMaxScrollWidth(container)
|
|
);
|
|
wrap.animate({scrollLeft:pos}, opts.scrollDuration);
|
|
}
|
|
|
|
setSelectedSize(container);
|
|
|
|
opts.onSelect.call(container, title, getTabIndex(container, panel));
|
|
}
|
|
|
|
function exists(container, which){
|
|
return getTab(container, which) != null;
|
|
}
|
|
|
|
|
|
$.fn.tabs = function(options, param){
|
|
if (typeof options == 'string') {
|
|
return $.fn.tabs.methods[options](this, param);
|
|
}
|
|
|
|
options = options || {};
|
|
return this.each(function(){
|
|
var state = $.data(this, 'tabs');
|
|
var opts;
|
|
if (state) {
|
|
opts = $.extend(state.options, options);
|
|
state.options = opts;
|
|
} else {
|
|
$.data(this, 'tabs', {
|
|
options: $.extend({},$.fn.tabs.defaults, $.fn.tabs.parseOptions(this), options),
|
|
tabs: [],
|
|
selectHis: []
|
|
});
|
|
wrapTabs(this);
|
|
}
|
|
|
|
addTools(this);
|
|
setProperties(this);
|
|
setSize(this);
|
|
|
|
doFirstSelect(this);
|
|
});
|
|
};
|
|
|
|
$.fn.tabs.methods = {
|
|
options: function(jq){
|
|
return $.data(jq[0], 'tabs').options;
|
|
},
|
|
tabs: function(jq){
|
|
return $.data(jq[0], 'tabs').tabs;
|
|
},
|
|
resize: function(jq){
|
|
return jq.each(function(){
|
|
setSize(this);
|
|
setSelectedSize(this);
|
|
});
|
|
},
|
|
add: function(jq, options){
|
|
return jq.each(function(){
|
|
addTab(this, options);
|
|
});
|
|
},
|
|
close: function(jq, which){
|
|
return jq.each(function(){
|
|
closeTab(this, which);
|
|
});
|
|
},
|
|
getTab: function(jq, which){
|
|
return getTab(jq[0], which);
|
|
},
|
|
getTabIndex: function(jq, tab){
|
|
return getTabIndex(jq[0], tab);
|
|
},
|
|
getSelected: function(jq){
|
|
return getSelectedTab(jq[0]);
|
|
},
|
|
select: function(jq, which){
|
|
return jq.each(function(){
|
|
selectTab(this, which);
|
|
});
|
|
},
|
|
exists: function(jq, which){
|
|
return exists(jq[0], which);
|
|
},
|
|
update: function(jq, options){
|
|
return jq.each(function(){
|
|
updateTab(this, options);
|
|
});
|
|
},
|
|
enableTab: function(jq, which){
|
|
return jq.each(function(){
|
|
$(this).tabs('getTab', which).panel('options').tab.removeClass('tabs-disabled');
|
|
});
|
|
},
|
|
disableTab: function(jq, which){
|
|
return jq.each(function(){
|
|
$(this).tabs('getTab', which).panel('options').tab.addClass('tabs-disabled');
|
|
});
|
|
}
|
|
};
|
|
|
|
$.fn.tabs.parseOptions = function(target){
|
|
return $.extend({}, $.parser.parseOptions(target, [
|
|
'width','height','tools',
|
|
{fit:'boolean',border:'boolean',plain:'boolean'}
|
|
]));
|
|
};
|
|
|
|
$.fn.tabs.defaults = {
|
|
width: 'auto',
|
|
height: 'auto',
|
|
plain: false,
|
|
fit: false,
|
|
border: true,
|
|
tools: null,
|
|
scrollIncrement: 100,
|
|
scrollDuration: 400,
|
|
onLoad: function(panel){},
|
|
onSelect: function(title, index){},
|
|
onBeforeClose: function(title, index){},
|
|
onClose: function(title, index){},
|
|
onAdd: function(title, index){},
|
|
onUpdate: function(title, index){},
|
|
onContextMenu: function(e, title, index){}
|
|
};
|
|
})(jQuery);
|