PageSourceSearch

https://orders.baseclear.com/static/js/jquery.slicknav.js

js baseclear.com collected 2026-10-03 19:02:36 UTC 15,935 bytes, 417 lines download raw bytes

1/*!
2    SlickNav Responsive Mobile Menu
3    (c) 2014 Josh Cope
4    licensed under MIT
5*/
6;(function ($, document, window) {
7    var
8    // default settings object.
9    defaults = {
10        label: '',
11        duplicate: true,
12        duration: 100,
13        easingOpen: 'swing',
14        easingClose: 'swing',
15        closedSymbol: '►',
16        openedSymbol: '▼',
17        prependTo: 'body',
18        parentTag: 'a',
19        closeOnClick: false,
20        allowParentLinks: false,
21        nestedParentLinks: true,
22        showChildren: false,
23        init: function(){},
24        open: function(){},
25        close: function(){}
26    },
27    mobileMenu = 'slicknav',
28    prefix = 'slicknav';
29    
30    function Plugin( element, options ) {
31        this.element = element;
32
33        // jQuery has an extend method which merges the contents of two or
34        // more objects, storing the result in the first object. The first object
35        // is generally empty as we don't want to alter the default options for
36        // future instances of the plugin
37        this.settings = $.extend( {}, defaults, options) ;
38        
39        this._defaults = defaults;
40        this._name = mobileMenu;
41        
42        this.init();
43    }
44    
45    Plugin.prototype.init = function () {
46        var $this = this;
47        var menu = $(this.element);
48        var settings = this.settings;
49        
50        // clone menu if needed
51        if (settings.duplicate) {
52            $this.mobileNav = menu.clone();
53            //remove ids from clone to prevent css issues
54            $this.mobileNav.removeAttr('id');
55            $this.mobileNav.find('*').each(function(i,e){
56                $(e).removeAttr('id');
57            });
58        }
59        else
60            $this.mobileNav = menu;
61        
62        // styling class for the button
63        var iconClass = prefix+'_icon';
64        
65        if (settings.label === '') {
66            iconClass += ' '+prefix+'_no-text';
67        }
68        
69        if (settings.parentTag == 'a') {
70            settings.parentTag = 'a href="#"';
71        }
72        
73        // create menu bar
74        $this.mobileNav.attr('class', prefix+'_nav');
75        var menuBar = $('<div class="'+prefix+'_menu"></div>');
76        $this.btn = $('<'+settings.parentTag+' aria-haspopup="true" tabindex="0" class="'+prefix+'_btn '+prefix+'_collapsed"><span class="'+prefix+'_menutxt">'+settings.label+'</span><span class="'+iconClass+'"><span class="'+prefix+'_icon-bar"></span><span class="'+prefix+'_icon-bar"></span><span class="'+prefix+'_icon-bar"></span></span></a>');
77        $(menuBar).append($this.btn);        
78        $(settings.prependTo).prepend(menuBar);
79        menuBar.append($this.mobileNav);
80        
81        // iterate over structure adding additional structure
82        var items = $this.mobileNav.find('li');
83        $(items).each(function () {
84            var item = $(this);
85            var data = {};
86            data.children = item.children('ul').attr('role','menu');
87            item.data("menu", data);
88            
89            // if a list item has a nested menu
90            if (data.children.length > 0) {
91            
92                // select all text before the child menu
93                // check for anchors
94                
95                var a = item.contents();
96                var containsAnchor = false;
97                
98                var nodes = [];
99                $(a).each(function(){
100                    if(!$(this).is("ul")) {
101                        nodes.push(this);
102                    }
103                    else {
104                        return false;
105                    }
106                    
107                    if($(this).is("a")) {
108                        containsAnchor = true;
109                    }
110                });
111                
112                var wrapElement = $('<'+settings.parentTag+' role="menuitem" aria-haspopup="true" tabindex="-1" class="'+prefix+'_item"/>');
113                
114                // wrap item text with tag and add classes unless we are separating parent links
115                if ((!settings.allowParentLinks || settings.nestedParentLinks) || !containsAnchor) {
116                    var $wrap = $(nodes).wrapAll(wrapElement).parent();
117                    $wrap.addClass(prefix+'_row');
118                } else
119                    $(nodes).wrapAll('<span class="'+prefix+'_parent-link '+prefix+'_row"/>').parent();
120                
121                item.addClass(prefix+'_collapsed');
122                item.addClass(prefix+'_parent');
123                
124                // create parent arrow. wrap with link if parent links and separating
125                var arrowElement = $('<span class="'+prefix+'_arrow">'+settings.closedSymbol+'</span>');
126                
vendor: 11,071 bytes, lines 127-417
127                if (settings.allowParentLinks && !settings.nestedParentLinks && containsAnchor)
128                    arrowElement = arrowElement.wrap(wrapElement).parent();
129                
130                //append arrow
131                $(nodes).last().after(arrowElement);
132                
133            
134            } else if ( item.children().length === 0) {
135                 item.addClass(prefix+'_txtnode');
136            }
137            
138            // accessibility for links
139            item.children('a').attr('role', 'menuitem').click(function(event){
140                //Emulate menu close if set
141                //Ensure that it's not a parent
142                if (settings.closeOnClick && !$(event.target).parent().closest('li').hasClass(prefix+'_parent'))
143                    $($this.btn).click();
144            });
145            
146            //also close on click if parent links are set
147            if (settings.closeOnClick && settings.allowParentLinks) {
148                item.children('a').children('a').click(function(event){
149                    //Emulate menu close
150                        $($this.btn).click();
151                });
152                
153                item.find('.'+prefix+'_parent-link a:not(.'+prefix+'_item)').click(function(event){
154                    //Emulate menu close
155                        $($this.btn).click();
156                });
157            }
158        });
159        
160        // structure is in place, now hide appropriate items
161        $(items).each(function () {
162            var data = $(this).data("menu");
163            if (!settings.showChildren){
164                $this._visibilityToggle(data.children, null, false, null, true);
165            }
166        });
167        
168        // finally toggle entire menu
169        $this._visibilityToggle($this.mobileNav, null, false, 'init', true);
170        
171        // accessibility for menu button
172        $this.mobileNav.attr('role','menu');
173        
174        // outline prevention when using mouse
175        $(document).mousedown(function(){
176            $this._outlines(false);
177        });
178        
179        $(document).keyup(function(){
180            $this._outlines(true);
181        });
182        
183        // menu button click
184        $($this.btn).click(function (e) {
185            e.preventDefault();
186            $this._menuToggle();
187        });
188        
189        // click on menu parent
190        $this.mobileNav.on('click', '.'+prefix+'_item', function(e){
191            e.preventDefault();
192            $this._itemClick($(this));
193        });
194        
195        // check for enter key on menu button and menu parents
196        $($this.btn).keydown(function (e) {
197            var ev = e || event;
198            if(ev.keyCode == 13) {
199                e.preventDefault();
200                $this._menuToggle();
201            }
202        });
203        
204        $this.mobileNav.on('keydown', '.'+prefix+'_item', function(e) {
205            var ev = e || event;
206            if(ev.keyCode == 13) {
207                e.preventDefault();
208                $this._itemClick($(e.target));
209            }
210        });
211        
212        // allow links clickable within parent tags if set
213        if (settings.allowParentLinks && settings.nestedParentLinks) {
214            $('.'+prefix+'_item a').click(function(e){
215                    e.stopImmediatePropagation();
216            });
217        }
218    };
219    
220    //toggle menu
221    Plugin.prototype._menuToggle = function(el){
222        var $this = this;
223        var btn = $this.btn;
224        var mobileNav = $this.mobileNav;
225        
226        if (btn.hasClass(prefix+'_collapsed')) {
227            btn.removeClass(prefix+'_collapsed');
228            btn.addClass(prefix+'_open');
229        } else {
230            btn.removeClass(prefix+'_open');
231            btn.addClass(prefix+'_collapsed');
232        }
233        btn.addClass(prefix+'_animating');
234        $this._visibilityToggle(mobileNav, btn.parent(), true, btn);
235    };
236    
237    // toggle clicked items
238    Plugin.prototype._itemClick = function(el) {
239        var $this = this;
240        var settings = $this.settings;
241        var data = el.data("menu");
242        if (!data) {
243            data = {};
244            data.arrow = el.children('.'+prefix+'_arrow');
245            data.ul = el.next('ul');
246            data.parent = el.parent();
247            //Separated parent link structure
248            if (data.parent.hasClass(prefix+'_parent-link')) {
249                data.parent = el.parent().parent();
250                data.ul = el.parent().next('ul');
251            }
252            el.data("menu", data);
253        }
254        if (data.parent.hasClass(prefix+'_collapsed')) {
255            data.arrow.html(settings.openedSymbol);
256            data.parent.removeClass(prefix+'_collapsed');
257            data.parent.addClass(prefix+'_open');
258            data.parent.addClass(prefix+'_animating');
259            $this._visibilityToggle(data.ul, data.parent, true, el);
260        } else {
261            data.arrow.html(settings.closedSymbol);
262            data.parent.addClass(prefix+'_collapsed');
263            data.parent.removeClass(prefix+'_open');
264            data.parent.addClass(prefix+'_animating');
265            $this._visibilityToggle(data.ul, data.parent, true, el);
266        }
267    };
268
269    // toggle actual visibility and accessibility tags
270    Plugin.prototype._visibilityToggle = function(el, parent, animate, trigger, init) {
271        var $this = this;
272        var settings = $this.settings;
273        var items = $this._getActionItems(el);
274        var duration = 0;
275        if (animate)
276            duration = settings.duration;
277        
278        if (el.hasClass(prefix+'_hidden')) {
279            el.removeClass(prefix+'_hidden');
280            el.slideDown(duration, settings.easingOpen, function(){
281                
282                $(trigger).removeClass(prefix+'_animating');
283                $(parent).removeClass(prefix+'_animating');
284                
285                //Fire open callback
286                if (!init) {
287                    settings.open(trigger);
288                }
289            });
290            el.attr('aria-hidden','false');
291            items.attr('tabindex', '0');
292            $this._setVisAttr(el, false);
293        } else {
294            el.addClass(prefix+'_hidden');
295            el.slideUp(duration, this.settings.easingClose, function() {
296                el.attr('aria-hidden','true');
297                items.attr('tabindex', '-1');
298                $this._setVisAttr(el, true);
299                el.hide(); //jQuery 1.7 bug fix
300                
301                $(trigger).removeClass(prefix+'_animating');
302                $(parent).removeClass(prefix+'_animating');
303                
304                //Fire init or close callback
305                if (!init)
306                    settings.close(trigger);
307                else if (trigger == 'init')
308                    settings.init();
309            });
310        }
311    };
312
313    // set attributes of element and children based on visibility
314    Plugin.prototype._setVisAttr = function(el, hidden) {
315        var $this = this;
316        
317        // select all parents that aren't hidden
318        var nonHidden = el.children('li').children('ul').not('.'+prefix+'_hidden');
319        
320        // iterate over all items setting appropriate tags
321        if (!hidden) {
322            nonHidden.each(function(){
323                var ul = $(this);
324                ul.attr('aria-hidden','false');
325                var items = $this._getActionItems(ul);
326                items.attr('tabindex', '0');
327                $this._setVisAttr(ul, hidden);
328            });
329        } else {
330            nonHidden.each(function(){
331                var ul = $(this);
332                ul.attr('aria-hidden','true');
333                var items = $this._getActionItems(ul);
334                items.attr('tabindex', '-1');
335                $this._setVisAttr(ul, hidden);
336            });
337        }
338    };
339
340    // get all 1st level items that are clickable
341    Plugin.prototype._getActionItems = function(el) {
342        var data = el.data("menu");
343        if (!data) {
344            data = {};
345            var items = el.children('li');
346            var anchors = items.find('a');
347            data.links = anchors.add(items.find('.'+prefix+'_item'));
348            el.data("menu", data);
349        }
350        return data.links;
351    };
352
353    Plugin.prototype._outlines = function(state) {
354        if (!state) {
355            $('.'+prefix+'_item, .'+prefix+'_btn').css('outline','none');
356        } else {
357            $('.'+prefix+'_item, .'+prefix+'_btn').css('outline','');
358        }
359    };
360    
361    Plugin.prototype.toggle = function(){
362        var $this = this;
363        $this._menuToggle();
364    };
365    
366    Plugin.prototype.open = function(){
367        var $this = this;
368        if ($this.btn.hasClass(prefix+'_collapsed')) {
369            $this._menuToggle();
370        }
371    };
372    
373    Plugin.prototype.close = function(){
374        var $this = this;
375        if ($this.btn.hasClass(prefix+'_open')) {
376            $this._menuToggle();
377        }
378    };
379    
380    $.fn[mobileMenu] = function ( options ) {
381        var args = arguments;
382
383        // Is the first parameter an object (options), or was omitted, instantiate a new instance
384        if (options === undefined || typeof options === 'object') {
385            return this.each(function () {
386
387                // Only allow the plugin to be instantiated once due to methods
388                if (!$.data(this, 'plugin_' + mobileMenu)) {
389
390                    // if it has no instance, create a new one, pass options to our plugin constructor,
391                    // and store the plugin instance in the elements jQuery data object.
392                    $.data(this, 'plugin_' + mobileMenu, new Plugin( this, options ));
393                }
394            });
395
396        // If is a string and doesn't start with an underscore or 'init' function, treat this as a call to a public method.
397        } else if (typeof options === 'string' && options[0] !== '_' && options !== 'init') {
398
399            // Cache the method call to make it possible to return a value
400            var returns;
401
402            this.each(function () {
403                var instance = $.data(this, 'plugin_' + mobileMenu);
404
405                // Tests that there's already a plugin-instance and checks that the requested public method exists
406                if (instance instanceof Plugin && typeof instance[options] === 'function') {
407
408                    // Call the method of our plugin instance, and pass it the supplied arguments.
409                    returns = instance[options].apply( instance, Array.prototype.slice.call( args, 1 ) );
410                }
411            });
412
413            // If the earlier cached method gives a value back return the value, otherwise return this to preserve chainability.
414            return returns !== undefined ? returns : this;
415        }
416    };
417}(jQuery, document, window));

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.