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.

516 lines
15 KiB

10 years ago
10 years ago
10 years ago
10 years ago
  1. /*
  2. * # Semantic - Sidebar
  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. $body = $('body'),
  17. $head = $('head'),
  18. moduleSelector = $allModules.selector || '',
  19. time = new Date().getTime(),
  20. performance = [],
  21. query = arguments[0],
  22. methodInvoked = (typeof query == 'string'),
  23. queryArguments = [].slice.call(arguments, 1),
  24. returnedValue
  25. ;
  26. $allModules
  27. .each(function() {
  28. var
  29. settings = ( $.isPlainObject(parameters) )
  30. ? $.extend(true, {}, _module.exports.settings, parameters)
  31. : $.extend({}, _module.exports.settings),
  32. selector = settings.selector,
  33. className = settings.className,
  34. namespace = settings.namespace,
  35. error = settings.error,
  36. eventNamespace = '.' + namespace,
  37. moduleNamespace = 'module-' + namespace,
  38. $module = $(this),
  39. $style = $('style[title=' + namespace + ']'),
  40. element = this,
  41. instance = $module.data(moduleNamespace),
  42. module
  43. ;
  44. module = {
  45. initialize: function() {
  46. module.debug('Initializing sidebar', $module);
  47. module.instantiate();
  48. },
  49. instantiate: function() {
  50. module.verbose('Storing instance of module', module);
  51. instance = module;
  52. $module
  53. .data(moduleNamespace, module)
  54. ;
  55. },
  56. destroy: function() {
  57. module.verbose('Destroying previous module for', $module);
  58. $module
  59. .off(eventNamespace)
  60. .removeData(moduleNamespace)
  61. ;
  62. },
  63. refresh: function() {
  64. module.verbose('Refreshing selector cache');
  65. $style = $('style[title=' + namespace + ']');
  66. },
  67. attachEvents: function(selector, event) {
  68. var
  69. $toggle = $(selector)
  70. ;
  71. event = $.isFunction(module[event])
  72. ? module[event]
  73. : module.toggle
  74. ;
  75. if($toggle.size() > 0) {
  76. module.debug('Attaching sidebar events to element', selector, event);
  77. $toggle
  78. .off(eventNamespace)
  79. .on('click' + eventNamespace, event)
  80. ;
  81. }
  82. else {
  83. module.error(error.notFound);
  84. }
  85. },
  86. show: function(callback) {
  87. callback = $.isFunction(callback)
  88. ? callback
  89. : function(){}
  90. ;
  91. module.debug('Showing sidebar', callback);
  92. if(module.is.closed()) {
  93. if(!settings.overlay) {
  94. if(settings.exclusive) {
  95. module.hideAll();
  96. }
  97. module.pushPage();
  98. }
  99. module.set.active();
  100. callback();
  101. $.proxy(settings.onChange, element)();
  102. $.proxy(settings.onShow, element)();
  103. }
  104. else {
  105. module.debug('Sidebar is already visible');
  106. }
  107. },
  108. hide: function(callback) {
  109. callback = $.isFunction(callback)
  110. ? callback
  111. : function(){}
  112. ;
  113. module.debug('Hiding sidebar', callback);
  114. if(module.is.open()) {
  115. if(!settings.overlay) {
  116. module.pullPage();
  117. module.remove.pushed();
  118. }
  119. module.remove.active();
  120. callback();
  121. $.proxy(settings.onChange, element)();
  122. $.proxy(settings.onHide, element)();
  123. }
  124. },
  125. hideAll: function() {
  126. $(selector.sidebar)
  127. .filter(':visible')
  128. .sidebar('hide')
  129. ;
  130. },
  131. toggle: function() {
  132. if(module.is.closed()) {
  133. module.show();
  134. }
  135. else {
  136. module.hide();
  137. }
  138. },
  139. pushPage: function() {
  140. var
  141. direction = module.get.direction(),
  142. distance = (module.is.vertical())
  143. ? $module.outerHeight()
  144. : $module.outerWidth()
  145. ;
  146. if(settings.useCSS) {
  147. module.debug('Using CSS to animate body');
  148. module.add.bodyCSS(direction, distance);
  149. module.set.pushed();
  150. }
  151. else {
  152. module.animatePage(direction, distance, module.set.pushed);
  153. }
  154. },
  155. pullPage: function() {
  156. var
  157. direction = module.get.direction()
  158. ;
  159. if(settings.useCSS) {
  160. module.debug('Resetting body position css');
  161. module.remove.bodyCSS();
  162. }
  163. else {
  164. module.debug('Resetting body position using javascript');
  165. module.animatePage(direction, 0);
  166. }
  167. module.remove.pushed();
  168. },
  169. animatePage: function(direction, distance) {
  170. var
  171. animateSettings = {}
  172. ;
  173. animateSettings['padding-' + direction] = distance;
  174. module.debug('Using javascript to animate body', animateSettings);
  175. $body
  176. .animate(animateSettings, settings.duration, module.set.pushed)
  177. ;
  178. },
  179. add: {
  180. bodyCSS: function(direction, distance) {
  181. var
  182. style
  183. ;
  184. if(direction !== className.bottom) {
  185. style = ''
  186. + '<style title="' + namespace + '">'
  187. + 'body.pushed {'
  188. + ' margin-' + direction + ': ' + distance + 'px !important;'
  189. + '}'
  190. + '</style>'
  191. ;
  192. }
  193. $head.append(style);
  194. module.debug('Adding body css to head', $style);
  195. }
  196. },
  197. remove: {
  198. bodyCSS: function() {
  199. module.debug('Removing body css styles', $style);
  200. module.refresh();
  201. $style.remove();
  202. },
  203. active: function() {
  204. $module.removeClass(className.active);
  205. },
  206. pushed: function() {
  207. module.verbose('Removing body push state', module.get.direction());
  208. $body
  209. .removeClass(className[ module.get.direction() ])
  210. .removeClass(className.pushed)
  211. ;
  212. }
  213. },
  214. set: {
  215. active: function() {
  216. $module.addClass(className.active);
  217. },
  218. pushed: function() {
  219. module.verbose('Adding body push state', module.get.direction());
  220. $body
  221. .addClass(className[ module.get.direction() ])
  222. .addClass(className.pushed)
  223. ;
  224. }
  225. },
  226. get: {
  227. direction: function() {
  228. if($module.hasClass(className.top)) {
  229. return className.top;
  230. }
  231. else if($module.hasClass(className.right)) {
  232. return className.right;
  233. }
  234. else if($module.hasClass(className.bottom)) {
  235. return className.bottom;
  236. }
  237. else {
  238. return className.left;
  239. }
  240. },
  241. transitionEvent: function() {
  242. var
  243. element = document.createElement('element'),
  244. transitions = {
  245. 'transition' :'transitionend',
  246. 'OTransition' :'oTransitionEnd',
  247. 'MozTransition' :'transitionend',
  248. 'WebkitTransition' :'webkitTransitionEnd'
  249. },
  250. transition
  251. ;
  252. for(transition in transitions){
  253. if( element.style[transition] !== undefined ){
  254. return transitions[transition];
  255. }
  256. }
  257. }
  258. },
  259. is: {
  260. open: function() {
  261. return $module.is(':animated') || $module.hasClass(className.active);
  262. },
  263. closed: function() {
  264. return !module.is.open();
  265. },
  266. vertical: function() {
  267. return $module.hasClass(className.top);
  268. }
  269. },
  270. setting: function(name, value) {
  271. if( $.isPlainObject(name) ) {
  272. $.extend(true, settings, name);
  273. }
  274. else if(value !== undefined) {
  275. settings[name] = value;
  276. }
  277. else {
  278. return settings[name];
  279. }
  280. },
  281. internal: function(name, value) {
  282. if( $.isPlainObject(name) ) {
  283. $.extend(true, module, name);
  284. }
  285. else if(value !== undefined) {
  286. module[name] = value;
  287. }
  288. else {
  289. return module[name];
  290. }
  291. },
  292. debug: function() {
  293. if(settings.debug) {
  294. if(settings.performance) {
  295. module.performance.log(arguments);
  296. }
  297. else {
  298. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  299. module.debug.apply(console, arguments);
  300. }
  301. }
  302. },
  303. verbose: function() {
  304. if(settings.verbose && settings.debug) {
  305. if(settings.performance) {
  306. module.performance.log(arguments);
  307. }
  308. else {
  309. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  310. module.verbose.apply(console, arguments);
  311. }
  312. }
  313. },
  314. error: function() {
  315. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  316. module.error.apply(console, arguments);
  317. },
  318. performance: {
  319. log: function(message) {
  320. var
  321. currentTime,
  322. executionTime,
  323. previousTime
  324. ;
  325. if(settings.performance) {
  326. currentTime = new Date().getTime();
  327. previousTime = time || currentTime;
  328. executionTime = currentTime - previousTime;
  329. time = currentTime;
  330. performance.push({
  331. 'Element' : element,
  332. 'Name' : message[0],
  333. 'Arguments' : [].slice.call(message, 1) || '',
  334. 'Execution Time' : executionTime
  335. });
  336. }
  337. clearTimeout(module.performance.timer);
  338. module.performance.timer = setTimeout(module.performance.display, 100);
  339. },
  340. display: function() {
  341. var
  342. title = settings.name + ':',
  343. totalTime = 0
  344. ;
  345. time = false;
  346. clearTimeout(module.performance.timer);
  347. $.each(performance, function(index, data) {
  348. totalTime += data['Execution Time'];
  349. });
  350. title += ' ' + totalTime + 'ms';
  351. if(moduleSelector) {
  352. title += ' \'' + moduleSelector + '\'';
  353. }
  354. if($allModules.size() > 1) {
  355. title += ' ' + '(' + $allModules.size() + ')';
  356. }
  357. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  358. console.groupCollapsed(title);
  359. if(console.table) {
  360. console.table(performance);
  361. }
  362. else {
  363. $.each(performance, function(index, data) {
  364. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  365. });
  366. }
  367. console.groupEnd();
  368. }
  369. performance = [];
  370. }
  371. },
  372. invoke: function(query, passedArguments, context) {
  373. var
  374. object = instance,
  375. maxDepth,
  376. found,
  377. response
  378. ;
  379. passedArguments = passedArguments || queryArguments;
  380. context = element || context;
  381. if(typeof query == 'string' && object !== undefined) {
  382. query = query.split(/[\. ]/);
  383. maxDepth = query.length - 1;
  384. $.each(query, function(depth, value) {
  385. var camelCaseValue = (depth != maxDepth)
  386. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  387. : query
  388. ;
  389. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  390. object = object[camelCaseValue];
  391. }
  392. else if( object[camelCaseValue] !== undefined ) {
  393. found = object[camelCaseValue];
  394. return false;
  395. }
  396. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  397. object = object[value];
  398. }
  399. else if( object[value] !== undefined ) {
  400. found = object[value];
  401. return false;
  402. }
  403. else {
  404. return false;
  405. }
  406. });
  407. }
  408. if ( $.isFunction( found ) ) {
  409. response = found.apply(context, passedArguments);
  410. }
  411. else if(found !== undefined) {
  412. response = found;
  413. }
  414. if($.isArray(returnedValue)) {
  415. returnedValue.push(response);
  416. }
  417. else if(returnedValue !== undefined) {
  418. returnedValue = [returnedValue, response];
  419. }
  420. else if(response !== undefined) {
  421. returnedValue = response;
  422. }
  423. return found;
  424. }
  425. };
  426. if(methodInvoked) {
  427. if(instance === undefined) {
  428. module.initialize();
  429. }
  430. module.invoke(query);
  431. }
  432. else {
  433. if(instance !== undefined) {
  434. module.destroy();
  435. }
  436. module.initialize();
  437. }
  438. })
  439. ;
  440. return (returnedValue !== undefined)
  441. ? returnedValue
  442. : this
  443. ;
  444. };
  445. module.exports.settings = {
  446. name : 'Sidebar',
  447. namespace : 'sidebar',
  448. debug : false,
  449. verbose : true,
  450. performance : true,
  451. useCSS : true,
  452. exclusive : true,
  453. overlay : false,
  454. duration : 300,
  455. onChange : function(){},
  456. onShow : function(){},
  457. onHide : function(){},
  458. className: {
  459. active : 'active',
  460. pushed : 'pushed',
  461. top : 'top',
  462. left : 'left',
  463. right : 'right',
  464. bottom : 'bottom'
  465. },
  466. selector: {
  467. sidebar: '.ui.sidebar'
  468. },
  469. error : {
  470. method : 'The method you called is not defined.',
  471. notFound : 'There were no elements that matched the specified selector'
  472. }
  473. };
  474. })( require("jquery"), window , document );