sidebar.js 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036
  1. /*!
  2. * # Fomantic-UI - Sidebar
  3. * http://github.com/fomantic/Fomantic-UI/
  4. *
  5. *
  6. * Released under the MIT license
  7. * http://opensource.org/licenses/MIT
  8. *
  9. */
  10. ;(function ($, window, document, undefined) {
  11. 'use strict';
  12. $.isFunction = $.isFunction || function(obj) {
  13. return typeof obj === "function" && typeof obj.nodeType !== "number";
  14. };
  15. window = (typeof window != 'undefined' && window.Math == Math)
  16. ? window
  17. : (typeof self != 'undefined' && self.Math == Math)
  18. ? self
  19. : Function('return this')()
  20. ;
  21. $.fn.sidebar = function(parameters) {
  22. var
  23. $allModules = $(this),
  24. $window = $(window),
  25. $document = $(document),
  26. $html = $('html'),
  27. $head = $('head'),
  28. moduleSelector = $allModules.selector || '',
  29. time = new Date().getTime(),
  30. performance = [],
  31. query = arguments[0],
  32. methodInvoked = (typeof query == 'string'),
  33. queryArguments = [].slice.call(arguments, 1),
  34. requestAnimationFrame = window.requestAnimationFrame
  35. || window.mozRequestAnimationFrame
  36. || window.webkitRequestAnimationFrame
  37. || window.msRequestAnimationFrame
  38. || function(callback) { setTimeout(callback, 0); },
  39. returnedValue
  40. ;
  41. $allModules
  42. .each(function() {
  43. var
  44. settings = ( $.isPlainObject(parameters) )
  45. ? $.extend(true, {}, $.fn.sidebar.settings, parameters)
  46. : $.extend({}, $.fn.sidebar.settings),
  47. selector = settings.selector,
  48. className = settings.className,
  49. namespace = settings.namespace,
  50. regExp = settings.regExp,
  51. error = settings.error,
  52. eventNamespace = '.' + namespace,
  53. moduleNamespace = 'module-' + namespace,
  54. $module = $(this),
  55. $context = $(settings.context),
  56. $sidebars = $module.children(selector.sidebar),
  57. $fixed = $context.children(selector.fixed),
  58. $pusher = $context.children(selector.pusher),
  59. $style,
  60. element = this,
  61. instance = $module.data(moduleNamespace),
  62. elementNamespace,
  63. id,
  64. currentScroll,
  65. transitionEvent,
  66. module
  67. ;
  68. module = {
  69. initialize: function() {
  70. module.debug('Initializing sidebar', parameters);
  71. module.create.id();
  72. transitionEvent = module.get.transitionEvent();
  73. // avoids locking rendering if initialized in onReady
  74. if(settings.delaySetup) {
  75. requestAnimationFrame(module.setup.layout);
  76. }
  77. else {
  78. module.setup.layout();
  79. }
  80. requestAnimationFrame(function() {
  81. module.setup.cache();
  82. });
  83. module.instantiate();
  84. },
  85. instantiate: function() {
  86. module.verbose('Storing instance of module', module);
  87. instance = module;
  88. $module
  89. .data(moduleNamespace, module)
  90. ;
  91. },
  92. create: {
  93. id: function() {
  94. id = (Math.random().toString(16) + '000000000').substr(2,8);
  95. elementNamespace = '.' + id;
  96. module.verbose('Creating unique id for element', id);
  97. }
  98. },
  99. destroy: function() {
  100. module.verbose('Destroying previous module for', $module);
  101. $module
  102. .off(eventNamespace)
  103. .removeData(moduleNamespace)
  104. ;
  105. if(module.is.ios()) {
  106. module.remove.ios();
  107. }
  108. // bound by uuid
  109. $context.off(elementNamespace);
  110. $window.off(elementNamespace);
  111. $document.off(elementNamespace);
  112. },
  113. event: {
  114. clickaway: function(event) {
  115. if(settings.closable){
  116. var
  117. clickedInPusher = ($pusher.find(event.target).length > 0 || $pusher.is(event.target)),
  118. clickedContext = ($context.is(event.target))
  119. ;
  120. if(clickedInPusher) {
  121. module.verbose('User clicked on dimmed page');
  122. module.hide();
  123. }
  124. if(clickedContext) {
  125. module.verbose('User clicked on dimmable context (scaled out page)');
  126. module.hide();
  127. }
  128. }
  129. },
  130. touch: function(event) {
  131. //event.stopPropagation();
  132. },
  133. containScroll: function(event) {
  134. if(element.scrollTop <= 0) {
  135. element.scrollTop = 1;
  136. }
  137. if((element.scrollTop + element.offsetHeight) >= element.scrollHeight) {
  138. element.scrollTop = element.scrollHeight - element.offsetHeight - 1;
  139. }
  140. },
  141. scroll: function(event) {
  142. if( $(event.target).closest(selector.sidebar).length === 0 ) {
  143. event.preventDefault();
  144. }
  145. }
  146. },
  147. bind: {
  148. clickaway: function() {
  149. module.verbose('Adding clickaway events to context', $context);
  150. $context
  151. .on('click' + elementNamespace, module.event.clickaway)
  152. .on('touchend' + elementNamespace, module.event.clickaway)
  153. ;
  154. },
  155. scrollLock: function() {
  156. if(settings.scrollLock) {
  157. module.debug('Disabling page scroll');
  158. $window
  159. .on('DOMMouseScroll' + elementNamespace, module.event.scroll)
  160. ;
  161. }
  162. module.verbose('Adding events to contain sidebar scroll');
  163. $document
  164. .on('touchmove' + elementNamespace, module.event.touch)
  165. ;
  166. $module
  167. .on('scroll' + eventNamespace, module.event.containScroll)
  168. ;
  169. }
  170. },
  171. unbind: {
  172. clickaway: function() {
  173. module.verbose('Removing clickaway events from context', $context);
  174. $context.off(elementNamespace);
  175. },
  176. scrollLock: function() {
  177. module.verbose('Removing scroll lock from page');
  178. $document.off(elementNamespace);
  179. $window.off(elementNamespace);
  180. $module.off('scroll' + eventNamespace);
  181. }
  182. },
  183. add: {
  184. inlineCSS: function() {
  185. var
  186. width = module.cache.width || $module.outerWidth(),
  187. height = module.cache.height || $module.outerHeight(),
  188. isRTL = module.is.rtl(),
  189. direction = module.get.direction(),
  190. distance = {
  191. left : width,
  192. right : -width,
  193. top : height,
  194. bottom : -height
  195. },
  196. style
  197. ;
  198. if(isRTL){
  199. module.verbose('RTL detected, flipping widths');
  200. distance.left = -width;
  201. distance.right = width;
  202. }
  203. style = '<style>';
  204. if(direction === 'left' || direction === 'right') {
  205. module.debug('Adding CSS rules for animation distance', width);
  206. style += ''
  207. + ' .ui.visible.' + direction + '.sidebar ~ .fixed,'
  208. + ' .ui.visible.' + direction + '.sidebar ~ .pusher {'
  209. + ' -webkit-transform: translate3d('+ distance[direction] + 'px, 0, 0);'
  210. + ' transform: translate3d('+ distance[direction] + 'px, 0, 0);'
  211. + ' }'
  212. ;
  213. }
  214. else if(direction === 'top' || direction == 'bottom') {
  215. style += ''
  216. + ' .ui.visible.' + direction + '.sidebar ~ .fixed,'
  217. + ' .ui.visible.' + direction + '.sidebar ~ .pusher {'
  218. + ' -webkit-transform: translate3d(0, ' + distance[direction] + 'px, 0);'
  219. + ' transform: translate3d(0, ' + distance[direction] + 'px, 0);'
  220. + ' }'
  221. ;
  222. }
  223. /* IE is only browser not to create context with transforms */
  224. /* https://www.w3.org/Bugs/Public/show_bug.cgi?id=16328 */
  225. if( module.is.ie() ) {
  226. if(direction === 'left' || direction === 'right') {
  227. module.debug('Adding CSS rules for animation distance', width);
  228. style += ''
  229. + ' body.pushable > .ui.visible.' + direction + '.sidebar ~ .pusher:after {'
  230. + ' -webkit-transform: translate3d('+ distance[direction] + 'px, 0, 0);'
  231. + ' transform: translate3d('+ distance[direction] + 'px, 0, 0);'
  232. + ' }'
  233. ;
  234. }
  235. else if(direction === 'top' || direction == 'bottom') {
  236. style += ''
  237. + ' body.pushable > .ui.visible.' + direction + '.sidebar ~ .pusher:after {'
  238. + ' -webkit-transform: translate3d(0, ' + distance[direction] + 'px, 0);'
  239. + ' transform: translate3d(0, ' + distance[direction] + 'px, 0);'
  240. + ' }'
  241. ;
  242. }
  243. /* opposite sides visible forces content overlay */
  244. style += ''
  245. + ' body.pushable > .ui.visible.left.sidebar ~ .ui.visible.right.sidebar ~ .pusher:after,'
  246. + ' body.pushable > .ui.visible.right.sidebar ~ .ui.visible.left.sidebar ~ .pusher:after {'
  247. + ' -webkit-transform: translate3d(0, 0, 0);'
  248. + ' transform: translate3d(0, 0, 0);'
  249. + ' }'
  250. ;
  251. }
  252. style += '</style>';
  253. $style = $(style)
  254. .appendTo($head)
  255. ;
  256. module.debug('Adding sizing css to head', $style);
  257. }
  258. },
  259. refresh: function() {
  260. module.verbose('Refreshing selector cache');
  261. $context = $(settings.context);
  262. $sidebars = $context.children(selector.sidebar);
  263. $pusher = $context.children(selector.pusher);
  264. $fixed = $context.children(selector.fixed);
  265. module.clear.cache();
  266. },
  267. refreshSidebars: function() {
  268. module.verbose('Refreshing other sidebars');
  269. $sidebars = $context.children(selector.sidebar);
  270. },
  271. repaint: function() {
  272. module.verbose('Forcing repaint event');
  273. element.style.display = 'none';
  274. var ignored = element.offsetHeight;
  275. element.scrollTop = element.scrollTop;
  276. element.style.display = '';
  277. },
  278. setup: {
  279. cache: function() {
  280. module.cache = {
  281. width : $module.outerWidth(),
  282. height : $module.outerHeight()
  283. };
  284. },
  285. layout: function() {
  286. if( $context.children(selector.pusher).length === 0 ) {
  287. module.debug('Adding wrapper element for sidebar');
  288. module.error(error.pusher);
  289. $pusher = $('<div class="pusher" />');
  290. $context
  291. .children()
  292. .not(selector.omitted)
  293. .not($sidebars)
  294. .wrapAll($pusher)
  295. ;
  296. module.refresh();
  297. }
  298. if($module.nextAll(selector.pusher).length === 0 || $module.nextAll(selector.pusher)[0] !== $pusher[0]) {
  299. module.debug('Moved sidebar to correct parent element');
  300. module.error(error.movedSidebar, element);
  301. $module.detach().prependTo($context);
  302. module.refresh();
  303. }
  304. module.clear.cache();
  305. module.set.pushable();
  306. module.set.direction();
  307. }
  308. },
  309. attachEvents: function(selector, event) {
  310. var
  311. $toggle = $(selector)
  312. ;
  313. event = $.isFunction(module[event])
  314. ? module[event]
  315. : module.toggle
  316. ;
  317. if($toggle.length > 0) {
  318. module.debug('Attaching sidebar events to element', selector, event);
  319. $toggle
  320. .on('click' + eventNamespace, event)
  321. ;
  322. }
  323. else {
  324. module.error(error.notFound, selector);
  325. }
  326. },
  327. show: function(callback) {
  328. callback = $.isFunction(callback)
  329. ? callback
  330. : function(){}
  331. ;
  332. if(module.is.hidden()) {
  333. module.refreshSidebars();
  334. if(settings.overlay) {
  335. module.error(error.overlay);
  336. settings.transition = 'overlay';
  337. }
  338. module.refresh();
  339. if(module.othersActive()) {
  340. module.debug('Other sidebars currently visible');
  341. if(settings.exclusive) {
  342. // if not overlay queue animation after hide
  343. if(settings.transition != 'overlay') {
  344. module.hideOthers(module.show);
  345. return;
  346. }
  347. else {
  348. module.hideOthers();
  349. }
  350. }
  351. else {
  352. settings.transition = 'overlay';
  353. }
  354. }
  355. module.pushPage(function() {
  356. callback.call(element);
  357. settings.onShow.call(element);
  358. });
  359. settings.onChange.call(element);
  360. settings.onVisible.call(element);
  361. }
  362. else {
  363. module.debug('Sidebar is already visible');
  364. }
  365. },
  366. hide: function(callback) {
  367. callback = $.isFunction(callback)
  368. ? callback
  369. : function(){}
  370. ;
  371. if(module.is.visible() || module.is.animating()) {
  372. module.debug('Hiding sidebar', callback);
  373. module.refreshSidebars();
  374. module.pullPage(function() {
  375. callback.call(element);
  376. settings.onHidden.call(element);
  377. });
  378. settings.onChange.call(element);
  379. settings.onHide.call(element);
  380. }
  381. },
  382. othersAnimating: function() {
  383. return ($sidebars.not($module).filter('.' + className.animating).length > 0);
  384. },
  385. othersVisible: function() {
  386. return ($sidebars.not($module).filter('.' + className.visible).length > 0);
  387. },
  388. othersActive: function() {
  389. return(module.othersVisible() || module.othersAnimating());
  390. },
  391. hideOthers: function(callback) {
  392. var
  393. $otherSidebars = $sidebars.not($module).filter('.' + className.visible),
  394. sidebarCount = $otherSidebars.length,
  395. callbackCount = 0
  396. ;
  397. callback = callback || function(){};
  398. $otherSidebars
  399. .sidebar('hide', function() {
  400. callbackCount++;
  401. if(callbackCount == sidebarCount) {
  402. callback();
  403. }
  404. })
  405. ;
  406. },
  407. toggle: function() {
  408. module.verbose('Determining toggled direction');
  409. if(module.is.hidden()) {
  410. module.show();
  411. }
  412. else {
  413. module.hide();
  414. }
  415. },
  416. pushPage: function(callback) {
  417. var
  418. transition = module.get.transition(),
  419. $transition = (transition === 'overlay' || module.othersActive())
  420. ? $module
  421. : $pusher,
  422. animate,
  423. dim,
  424. transitionEnd
  425. ;
  426. callback = $.isFunction(callback)
  427. ? callback
  428. : function(){}
  429. ;
  430. if(settings.transition == 'scale down') {
  431. module.scrollToTop();
  432. }
  433. module.set.transition(transition);
  434. module.repaint();
  435. animate = function() {
  436. module.bind.clickaway();
  437. module.add.inlineCSS();
  438. module.set.animating();
  439. module.set.visible();
  440. };
  441. dim = function() {
  442. module.set.dimmed();
  443. };
  444. transitionEnd = function(event) {
  445. if( event.target == $transition[0] ) {
  446. $transition.off(transitionEvent + elementNamespace, transitionEnd);
  447. module.remove.animating();
  448. module.bind.scrollLock();
  449. callback.call(element);
  450. }
  451. };
  452. $transition.off(transitionEvent + elementNamespace);
  453. $transition.on(transitionEvent + elementNamespace, transitionEnd);
  454. requestAnimationFrame(animate);
  455. if(settings.dimPage && !module.othersVisible()) {
  456. requestAnimationFrame(dim);
  457. }
  458. },
  459. pullPage: function(callback) {
  460. var
  461. transition = module.get.transition(),
  462. $transition = (transition == 'overlay' || module.othersActive())
  463. ? $module
  464. : $pusher,
  465. animate,
  466. transitionEnd
  467. ;
  468. callback = $.isFunction(callback)
  469. ? callback
  470. : function(){}
  471. ;
  472. module.verbose('Removing context push state', module.get.direction());
  473. module.unbind.clickaway();
  474. module.unbind.scrollLock();
  475. animate = function() {
  476. module.set.transition(transition);
  477. module.set.animating();
  478. module.remove.visible();
  479. if(settings.dimPage && !module.othersVisible()) {
  480. $pusher.removeClass(className.dimmed);
  481. }
  482. };
  483. transitionEnd = function(event) {
  484. if( event.target == $transition[0] ) {
  485. $transition.off(transitionEvent + elementNamespace, transitionEnd);
  486. module.remove.animating();
  487. module.remove.transition();
  488. module.remove.inlineCSS();
  489. if(transition == 'scale down' || (settings.returnScroll && module.is.mobile()) ) {
  490. module.scrollBack();
  491. }
  492. callback.call(element);
  493. }
  494. };
  495. $transition.off(transitionEvent + elementNamespace);
  496. $transition.on(transitionEvent + elementNamespace, transitionEnd);
  497. requestAnimationFrame(animate);
  498. },
  499. scrollToTop: function() {
  500. module.verbose('Scrolling to top of page to avoid animation issues');
  501. currentScroll = $(window).scrollTop();
  502. $module.scrollTop(0);
  503. window.scrollTo(0, 0);
  504. },
  505. scrollBack: function() {
  506. module.verbose('Scrolling back to original page position');
  507. window.scrollTo(0, currentScroll);
  508. },
  509. clear: {
  510. cache: function() {
  511. module.verbose('Clearing cached dimensions');
  512. module.cache = {};
  513. }
  514. },
  515. set: {
  516. // ios only (scroll on html not document). This prevent auto-resize canvas/scroll in ios
  517. // (This is no longer necessary in latest iOS)
  518. ios: function() {
  519. $html.addClass(className.ios);
  520. },
  521. // container
  522. pushed: function() {
  523. $context.addClass(className.pushed);
  524. },
  525. pushable: function() {
  526. $context.addClass(className.pushable);
  527. },
  528. // pusher
  529. dimmed: function() {
  530. $pusher.addClass(className.dimmed);
  531. },
  532. // sidebar
  533. active: function() {
  534. $module.addClass(className.active);
  535. },
  536. animating: function() {
  537. $module.addClass(className.animating);
  538. },
  539. transition: function(transition) {
  540. transition = transition || module.get.transition();
  541. $module.addClass(transition);
  542. },
  543. direction: function(direction) {
  544. direction = direction || module.get.direction();
  545. $module.addClass(className[direction]);
  546. },
  547. visible: function() {
  548. $module.addClass(className.visible);
  549. },
  550. overlay: function() {
  551. $module.addClass(className.overlay);
  552. }
  553. },
  554. remove: {
  555. inlineCSS: function() {
  556. module.debug('Removing inline css styles', $style);
  557. if($style && $style.length > 0) {
  558. $style.remove();
  559. }
  560. },
  561. // ios scroll on html not document
  562. ios: function() {
  563. $html.removeClass(className.ios);
  564. },
  565. // context
  566. pushed: function() {
  567. $context.removeClass(className.pushed);
  568. },
  569. pushable: function() {
  570. $context.removeClass(className.pushable);
  571. },
  572. // sidebar
  573. active: function() {
  574. $module.removeClass(className.active);
  575. },
  576. animating: function() {
  577. $module.removeClass(className.animating);
  578. },
  579. transition: function(transition) {
  580. transition = transition || module.get.transition();
  581. $module.removeClass(transition);
  582. },
  583. direction: function(direction) {
  584. direction = direction || module.get.direction();
  585. $module.removeClass(className[direction]);
  586. },
  587. visible: function() {
  588. $module.removeClass(className.visible);
  589. },
  590. overlay: function() {
  591. $module.removeClass(className.overlay);
  592. }
  593. },
  594. get: {
  595. direction: function() {
  596. if($module.hasClass(className.top)) {
  597. return className.top;
  598. }
  599. else if($module.hasClass(className.right)) {
  600. return className.right;
  601. }
  602. else if($module.hasClass(className.bottom)) {
  603. return className.bottom;
  604. }
  605. return className.left;
  606. },
  607. transition: function() {
  608. var
  609. direction = module.get.direction(),
  610. transition
  611. ;
  612. transition = ( module.is.mobile() )
  613. ? (settings.mobileTransition == 'auto')
  614. ? settings.defaultTransition.mobile[direction]
  615. : settings.mobileTransition
  616. : (settings.transition == 'auto')
  617. ? settings.defaultTransition.computer[direction]
  618. : settings.transition
  619. ;
  620. module.verbose('Determined transition', transition);
  621. return transition;
  622. },
  623. transitionEvent: function() {
  624. var
  625. element = document.createElement('element'),
  626. transitions = {
  627. 'transition' :'transitionend',
  628. 'OTransition' :'oTransitionEnd',
  629. 'MozTransition' :'transitionend',
  630. 'WebkitTransition' :'webkitTransitionEnd'
  631. },
  632. transition
  633. ;
  634. for(transition in transitions){
  635. if( element.style[transition] !== undefined ){
  636. return transitions[transition];
  637. }
  638. }
  639. }
  640. },
  641. is: {
  642. ie: function() {
  643. var
  644. isIE11 = (!(window.ActiveXObject) && 'ActiveXObject' in window),
  645. isIE = ('ActiveXObject' in window)
  646. ;
  647. return (isIE11 || isIE);
  648. },
  649. ios: function() {
  650. var
  651. userAgent = navigator.userAgent,
  652. isIOS = userAgent.match(regExp.ios),
  653. isMobileChrome = userAgent.match(regExp.mobileChrome)
  654. ;
  655. if(isIOS && !isMobileChrome) {
  656. module.verbose('Browser was found to be iOS', userAgent);
  657. return true;
  658. }
  659. else {
  660. return false;
  661. }
  662. },
  663. mobile: function() {
  664. var
  665. userAgent = navigator.userAgent,
  666. isMobile = userAgent.match(regExp.mobile)
  667. ;
  668. if(isMobile) {
  669. module.verbose('Browser was found to be mobile', userAgent);
  670. return true;
  671. }
  672. else {
  673. module.verbose('Browser is not mobile, using regular transition', userAgent);
  674. return false;
  675. }
  676. },
  677. hidden: function() {
  678. return !module.is.visible();
  679. },
  680. visible: function() {
  681. return $module.hasClass(className.visible);
  682. },
  683. // alias
  684. open: function() {
  685. return module.is.visible();
  686. },
  687. closed: function() {
  688. return module.is.hidden();
  689. },
  690. vertical: function() {
  691. return $module.hasClass(className.top);
  692. },
  693. animating: function() {
  694. return $context.hasClass(className.animating);
  695. },
  696. rtl: function () {
  697. if(module.cache.rtl === undefined) {
  698. module.cache.rtl = $module.attr('dir') === 'rtl' || $module.css('direction') === 'rtl';
  699. }
  700. return module.cache.rtl;
  701. }
  702. },
  703. setting: function(name, value) {
  704. module.debug('Changing setting', name, value);
  705. if( $.isPlainObject(name) ) {
  706. $.extend(true, settings, name);
  707. }
  708. else if(value !== undefined) {
  709. if($.isPlainObject(settings[name])) {
  710. $.extend(true, settings[name], value);
  711. }
  712. else {
  713. settings[name] = value;
  714. }
  715. }
  716. else {
  717. return settings[name];
  718. }
  719. },
  720. internal: function(name, value) {
  721. if( $.isPlainObject(name) ) {
  722. $.extend(true, module, name);
  723. }
  724. else if(value !== undefined) {
  725. module[name] = value;
  726. }
  727. else {
  728. return module[name];
  729. }
  730. },
  731. debug: function() {
  732. if(!settings.silent && settings.debug) {
  733. if(settings.performance) {
  734. module.performance.log(arguments);
  735. }
  736. else {
  737. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  738. module.debug.apply(console, arguments);
  739. }
  740. }
  741. },
  742. verbose: function() {
  743. if(!settings.silent && settings.verbose && settings.debug) {
  744. if(settings.performance) {
  745. module.performance.log(arguments);
  746. }
  747. else {
  748. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  749. module.verbose.apply(console, arguments);
  750. }
  751. }
  752. },
  753. error: function() {
  754. if(!settings.silent) {
  755. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  756. module.error.apply(console, arguments);
  757. }
  758. },
  759. performance: {
  760. log: function(message) {
  761. var
  762. currentTime,
  763. executionTime,
  764. previousTime
  765. ;
  766. if(settings.performance) {
  767. currentTime = new Date().getTime();
  768. previousTime = time || currentTime;
  769. executionTime = currentTime - previousTime;
  770. time = currentTime;
  771. performance.push({
  772. 'Name' : message[0],
  773. 'Arguments' : [].slice.call(message, 1) || '',
  774. 'Element' : element,
  775. 'Execution Time' : executionTime
  776. });
  777. }
  778. clearTimeout(module.performance.timer);
  779. module.performance.timer = setTimeout(module.performance.display, 500);
  780. },
  781. display: function() {
  782. var
  783. title = settings.name + ':',
  784. totalTime = 0
  785. ;
  786. time = false;
  787. clearTimeout(module.performance.timer);
  788. $.each(performance, function(index, data) {
  789. totalTime += data['Execution Time'];
  790. });
  791. title += ' ' + totalTime + 'ms';
  792. if(moduleSelector) {
  793. title += ' \'' + moduleSelector + '\'';
  794. }
  795. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  796. console.groupCollapsed(title);
  797. if(console.table) {
  798. console.table(performance);
  799. }
  800. else {
  801. $.each(performance, function(index, data) {
  802. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  803. });
  804. }
  805. console.groupEnd();
  806. }
  807. performance = [];
  808. }
  809. },
  810. invoke: function(query, passedArguments, context) {
  811. var
  812. object = instance,
  813. maxDepth,
  814. found,
  815. response
  816. ;
  817. passedArguments = passedArguments || queryArguments;
  818. context = element || context;
  819. if(typeof query == 'string' && object !== undefined) {
  820. query = query.split(/[\. ]/);
  821. maxDepth = query.length - 1;
  822. $.each(query, function(depth, value) {
  823. var camelCaseValue = (depth != maxDepth)
  824. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  825. : query
  826. ;
  827. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  828. object = object[camelCaseValue];
  829. }
  830. else if( object[camelCaseValue] !== undefined ) {
  831. found = object[camelCaseValue];
  832. return false;
  833. }
  834. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  835. object = object[value];
  836. }
  837. else if( object[value] !== undefined ) {
  838. found = object[value];
  839. return false;
  840. }
  841. else {
  842. module.error(error.method, query);
  843. return false;
  844. }
  845. });
  846. }
  847. if ( $.isFunction( found ) ) {
  848. response = found.apply(context, passedArguments);
  849. }
  850. else if(found !== undefined) {
  851. response = found;
  852. }
  853. if(Array.isArray(returnedValue)) {
  854. returnedValue.push(response);
  855. }
  856. else if(returnedValue !== undefined) {
  857. returnedValue = [returnedValue, response];
  858. }
  859. else if(response !== undefined) {
  860. returnedValue = response;
  861. }
  862. return found;
  863. }
  864. }
  865. ;
  866. if(methodInvoked) {
  867. if(instance === undefined) {
  868. module.initialize();
  869. }
  870. module.invoke(query);
  871. }
  872. else {
  873. if(instance !== undefined) {
  874. module.invoke('destroy');
  875. }
  876. module.initialize();
  877. }
  878. });
  879. return (returnedValue !== undefined)
  880. ? returnedValue
  881. : this
  882. ;
  883. };
  884. $.fn.sidebar.settings = {
  885. name : 'Sidebar',
  886. namespace : 'sidebar',
  887. silent : false,
  888. debug : false,
  889. verbose : false,
  890. performance : true,
  891. transition : 'auto',
  892. mobileTransition : 'auto',
  893. defaultTransition : {
  894. computer: {
  895. left : 'uncover',
  896. right : 'uncover',
  897. top : 'overlay',
  898. bottom : 'overlay'
  899. },
  900. mobile: {
  901. left : 'uncover',
  902. right : 'uncover',
  903. top : 'overlay',
  904. bottom : 'overlay'
  905. }
  906. },
  907. context : 'body',
  908. exclusive : false,
  909. closable : true,
  910. dimPage : true,
  911. scrollLock : false,
  912. returnScroll : false,
  913. delaySetup : false,
  914. duration : 500,
  915. onChange : function(){},
  916. onShow : function(){},
  917. onHide : function(){},
  918. onHidden : function(){},
  919. onVisible : function(){},
  920. className : {
  921. active : 'active',
  922. animating : 'animating',
  923. dimmed : 'dimmed',
  924. ios : 'ios',
  925. pushable : 'pushable',
  926. pushed : 'pushed',
  927. right : 'right',
  928. top : 'top',
  929. left : 'left',
  930. bottom : 'bottom',
  931. visible : 'visible'
  932. },
  933. selector: {
  934. fixed : '.fixed',
  935. omitted : 'script, link, style, .ui.modal, .ui.dimmer, .ui.nag, .ui.fixed',
  936. pusher : '.pusher',
  937. sidebar : '.ui.sidebar'
  938. },
  939. regExp: {
  940. ios : /(iPad|iPhone|iPod)/g,
  941. mobileChrome : /(CriOS)/g,
  942. mobile : /Mobile|iP(hone|od|ad)|Android|BlackBerry|IEMobile|Kindle|NetFront|Silk-Accelerated|(hpw|web)OS|Fennec|Minimo|Opera M(obi|ini)|Blazer|Dolfin|Dolphin|Skyfire|Zune/g
  943. },
  944. error : {
  945. method : 'The method you called is not defined.',
  946. pusher : 'Had to add pusher element. For optimal performance make sure body content is inside a pusher element',
  947. movedSidebar : 'Had to move sidebar. For optimal performance make sure sidebar and pusher are direct children of your body tag',
  948. overlay : 'The overlay setting is no longer supported, use animation: overlay',
  949. notFound : 'There were no elements that matched the specified selector'
  950. }
  951. };
  952. })( jQuery, window, document );