From 8a2f773f4836f425ad471989a7b0a56b29b71346 Mon Sep 17 00:00:00 2001 From: giolvani Date: Fri, 7 Mar 2014 16:49:58 -0300 Subject: [PATCH 1/2] Update jquery.navgogo.js Replacing the store method, from cookies to localStorage (HTML5). The advantage that use less third libs. --- src/jquery.navgoco.js | 426 ++++++++++++++++++++++-------------------- 1 file changed, 219 insertions(+), 207 deletions(-) diff --git a/src/jquery.navgoco.js b/src/jquery.navgoco.js index b97fb1a..abc989e 100644 --- a/src/jquery.navgoco.js +++ b/src/jquery.navgoco.js @@ -1,15 +1,16 @@ /* - * jQuery Navgoco Menus Plugin v0.1.5 (2013-09-07) + * jQuery Navgoco Menus Plugin v0.1.6 (2014-03-07) * https://github.com/tefra/navgoco * * Copyright (c) 2013 Chris T (@tefra) + * Contribuitor Giolvani de Matos * BSD - https://github.com/tefra/navgoco/blob/master/LICENSE-BSD */ -(function($) { +(function ($) { - "use strict"; + "use strict"; - /** + /** * Plugin Constructor. Every menu must have a unique id which will either * be the actual id attribute or its index in the page. * @@ -18,76 +19,80 @@ * @param {Integer} idx * @returns {Object} Plugin Instance */ - var Plugin = function(el, options, idx) { - this.el = el; - this.$el = $(el); - this.options = options; - this.uuid = this.$el.attr('id') ? this.$el.attr('id') : idx; - this.state = {}; - this.init(); - return this; - }; + var Plugin = function (el, options, idx) { + this.el = el; + this.$el = $(el); + this.options = options; + this.uuid = this.$el.attr('id') ? this.$el.attr('id') : idx; + this.state = {}; + this.init(); + return this; + }; - /** + /** * Plugin methods */ - Plugin.prototype = { - /** - * Load cookie, assign a unique data-index attribute to - * all sub-menus and show|hide them according to cookie + Plugin.prototype = { + /** + * Load local storage, assign a unique data-index attribute to + * all sub-menus and show|hide them according to local storage * or based on the parent open class. Find all parent li > a * links add the carent if it's on and attach the event click * to them. */ - init: function() { - var self = this; - self._load(); - self.$el.find('ul').each(function(idx) { - var sub = $(this); - sub.attr('data-index', idx); - if (self.options.save && self.state.hasOwnProperty(idx)) { - sub.parent().addClass(self.options.openClass); - sub.show(); - } else if (sub.parent().hasClass(self.options.openClass)) { - sub.show(); - self.state[idx] = 1; - } else { - sub.hide(); - } - }); + init: function () { + var self = this; + self._load(); + self.$el.find('ul').each(function (idx) { + var sub = $(this); + sub.attr('data-index', idx); + if (self.options.save && self.state.hasOwnProperty(idx)) { + sub.parent().addClass(self.options.openClass); + sub.show(); + } else if (sub.parent().hasClass(self.options.openClass)) { + sub.show(); + self.state[idx] = 1; + } else { + sub.hide(); + } + }); - if (self.options.caret) { - self.$el.find("li:has(ul) > a").append(self.options.caret); - } + if (typeof self.options.caret == 'object') { + var method = self.options.caret.method ? self.options.caret.method : 'append'; + var caret = self.options.caret.element; + if (caret) { + self.$el.find("li:has(ul) > a")[method](caret); + } + } - var links = self.$el.find("li > a"); - links.on('click', function(event) { - event.stopPropagation(); - var sub = $(this).next(); - sub = sub.length > 0 ? sub : false; - self.options.onClickBefore.call(this, event, sub); - if (sub) { - event.preventDefault(); - self._toggle(sub, sub.is(":hidden")); - self._save(); - } else { - if (self.options.accordion) { - var allowed = self.state = self._parents($(this)); - self.$el.find('ul').filter(':visible').each(function() { - var sub = $(this), + var links = self.$el.find("li > a"); + links.on('click', function (event) { + event.stopPropagation(); + var sub = $(this).next(); + sub = sub.length > 0 ? sub : false; + self.options.onClickBefore.call(this, event, sub); + if (sub) { + event.preventDefault(); + self._toggle(sub, sub.is(":hidden")); + self._save(); + } else { + if (self.options.accordion) { + var allowed = self.state = self._parents($(this)); + self.$el.find('ul').filter(':visible').each(function () { + var sub = $(this), idx = sub.attr('data-index'); - if (!allowed.hasOwnProperty(idx)) { - self._toggle(sub, false); - } - }); - self._save(); - } - } - self.options.onClickAfter.call(this, event, sub); - }); - }, - /** + if (!allowed.hasOwnProperty(idx)) { + self._toggle(sub, false); + } + }); + self._save(); + } + } + self.options.onClickAfter.call(this, event, sub); + }); + }, + /** * Accepts a JQuery Element and a boolean flag. If flag is false it removes the `open` css * class from the parent li and slides up the sub-menu. If flag is open it adds the `open` * css class to the parent li and slides down the menu. If accordion mode is on all @@ -97,38 +102,38 @@ * @param {Element} sub * @param {Boolean} open */ - _toggle: function(sub, open) { - var self = this, + _toggle: function (sub, open) { + var self = this, idx = sub.attr('data-index'), parent = sub.parent(); - self.options.onToggleBefore.call(this, sub, open); - if (open) { - parent.addClass(self.options.openClass); - sub.slideDown(self.options.slide); - self.state[idx] = 1; + self.options.onToggleBefore.call(this, sub, open); + if (open) { + parent.addClass(self.options.openClass); + sub.slideDown(self.options.slide); + self.state[idx] = 1; - if (self.options.accordion) { - var allowed = self.state = self._parents(sub); - allowed[idx] = self.state[idx] = 1; + if (self.options.accordion) { + var allowed = self.state = self._parents(sub); + allowed[idx] = self.state[idx] = 1; - self.$el.find('ul').filter(':visible').each(function() { - var sub = $(this), + self.$el.find('ul').filter(':visible').each(function () { + var sub = $(this), idx = sub.attr('data-index'); - if (!allowed.hasOwnProperty(idx)) { - self._toggle(sub, false); - } - }); - } - } else { - parent.removeClass(self.options.openClass); - sub.slideUp(self.options.slide); - self.state[idx] = 0; - } - self.options.onToggleAfter.call(this, sub, open); - }, - /** + if (!allowed.hasOwnProperty(idx)) { + self._toggle(sub, false); + } + }); + } + } else { + parent.removeClass(self.options.openClass); + sub.slideUp(self.options.slide); + self.state[idx] = 0; + } + self.options.onToggleAfter.call(this, sub, open); + }, + /** * Returns all parents of a sub-menu. When obj is true It returns an object with indexes for * keys and the elements as values, if obj is false the object is filled with the value `1`. * @@ -137,52 +142,61 @@ * @param {Boolean} obj * @returns {Object} */ - _parents: function(sub, obj) { - var result = {}, + _parents: function (sub, obj) { + var result = {}, parent = sub.parent(), parents = parent.parents('ul'); - parents.each(function() { - var par = $(this), + parents.each(function () { + var par = $(this), idx = par.attr('data-index'); - if (!idx) { - return false; - } - result[idx] = obj ? par : 1; - }); - return result; - }, - /** + if (!idx) { + return false; + } + result[idx] = obj ? par : 1; + }); + return result; + }, + /** * If `save` option is on the internal object that keeps track of the sub-menus states is - * saved with a cookie. For size reasons only the open sub-menus indexes are stored. * + * saved with a local storage. For size reasons only the open sub-menus indexes are stored. * */ - _save: function() { - if (this.options.save) { - var save = {}; - for (var key in this.state) { - if (this.state[key] === 1) { - save[key] = 1; - } - } - cookie[this.uuid] = this.state = save; - $.cookie(this.options.cookie.name, JSON.stringify(cookie), this.options.cookie); - } - }, - /** - * If `save` option is on it reads the cookie data. The cookie contains data for all - * navgoco menus so the read happens only once and stored in the global `cookie` var. + _save: function () { + if (this.options.save) { + var save = {}; + for (var key in this.state) { + if (this.state[key] === 1) { + save[key] = 1; + } + } + + if (this._localStorageIsAvailable()) { + storage[this.uuid] = this.state = save; + localStorage[this.options.storage.name] = JSON.stringify(storage); + } + } + }, + /** + * If `save` option is on it reads the local storage data. The storage contains data for all + * navgoco menus so the read happens only once and stored in the global `storage` var. */ - _load: function() { - if (this.options.save) { - if (cookie === null) { - var data = $.cookie(this.options.cookie.name); - cookie = (data) ? JSON.parse(data) : {}; - } - this.state = cookie.hasOwnProperty(this.uuid) ? cookie[this.uuid] : {}; - } - }, - /** + _load: function () { + if (this.options.save) { + if (storage === null) { + var data = localStorage[this.options.storage.name]; + storage = (data) ? JSON.parse(data) : {}; + } + this.state = storage.hasOwnProperty(this.uuid) ? storage[this.uuid] : {}; + } + }, + /** + * Check if localstorage is available + */ + _localStorageIsAvailable: function() { + return typeof (Storage) !== "undefined"; + }, + /** * Public method toggle to manually show|hide sub-menus. If no indexes are provided all * items will be toggled. You can pass sub-menus indexes as regular params. eg: * navgoco('toggle', true, 1, 2, 3, 4, 5); @@ -191,111 +205,109 @@ * * @param {Boolean} open */ - toggle: function(open) { - var self = this, + toggle: function (open) { + var self = this, length = arguments.length; - if (length <= 1) { - self.$el.find('ul').each(function() { - var sub = $(this); - self._toggle(sub, open); - }); - } else { - var idx, + if (length <= 1) { + self.$el.find('ul').each(function () { + var sub = $(this); + self._toggle(sub, open); + }); + } else { + var idx, list = {}, args = Array.prototype.slice.call(arguments, 1); - length--; + length--; - for (var i = 0; i < length; i++) { - idx = args[i]; - var sub = self.$el.find('ul[data-index="' + idx + '"]').first(); - if (sub) { - list[idx] = sub; - if (open) { - var parents = self._parents(sub, true); - for (var pIdx in parents) { - if (!list.hasOwnProperty(pIdx)) { - list[pIdx] = parents[pIdx]; - } - } - } - } - } + for (var i = 0; i < length; i++) { + idx = args[i]; + var sub = self.$el.find('ul[data-index="' + idx + '"]').first(); + if (sub) { + list[idx] = sub; + if (open) { + var parents = self._parents(sub, true); + for (var pIdx in parents) { + if (!list.hasOwnProperty(pIdx)) { + list[pIdx] = parents[pIdx]; + } + } + } + } + } - for (idx in list) { - self._toggle(list[idx], open); - } - } - self._save(); - }, - /** + for (idx in list) { + self._toggle(list[idx], open); + } + } + self._save(); + }, + /** * Removes instance from JQuery data cache and unbinds events. */ - destroy: function() { - $.removeData(this.$el); - this.$el.find("li:has(ul) > a").unbind('click'); - } - }; + destroy: function () { + $.removeData(this.$el); + this.$el.find("li:has(ul) > a").unbind('click'); + } + }; - /** + /** * A JQuery plugin wrapper for navgoco. It prevents from multiple instances and also handles * public methods calls. If we attempt to call a public method on an element that doesn't have * a navgoco instance, one will be created for it with the default options. * * @param {Object|String} options */ - $.fn.navgoco = function(options) { - if (typeof options === 'string' && options.charAt(0) !== '_' && options !== 'init') { - var callback = true, + $.fn.navgoco = function (options) { + if (typeof options === 'string' && options.charAt(0) !== '_' && options !== 'init') { + var callback = true, args = Array.prototype.slice.call(arguments, 1); - } else { - options = $.extend({}, $.fn.navgoco.defaults, options || {}); - if (!$.cookie) { - options.save = false; - } - } - return this.each(function(idx) { - var $this = $(this), + } else { + options = $.extend({}, $.fn.navgoco.defaults, options || {}); + if (typeof (Storage) === "undefined") { + options.save = false; + } + } + return this.each(function (idx) { + var $this = $(this), obj = $this.data('navgoco'); - if (!obj) { - obj = new Plugin(this, callback ? $.fn.navgoco.defaults : options, idx); - $this.data('navgoco', obj); - } - if (callback) { - obj[options].apply(obj, args); - } - }); - }; - /** + if (!obj) { + obj = new Plugin(this, callback ? $.fn.navgoco.defaults : options, idx); + $this.data('navgoco', obj); + } + if (callback) { + obj[options].apply(obj, args); + } + }); + }; + /** * Global var holding all navgoco menus open states * * @type {Object} */ - var cookie = null; + var storage = null; - /** + /** * Default navgoco options * * @type {Object} */ - $.fn.navgoco.defaults = { - caret: '', - accordion: false, - openClass: 'open', - save: true, - cookie: { - name: 'navgoco', - expires: false, - path: '/' - }, - slide: { - duration: 400, - easing: 'swing' - }, - onClickBefore: $.noop, - onClickAfter: $.noop, - onToggleBefore: $.noop, - onToggleAfter: $.noop - }; -})(jQuery); \ No newline at end of file + $.fn.navgoco.defaults = { + caret: { method: 'append', element: '' }, + accordion: false, + openClass: 'open', + save: true, + storage: { + name: 'navgoco' + }, + slide: { + duration: 400, + easing: 'swing' + }, + onClickBefore: $.noop, + onClickAfter: $.noop, + onToggleBefore: $.noop, + onToggleAfter: $.noop + }; +})(jQuery); From 17378c457710bd889429284f5d3ef956b0535dec Mon Sep 17 00:00:00 2001 From: giolvani Date: Fri, 7 Mar 2014 16:52:03 -0300 Subject: [PATCH 2/2] Update index.html Replacing initializer to use localstorage --- demo/index.html | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/demo/index.html b/demo/index.html index 58ac85c..7a7fc0c 100644 --- a/demo/index.html +++ b/demo/index.html @@ -10,8 +10,8 @@ - - + @@ -24,10 +24,8 @@ accordion: false, openClass: 'open', save: true, - cookie: { - name: 'navgoco', - expires: false, - path: '/' + storage: { + name: 'navgoco' }, slide: { duration: 400, @@ -168,4 +166,4 @@

navgocoKomposta.net 2013 All Rights Reserved - \ No newline at end of file +