jquery.tabs.js 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889
  1. /**
  2. * jQuery EasyUI 1.5.2
  3. *
  4. * Copyright (c) 2009-2017 www.jeasyui.com. All rights reserved.
  5. *
  6. * Licensed under the freeware license: http://www.jeasyui.com/license_freeware.php
  7. * To use it on other terms please contact us: info@jeasyui.com
  8. *
  9. */
  10. /**
  11. * tabs - jQuery EasyUI
  12. *
  13. * Dependencies:
  14. * panel
  15. * linkbutton
  16. *
  17. */
  18. (function($){
  19. function getContentWidth(c){
  20. var w = 0;
  21. $(c).children().each(function(){
  22. w += $(this).outerWidth(true);
  23. });
  24. return w;
  25. }
  26. /**
  27. * set the tabs scrollers to show or not,
  28. * dependent on the tabs count and width
  29. */
  30. function setScrollers(container) {
  31. var opts = $.data(container, 'tabs').options;
  32. if (opts.tabPosition == 'left' || opts.tabPosition == 'right' || !opts.showHeader){return}
  33. var header = $(container).children('div.tabs-header');
  34. var tool = header.children('div.tabs-tool:not(.tabs-tool-hidden)');
  35. var sLeft = header.children('div.tabs-scroller-left');
  36. var sRight = header.children('div.tabs-scroller-right');
  37. var wrap = header.children('div.tabs-wrap');
  38. // set the tool height
  39. var tHeight = header.outerHeight();
  40. if (opts.plain){
  41. tHeight -= tHeight - header.height();
  42. }
  43. tool._outerHeight(tHeight);
  44. var tabsWidth = getContentWidth(header.find('ul.tabs'));
  45. var cWidth = header.width() - tool._outerWidth();
  46. if (tabsWidth > cWidth) {
  47. sLeft.add(sRight).show()._outerHeight(tHeight);
  48. if (opts.toolPosition == 'left'){
  49. tool.css({
  50. left: sLeft.outerWidth(),
  51. right: ''
  52. });
  53. wrap.css({
  54. marginLeft: sLeft.outerWidth() + tool._outerWidth(),
  55. marginRight: sRight._outerWidth(),
  56. width: cWidth - sLeft.outerWidth() - sRight.outerWidth()
  57. });
  58. } else {
  59. tool.css({
  60. left: '',
  61. right: sRight.outerWidth()
  62. });
  63. wrap.css({
  64. marginLeft: sLeft.outerWidth(),
  65. marginRight: sRight.outerWidth() + tool._outerWidth(),
  66. width: cWidth - sLeft.outerWidth() - sRight.outerWidth()
  67. });
  68. }
  69. } else {
  70. sLeft.add(sRight).hide();
  71. if (opts.toolPosition == 'left'){
  72. tool.css({
  73. left: 0,
  74. right: ''
  75. });
  76. wrap.css({
  77. marginLeft: tool._outerWidth(),
  78. marginRight: 0,
  79. width: cWidth
  80. });
  81. } else {
  82. tool.css({
  83. left: '',
  84. right: 0
  85. });
  86. wrap.css({
  87. marginLeft: 0,
  88. marginRight: tool._outerWidth(),
  89. width: cWidth
  90. });
  91. }
  92. }
  93. }
  94. function addTools(container){
  95. var opts = $.data(container, 'tabs').options;
  96. var header = $(container).children('div.tabs-header');
  97. if (opts.tools) {
  98. if (typeof opts.tools == 'string'){
  99. $(opts.tools).addClass('tabs-tool').appendTo(header);
  100. $(opts.tools).show();
  101. } else {
  102. header.children('div.tabs-tool').remove();
  103. var tools = $('<div class="tabs-tool"><table cellspacing="0" cellpadding="0" style="height:100%"><tr></tr></table></div>').appendTo(header);
  104. var tr = tools.find('tr');
  105. for(var i=0; i<opts.tools.length; i++){
  106. var td = $('<td></td>').appendTo(tr);
  107. var tool = $('<a href="javascript:;"></a>').appendTo(td);
  108. tool[0].onclick = eval(opts.tools[i].handler || function(){});
  109. tool.linkbutton($.extend({}, opts.tools[i], {
  110. plain: true
  111. }));
  112. }
  113. }
  114. } else {
  115. header.children('div.tabs-tool').remove();
  116. }
  117. }
  118. function setSize(container, param) {
  119. var state = $.data(container, 'tabs');
  120. var opts = state.options;
  121. var cc = $(container);
  122. if (!opts.doSize){return}
  123. if (param){
  124. $.extend(opts, {
  125. width: param.width,
  126. height: param.height
  127. });
  128. }
  129. cc._size(opts);
  130. var header = cc.children('div.tabs-header');
  131. var panels = cc.children('div.tabs-panels');
  132. var wrap = header.find('div.tabs-wrap');
  133. var ul = wrap.find('.tabs');
  134. ul.children('li').removeClass('tabs-first tabs-last');
  135. ul.children('li:first').addClass('tabs-first');
  136. ul.children('li:last').addClass('tabs-last');
  137. if (opts.tabPosition == 'left' || opts.tabPosition == 'right'){
  138. header._outerWidth(opts.showHeader ? opts.headerWidth : 0);
  139. panels._outerWidth(cc.width() - header.outerWidth());
  140. header.add(panels)._size('height', isNaN(parseInt(opts.height)) ? '' : cc.height());
  141. wrap._outerWidth(header.width());
  142. ul._outerWidth(wrap.width()).css('height','');
  143. } else {
  144. header.children('div.tabs-scroller-left,div.tabs-scroller-right,div.tabs-tool:not(.tabs-tool-hidden)').css('display', opts.showHeader?'block':'none');
  145. header._outerWidth(cc.width()).css('height','');
  146. if (opts.showHeader){
  147. header.css('background-color','');
  148. wrap.css('height','');
  149. } else {
  150. header.css('background-color','transparent');
  151. header._outerHeight(0);
  152. wrap._outerHeight(0);
  153. }
  154. ul._outerHeight(opts.tabHeight).css('width','');
  155. ul._outerHeight(ul.outerHeight()-ul.height()-1+opts.tabHeight).css('width','');
  156. panels._size('height', isNaN(parseInt(opts.height)) ? '' : (cc.height()-header.outerHeight()));
  157. panels._size('width', cc.width());
  158. }
  159. if (state.tabs.length){
  160. var d1 = ul.outerWidth(true) - ul.width();
  161. var li = ul.children('li:first');
  162. var d2 = li.outerWidth(true) - li.width();
  163. var hwidth = header.width() - header.children('.tabs-tool:not(.tabs-tool-hidden)')._outerWidth();
  164. var justifiedWidth = Math.floor((hwidth-d1-d2*state.tabs.length)/state.tabs.length);
  165. $.map(state.tabs, function(p){
  166. setTabSize(p, (opts.justified && $.inArray(opts.tabPosition,['top','bottom'])>=0) ? justifiedWidth : undefined);
  167. });
  168. if (opts.justified && $.inArray(opts.tabPosition,['top','bottom'])>=0){
  169. var deltaWidth = hwidth - d1 - getContentWidth(ul);
  170. setTabSize(state.tabs[state.tabs.length-1], justifiedWidth+deltaWidth);
  171. }
  172. }
  173. setScrollers(container);
  174. function setTabSize(p, width){
  175. var p_opts = p.panel('options');
  176. var p_t = p_opts.tab.find('a.tabs-inner');
  177. var width = width ? width : (parseInt(p_opts.tabWidth||opts.tabWidth||undefined));
  178. if (width){
  179. p_t._outerWidth(width);
  180. } else {
  181. p_t.css('width', '');
  182. }
  183. p_t._outerHeight(opts.tabHeight);
  184. p_t.css('lineHeight', p_t.height()+'px');
  185. p_t.find('.easyui-fluid:visible').triggerHandler('_resize');
  186. }
  187. }
  188. /**
  189. * set selected tab panel size
  190. */
  191. function setSelectedSize(container){
  192. var opts = $.data(container, 'tabs').options;
  193. var tab = getSelectedTab(container);
  194. if (tab){
  195. var panels = $(container).children('div.tabs-panels');
  196. var width = opts.width=='auto' ? 'auto' : panels.width();
  197. var height = opts.height=='auto' ? 'auto' : panels.height();
  198. tab.panel('resize', {
  199. width: width,
  200. height: height
  201. });
  202. }
  203. }
  204. /**
  205. * wrap the tabs header and body
  206. */
  207. function wrapTabs(container) {
  208. var tabs = $.data(container, 'tabs').tabs;
  209. var cc = $(container).addClass('tabs-container');
  210. var panels = $('<div class="tabs-panels"></div>').insertBefore(cc);
  211. cc.children('div').each(function(){
  212. panels[0].appendChild(this);
  213. });
  214. cc[0].appendChild(panels[0]);
  215. $('<div class="tabs-header">'
  216. + '<div class="tabs-scroller-left"></div>'
  217. + '<div class="tabs-scroller-right"></div>'
  218. + '<div class="tabs-wrap">'
  219. + '<ul class="tabs"></ul>'
  220. + '</div>'
  221. + '</div>').prependTo(container);
  222. cc.children('div.tabs-panels').children('div').each(function(i){
  223. var opts = $.extend({}, $.parser.parseOptions(this), {
  224. disabled: ($(this).attr('disabled') ? true : undefined),
  225. selected: ($(this).attr('selected') ? true : undefined)
  226. });
  227. createTab(container, opts, $(this));
  228. });
  229. cc.children('div.tabs-header').find('.tabs-scroller-left, .tabs-scroller-right').hover(
  230. function(){$(this).addClass('tabs-scroller-over');},
  231. function(){$(this).removeClass('tabs-scroller-over');}
  232. );
  233. cc.bind('_resize', function(e,force){
  234. if ($(this).hasClass('easyui-fluid') || force){
  235. setSize(container);
  236. setSelectedSize(container);
  237. }
  238. return false;
  239. });
  240. }
  241. function bindEvents(container){
  242. var state = $.data(container, 'tabs')
  243. var opts = state.options;
  244. $(container).children('div.tabs-header').unbind().bind('click', function(e){
  245. if ($(e.target).hasClass('tabs-scroller-left')){
  246. $(container).tabs('scrollBy', -opts.scrollIncrement);
  247. } else if ($(e.target).hasClass('tabs-scroller-right')){
  248. $(container).tabs('scrollBy', opts.scrollIncrement);
  249. } else {
  250. var li = $(e.target).closest('li');
  251. if (li.hasClass('tabs-disabled')){return false;}
  252. var a = $(e.target).closest('a.tabs-close');
  253. if (a.length){
  254. closeTab(container, getLiIndex(li));
  255. } else if (li.length){
  256. // selectTab(container, getLiIndex(li));
  257. var index = getLiIndex(li);
  258. var popts = state.tabs[index].panel('options');
  259. if (popts.collapsible){
  260. popts.closed ? selectTab(container, index) : unselectTab(container, index);
  261. } else {
  262. selectTab(container, index);
  263. }
  264. }
  265. return false;
  266. }
  267. }).bind('contextmenu', function(e){
  268. var li = $(e.target).closest('li');
  269. if (li.hasClass('tabs-disabled')){return;}
  270. if (li.length){
  271. opts.onContextMenu.call(container, e, li.find('span.tabs-title').html(), getLiIndex(li));
  272. }
  273. });
  274. function getLiIndex(li){
  275. var index = 0;
  276. li.parent().children('li').each(function(i){
  277. if (li[0] == this){
  278. index = i;
  279. return false;
  280. }
  281. });
  282. return index;
  283. }
  284. }
  285. function setProperties(container){
  286. var opts = $.data(container, 'tabs').options;
  287. var header = $(container).children('div.tabs-header');
  288. var panels = $(container).children('div.tabs-panels');
  289. header.removeClass('tabs-header-top tabs-header-bottom tabs-header-left tabs-header-right');
  290. panels.removeClass('tabs-panels-top tabs-panels-bottom tabs-panels-left tabs-panels-right');
  291. if (opts.tabPosition == 'top'){
  292. header.insertBefore(panels);
  293. } else if (opts.tabPosition == 'bottom'){
  294. header.insertAfter(panels);
  295. header.addClass('tabs-header-bottom');
  296. panels.addClass('tabs-panels-top');
  297. } else if (opts.tabPosition == 'left'){
  298. header.addClass('tabs-header-left');
  299. panels.addClass('tabs-panels-right');
  300. } else if (opts.tabPosition == 'right'){
  301. header.addClass('tabs-header-right');
  302. panels.addClass('tabs-panels-left');
  303. }
  304. if (opts.plain == true) {
  305. header.addClass('tabs-header-plain');
  306. } else {
  307. header.removeClass('tabs-header-plain');
  308. }
  309. header.removeClass('tabs-header-narrow').addClass(opts.narrow?'tabs-header-narrow':'');
  310. var tabs = header.find('.tabs');
  311. tabs.removeClass('tabs-pill').addClass(opts.pill?'tabs-pill':'');
  312. tabs.removeClass('tabs-narrow').addClass(opts.narrow?'tabs-narrow':'');
  313. tabs.removeClass('tabs-justified').addClass(opts.justified?'tabs-justified':'');
  314. if (opts.border == true){
  315. header.removeClass('tabs-header-noborder');
  316. panels.removeClass('tabs-panels-noborder');
  317. } else {
  318. header.addClass('tabs-header-noborder');
  319. panels.addClass('tabs-panels-noborder');
  320. }
  321. opts.doSize = true;
  322. }
  323. function createTab(container, options, pp) {
  324. options = options || {};
  325. var state = $.data(container, 'tabs');
  326. var tabs = state.tabs;
  327. if (options.index == undefined || options.index > tabs.length){options.index = tabs.length}
  328. if (options.index < 0){options.index = 0}
  329. var ul = $(container).children('div.tabs-header').find('ul.tabs');
  330. var panels = $(container).children('div.tabs-panels');
  331. var tab = $(
  332. '<li>' +
  333. '<a href="javascript:;" class="tabs-inner">' +
  334. '<span class="tabs-title"></span>' +
  335. '<span class="tabs-icon"></span>' +
  336. '</a>' +
  337. '</li>');
  338. if (!pp){pp = $('<div></div>');}
  339. if (options.index >= tabs.length){
  340. tab.appendTo(ul);
  341. pp.appendTo(panels);
  342. tabs.push(pp);
  343. } else {
  344. tab.insertBefore(ul.children('li:eq('+options.index+')'));
  345. pp.insertBefore(panels.children('div.panel:eq('+options.index+')'));
  346. tabs.splice(options.index, 0, pp);
  347. }
  348. // create panel
  349. pp.panel($.extend({}, options, {
  350. tab: tab,
  351. border: false,
  352. noheader: true,
  353. closed: true,
  354. doSize: false,
  355. iconCls: (options.icon ? options.icon : undefined),
  356. onLoad: function(){
  357. if (options.onLoad){
  358. options.onLoad.call(this, arguments);
  359. }
  360. state.options.onLoad.call(container, $(this));
  361. },
  362. onBeforeOpen: function(){
  363. if (options.onBeforeOpen){
  364. if (options.onBeforeOpen.call(this) == false){return false;}
  365. }
  366. var p = $(container).tabs('getSelected');
  367. if (p){
  368. if (p[0] != this){
  369. $(container).tabs('unselect', getTabIndex(container, p));
  370. p = $(container).tabs('getSelected');
  371. if (p){
  372. return false;
  373. }
  374. } else {
  375. setSelectedSize(container);
  376. return false;
  377. }
  378. }
  379. var popts = $(this).panel('options');
  380. popts.tab.addClass('tabs-selected');
  381. // scroll the tab to center position if required.
  382. var wrap = $(container).find('>div.tabs-header>div.tabs-wrap');
  383. var left = popts.tab.position().left;
  384. var right = left + popts.tab.outerWidth();
  385. if (left < 0 || right > wrap.width()){
  386. var deltaX = left - (wrap.width()-popts.tab.width()) / 2;
  387. $(container).tabs('scrollBy', deltaX);
  388. } else {
  389. $(container).tabs('scrollBy', 0);
  390. }
  391. var panel = $(this).panel('panel');
  392. panel.css('display','block');
  393. setSelectedSize(container);
  394. panel.css('display','none');
  395. },
  396. onOpen: function(){
  397. if (options.onOpen){
  398. options.onOpen.call(this);
  399. }
  400. var popts = $(this).panel('options');
  401. state.selectHis.push(popts.title);
  402. state.options.onSelect.call(container, popts.title, getTabIndex(container, this));
  403. },
  404. onBeforeClose: function(){
  405. if (options.onBeforeClose){
  406. if (options.onBeforeClose.call(this) == false){return false;}
  407. }
  408. $(this).panel('options').tab.removeClass('tabs-selected');
  409. },
  410. onClose: function(){
  411. if (options.onClose){
  412. options.onClose.call(this);
  413. }
  414. var popts = $(this).panel('options');
  415. state.options.onUnselect.call(container, popts.title, getTabIndex(container, this));
  416. }
  417. }));
  418. // only update the tab header
  419. $(container).tabs('update', {
  420. tab: pp,
  421. options: pp.panel('options'),
  422. type: 'header'
  423. });
  424. }
  425. function addTab(container, options) {
  426. var state = $.data(container, 'tabs');
  427. var opts = state.options;
  428. if (options.selected == undefined) options.selected = true;
  429. createTab(container, options);
  430. opts.onAdd.call(container, options.title, options.index);
  431. if (options.selected){
  432. selectTab(container, options.index); // select the added tab panel
  433. }
  434. }
  435. /**
  436. * update tab panel, param has following properties:
  437. * tab: the tab panel to be updated
  438. * options: the tab panel options
  439. * type: the update type, possible values are: 'header','body','all'
  440. */
  441. function updateTab(container, param){
  442. param.type = param.type || 'all';
  443. var selectHis = $.data(container, 'tabs').selectHis;
  444. var pp = param.tab; // the tab panel
  445. var opts = pp.panel('options'); // get the tab panel options
  446. var oldTitle = opts.title;
  447. $.extend(opts, param.options, {
  448. iconCls: (param.options.icon ? param.options.icon : undefined)
  449. });
  450. if (param.type == 'all' || param.type == 'body'){
  451. pp.panel();
  452. }
  453. if (param.type == 'all' || param.type == 'header'){
  454. var tab = opts.tab;
  455. if (opts.header){
  456. tab.find('.tabs-inner').html($(opts.header));
  457. } else {
  458. var s_title = tab.find('span.tabs-title');
  459. var s_icon = tab.find('span.tabs-icon');
  460. s_title.html(opts.title);
  461. s_icon.attr('class', 'tabs-icon');
  462. tab.find('a.tabs-close').remove();
  463. if (opts.closable){
  464. s_title.addClass('tabs-closable');
  465. $('<a href="javascript:;" class="tabs-close"></a>').appendTo(tab);
  466. } else{
  467. s_title.removeClass('tabs-closable');
  468. }
  469. if (opts.iconCls){
  470. s_title.addClass('tabs-with-icon');
  471. s_icon.addClass(opts.iconCls);
  472. } else {
  473. s_title.removeClass('tabs-with-icon');
  474. }
  475. if (opts.tools){
  476. var p_tool = tab.find('span.tabs-p-tool');
  477. if (!p_tool.length){
  478. var p_tool = $('<span class="tabs-p-tool"></span>').insertAfter(tab.find('a.tabs-inner'));
  479. }
  480. if ($.isArray(opts.tools)){
  481. p_tool.empty();
  482. for(var i=0; i<opts.tools.length; i++){
  483. var t = $('<a href="javascript:;"></a>').appendTo(p_tool);
  484. t.addClass(opts.tools[i].iconCls);
  485. if (opts.tools[i].handler){
  486. t.bind('click', {handler:opts.tools[i].handler}, function(e){
  487. if ($(this).parents('li').hasClass('tabs-disabled')){return;}
  488. e.data.handler.call(this);
  489. });
  490. }
  491. }
  492. } else {
  493. $(opts.tools).children().appendTo(p_tool);
  494. }
  495. var pr = p_tool.children().length * 12;
  496. if (opts.closable) {
  497. pr += 8;
  498. p_tool.css('right', '');
  499. } else {
  500. pr -= 3;
  501. p_tool.css('right','5px');
  502. }
  503. s_title.css('padding-right', pr+'px');
  504. } else {
  505. tab.find('span.tabs-p-tool').remove();
  506. s_title.css('padding-right', '');
  507. }
  508. }
  509. if (oldTitle != opts.title){
  510. for(var i=0; i<selectHis.length; i++){
  511. if (selectHis[i] == oldTitle){
  512. selectHis[i] = opts.title;
  513. }
  514. }
  515. }
  516. }
  517. if (opts.disabled){
  518. opts.tab.addClass('tabs-disabled');
  519. } else {
  520. opts.tab.removeClass('tabs-disabled');
  521. }
  522. setSize(container);
  523. $.data(container, 'tabs').options.onUpdate.call(container, opts.title, getTabIndex(container, pp));
  524. }
  525. /**
  526. * close a tab with specified index or title
  527. */
  528. function closeTab(container, which) {
  529. var opts = $.data(container, 'tabs').options;
  530. var tabs = $.data(container, 'tabs').tabs;
  531. var selectHis = $.data(container, 'tabs').selectHis;
  532. if (!exists(container, which)) return;
  533. var tab = getTab(container, which);
  534. var title = tab.panel('options').title;
  535. var index = getTabIndex(container, tab);
  536. if (opts.onBeforeClose.call(container, title, index) == false) return;
  537. var tab = getTab(container, which, true);
  538. tab.panel('options').tab.remove();
  539. tab.panel('destroy');
  540. opts.onClose.call(container, title, index);
  541. // setScrollers(container);
  542. setSize(container);
  543. // remove the select history item
  544. for(var i=0; i<selectHis.length; i++){
  545. if (selectHis[i] == title){
  546. selectHis.splice(i, 1);
  547. i --;
  548. }
  549. }
  550. // select the nearest tab panel
  551. var hisTitle = selectHis.pop();
  552. if (hisTitle){
  553. selectTab(container, hisTitle);
  554. } else if (tabs.length){
  555. selectTab(container, 0);
  556. }
  557. }
  558. /**
  559. * get the specified tab panel
  560. */
  561. function getTab(container, which, removeit){
  562. var tabs = $.data(container, 'tabs').tabs;
  563. var tab = null;
  564. if (typeof which == 'number'){
  565. if (which >=0 && which < tabs.length){
  566. tab = tabs[which];
  567. if (removeit){
  568. tabs.splice(which, 1);
  569. }
  570. }
  571. } else {
  572. var tmp = $('<span></span>');
  573. for(var i=0; i<tabs.length; i++){
  574. var p = tabs[i];
  575. tmp.html(p.panel('options').title);
  576. if (tmp.text() == which){
  577. tab = p;
  578. if (removeit){
  579. tabs.splice(i, 1);
  580. }
  581. break;
  582. }
  583. }
  584. tmp.remove();
  585. }
  586. return tab;
  587. }
  588. function getTabIndex(container, tab){
  589. var tabs = $.data(container, 'tabs').tabs;
  590. for(var i=0; i<tabs.length; i++){
  591. if (tabs[i][0] == $(tab)[0]){
  592. return i;
  593. }
  594. }
  595. return -1;
  596. }
  597. function getSelectedTab(container){
  598. var tabs = $.data(container, 'tabs').tabs;
  599. for(var i=0; i<tabs.length; i++){
  600. var tab = tabs[i];
  601. if (tab.panel('options').tab.hasClass('tabs-selected')){
  602. return tab;
  603. }
  604. }
  605. return null;
  606. }
  607. /**
  608. * do first select action, if no tab is setted the first tab will be selected.
  609. */
  610. function doFirstSelect(container){
  611. var state = $.data(container, 'tabs')
  612. var tabs = state.tabs;
  613. for(var i=0; i<tabs.length; i++){
  614. var opts = tabs[i].panel('options');
  615. if (opts.selected && !opts.disabled){
  616. selectTab(container, i);
  617. return;
  618. }
  619. }
  620. selectTab(container, state.options.selected);
  621. }
  622. function selectTab(container, which){
  623. var p = getTab(container, which);
  624. if (p && !p.is(':visible')){
  625. stopAnimate(container);
  626. if (!p.panel('options').disabled){
  627. p.panel('open');
  628. }
  629. }
  630. }
  631. function unselectTab(container, which){
  632. var p = getTab(container, which);
  633. if (p && p.is(':visible')){
  634. stopAnimate(container);
  635. p.panel('close');
  636. }
  637. }
  638. function stopAnimate(container){
  639. $(container).children('div.tabs-panels').each(function(){
  640. $(this).stop(true, true);
  641. });
  642. }
  643. function exists(container, which){
  644. return getTab(container, which) != null;
  645. }
  646. function showHeader(container, visible){
  647. var opts = $.data(container, 'tabs').options;
  648. opts.showHeader = visible;
  649. $(container).tabs('resize');
  650. }
  651. function showTool(container, visible){
  652. var tool = $(container).find('>.tabs-header>.tabs-tool');
  653. if (visible){
  654. tool.removeClass('tabs-tool-hidden').show();
  655. } else {
  656. tool.addClass('tabs-tool-hidden').hide();
  657. }
  658. $(container).tabs('resize').tabs('scrollBy', 0);
  659. }
  660. $.fn.tabs = function(options, param){
  661. if (typeof options == 'string') {
  662. return $.fn.tabs.methods[options](this, param);
  663. }
  664. options = options || {};
  665. return this.each(function(){
  666. var state = $.data(this, 'tabs');
  667. if (state) {
  668. $.extend(state.options, options);
  669. } else {
  670. $.data(this, 'tabs', {
  671. options: $.extend({},$.fn.tabs.defaults, $.fn.tabs.parseOptions(this), options),
  672. tabs: [],
  673. selectHis: []
  674. });
  675. wrapTabs(this);
  676. }
  677. addTools(this);
  678. setProperties(this);
  679. setSize(this);
  680. bindEvents(this);
  681. doFirstSelect(this);
  682. });
  683. };
  684. $.fn.tabs.methods = {
  685. options: function(jq){
  686. var cc = jq[0];
  687. var opts = $.data(cc, 'tabs').options;
  688. var s = getSelectedTab(cc);
  689. opts.selected = s ? getTabIndex(cc, s) : -1;
  690. return opts;
  691. },
  692. tabs: function(jq){
  693. return $.data(jq[0], 'tabs').tabs;
  694. },
  695. resize: function(jq, param){
  696. return jq.each(function(){
  697. setSize(this, param);
  698. setSelectedSize(this);
  699. });
  700. },
  701. add: function(jq, options){
  702. return jq.each(function(){
  703. addTab(this, options);
  704. });
  705. },
  706. close: function(jq, which){
  707. return jq.each(function(){
  708. closeTab(this, which);
  709. });
  710. },
  711. getTab: function(jq, which){
  712. return getTab(jq[0], which);
  713. },
  714. getTabIndex: function(jq, tab){
  715. return getTabIndex(jq[0], tab);
  716. },
  717. getSelected: function(jq){
  718. return getSelectedTab(jq[0]);
  719. },
  720. select: function(jq, which){
  721. return jq.each(function(){
  722. selectTab(this, which);
  723. });
  724. },
  725. unselect: function(jq, which){
  726. return jq.each(function(){
  727. unselectTab(this, which);
  728. });
  729. },
  730. exists: function(jq, which){
  731. return exists(jq[0], which);
  732. },
  733. update: function(jq, options){
  734. return jq.each(function(){
  735. updateTab(this, options);
  736. });
  737. },
  738. enableTab: function(jq, which){
  739. return jq.each(function(){
  740. var opts = $(this).tabs('getTab', which).panel('options');
  741. opts.tab.removeClass('tabs-disabled');
  742. opts.disabled = false;
  743. });
  744. },
  745. disableTab: function(jq, which){
  746. return jq.each(function(){
  747. var opts = $(this).tabs('getTab', which).panel('options');
  748. opts.tab.addClass('tabs-disabled');
  749. opts.disabled = true;
  750. });
  751. },
  752. showHeader: function(jq){
  753. return jq.each(function(){
  754. showHeader(this, true);
  755. });
  756. },
  757. hideHeader: function(jq){
  758. return jq.each(function(){
  759. showHeader(this, false);
  760. });
  761. },
  762. showTool: function(jq){
  763. return jq.each(function(){
  764. showTool(this, true);
  765. });
  766. },
  767. hideTool: function(jq){
  768. return jq.each(function(){
  769. showTool(this, false);
  770. });
  771. },
  772. scrollBy: function(jq, deltaX){ // scroll the tab header by the specified amount of pixels
  773. return jq.each(function(){
  774. var opts = $(this).tabs('options');
  775. var wrap = $(this).find('>div.tabs-header>div.tabs-wrap');
  776. var pos = Math.min(wrap._scrollLeft() + deltaX, getMaxScrollWidth());
  777. wrap.animate({scrollLeft: pos}, opts.scrollDuration);
  778. function getMaxScrollWidth(){
  779. var w = 0;
  780. var ul = wrap.children('ul');
  781. ul.children('li').each(function(){
  782. w += $(this).outerWidth(true);
  783. });
  784. return w - wrap.width() + (ul.outerWidth() - ul.width());
  785. }
  786. });
  787. }
  788. };
  789. $.fn.tabs.parseOptions = function(target){
  790. return $.extend({}, $.parser.parseOptions(target, [
  791. 'tools','toolPosition','tabPosition',
  792. {fit:'boolean',border:'boolean',plain:'boolean'},
  793. {headerWidth:'number',tabWidth:'number',tabHeight:'number',selected:'number'},
  794. {showHeader:'boolean',justified:'boolean',narrow:'boolean',pill:'boolean'}
  795. ]));
  796. };
  797. $.fn.tabs.defaults = {
  798. width: 'auto',
  799. height: 'auto',
  800. headerWidth: 150, // the tab header width, it is valid only when tabPosition set to 'left' or 'right'
  801. tabWidth: 'auto', // the tab width
  802. tabHeight: 27, // the tab height
  803. selected: 0, // the initialized selected tab index
  804. showHeader: true,
  805. plain: false,
  806. fit: false,
  807. border: true,
  808. justified: false,
  809. narrow: false,
  810. pill: false,
  811. tools: null,
  812. toolPosition: 'right', // left,right
  813. tabPosition: 'top', // possible values: top,bottom
  814. scrollIncrement: 100,
  815. scrollDuration: 400,
  816. onLoad: function(panel){},
  817. onSelect: function(title, index){},
  818. onUnselect: function(title, index){},
  819. onBeforeClose: function(title, index){},
  820. onClose: function(title, index){},
  821. onAdd: function(title, index){},
  822. onUpdate: function(title, index){},
  823. onContextMenu: function(e, title, index){}
  824. };
  825. })(jQuery);