slidebars.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. // -----------------------------------
  2. // Slidebars
  3. // Development version, do not use this in your site, use the latest in the distribution folder.
  4. // http://plugins.adchsm.me/slidebars/
  5. //
  6. // Written by Adam Smith
  7. // http://www.adchsm.me/
  8. //
  9. // Released under MIT License
  10. // http://plugins.adchsm.me/slidebars/license.txt
  11. //
  12. // ---------------------
  13. // Index of Slidebars.js
  14. //
  15. // 001 - Default Settings
  16. // 002 - Feature Detection
  17. // 003 - User Agents
  18. // 004 - Setup
  19. // 005 - Animation
  20. // 006 - Operations
  21. // 007 - API
  22. // 008 - User Input
  23. ;(function($) {
  24. $.slidebars = function(options) {
  25. // ----------------------
  26. // 001 - Default Settings
  27. var settings = $.extend({
  28. siteClose: true, // true or false - Enable closing of Slidebars by clicking on #sb-site.
  29. scrollLock: false, // true or false - Prevent scrolling of site when a Slidebar is open.
  30. disableOver: false, // integer or false - Hide Slidebars over a specific width.
  31. hideControlClasses: false // true or false - Hide controls at same width as disableOver.
  32. }, options);
  33. // -----------------------
  34. // 002 - Feature Detection
  35. var test = document.createElement('div').style, // Create element to test on.
  36. supportTransition = false, // Variable for testing transitions.
  37. supportTransform = false; // variable for testing transforms.
  38. // Test for CSS Transitions
  39. if (test.MozTransition === '' || test.WebkitTransition === '' || test.OTransition === '' || test.transition === '') supportTransition = true;
  40. // Test for CSS Transforms
  41. if (test.MozTransform === '' || test.WebkitTransform === '' || test.OTransform === '' || test.transform === '') supportTransform = true;
  42. // -----------------
  43. // 003 - User Agents
  44. var ua = navigator.userAgent, // Get user agent string.
  45. android = false, // Variable for storing android version.
  46. iOS = false; // Variable for storing iOS version.
  47. if (/Android/.test(ua)) { // Detect Android in user agent string.
  48. android = ua.substr(ua.indexOf('Android')+8, 3); // Set version of Android.
  49. } else if (/(iPhone|iPod|iPad)/.test(ua)) { // Detect iOS in user agent string.
  50. iOS = ua.substr(ua.indexOf('OS ')+3, 3).replace('_', '.'); // Set version of iOS.
  51. }
  52. if (android && android < 3 || iOS && iOS < 5) $('html').addClass('sb-static'); // Add helper class for older versions of Android & iOS.
  53. // -----------
  54. // 004 - Setup
  55. // Site container
  56. var $site = $('#sb-site, .sb-site-container'); // Cache the selector.
  57. // Left Slidebar
  58. if ($('.sb-left').length) { // Check if the left Slidebar exists.
  59. var $left = $('.sb-left'), // Cache the selector.
  60. leftActive = false; // Used to check whether the left Slidebar is open or closed.
  61. }
  62. // Right Slidebar
  63. if ($('.sb-right').length) { // Check if the right Slidebar exists.
  64. var $right = $('.sb-right'), // Cache the selector.
  65. rightActive = false; // Used to check whether the right Slidebar is open or closed.
  66. }
  67. var init = false, // Initialisation variable.
  68. windowWidth = $(window).width(), // Get width of window.
  69. $controls = $('.sb-toggle-left, .sb-toggle-right, .sb-open-left, .sb-open-right, .sb-close'), // Cache the control classes.
  70. $slide = $('.sb-slide'); // Cache users elements to animate.
  71. // Initailise Slidebars
  72. function initialise() {
  73. if (!settings.disableOver || (typeof settings.disableOver === 'number' && settings.disableOver >= windowWidth)) { // False or larger than window size.
  74. init = true; // true enabled Slidebars to open.
  75. $('html').addClass('sb-init'); // Add helper class.
  76. if (settings.hideControlClasses) $controls.removeClass('sb-hide'); // Remove class just incase Slidebars was originally disabled.
  77. css(); // Set required inline styles.
  78. } else if (typeof settings.disableOver === 'number' && settings.disableOver < windowWidth) { // Less than window size.
  79. init = false; // false stop Slidebars from opening.
  80. $('html').removeClass('sb-init'); // Remove helper class.
  81. if (settings.hideControlClasses) $controls.addClass('sb-hide'); // Hide controls
  82. $site.css('minHeight', ''); // Remove minimum height.
  83. if (leftActive || rightActive) close(); // Close Slidebars if open.
  84. }
  85. }
  86. initialise();
  87. // Inline CSS
  88. function css() {
  89. // Set minimum height.
  90. $site.css('minHeight', ''); // Reset minimum height.
  91. $site.css('minHeight', $('html').height() + 'px'); // Set minimum height of the site to the minimum height of the html.
  92. // Custom Slidebar widths.
  93. if ($left && $left.hasClass('sb-width-custom')) $left.css('width', $left.attr('data-sb-width')); // Set user custom width.
  94. if ($right && $right.hasClass('sb-width-custom')) $right.css('width', $right.attr('data-sb-width')); // Set user custom width.
  95. // Set off-canvas margins for Slidebars with push and overlay animations.
  96. if ($left && ($left.hasClass('sb-style-push') || $left.hasClass('sb-style-overlay'))) $left.css('marginLeft', '-' + $left.css('width'));
  97. if ($right && ($right.hasClass('sb-style-push') || $right.hasClass('sb-style-overlay'))) $right.css('marginRight', '-' + $right.css('width'));
  98. // Site scroll locking.
  99. if (settings.scrollLock) $('html').addClass('sb-scroll-lock');
  100. }
  101. // Resize Functions
  102. $(window).resize(function() {
  103. var resizedWindowWidth = $(window).width(); // Get resized window width.
  104. if (windowWidth !== resizedWindowWidth) { // Slidebars is running and window was actually resized.
  105. windowWidth = resizedWindowWidth; // Set the new window width.
  106. initialise(); // Call initalise to see if Slidebars should still be running.
  107. if (leftActive) open('left'); // If left Slidebar is open, calling open will ensure it is the correct size.
  108. if (rightActive) open('right'); // If right Slidebar is open, calling open will ensure it is the correct size.
  109. }
  110. });
  111. // I may include a height check along side a width check here in future.
  112. // ---------------
  113. // 005 - Animation
  114. var animation; // Animation type.
  115. // Set animation type.
  116. if (supportTransition && supportTransform) { // Browser supports css transitions and transforms.
  117. animation = 'translate'; // Translate for browsers that support it.
  118. if (android && android < 4.4) animation = 'side'; // Android supports both, but can't translate any fixed positions, so use left instead.
  119. } else {
  120. animation = 'jQuery'; // Browsers that don't support css transitions and transitions.
  121. }
  122. // Animate mixin.
  123. function animate(object, amount, side) {
  124. // Choose selectors depending on animation style.
  125. var selector;
  126. if (object.hasClass('sb-style-push')) {
  127. selector = $site.add(object).add($slide); // Push - Animate site, Slidebar and user elements.
  128. } else if (object.hasClass('sb-style-overlay')) {
  129. selector = object; // Overlay - Animate Slidebar only.
  130. } else {
  131. selector = $site.add($slide); // Reveal - Animate site and user elements.
  132. }
  133. // Apply animation
  134. if (animation === 'translate') {
  135. selector.css('transform', 'translate(' + amount + ')'); // Apply the animation.
  136. } else if (animation === 'side') {
  137. if (amount[0] === '-') amount = amount.substr(1); // Remove the '-' from the passed amount for side animations.
  138. if (amount !== '0px') selector.css(side, '0px'); // Add a 0 value so css transition works.
  139. setTimeout(function() { // Set a timeout to allow the 0 value to be applied above.
  140. selector.css(side, amount); // Apply the animation.
  141. }, 1);
  142. } else if (animation === 'jQuery') {
  143. if (amount[0] === '-') amount = amount.substr(1); // Remove the '-' from the passed amount for jQuery animations.
  144. var properties = {};
  145. properties[side] = amount;
  146. selector.stop().animate(properties, 400); // Stop any current jQuery animation before starting another.
  147. }
  148. // If closed, remove the inline styling on completion of the animation.
  149. setTimeout(function() {
  150. if (amount === '0px') {
  151. selector.removeAttr('style');
  152. css();
  153. }
  154. }, 400);
  155. }
  156. // ----------------
  157. // 006 - Operations
  158. // Open a Slidebar
  159. function open(side, callback) {
  160. // Check to see if opposite Slidebar is open.
  161. if (side === 'left' && $left && rightActive || side === 'right' && $right && leftActive) { // It's open, close it, then continue.
  162. close();
  163. setTimeout(proceed, 400);
  164. } else { // Its not open, continue.
  165. proceed();
  166. }
  167. // Open
  168. function proceed() {
  169. if (init && side === 'left' && $left) { // Slidebars is initiated, left is in use and called to open.
  170. $('html').addClass('sb-active sb-active-left'); // Add active classes.
  171. $left.addClass('sb-active');
  172. animate($left, $left.css('width'), 'left'); // Animation
  173. setTimeout(function() {
  174. leftActive = true;
  175. if (typeof callback === 'function') callback(); // Run callback function.
  176. }, 400); // Set active variables.
  177. } else if (init && side === 'right' && $right) { // Slidebars is initiated, right is in use and called to open.
  178. $('html').addClass('sb-active sb-active-right'); // Add active classes.
  179. $right.addClass('sb-active');
  180. animate($right, '-' + $right.css('width'), 'right'); // Animation
  181. setTimeout(function() {
  182. rightActive = true;
  183. if (typeof callback === 'function') callback(); // Run callback function.
  184. }, 400); // Set active variables.
  185. }
  186. }
  187. }
  188. // Close either Slidebar
  189. function close(callback) {
  190. if (leftActive || rightActive) { // If a Slidebar is open.
  191. if (leftActive) {
  192. animate($left, '0px', 'left'); // Animation
  193. leftActive = false;
  194. }
  195. if (rightActive) {
  196. animate($right, '0px', 'right'); // Animation
  197. rightActive = false;
  198. }
  199. setTimeout(function() { // Wait for closing animation to finish.
  200. $('html').removeClass('sb-active sb-active-left sb-active-right'); // Remove active classes.
  201. if ($left) $left.removeClass('sb-active');
  202. if ($right) $right.removeClass('sb-active');
  203. if (typeof callback === 'function') callback(); // Run callback function.
  204. }, 400);
  205. }
  206. }
  207. // Toggle either Slidebar
  208. function toggle(side, callback) {
  209. if (side === 'left' && $left) { // If left Slidebar is called and in use.
  210. if (!leftActive) {
  211. open('left', callback); // Slidebar is closed, open it.
  212. } else {
  213. close(null, callback); // Slidebar is open, close it.
  214. }
  215. }
  216. if (side === 'right' && $right) { // If right Slidebar is called and in use.
  217. if (!rightActive) {
  218. open('right', callback); // Slidebar is closed, open it.
  219. } else {
  220. close(null, callback); // Slidebar is open, close it.
  221. }
  222. }
  223. }
  224. // ---------
  225. // 007 - API
  226. this.slidebars = {
  227. open: open, // Maps user variable name to the open method.
  228. close: close, // Maps user variable name to the close method.
  229. toggle: toggle, // Maps user variable name to the toggle method.
  230. init: function() { // Returns true or false whether Slidebars are running or not.
  231. return init; // Returns true or false whether Slidebars are running.
  232. },
  233. reInit: initialise, // Run the init method to check if the plugin should still be running.
  234. resetCSS: css, // Reset inline
  235. active: function(side) { // Returns true or false whether Slidebar is open or closed.
  236. if (side === 'left' && $left) return leftActive;
  237. if (side === 'right' && $right) return rightActive;
  238. },
  239. destroy: function(side) { // Removes the Slidebar from the DOM.
  240. if (side === 'left' && $left) {
  241. if (leftActive) close(); // Close if its open.
  242. setTimeout(function() {
  243. $left.remove(); // Remove it.
  244. $left = false; // Set variable to false so it cannot be opened again.
  245. }, 400);
  246. }
  247. if (side === 'right' && $right) {
  248. if (rightActive) close(); // Close if its open.
  249. setTimeout(function() {
  250. $right.remove(); // Remove it.
  251. $right = false; // Set variable to false so it cannot be opened again.
  252. }, 400);
  253. }
  254. }
  255. };
  256. // ----------------
  257. // 008 - User Input
  258. function eventHandler(event, selector) {
  259. event.stopPropagation(); // Stop event bubbling.
  260. event.preventDefault(); // Prevent default behaviour.
  261. if (event.type === 'touchend') selector.off('click'); // If event type was touch, turn off clicks to prevent phantom clicks.
  262. }
  263. // Toggle left Slidebar
  264. $('.sb-toggle-left').on('touchend click', function(event) {
  265. eventHandler(event, $(this)); // Handle the event.
  266. toggle('left'); // Toggle the left Slidbar.
  267. });
  268. // Toggle right Slidebar
  269. $('.sb-toggle-right').on('touchend click', function(event) {
  270. eventHandler(event, $(this)); // Handle the event.
  271. toggle('right'); // Toggle the right Slidbar.
  272. });
  273. // Open left Slidebar
  274. $('.sb-open-left').on('touchend click', function(event) {
  275. eventHandler(event, $(this)); // Handle the event.
  276. open('left'); // Open the left Slidebar.
  277. });
  278. // Open right Slidebar
  279. $('.sb-open-right').on('touchend click', function(event) {
  280. eventHandler(event, $(this)); // Handle the event.
  281. open('right'); // Open the right Slidebar.
  282. });
  283. // Close Slidebar
  284. $('.sb-close').on('touchend click', function(event) {
  285. if ( $(this).is('a') || $(this).children().is('a') ) { // Is a link or contains a link.
  286. if ( event.type === 'click' ) { // Make sure the user wanted to follow the link.
  287. event.preventDefault(); // Stop default behaviour.
  288. var href = ( $(this).is('a') ? $(this).attr('href') : $(this).find('a').attr('href') ); // Get the href.
  289. close(function() { // Close Slidebar and pass callback to redirect.
  290. window.location = href;
  291. });
  292. }
  293. } else { // Just a normal control class.
  294. eventHandler(event, $(this)); // Handle the event.
  295. close(); // Close Slidebar.
  296. }
  297. });
  298. // Close Slidebar via site
  299. $site.on('touchend click', function(event) {
  300. if (settings.siteClose && (leftActive || rightActive)) { // If settings permit closing by site and left or right Slidebar is open.
  301. eventHandler(event, $(this)); // Handle the event.
  302. close(); // Close it.
  303. }
  304. });
  305. }; // End Slidebars function.
  306. }) (jQuery);