jquery.accordion.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  1. /**
  2. * jQuery EasyUI 1.4.2
  3. *
  4. * Copyright (c) 2009-2015 www.jeasyui.com. All rights reserved.
  5. *
  6. * Licensed under the GPL license: http://www.gnu.org/licenses/gpl.txt
  7. * To use it on other terms please contact us at info@jeasyui.com
  8. *
  9. */
  10. /**
  11. * accordion - jQuery EasyUI
  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. /**
  58. * find a panel by specified property, return the panel object or panel index.
  59. */
  60. function findBy(container, property, value, all){
  61. var panels = $.data(container, 'accordion').panels;
  62. var pp = [];
  63. for(var i=0; i<panels.length; i++){
  64. var p = panels[i];
  65. if (property){
  66. if (p.panel('options')[property] == value){
  67. pp.push(p);
  68. }
  69. } else {
  70. if (p[0] == $(value)[0]){
  71. return i;
  72. }
  73. }
  74. }
  75. if (property){
  76. return all ? pp : (pp.length ? pp[0] : null);
  77. } else {
  78. return -1;
  79. }
  80. }
  81. function getSelections(container){
  82. return findBy(container, 'collapsed', false, true);
  83. }
  84. function getSelected(container){
  85. var pp = getSelections(container);
  86. return pp.length ? pp[0] : null;
  87. }
  88. /**
  89. * get panel index, start with 0
  90. */
  91. function getPanelIndex(container, panel){
  92. return findBy(container, null, panel);
  93. }
  94. /**
  95. * get the specified panel.
  96. */
  97. function getPanel(container, which){
  98. var panels = $.data(container, 'accordion').panels;
  99. if (typeof which == 'number'){
  100. if (which < 0 || which >= panels.length){
  101. return null;
  102. } else {
  103. return panels[which];
  104. }
  105. }
  106. return findBy(container, 'title', which);
  107. }
  108. function setProperties(container){
  109. var opts = $.data(container, 'accordion').options;
  110. var cc = $(container);
  111. if (opts.border){
  112. cc.removeClass('accordion-noborder');
  113. } else {
  114. cc.addClass('accordion-noborder');
  115. }
  116. }
  117. function init(container){
  118. var state = $.data(container, 'accordion');
  119. var cc = $(container);
  120. cc.addClass('accordion');
  121. state.panels = [];
  122. cc.children('div').each(function(){
  123. var opts = $.extend({}, $.parser.parseOptions(this), {
  124. selected: ($(this).attr('selected') ? true : undefined)
  125. });
  126. var pp = $(this);
  127. state.panels.push(pp);
  128. createPanel(container, pp, opts);
  129. });
  130. cc.bind('_resize', function(e,force){
  131. if ($(this).hasClass('easyui-fluid') || force){
  132. setSize(container);
  133. }
  134. return false;
  135. });
  136. }
  137. function createPanel(container, pp, options){
  138. var opts = $.data(container, 'accordion').options;
  139. pp.panel($.extend({}, {
  140. collapsible: true,
  141. minimizable: false,
  142. maximizable: false,
  143. closable: false,
  144. doSize: false,
  145. collapsed: true,
  146. headerCls: 'accordion-header',
  147. bodyCls: 'accordion-body'
  148. }, options, {
  149. onBeforeExpand: function(){
  150. if (options.onBeforeExpand){
  151. if (options.onBeforeExpand.call(this) == false){return false}
  152. }
  153. if (!opts.multiple){
  154. // get all selected panel
  155. var all = $.grep(getSelections(container), function(p){
  156. return p.panel('options').collapsible;
  157. });
  158. for(var i=0; i<all.length; i++){
  159. unselect(container, getPanelIndex(container, all[i]));
  160. }
  161. }
  162. var header = $(this).panel('header');
  163. header.addClass('accordion-header-selected');
  164. header.find('.accordion-collapse').removeClass('accordion-expand');
  165. },
  166. onExpand: function(){
  167. if (options.onExpand){options.onExpand.call(this)}
  168. opts.onSelect.call(container, $(this).panel('options').title, getPanelIndex(container, this));
  169. },
  170. onBeforeCollapse: function(){
  171. if (options.onBeforeCollapse){
  172. if (options.onBeforeCollapse.call(this) == false){return false}
  173. }
  174. var header = $(this).panel('header');
  175. header.removeClass('accordion-header-selected');
  176. header.find('.accordion-collapse').addClass('accordion-expand');
  177. },
  178. onCollapse: function(){
  179. if (options.onCollapse){options.onCollapse.call(this)}
  180. opts.onUnselect.call(container, $(this).panel('options').title, getPanelIndex(container, this));
  181. }
  182. }));
  183. var header = pp.panel('header');
  184. var tool = header.children('div.panel-tool');
  185. tool.children('a.panel-tool-collapse').hide(); // hide the old collapse button
  186. var t = $('<a href="javascript:void(0)"></a>').addClass('accordion-collapse accordion-expand').appendTo(tool);
  187. t.bind('click', function(){
  188. togglePanel(pp);
  189. return false;
  190. });
  191. pp.panel('options').collapsible ? t.show() : t.hide();
  192. header.click(function(){
  193. togglePanel(pp);
  194. return false;
  195. });
  196. function togglePanel(p){
  197. var popts = p.panel('options');
  198. if (popts.collapsible){
  199. var index = getPanelIndex(container, p);
  200. if (popts.collapsed){
  201. select(container, index);
  202. } else {
  203. unselect(container, index);
  204. }
  205. }
  206. }
  207. }
  208. /**
  209. * select and set the specified panel active
  210. */
  211. function select(container, which){
  212. var p = getPanel(container, which);
  213. if (!p){return}
  214. stopAnimate(container);
  215. var opts = $.data(container, 'accordion').options;
  216. p.panel('expand', opts.animate);
  217. }
  218. function unselect(container, which){
  219. var p = getPanel(container, which);
  220. if (!p){return}
  221. stopAnimate(container);
  222. var opts = $.data(container, 'accordion').options;
  223. p.panel('collapse', opts.animate);
  224. }
  225. function doFirstSelect(container){
  226. var opts = $.data(container, 'accordion').options;
  227. var p = findBy(container, 'selected', true);
  228. if (p){
  229. _select(getPanelIndex(container, p));
  230. } else {
  231. _select(opts.selected);
  232. }
  233. function _select(index){
  234. var animate = opts.animate;
  235. opts.animate = false;
  236. select(container, index);
  237. opts.animate = animate;
  238. }
  239. }
  240. /**
  241. * stop the animation of all panels
  242. */
  243. function stopAnimate(container){
  244. var panels = $.data(container, 'accordion').panels;
  245. for(var i=0; i<panels.length; i++){
  246. panels[i].stop(true,true);
  247. }
  248. }
  249. function add(container, options){
  250. var state = $.data(container, 'accordion');
  251. var opts = state.options;
  252. var panels = state.panels;
  253. if (options.selected == undefined) options.selected = true;
  254. stopAnimate(container);
  255. var pp = $('<div></div>').appendTo(container);
  256. panels.push(pp);
  257. createPanel(container, pp, options);
  258. setSize(container);
  259. opts.onAdd.call(container, options.title, panels.length-1);
  260. if (options.selected){
  261. select(container, panels.length-1);
  262. }
  263. }
  264. function remove(container, which){
  265. var state = $.data(container, 'accordion');
  266. var opts = state.options;
  267. var panels = state.panels;
  268. stopAnimate(container);
  269. var panel = getPanel(container, which);
  270. var title = panel.panel('options').title;
  271. var index = getPanelIndex(container, panel);
  272. if (!panel){return}
  273. if (opts.onBeforeRemove.call(container, title, index) == false){return}
  274. panels.splice(index, 1);
  275. panel.panel('destroy');
  276. if (panels.length){
  277. setSize(container);
  278. var curr = getSelected(container);
  279. if (!curr){
  280. select(container, 0);
  281. }
  282. }
  283. opts.onRemove.call(container, title, index);
  284. }
  285. $.fn.accordion = function(options, param){
  286. if (typeof options == 'string'){
  287. return $.fn.accordion.methods[options](this, param);
  288. }
  289. options = options || {};
  290. return this.each(function(){
  291. var state = $.data(this, 'accordion');
  292. if (state){
  293. $.extend(state.options, options);
  294. } else {
  295. $.data(this, 'accordion', {
  296. options: $.extend({}, $.fn.accordion.defaults, $.fn.accordion.parseOptions(this), options),
  297. accordion: $(this).addClass('accordion'),
  298. panels: []
  299. });
  300. init(this);
  301. }
  302. setProperties(this);
  303. setSize(this);
  304. doFirstSelect(this);
  305. });
  306. };
  307. $.fn.accordion.methods = {
  308. options: function(jq){
  309. return $.data(jq[0], 'accordion').options;
  310. },
  311. panels: function(jq){
  312. return $.data(jq[0], 'accordion').panels;
  313. },
  314. resize: function(jq, param){
  315. return jq.each(function(){
  316. setSize(this, param);
  317. });
  318. },
  319. getSelections: function(jq){
  320. return getSelections(jq[0]);
  321. },
  322. getSelected: function(jq){
  323. return getSelected(jq[0]);
  324. },
  325. getPanel: function(jq, which){
  326. return getPanel(jq[0], which);
  327. },
  328. getPanelIndex: function(jq, panel){
  329. return getPanelIndex(jq[0], panel);
  330. },
  331. select: function(jq, which){
  332. return jq.each(function(){
  333. select(this, which);
  334. });
  335. },
  336. unselect: function(jq, which){
  337. return jq.each(function(){
  338. unselect(this, which);
  339. });
  340. },
  341. add: function(jq, options){
  342. return jq.each(function(){
  343. add(this, options);
  344. });
  345. },
  346. remove: function(jq, which){
  347. return jq.each(function(){
  348. remove(this, which);
  349. });
  350. }
  351. };
  352. $.fn.accordion.parseOptions = function(target){
  353. var t = $(target);
  354. return $.extend({}, $.parser.parseOptions(target, [
  355. 'width','height',
  356. {fit:'boolean',border:'boolean',animate:'boolean',multiple:'boolean',selected:'number'}
  357. ]));
  358. };
  359. $.fn.accordion.defaults = {
  360. width: 'auto',
  361. height: 'auto',
  362. fit: false,
  363. border: true,
  364. animate: true,
  365. multiple: false,
  366. selected: 0,
  367. onSelect: function(title, index){},
  368. onUnselect: function(title, index){},
  369. onAdd: function(title, index){},
  370. onBeforeRemove: function(title, index){},
  371. onRemove: function(title, index){}
  372. };
  373. })(jQuery);