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