jquery.accordion.js 13 KB

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