jquery.accordion.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493
  1. /**
  2. * EasyUI for jQuery 1.5.5.6
  3. *
  4. * Copyright (c) 2009-2018 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. * accordion - EasyUI for jQuery
  12. *
  13. * Dependencies:
  14. * panel
  15. *
  16. */
  17. (function($){
  18. // function setSize(container, param){
  19. // var state = $.data(container, 'accordion');
  20. // var opts = state.options;
  21. // var panels = state.panels;
  22. // var cc = $(container);
  23. // if (param){
  24. // $.extend(opts, {
  25. // width: param.width,
  26. // height: param.height
  27. // });
  28. // }
  29. // cc._size(opts);
  30. // var headerHeight = 0;
  31. // var bodyHeight = 'auto';
  32. // var headers = cc.find('>.panel>.accordion-header');
  33. // if (headers.length){
  34. // headerHeight = $(headers[0]).css('height', '')._outerHeight();
  35. // }
  36. // if (!isNaN(parseInt(opts.height))){
  37. // bodyHeight = cc.height() - headerHeight*headers.length;
  38. // }
  39. // _resize(true, bodyHeight - _resize(false) + 1);
  40. // function _resize(collapsible, height){
  41. // var totalHeight = 0;
  42. // for(var i=0; i<panels.length; i++){
  43. // var p = panels[i];
  44. // var h = p.panel('header')._outerHeight(headerHeight);
  45. // if (p.panel('options').collapsible == collapsible){
  46. // var pheight = isNaN(height) ? undefined : (height+headerHeight*h.length);
  47. // p.panel('resize', {
  48. // width: cc.width(),
  49. // height: (collapsible ? pheight : undefined)
  50. // });
  51. // totalHeight += p.panel('panel').outerHeight()-headerHeight*h.length;
  52. // }
  53. // }
  54. // return totalHeight;
  55. // }
  56. // }
  57. function setSize(container, param){
  58. var state = $.data(container, 'accordion');
  59. var opts = state.options;
  60. var panels = state.panels;
  61. var cc = $(container);
  62. var isHorizontal = (opts.halign=='left' || opts.halign=='right');
  63. cc.children('.panel-last').removeClass('panel-last');
  64. cc.children('.panel:last').addClass('panel-last');
  65. if (param){
  66. $.extend(opts, {
  67. width: param.width,
  68. height: param.height
  69. });
  70. }
  71. cc._size(opts);
  72. var headerHeight = 0;
  73. var bodyHeight = 'auto';
  74. var headers = cc.find('>.panel>.accordion-header');
  75. if (headers.length){
  76. if (isHorizontal){
  77. $(panels[0]).panel('resize', {width:cc.width(),height:cc.height()});
  78. headerHeight = $(headers[0])._outerWidth();
  79. } else {
  80. headerHeight = $(headers[0]).css('height', '')._outerHeight();
  81. }
  82. }
  83. if (!isNaN(parseInt(opts.height))){
  84. if (isHorizontal){
  85. bodyHeight = cc.width() - headerHeight*headers.length;
  86. } else {
  87. bodyHeight = cc.height() - headerHeight*headers.length;
  88. }
  89. }
  90. // _resize(true, bodyHeight - _resize(false) + 1);
  91. _resize(true, bodyHeight - _resize(false));
  92. function _resize(collapsible, height){
  93. var totalHeight = 0;
  94. for(var i=0; i<panels.length; i++){
  95. var p = panels[i];
  96. if (isHorizontal){
  97. var h = p.panel('header')._outerWidth(headerHeight);
  98. } else {
  99. var h = p.panel('header')._outerHeight(headerHeight);
  100. }
  101. if (p.panel('options').collapsible == collapsible){
  102. var pheight = isNaN(height) ? undefined : (height+headerHeight*h.length);
  103. if (isHorizontal){
  104. p.panel('resize', {
  105. height: cc.height(),
  106. width: (collapsible ? pheight : undefined)
  107. });
  108. totalHeight += p.panel('panel')._outerWidth()-headerHeight*h.length;
  109. } else {
  110. p.panel('resize', {
  111. width: cc.width(),
  112. height: (collapsible ? pheight : undefined)
  113. });
  114. totalHeight += p.panel('panel').outerHeight()-headerHeight*h.length;
  115. }
  116. }
  117. }
  118. return totalHeight;
  119. }
  120. }
  121. /**
  122. * find a panel by specified property, return the panel object or panel index.
  123. */
  124. function findBy(container, property, value, all){
  125. var panels = $.data(container, 'accordion').panels;
  126. var pp = [];
  127. for(var i=0; i<panels.length; i++){
  128. var p = panels[i];
  129. if (property){
  130. if (p.panel('options')[property] == value){
  131. pp.push(p);
  132. }
  133. } else {
  134. if (p[0] == $(value)[0]){
  135. return i;
  136. }
  137. }
  138. }
  139. if (property){
  140. return all ? pp : (pp.length ? pp[0] : null);
  141. } else {
  142. return -1;
  143. }
  144. }
  145. function getSelections(container){
  146. return findBy(container, 'collapsed', false, true);
  147. }
  148. function getSelected(container){
  149. var pp = getSelections(container);
  150. return pp.length ? pp[0] : null;
  151. }
  152. /**
  153. * get panel index, start with 0
  154. */
  155. function getPanelIndex(container, panel){
  156. return findBy(container, null, panel);
  157. }
  158. /**
  159. * get the specified panel.
  160. */
  161. function getPanel(container, which){
  162. var panels = $.data(container, 'accordion').panels;
  163. if (typeof which == 'number'){
  164. if (which < 0 || which >= panels.length){
  165. return null;
  166. } else {
  167. return panels[which];
  168. }
  169. }
  170. return findBy(container, 'title', which);
  171. }
  172. function setProperties(container){
  173. var opts = $.data(container, 'accordion').options;
  174. var cc = $(container);
  175. if (opts.border){
  176. cc.removeClass('accordion-noborder');
  177. } else {
  178. cc.addClass('accordion-noborder');
  179. }
  180. }
  181. function init(container){
  182. var state = $.data(container, 'accordion');
  183. var cc = $(container);
  184. cc.addClass('accordion');
  185. state.panels = [];
  186. cc.children('div').each(function(){
  187. var opts = $.extend({}, $.parser.parseOptions(this), {
  188. selected: ($(this).attr('selected') ? true : undefined)
  189. });
  190. var pp = $(this);
  191. state.panels.push(pp);
  192. createPanel(container, pp, opts);
  193. });
  194. cc.bind('_resize', function(e,force){
  195. if ($(this).hasClass('easyui-fluid') || force){
  196. setSize(container);
  197. }
  198. return false;
  199. });
  200. }
  201. function createPanel(container, pp, options){
  202. var opts = $.data(container, 'accordion').options;
  203. pp.panel($.extend({}, {
  204. collapsible: true,
  205. minimizable: false,
  206. maximizable: false,
  207. closable: false,
  208. doSize: false,
  209. collapsed: true,
  210. headerCls: 'accordion-header',
  211. bodyCls: 'accordion-body',
  212. halign: opts.halign
  213. }, options, {
  214. onBeforeExpand: function(){
  215. if (options.onBeforeExpand){
  216. if (options.onBeforeExpand.call(this) == false){return false}
  217. }
  218. if (!opts.multiple){
  219. // get all selected panel
  220. var all = $.grep(getSelections(container), function(p){
  221. return p.panel('options').collapsible;
  222. });
  223. for(var i=0; i<all.length; i++){
  224. unselect(container, getPanelIndex(container, all[i]));
  225. }
  226. }
  227. var header = $(this).panel('header');
  228. header.addClass('accordion-header-selected');
  229. header.find('.accordion-collapse').removeClass('accordion-expand');
  230. },
  231. onExpand: function(){
  232. $(container).find('>.panel-last>.accordion-header').removeClass('accordion-header-border');
  233. if (options.onExpand){options.onExpand.call(this)}
  234. opts.onSelect.call(container, $(this).panel('options').title, getPanelIndex(container, this));
  235. },
  236. onBeforeCollapse: function(){
  237. if (options.onBeforeCollapse){
  238. if (options.onBeforeCollapse.call(this) == false){return false}
  239. }
  240. $(container).find('>.panel-last>.accordion-header').addClass('accordion-header-border');
  241. var header = $(this).panel('header');
  242. header.removeClass('accordion-header-selected');
  243. header.find('.accordion-collapse').addClass('accordion-expand');
  244. },
  245. onCollapse: function(){
  246. if (isNaN(parseInt(opts.height))){
  247. $(container).find('>.panel-last>.accordion-header').removeClass('accordion-header-border');
  248. }
  249. if (options.onCollapse){options.onCollapse.call(this)}
  250. opts.onUnselect.call(container, $(this).panel('options').title, getPanelIndex(container, this));
  251. }
  252. }));
  253. var header = pp.panel('header');
  254. var tool = header.children('div.panel-tool');
  255. tool.children('a.panel-tool-collapse').hide(); // hide the old collapse button
  256. var t = $('<a href="javascript:;"></a>').addClass('accordion-collapse accordion-expand').appendTo(tool);
  257. t.bind('click', function(){
  258. togglePanel(pp);
  259. return false;
  260. });
  261. pp.panel('options').collapsible ? t.show() : t.hide();
  262. if (opts.halign=='left' || opts.halign=='right'){
  263. t.hide();
  264. }
  265. header.click(function(){
  266. togglePanel(pp);
  267. return false;
  268. });
  269. function togglePanel(p){
  270. var popts = p.panel('options');
  271. if (popts.collapsible){
  272. var index = getPanelIndex(container, p);
  273. if (popts.collapsed){
  274. select(container, index);
  275. } else {
  276. unselect(container, index);
  277. }
  278. }
  279. }
  280. }
  281. /**
  282. * select and set the specified panel active
  283. */
  284. function select(container, which){
  285. var p = getPanel(container, which);
  286. if (!p){return}
  287. stopAnimate(container);
  288. var opts = $.data(container, 'accordion').options;
  289. p.panel('expand', opts.animate);
  290. }
  291. function unselect(container, which){
  292. var p = getPanel(container, which);
  293. if (!p){return}
  294. stopAnimate(container);
  295. var opts = $.data(container, 'accordion').options;
  296. p.panel('collapse', opts.animate);
  297. }
  298. function doFirstSelect(container){
  299. var opts = $.data(container, 'accordion').options;
  300. $(container).find('>.panel-last>.accordion-header').addClass('accordion-header-border');
  301. var p = findBy(container, 'selected', true);
  302. if (p){
  303. _select(getPanelIndex(container, p));
  304. } else {
  305. _select(opts.selected);
  306. }
  307. function _select(index){
  308. var animate = opts.animate;
  309. opts.animate = false;
  310. select(container, index);
  311. opts.animate = animate;
  312. }
  313. }
  314. /**
  315. * stop the animation of all panels
  316. */
  317. function stopAnimate(container){
  318. var panels = $.data(container, 'accordion').panels;
  319. for(var i=0; i<panels.length; i++){
  320. panels[i].stop(true,true);
  321. }
  322. }
  323. function add(container, options){
  324. var state = $.data(container, 'accordion');
  325. var opts = state.options;
  326. var panels = state.panels;
  327. if (options.selected == undefined) options.selected = true;
  328. stopAnimate(container);
  329. var pp = $('<div></div>').appendTo(container);
  330. panels.push(pp);
  331. createPanel(container, pp, options);
  332. setSize(container);
  333. opts.onAdd.call(container, options.title, panels.length-1);
  334. if (options.selected){
  335. select(container, panels.length-1);
  336. }
  337. }
  338. function remove(container, which){
  339. var state = $.data(container, 'accordion');
  340. var opts = state.options;
  341. var panels = state.panels;
  342. stopAnimate(container);
  343. var panel = getPanel(container, which);
  344. var title = panel.panel('options').title;
  345. var index = getPanelIndex(container, panel);
  346. if (!panel){return}
  347. if (opts.onBeforeRemove.call(container, title, index) == false){return}
  348. panels.splice(index, 1);
  349. panel.panel('destroy');
  350. if (panels.length){
  351. setSize(container);
  352. var curr = getSelected(container);
  353. if (!curr){
  354. select(container, 0);
  355. }
  356. }
  357. opts.onRemove.call(container, title, index);
  358. }
  359. $.fn.accordion = function(options, param){
  360. if (typeof options == 'string'){
  361. return $.fn.accordion.methods[options](this, param);
  362. }
  363. options = options || {};
  364. return this.each(function(){
  365. var state = $.data(this, 'accordion');
  366. if (state){
  367. $.extend(state.options, options);
  368. } else {
  369. $.data(this, 'accordion', {
  370. options: $.extend({}, $.fn.accordion.defaults, $.fn.accordion.parseOptions(this), options),
  371. accordion: $(this).addClass('accordion'),
  372. panels: []
  373. });
  374. init(this);
  375. }
  376. setProperties(this);
  377. setSize(this);
  378. doFirstSelect(this);
  379. });
  380. };
  381. $.fn.accordion.methods = {
  382. options: function(jq){
  383. return $.data(jq[0], 'accordion').options;
  384. },
  385. panels: function(jq){
  386. return $.data(jq[0], 'accordion').panels;
  387. },
  388. resize: function(jq, param){
  389. return jq.each(function(){
  390. setSize(this, param);
  391. });
  392. },
  393. getSelections: function(jq){
  394. return getSelections(jq[0]);
  395. },
  396. getSelected: function(jq){
  397. return getSelected(jq[0]);
  398. },
  399. getPanel: function(jq, which){
  400. return getPanel(jq[0], which);
  401. },
  402. getPanelIndex: function(jq, panel){
  403. return getPanelIndex(jq[0], panel);
  404. },
  405. select: function(jq, which){
  406. return jq.each(function(){
  407. select(this, which);
  408. });
  409. },
  410. unselect: function(jq, which){
  411. return jq.each(function(){
  412. unselect(this, which);
  413. });
  414. },
  415. add: function(jq, options){
  416. return jq.each(function(){
  417. add(this, options);
  418. });
  419. },
  420. remove: function(jq, which){
  421. return jq.each(function(){
  422. remove(this, which);
  423. });
  424. }
  425. };
  426. $.fn.accordion.parseOptions = function(target){
  427. var t = $(target);
  428. return $.extend({}, $.parser.parseOptions(target, [
  429. 'width','height','halign',
  430. {fit:'boolean',border:'boolean',animate:'boolean',multiple:'boolean',selected:'number'}
  431. ]));
  432. };
  433. $.fn.accordion.defaults = {
  434. width: 'auto',
  435. height: 'auto',
  436. fit: false,
  437. border: true,
  438. animate: true,
  439. multiple: false,
  440. selected: 0,
  441. halign: 'top', // the header alignment: 'top','left','right'
  442. onSelect: function(title, index){},
  443. onUnselect: function(title, index){},
  444. onAdd: function(title, index){},
  445. onBeforeRemove: function(title, index){},
  446. onRemove: function(title, index){}
  447. };
  448. })(jQuery);