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

/**
* 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);