PageSourceSearch

https://www.glensbarrylaw.com/wp-content/themes/glenbarry/assets/js/jquery.slicknav.js?ver=1.0.8

js glensbarrylaw.com collected 2026-10-06 04:58:49 UTC 15,524 bytes, 434 lines download raw bytes

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