1'use strict'; 2 3var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 4 5function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 6 7// TODO: make this library agnostic 8// TODO: document the events 9 10(function ($) { 11 12 var PLUGIN_NAME = 'slideMenu'; 13 var DEFAULT_OPTIONS = { 14 position: 'right', 15 showBackLink: true, 16 keycodeOpen: null, 17 keycodeClose: 27, //esc 18 submenuLinkBefore: '', 19 submenuLinkAfter: '', 20 backLinkBefore: '', 21 backLinkAfter: '' 22 }; 23 24 var SlideMenu = function () { 25 function SlideMenu(options) { 26 _classCallCheck(this, SlideMenu); 27 28 this.options = options; 29 30 this._menu = options.elem; 31 32 // Add wrapper 33 this._menu.find('ul:first').wrap('<div class="slider">'); 34 35 this._anchors = this._menu.find('a'); 36 this._slider = this._menu.find('.slider:first'); 37 38 this._level = 0; 39 this._isOpen = false; 40 this._isAnimating = false; 41 this._hasMenu = this._anchors.length > 0; 42 this._lastAction = null; 43 44 this._setupEventHandlers(); 45 this._setupMenu(); 46 47 if (this._hasMenu) this._setupSubmenus(); 48 } 49 50 /** 51 * Toggle the menu 52 * @param {boolean|null} open 53 * @param {boolean} animate 54 */ 55 56 57 _createClass(SlideMenu, [{ 58 key: 'toggle', 59 value: function toggle() { 60 var open = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; 61 var animate = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; 62 63 var offset = void 0; 64 65 if (open === null) { 66 if (this._isOpen) { 67 this.close(); 68 } else { 69 this.open(); 70 } 71 return; 72 } else if (open) { 73 offset = 0; 74 this._isOpen = true; 75 } else { 76 offset = this.options.position === 'left' ? '-100%' : '100%'; 77 this._isOpen = false; 78 } 79 80 this._triggerEvent(); 81 82 if (animate) this._triggerAnimation(this._menu, offset);else { 83 this._pauseAnimations(this._triggerAnimation.bind(this, this._menu, offset)); 84 this._isAnimating = false; 85 } 86 } 87 88 /** 89 * Open the menu 90 * @param {boolean} animate Use CSS transitions 91 */ 92 93 }, { 94 key: 'open', 95 value: function open() { 96 var animate = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; 97 98 this._lastAction = 'open'; 99 this.toggle(true, animate); 100 } 101 102 /** 103 * Close the menu 104 * @param {boolean} animate Use CSS transitions 105 */ 106 107 }, { 108 key: 'close', 109 value: function close() { 110 var animate = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; 111 112 this._lastAction = 'close'; 113 this.toggle(false, animate); 114 } 115 116 /** 117 * Navigate one menu hierarchy back if possible 118 */ 119 120 }, { 121 key: 'back', 122 value: function back() { 123 this._lastAction = 'back'; 124 this._navigate(null, -1); 125 } 126 127 /** 128 * Navigate to a specific link on any level (useful to open the correct hierarchy directly) 129 * @param {string|object}
129 target A string selector a plain DOM object or a jQuery instance 130 */ 131 132 }, { 133 key: 'navigateTo', 134 value: function navigateTo(target) { 135 var _this = this; 136 137 target = this._menu.find($(target)).first(); 138 139 if (!target.length) return false; 140 141 var parents = target.parents('ul'); 142 var level = parents.length - 1; 143 144 if (level === 0) return false; 145 146 this._pauseAnimations(function () { 147 _this._level = level; 148 parents.show().first().addClass('active'); 149 _this._triggerAnimation(_this._slider, -_this._level * 100); 150 }); 151 } 152 153 /** 154 * Set up all event handlers 155 * @private 156 */ 157 158 }, { 159 key: '_setupEventHandlers', 160 value: function _setupEventHandlers() { 161 var _this2 = this; 162 163 if (this._hasMenu) { 164 this._anchors.click(function (event) { 165 var anchor = $(event.target).is('a') ? $(event.target) : $(event.target).parents('a:first'); 166 _this2._navigate(anchor); 167 }); 168 } 169 170 $(this._menu.add(this._slider)).on('transitionend msTransitionEnd', function () { 171 _this2._isAnimating = false; 172 _this2._triggerEvent(true); 173 }); 174 175 $(document).keydown(function (e) { 176 switch (e.which) { 177 case _this2.options.keycodeClose: 178 _this2.close(); 179 break; 180 181 case _this2.options.keycodeOpen: 182 _this2.open(); 183 break; 184 185 default: 186 return; 187 } 188 e.preventDefault(); 189 }); 190 191 this._menu.on('sm.back-after', function () { 192 var lastActiveUl = 'ul ' + '.active '.repeat(_this2._level + 1); 193 _this2._menu.find(lastActiveUl).removeClass('active').hide(); 194 }); 195 } 196 197 /** 198 * Trigger a custom event to support callbacks 199 * @param {boolean} afterAnimation Mark this event as `before` or `after` callback 200 * @private 201 */ 202 203 }, { 204 key: '_triggerEvent', 205 value: function _triggerEvent() { 206 var afterAnimation = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; 207 208 var eventName = 'sm.' + this._lastAction; 209 if (afterAnimation) eventName += '-after'; 210 this._menu.trigger(eventName); 211 } 212 213 /** 214 * Navigate the _menu - that is slide it one step left or right 215 * @param {jQuery} anchor The clicked anchor or button element 216 * @param {int} dir Navigation direction: 1 = forward, 0 = backwards 217 * @private 218 */ 219 220 }, { 221 key: '_navigate', 222 value: function _navigate(anchor) { 223 var dir = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1; 224 225 // Abort if an animation is still running 226 if (this._isAnimating) { 227 return; 228 } 229 230 var offset = (this._level + dir) * -100; 231 232 if (dir > 0) { 233 if (!anchor.next('ul').length) return; 234 235 anchor.next('ul').addClass('active').show(); 236 } else if (this._level === 0) { 237 return; 238 } 239 240 this._lastAction = dir > 0 ? 'forward' : 'back'; 241 this._level = this._level + dir; 242 243 this._triggerAnimation(this._slider, offset); 244 } 245 246 /** 247 * Start the animation (the CSS transition) 248 * @param elem 249 * @param offset 250 * @private 251 */ 252 253 }, { 254 key: '_triggerAnimation', 255 value: function _triggerAnimation(elem, offset) { 256 this._triggerEvent(); 257 258 if (!(String(offset).indexOf('%') !== -1)) offset += '%'; 259 260 elem.css('transform', 'translateX(' + offset + ')'); 261 this._isAnimating = true; 262 } 263 264 /** 265 * Initialize the menu 266 * @private 267 */ 268 269 }, { 270 key: '_setupMenu', 271 value: function _setupMenu() { 272 var _this3 = this; 273 274 this._pauseAnimations(function () { 275 switch (_this3.options.position) { 276 case 'left': 277 _this3._menu.css({ 278 left: 0, 279 right: 'auto', 280 transform: 'translateX(-100%)' 281 }); 282 break; 283 default: 284 _this3._menu.css({ 285 left: 'auto', 286 right: 0 287 }); 288 break; 289 } 290 _this3._menu.show(); 291 }); 292 } 293 294 /** 295 * Pause the CSS transitions, to apply CSS changes directly without an animation 296 * @param work 297 * @private 298 */ 299 300 }, { 301 key: '_pauseAnimations', 302 value: function _pauseAnimations(work) { 303 this._menu.addClass('no-transition'); 304 work(); 305 this._menu[0].offsetHeight; // trigger a reflow, flushing the CSS changes 306 this._menu.removeClass('no-transition'); 307 } 308 309 /** 310 * Enhance the markup of menu items which contain a submenu 311 * @private 312 */ 313 314 }, { 315 key: '_setupSubmenus', 316 value: function _setupSubmenus() { 317 var _this4 = this; 318 319 this._anchors.each(function (i, anchor) { 320 anchor = $(anchor); 321 if (anchor.next('ul').length) { 322 // prevent default behaviour (use link just to navigate) 323 anchor.click(function (ev) { 324 ev.preventDefault(); 325 }); 326 327 // add `before` and `after` text 328 var anchorTitle = anchor.text(); 329 anchor.html(_this4.options.submenuLinkBefore + anchorTitle + _this4.options.submenuLinkAfter); 330 331 // add a back button 332 if (_this4.options.showBackLink) { 333 var backLink = $('<a href class="slide-menu-control" data-action="back">' + anchorTitle + '</a>'); 334 backLink.html(_this4.options.backLinkBefore + backLink.text() + _this4.options.backLinkAfter);
335 anchor.next('ul').prepend($('<li>').append(backLink)); 336 } 337 } 338 }); 339 } 340 }]); 341 342 return SlideMenu; 343 }(); 344 345 // Link control buttons with the API 346 347 348 $('body').on('click', '.slide-menu-control', function (e) { 349 var menu = void 0; 350 var target = $(this).data('target'); 351 352 if (!target || target === 'this') { 353 menu = $(this).parents('.slide-menu:first'); 354 } else { 355 menu = $('#' + target); 356 } 357 358 if (!menu.length) return; 359 360 var instance = menu.data(PLUGIN_NAME); 361 var action = $(this).data('action'); 362 363 if (instance && typeof instance[action] === 'function') { 364 instance[action](); 365 } 366 367 return false; 368 }); 369 370 // Register the jQuery plugin 371 $.fn[PLUGIN_NAME] = function (options) { 372 if (!$(this).length) { 373 console.warn('Slide Menu: Unable to find menu DOM element. Maybe a typo?'); 374 return; 375 } 376 377 options = $.extend({}, DEFAULT_OPTIONS, options); 378 options.elem = $(this); 379 380 var instance = new SlideMenu(options); 381 $(this).data(PLUGIN_NAME, instance); 382 383 return instance; 384 }; 385})(jQuery); 386//# sourceMappingURL=slide-menu.js.map
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.