1/* 2 * jQuery Navgoco Menus Plugin v0.2.1 (2014-04-11) 3 * https://github.com/tefra/navgoco 4 * 5 * Copyright (c) 2014 Chris T (@tefra) 6 * BSD - https://github.com/tefra/navgoco/blob/master/LICENSE-BSD 7 */ 8(function($) { 9 10 "use strict"; 11 12 /** 13 * Plugin Constructor. Every menu must have a unique id which will either 14 * be the actual id attribute or its index in the page. 15 * 16 * @param {Element} el 17 * @param {Object} options 18 * @param {Integer} idx 19 * @returns {Object} Plugin Instance 20 */ 21 var Plugin = function(el, options, idx) { 22 this.el = el; 23 this.$el = $(el); 24 this.options = options; 25 this.uuid = this.$el.attr('id') ? this.$el.attr('id') : idx; 26 this.state = {}; 27 this.init(); 28 return this; 29 }; 30 31 /** 32 * Plugin methods 33 */ 34 Plugin.prototype = { 35 /** 36 * Load cookie, assign a unique data-index attribute to 37 * all sub-menus and show|hide them according to cookie 38 * or based on the parent open class. Find all parent li > a 39 * links add the carent if it's on and attach the event click 40 * to them. 41 */ 42 init: function() { 43 var self = this; 44 self._load(); 45 self.$el.find('ul').each(function(idx) { 46 var sub = $(this); 47 sub.attr('data-index', idx); 48 if (self.options.save && self.state.hasOwnProperty(idx)) { 49 sub.parent().addClass(self.options.openClass); 50 sub.show(); 51 } else if (sub.parent().hasClass(self.options.openClass)) { 52 sub.show(); 53 self.state[idx] = 1; 54 } else { 55 sub.hide(); 56 } 57 }); 58 59 var caret = $('<span class="wpb-submenu-indicator"></span>').prepend(self.options.caretHtml); 60 var links = self.$el.find("li > a"); 61 self._trigger(caret, false); 62 self._trigger(links, true); 63 self.$el.find("li:has(ul) > a").prepend(caret); 64 }, 65 /** 66 * Add the main event trigger to toggle menu items to the given sources 67 * @param {Element} sources 68 * @param {Boolean} isLink 69 */ 70 _trigger: function(sources, isLink) { 71 var self = this; 72 /** 73 * click for open accordion on click 74 * mouseenter for open accordion on hover 75 */ 76 77 sources.on( self.options.triggerType , function(event) { 78 event.stopPropagation(); 79 var sub = isLink ? $(this).next() : $(this).parent().next(); 80 var isAnchor = false; 81 if (isLink) { 82 var href = $(this).attr('href'); 83 isAnchor = href === undefined || href === '' || href === '#'; 84 } 85 sub = sub.length > 0 ? sub : false; 86 self.options.onClickBefore.call(this, event, sub); 87 88 if (!isLink || sub && isAnchor) { 89 event.preventDefault(); 90 self._toggle(sub, sub.is(":hidden")); 91 self._save(); 92 } else if (self.options.accordion) { 93 var allowed = self.state = self._parents($(this)); 94 self.$el.find('ul').filter(':visible').each(function() { 95 var sub = $(this), 96 idx = sub.attr('data-index'); 97 98 if (!allowed.hasOwnProperty(idx)) { 99 self._toggle(sub, false); 100 } 101 }); 102 self._save(); 103 } 104 self.options.onClickAfter.call(this, event, sub); 105 }); 106 }, 107 /** 108 * Accepts a JQuery Element and a boolean flag. If flag is false it removes the `open` css 109 * class from the parent li and slides up the sub-menu. If flag is open it adds the `open` 110 * css class to the parent li and slides down the menu. If accordion mode is on all 111 * sub-menus except the direct parent tree will close. Internally an object with the menus 112 * states is maintained for later save duty. 113 * 114 * @param {Element} sub 115 * @param {Boolean} open 116 */ 117 _toggle: function(sub, open) { 118 var self = this, 119 idx = sub.attr('data-index'), 120 parent = sub.parent(); 121 122 self.options.onToggleBefore.call(this, sub, open); 123 if (open) { 124 parent.addClass(self.options.openClass); 125 sub.slideDown(self.options.slide); 126 self.state[idx] = 1; 127 128 if (self.options.accordion) { 129 var allowed = self.state = self._parents(sub); 130 allowed[idx] = self.state[idx] = 1; 131 132 self.$el.find('ul').filter(':visible').each(function() { 133 var sub = $(this), 134 idx = sub.attr('data-index'); 135 136 if (!allowed.hasOwnProperty(idx)) { 137 self._toggle(sub, false); 138 } 139 }); 140 } 141 } else { 142 parent.removeClass(self.options.openClass); 143 sub.slideUp(self.options.slide); 144 self.state[idx] = 0; 145 } 146 self.options.onToggleAfter.call(this, sub, open); 147 }, 148 /** 149 * Returns all parents of a sub-menu. When obj is true It returns an object with indexes for 150 * keys and the elements as values, if obj is false the object is filled with the value `1`. 151 * 152 * @since v0.1.2 153 * @param {Element} sub 154 * @param {Boolean} obj 155 * @returns {Object} 156 */ 157 _parents: function(sub, obj) { 158 var result = {}, 159 parent = sub.parent(), 160 parents = parent.parents('ul'); 161 162 parents.each(function() { 163 var par = $(this), 164 idx = par.attr('data-index'); 165 166 if (!idx) { 167 return false;
168 } 169 result[idx] = obj ? par : 1; 170 }); 171 return result; 172 }, 173 /** 174 * If `save` option is on the internal object that keeps track of the sub-menus states is 175 * saved with a cookie. For size reasons only the open sub-menus indexes are stored. * 176 */ 177 _save: function() { 178 if (this.options.save) { 179 var save = {}; 180 for (var key in this.state) { 181 if (this.state[key] === 1) { 182 save[key] = 1; 183 } 184 } 185 cookie[this.uuid] = this.state = save; 186 $.cookie(this.options.cookie.name, JSON.stringify(cookie), this.options.cookie); 187 } 188 }, 189 /** 190 * If `save` option is on it reads the cookie data. The cookie contains data for all 191 * navgoco menus so the read happens only once and stored in the global `cookie` var. 192 */ 193 _load: function() { 194 if (this.options.save) { 195 if (cookie === null) { 196 var data = $.cookie(this.options.cookie.name); 197 cookie = (data) ? JSON.parse(data) : {}; 198 } 199 this.state = cookie.hasOwnProperty(this.uuid) ? cookie[this.uuid] : {}; 200 } 201 }, 202 /** 203 * Public method toggle to manually show|hide sub-menus. If no indexes are provided all 204 * items will be toggled. You can pass sub-menus indexes as regular params. eg: 205 * navgoco('toggle', true, 1, 2, 3, 4, 5); 206 * 207 * Since v0.1.2 it will also open parents when providing sub-menu indexes. 208 * 209 * @param {Boolean} open 210 */ 211 toggle: function(open) { 212 var self = this, 213 length = arguments.length; 214 215 if (length <= 1) { 216 self.$el.find('ul').each(function() { 217 var sub = $(this); 218 self._toggle(sub, open); 219 }); 220 } else { 221 var idx, 222 list = {}, 223 args = Array.prototype.slice.call(arguments, 1); 224 length--; 225 226 for (var i = 0; i < length; i++) { 227 idx = args[i]; 228 var sub = self.$el.find('ul[data-index="' + idx + '"]').first(); 229 if (sub) { 230 list[idx] = sub; 231 if (open) { 232 var parents = self._parents(sub, true); 233 for (var pIdx in parents) { 234 if (!list.hasOwnProperty(pIdx)) { 235 list[pIdx] = parents[pIdx]; 236 } 237 } 238 } 239 } 240 } 241 242 for (idx in list) { 243 self._toggle(list[idx], open); 244 } 245 } 246 self._save(); 247 }, 248 /** 249 * Removes instance from JQuery data cache and unbinds events. 250 */ 251 destroy: function() { 252 $.removeData(this.$el); 253 this.$el.find("li:has(ul) > a").unbind('click'); 254 this.$el.find("li:has(ul) > a > span").unbind('click'); 255 } 256 }; 257 258 /** 259 * A JQuery plugin wrapper for navgoco. It prevents from multiple instances and also handles 260 * public methods calls. If we attempt to call a public method on an element that doesn't have 261 * a navgoco instance, one will be created for it with the default options. 262 * 263 * @param {Object|String} options 264 */ 265 $.fn.navgoco = function(options) { 266 if (typeof options === 'string' && options.charAt(0) !== '_' && options !== 'init') { 267 var callback = true, 268 args = Array.prototype.slice.call(arguments, 1); 269 } else { 270 options = $.extend({}, $.fn.navgoco.defaults, options || {}); 271 if (!$.cookie) { 272 options.save = false; 273 } 274 } 275 return this.each(function(idx) { 276 var $this = $(this), 277 obj = $this.data('navgoco'); 278 279 if (!obj) { 280 obj = new Plugin(this, callback ? $.fn.navgoco.defaults : options, idx); 281 $this.data('navgoco', obj); 282 } 283 if (callback) { 284 obj[options].apply(obj, args); 285 } 286 }); 287 }; 288 /** 289 * Global var holding all navgoco menus open states 290 * 291 * @type {Object} 292 */ 293 var cookie = null; 294 295 /** 296 * Default navgoco options 297 * 298 * @type {Object} 299 */ 300 $.fn.navgoco.defaults = { 301 caretHtml: '', 302 accordion: false, 303 openClass: 'wpb-submenu-indicator-minus', 304 triggerType: 'mouseenter', // click, mouseenter 305 save: true, 306 cookie: { 307 name: 'navgoco', 308 expires: false, 309 path: '/' 310 }, 311 slide: { 312 duration: 400, 313 easing: 'swing' 314 }, 315 onClickBefore: $.noop, 316 onClickAfter: $.noop, 317 onToggleBefore: $.noop, 318 onToggleAfter: $.noop 319 }; 320})(jQuery);
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.