You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

440 lines
13 KiB

11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
  1. /*
  2. * # Semantic - Accordion
  3. * http://github.com/jlukic/semantic-ui/
  4. *
  5. *
  6. * Copyright 2014 Contributors
  7. * Released under the MIT license
  8. * http://opensource.org/licenses/MIT
  9. *
  10. */
  11. ;(function ($, window, document, undefined) {
  12. module.exports = function(parameters) {
  13. var _module = module;
  14. var
  15. $allModules = $(this),
  16. time = new Date().getTime(),
  17. performance = [],
  18. query = arguments[0],
  19. methodInvoked = (typeof query == 'string'),
  20. queryArguments = [].slice.call(arguments, 1),
  21. returnedValue
  22. ;
  23. $allModules
  24. .each(function() {
  25. var
  26. settings = ( $.isPlainObject(parameters) )
  27. ? $.extend(true, {}, _module.exports.settings, parameters)
  28. : $.extend({}, _module.exports.settings),
  29. className = settings.className,
  30. namespace = settings.namespace,
  31. selector = settings.selector,
  32. error = settings.error,
  33. eventNamespace = '.' + namespace,
  34. moduleNamespace = 'module-' + namespace,
  35. moduleSelector = $allModules.selector || '',
  36. $module = $(this),
  37. $title = $module.find(selector.title),
  38. $content = $module.find(selector.content),
  39. element = this,
  40. instance = $module.data(moduleNamespace),
  41. module
  42. ;
  43. module = {
  44. initialize: function() {
  45. module.debug('Initializing accordion with bound events', $module);
  46. // initializing
  47. $title
  48. .on('click' + eventNamespace, module.event.click)
  49. ;
  50. module.instantiate();
  51. },
  52. instantiate: function() {
  53. instance = module;
  54. $module
  55. .data(moduleNamespace, module)
  56. ;
  57. },
  58. destroy: function() {
  59. module.debug('Destroying previous accordion for', $module);
  60. $module
  61. .removeData(moduleNamespace)
  62. ;
  63. $title
  64. .off(eventNamespace)
  65. ;
  66. },
  67. event: {
  68. click: function() {
  69. module.verbose('Title clicked', this);
  70. var
  71. $activeTitle = $(this),
  72. index = $title.index($activeTitle)
  73. ;
  74. module.toggle(index);
  75. },
  76. resetDisplay: function() {
  77. $(this).css('display', '');
  78. if( $(this).attr('style') == '') {
  79. $(this)
  80. .attr('style', '')
  81. .removeAttr('style')
  82. ;
  83. }
  84. },
  85. resetOpacity: function() {
  86. $(this).css('opacity', '');
  87. if( $(this).attr('style') == '') {
  88. $(this)
  89. .attr('style', '')
  90. .removeAttr('style')
  91. ;
  92. }
  93. }
  94. },
  95. toggle: function(index) {
  96. module.debug('Toggling content content at index', index);
  97. var
  98. $activeTitle = $title.eq(index),
  99. $activeContent = $activeTitle.next($content),
  100. contentIsOpen = $activeContent.is(':visible')
  101. ;
  102. if(contentIsOpen) {
  103. if(settings.collapsible) {
  104. module.close(index);
  105. }
  106. else {
  107. module.debug('Cannot close accordion content collapsing is disabled');
  108. }
  109. }
  110. else {
  111. module.open(index);
  112. }
  113. },
  114. open: function(index) {
  115. var
  116. $activeTitle = $title.eq(index),
  117. $activeContent = $activeTitle.next($content),
  118. $otherSections = module.is.menu()
  119. ? $activeTitle.parent().siblings(selector.item).find(selector.title)
  120. : $activeTitle.siblings(selector.title),
  121. $previousTitle = $otherSections.filter('.' + className.active),
  122. $previousContent = $previousTitle.next($title),
  123. contentIsOpen = ($previousTitle.size() > 0)
  124. ;
  125. if( !$activeContent.is(':animated') ) {
  126. module.debug('Opening accordion content', $activeTitle);
  127. if(settings.exclusive && contentIsOpen) {
  128. $previousTitle
  129. .removeClass(className.active)
  130. ;
  131. $previousContent
  132. .stop()
  133. .children()
  134. .stop()
  135. .animate({
  136. opacity: 0
  137. }, settings.duration, module.event.resetOpacity)
  138. .end()
  139. .slideUp(settings.duration , settings.easing, function() {
  140. $previousContent
  141. .removeClass(className.active)
  142. .children()
  143. ;
  144. $.proxy(module.event.resetDisplay, this)();
  145. })
  146. ;
  147. }
  148. $activeTitle
  149. .addClass(className.active)
  150. ;
  151. $activeContent
  152. .stop()
  153. .children()
  154. .stop()
  155. .animate({
  156. opacity: 1
  157. }, settings.duration)
  158. .end()
  159. .slideDown(settings.duration, settings.easing, function() {
  160. $activeContent
  161. .addClass(className.active)
  162. ;
  163. $.proxy(module.event.resetDisplay, this)();
  164. $.proxy(settings.onOpen, $activeContent)();
  165. $.proxy(settings.onChange, $activeContent)();
  166. })
  167. ;
  168. }
  169. },
  170. close: function(index) {
  171. var
  172. $activeTitle = $title.eq(index),
  173. $activeContent = $activeTitle.next($content)
  174. ;
  175. module.debug('Closing accordion content', $activeContent);
  176. $activeTitle
  177. .removeClass(className.active)
  178. ;
  179. $activeContent
  180. .removeClass(className.active)
  181. .show()
  182. .stop()
  183. .children()
  184. .stop()
  185. .animate({
  186. opacity: 0
  187. }, settings.duration, module.event.resetOpacity)
  188. .end()
  189. .slideUp(settings.duration, settings.easing, function(){
  190. $.proxy(module.event.resetDisplay, this)();
  191. $.proxy(settings.onClose, $activeContent)();
  192. $.proxy(settings.onChange, $activeContent)();
  193. })
  194. ;
  195. },
  196. is: {
  197. menu: function () {
  198. return $module.hasClass(className.menu);
  199. }
  200. },
  201. setting: function(name, value) {
  202. if( $.isPlainObject(name) ) {
  203. $.extend(true, settings, name);
  204. }
  205. else if(value !== undefined) {
  206. settings[name] = value;
  207. }
  208. else {
  209. return settings[name];
  210. }
  211. },
  212. internal: function(name, value) {
  213. module.debug('Changing internal', name, value);
  214. if(value !== undefined) {
  215. if( $.isPlainObject(name) ) {
  216. $.extend(true, module, name);
  217. }
  218. else {
  219. module[name] = value;
  220. }
  221. }
  222. else {
  223. return module[name];
  224. }
  225. },
  226. debug: function() {
  227. if(settings.debug) {
  228. if(settings.performance) {
  229. module.performance.log(arguments);
  230. }
  231. else {
  232. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  233. module.debug.apply(console, arguments);
  234. }
  235. }
  236. },
  237. verbose: function() {
  238. if(settings.verbose && settings.debug) {
  239. if(settings.performance) {
  240. module.performance.log(arguments);
  241. }
  242. else {
  243. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  244. module.verbose.apply(console, arguments);
  245. }
  246. }
  247. },
  248. error: function() {
  249. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  250. module.error.apply(console, arguments);
  251. },
  252. performance: {
  253. log: function(message) {
  254. var
  255. currentTime,
  256. executionTime,
  257. previousTime
  258. ;
  259. if(settings.performance) {
  260. currentTime = new Date().getTime();
  261. previousTime = time || currentTime;
  262. executionTime = currentTime - previousTime;
  263. time = currentTime;
  264. performance.push({
  265. 'Element' : element,
  266. 'Name' : message[0],
  267. 'Arguments' : [].slice.call(message, 1) || '',
  268. 'Execution Time' : executionTime
  269. });
  270. }
  271. clearTimeout(module.performance.timer);
  272. module.performance.timer = setTimeout(module.performance.display, 100);
  273. },
  274. display: function() {
  275. var
  276. title = settings.name + ':',
  277. totalTime = 0
  278. ;
  279. time = false;
  280. clearTimeout(module.performance.timer);
  281. $.each(performance, function(index, data) {
  282. totalTime += data['Execution Time'];
  283. });
  284. title += ' ' + totalTime + 'ms';
  285. if(moduleSelector) {
  286. title += ' \'' + moduleSelector + '\'';
  287. }
  288. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  289. console.groupCollapsed(title);
  290. if(console.table) {
  291. console.table(performance);
  292. }
  293. else {
  294. $.each(performance, function(index, data) {
  295. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  296. });
  297. }
  298. console.groupEnd();
  299. }
  300. performance = [];
  301. }
  302. },
  303. invoke: function(query, passedArguments, context) {
  304. var
  305. object = instance,
  306. maxDepth,
  307. found,
  308. response
  309. ;
  310. passedArguments = passedArguments || queryArguments;
  311. context = element || context;
  312. if(typeof query == 'string' && object !== undefined) {
  313. query = query.split(/[\. ]/);
  314. maxDepth = query.length - 1;
  315. $.each(query, function(depth, value) {
  316. var camelCaseValue = (depth != maxDepth)
  317. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  318. : query
  319. ;
  320. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  321. object = object[camelCaseValue];
  322. }
  323. else if( object[camelCaseValue] !== undefined ) {
  324. found = object[camelCaseValue];
  325. return false;
  326. }
  327. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  328. object = object[value];
  329. }
  330. else if( object[value] !== undefined ) {
  331. found = object[value];
  332. return false;
  333. }
  334. else {
  335. return false;
  336. }
  337. });
  338. }
  339. if ( $.isFunction( found ) ) {
  340. response = found.apply(context, passedArguments);
  341. }
  342. else if(found !== undefined) {
  343. response = found;
  344. }
  345. if($.isArray(returnedValue)) {
  346. returnedValue.push(response);
  347. }
  348. else if(returnedValue !== undefined) {
  349. returnedValue = [returnedValue, response];
  350. }
  351. else if(response !== undefined) {
  352. returnedValue = response;
  353. }
  354. return found;
  355. }
  356. };
  357. if(methodInvoked) {
  358. if(instance === undefined) {
  359. module.initialize();
  360. }
  361. module.invoke(query);
  362. }
  363. else {
  364. if(instance !== undefined) {
  365. module.destroy();
  366. }
  367. module.initialize();
  368. }
  369. })
  370. ;
  371. return (returnedValue !== undefined)
  372. ? returnedValue
  373. : this
  374. ;
  375. };
  376. module.exports.settings = {
  377. name : 'Accordion',
  378. namespace : 'accordion',
  379. debug : false,
  380. verbose : true,
  381. performance : true,
  382. exclusive : true,
  383. collapsible : true,
  384. duration : 500,
  385. easing : 'easeInOutQuint',
  386. onOpen : function(){},
  387. onClose : function(){},
  388. onChange : function(){},
  389. error: {
  390. method : 'The method you called is not defined'
  391. },
  392. className : {
  393. active : 'active',
  394. menu : 'menu',
  395. },
  396. selector : {
  397. title : '.title',
  398. content : '.content',
  399. menu : '.menu',
  400. item : '.item',
  401. }
  402. };
  403. // Adds easing
  404. $.extend( $.easing, {
  405. easeInOutQuint: function (x, t, b, c, d) {
  406. if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
  407. return c/2*((t-=2)*t*t*t*t + 2) + b;
  408. }
  409. });
  410. })( require("jquery"), window , document );