vendor/assets/javascripts/responsive-nav.js in responsive-nav-rails-1.0.20 vs vendor/assets/javascripts/responsive-nav.js in responsive-nav-rails-1.0.21

- old
+ new

@@ -1,429 +1,428 @@ -/*! responsive-nav.js v1.0.20 - * https://github.com/viljamis/responsive-nav.js - * http://responsive-nav.com - * - * Copyright (c) 2013 @viljamis - * Available under the MIT license - */ - -/* jshint strict:false, forin:false, noarg:true, noempty:true, eqeqeq:true, -boss:true, bitwise:true, browser:true, devel:true, indent:2 */ -/* exported responsiveNav */ - -var responsiveNav = (function (window, document) { - - var computed = !!window.getComputedStyle; - - // getComputedStyle polyfill - if (!window.getComputedStyle) { - window.getComputedStyle = function(el) { - this.el = el; - this.getPropertyValue = function(prop) { - var re = /(\-([a-z]){1})/g; - if (prop === "float") { - prop = "styleFloat"; - } - if (re.test(prop)) { - prop = prop.replace(re, function () { - return arguments[2].toUpperCase(); - }); - } - return el.currentStyle[prop] ? el.currentStyle[prop] : null; - }; - return this; - }; - } - - var nav, - opts, - navToggle, - styleElement = document.createElement("style"), - hasAnimFinished, - navOpen, - - // fn arg can be an object or a function, thanks to handleEvent - // read more at: http://www.thecssninja.com/javascript/handleevent - addEvent = function (el, evt, fn, bubble) { - if ("addEventListener" in el) { - // BBOS6 doesn't support handleEvent, catch and polyfill - try { - el.addEventListener(evt, fn, bubble); - } catch (e) { - if (typeof fn === "object" && fn.handleEvent) { - el.addEventListener(evt, function (e) { - // Bind fn as this and set first arg as event object - fn.handleEvent.call(fn, e); - }, bubble); - } else { - throw e; - } - } - } else if ("attachEvent" in el) { - // check if the callback is an object and contains handleEvent - if (typeof fn === "object" && fn.handleEvent) { - el.attachEvent("on" + evt, function () { - // Bind fn as this - fn.handleEvent.call(fn); - }); - } else { - el.attachEvent("on" + evt, fn); - } - } - }, - - removeEvent = function (el, evt, fn, bubble) { - if ("removeEventListener" in el) { - try { - el.removeEventListener(evt, fn, bubble); - } catch (e) { - if (typeof fn === "object" && fn.handleEvent) { - el.removeEventListener(evt, function (e) { - fn.handleEvent.call(fn, e); - }, bubble); - } else { - throw e; - } - } - } else if ("detachEvent" in el) { - if (typeof fn === "object" && fn.handleEvent) { - el.detachEvent("on" + evt, function () { - fn.handleEvent.call(fn); - }); - } else { - el.detachEvent("on" + evt, fn); - } - } - }, - - getChildren = function (e) { - if (e.children.length < 1) { - throw new Error("The Nav container has no containing elements"); - } - // Store all children in array - var children = []; - // Loop through children and store in array if child != TextNode - for (var i = 0; i < e.children.length; i++) { - if (e.children[i].nodeType === 1) { - children.push(e.children[i]); - } - } - return children; - }, - - setAttributes = function (el, attrs) { - for (var key in attrs) { - el.setAttribute(key, attrs[key]); - } - }, - - addClass = function (el, cls) { - el.className += " " + cls; - el.className = el.className.replace(/(^\s*)|(\s*$)/g,""); - }, - - removeClass = function (el, cls) { - var reg = new RegExp("(\\s|^)" + cls + "(\\s|$)"); - el.className = el.className.replace(reg, " ").replace(/(^\s*)|(\s*$)/g,""); - }, - - ResponsiveNav = function (el, options) { - var i; - - // Default options - this.options = { - animate: true, // Boolean: Use CSS3 transitions, true or false - transition: 350, // Integer: Speed of the transition, in milliseconds - label: "Menu", // String: Label for the navigation toggle - insert: "after", // String: Insert the toggle before or after the navigation - customToggle: "", // Selector: Specify the ID of a custom toggle - openPos: "relative", // String: Position of the opened nav, relative or static - jsClass: "js", // String: 'JS enabled' class which is added to <html> el - init: function(){}, // Function: Init callback - open: function(){}, // Function: Open callback - close: function(){} // Function: Close callback - }; - - // User defined options - for (i in options) { - this.options[i] = options[i]; - } - - // Adds "js" class for <html> - addClass(document.documentElement, this.options.jsClass); - - // Wrapper - this.wrapperEl = el.replace("#", ""); - if (document.getElementById(this.wrapperEl)) { - this.wrapper = document.getElementById(this.wrapperEl); - } else { - // If el doesn't exists, stop here. - throw new Error("The nav element you are trying to select doesn't exist"); - } - - // Inner wrapper - this.wrapper.inner = getChildren(this.wrapper); - - // For minification - opts = this.options; - nav = this.wrapper; - - // Init - this._init(this); - }; - - ResponsiveNav.prototype = { - // Public methods - destroy: function () { - this._removeStyles(); - removeClass(nav, "closed"); - removeClass(nav, "opened"); - nav.removeAttribute("style"); - nav.removeAttribute("aria-hidden"); - nav = null; - _instance = null; - - removeEvent(window, "resize", this, false); - removeEvent(document.body, "touchmove", this, false); - removeEvent(navToggle, "touchstart", this, false); - removeEvent(navToggle, "touchend", this, false); - removeEvent(navToggle, "keyup", this, false); - removeEvent(navToggle, "click", this, false); - removeEvent(navToggle, "mouseup", this, false); - - if (!opts.customToggle) { - navToggle.parentNode.removeChild(navToggle); - } else { - navToggle.removeAttribute("aria-hidden"); - } - }, - - toggle: function () { - if (hasAnimFinished === true) { - if (!navOpen) { - removeClass(nav, "closed"); - addClass(nav, "opened"); - nav.style.position = opts.openPos; - setAttributes(nav, {"aria-hidden": "false"}); - - navOpen = true; - opts.open(); - } else { - removeClass(nav, "opened"); - addClass(nav, "closed"); - setAttributes(nav, {"aria-hidden": "true"}); - - if (opts.animate) { - hasAnimFinished = false; - setTimeout(function () { - nav.style.position = "absolute"; - hasAnimFinished = true; - }, opts.transition + 10); - } else { - nav.style.position = "absolute"; - } - - navOpen = false; - opts.close(); - } - } - }, - - handleEvent: function (e) { - var evt = e || window.event; - - switch (evt.type) { - case "touchstart": - this._onTouchStart(evt); - break; - case "touchmove": - this._onTouchMove(evt); - break; - case "touchend": - case "mouseup": - this._onTouchEnd(evt); - break; - case "click": - this._preventDefault(evt); - break; - case "keyup": - this._onKeyUp(evt); - break; - case "resize": - this._resize(evt); - break; - } - }, - - // Private methods - _init: function () { - addClass(nav, "closed"); - hasAnimFinished = true; - navOpen = false; - - this._createToggle(); - this._transitions(); - this._resize(); - - addEvent(window, "resize", this, false); - addEvent(document.body, "touchmove", this, false); - addEvent(navToggle, "touchstart", this, false); - addEvent(navToggle, "touchend", this, false); - addEvent(navToggle, "mouseup", this, false); - addEvent(navToggle, "keyup", this, false); - addEvent(navToggle, "click", this, false); - - // Init callback - opts.init(); - }, - - _createStyles: function () { - if (!styleElement.parentNode) { - document.getElementsByTagName("head")[0].appendChild(styleElement); - } - }, - - _removeStyles: function () { - if (styleElement.parentNode) { - styleElement.parentNode.removeChild(styleElement); - } - }, - - _createToggle: function () { - if (!opts.customToggle) { - var toggle = document.createElement("a"); - toggle.innerHTML = opts.label; - setAttributes(toggle, { - "href": "#", - "id": "nav-toggle" - }); - - if (opts.insert === "after") { - nav.parentNode.insertBefore(toggle, nav.nextSibling); - } else { - nav.parentNode.insertBefore(toggle, nav); - } - - navToggle = document.getElementById("nav-toggle"); - } else { - var toggleEl = opts.customToggle.replace("#", ""); - - if (document.getElementById(toggleEl)) { - navToggle = document.getElementById(toggleEl); - } else { - throw new Error("The custom nav toggle you are trying to select doesn't exist"); - } - } - }, - - _preventDefault: function(e) { - if (e.preventDefault) { - e.preventDefault(); - e.stopPropagation(); - } else { - e.returnValue = false; - } - }, - - _onTouchStart: function (e) { - e.stopPropagation(); - this.startX = e.touches[0].clientX; - this.startY = e.touches[0].clientY; - this.touchHasMoved = false; - removeEvent(navToggle, "mouseup", this, false); - }, - - _onTouchMove: function (e) { - if (Math.abs(e.touches[0].clientX - this.startX) > 10 || - Math.abs(e.touches[0].clientY - this.startY) > 10) { - this.touchHasMoved = true; - } - }, - - _onTouchEnd: function (e) { - this._preventDefault(e); - if (!this.touchHasMoved) { - if (e.type === "touchend") { - this.toggle(e); - // Prevent click on the underlying menu on Android 2.3 - var that = this; - nav.addEventListener("click", that._preventDefault, true); - setTimeout(function () { - nav.removeEventListener("click", that._preventDefault, true); - }, opts.transition + 100); - return; - } else { - var evt = e || window.event; - // If it isn't a right click - if (!(evt.which === 3 || evt.button === 2)) { - this.toggle(e); - } - } - } - }, - - _onKeyUp: function (e) { - var evt = e || window.event; - if (evt.keyCode === 13) { - this.toggle(e); - } - }, - - _transitions: function () { - if (opts.animate) { - var objStyle = nav.style, - transition = "max-height " + opts.transition + "ms"; - - objStyle.WebkitTransition = transition; - objStyle.MozTransition = transition; - objStyle.OTransition = transition; - objStyle.transition = transition; - } - }, - - _calcHeight: function () { - var savedHeight = 0; - for (var i = 0; i < nav.inner.length; i++) { - savedHeight += nav.inner[i].offsetHeight; - } - - var innerStyles = "#" + this.wrapperEl + ".opened{max-height:" + savedHeight + "px}"; - - // Hide from old IE - if (computed) { - styleElement.innerHTML = innerStyles; - innerStyles = ""; - } - }, - - _resize: function () { - if (window.getComputedStyle(navToggle, null).getPropertyValue("display") !== "none") { - setAttributes(navToggle, {"aria-hidden": "false"}); - - // If the navigation is hidden - if (nav.className.match(/(^|\s)closed(\s|$)/)) { - setAttributes(nav, {"aria-hidden": "true"}); - nav.style.position = "absolute"; - } - - this._createStyles(); - this._calcHeight(); - } else { - setAttributes(navToggle, {"aria-hidden": "true"}); - setAttributes(nav, {"aria-hidden": "false"}); - nav.style.position = opts.openPos; - this._removeStyles(); - } - } - - }; - - var _instance; - function rn (el, options) { - if (!_instance) { - _instance = new ResponsiveNav(el, options); - } - return _instance; - } - - return rn; -})(window, document); +/*! responsive-nav.js v1.0.21 + * https://github.com/viljamis/responsive-nav.js + * http://responsive-nav.com + * + * Copyright (c) 2013 @viljamis + * Available under the MIT license + */ + +/* jshint strict:false, forin:false, noarg:true, noempty:true, eqeqeq:true, +boss:true, bitwise:true, browser:true, devel:true, indent:2 */ +/* exported responsiveNav */ + +var responsiveNav = function (el, options) { + + var computed = !!window.getComputedStyle; + + // getComputedStyle polyfill + if (!computed) { + window.getComputedStyle = function(el) { + this.el = el; + this.getPropertyValue = function(prop) { + var re = /(\-([a-z]){1})/g; + if (prop === "float") { + prop = "styleFloat"; + } + if (re.test(prop)) { + prop = prop.replace(re, function () { + return arguments[2].toUpperCase(); + }); + } + return el.currentStyle[prop] ? el.currentStyle[prop] : null; + }; + return this; + }; + } + + var nav, + opts, + navToggle, + styleElement = document.createElement("style"), + hasAnimFinished, + navOpen, + + // fn arg can be an object or a function, thanks to handleEvent + // read more at: http://www.thecssninja.com/javascript/handleevent + addEvent = function (el, evt, fn, bubble) { + if ("addEventListener" in el) { + // BBOS6 doesn't support handleEvent, catch and polyfill + try { + el.addEventListener(evt, fn, bubble); + } catch (e) { + if (typeof fn === "object" && fn.handleEvent) { + el.addEventListener(evt, function (e) { + // Bind fn as this and set first arg as event object + fn.handleEvent.call(fn, e); + }, bubble); + } else { + throw e; + } + } + } else if ("attachEvent" in el) { + // check if the callback is an object and contains handleEvent + if (typeof fn === "object" && fn.handleEvent) { + el.attachEvent("on" + evt, function () { + // Bind fn as this + fn.handleEvent.call(fn); + }); + } else { + el.attachEvent("on" + evt, fn); + } + } + }, + + removeEvent = function (el, evt, fn, bubble) { + if ("removeEventListener" in el) { + try { + el.removeEventListener(evt, fn, bubble); + } catch (e) { + if (typeof fn === "object" && fn.handleEvent) { + el.removeEventListener(evt, function (e) { + fn.handleEvent.call(fn, e); + }, bubble); + } else { + throw e; + } + } + } else if ("detachEvent" in el) { + if (typeof fn === "object" && fn.handleEvent) { + el.detachEvent("on" + evt, function () { + fn.handleEvent.call(fn); + }); + } else { + el.detachEvent("on" + evt, fn); + } + } + }, + + getChildren = function (e) { + if (e.children.length < 1) { + throw new Error("The Nav container has no containing elements"); + } + // Store all children in array + var children = []; + // Loop through children and store in array if child != TextNode + for (var i = 0; i < e.children.length; i++) { + if (e.children[i].nodeType === 1) { + children.push(e.children[i]); + } + } + return children; + }, + + setAttributes = function (el, attrs) { + for (var key in attrs) { + el.setAttribute(key, attrs[key]); + } + }, + + addClass = function (el, cls) { + if (el.className.indexOf(cls) !== 0) { + el.className += " " + cls; + el.className = el.className.replace(/(^\s*)|(\s*$)/g,""); + } + }, + + removeClass = function (el, cls) { + var reg = new RegExp("(\\s|^)" + cls + "(\\s|$)"); + el.className = el.className.replace(reg, " ").replace(/(^\s*)|(\s*$)/g,""); + }, + + ResponsiveNav = function (el, options) { + var i; + + // Default options + this.options = { + animate: true, // Boolean: Use CSS3 transitions, true or false + transition: 250, // Integer: Speed of the transition, in milliseconds + label: "Menu", // String: Label for the navigation toggle + insert: "after", // String: Insert the toggle before or after the navigation + customToggle: "", // Selector: Specify the ID of a custom toggle + openPos: "relative", // String: Position of the opened nav, relative or static + jsClass: "js", // String: 'JS enabled' class which is added to <html> el + init: function(){}, // Function: Init callback + open: function(){}, // Function: Open callback + close: function(){} // Function: Close callback + }; + + // User defined options + for (i in options) { + this.options[i] = options[i]; + } + + // Adds "js" class for <html> + addClass(document.documentElement, this.options.jsClass); + + // Wrapper + this.wrapperEl = el.replace("#", ""); + if (document.getElementById(this.wrapperEl)) { + this.wrapper = document.getElementById(this.wrapperEl); + } else if (document.querySelector(this.wrapperEl)) { + this.wrapper = document.querySelector(this.wrapperEl); + } else { + // If el doesn't exists, stop here. + throw new Error("The nav element you are trying to select doesn't exist"); + } + + // Inner wrapper + this.wrapper.inner = getChildren(this.wrapper); + + // For minification + opts = this.options; + nav = this.wrapper; + + // Init + this._init(this); + }; + + ResponsiveNav.prototype = { + // Public methods + destroy: function () { + this._removeStyles(); + removeClass(nav, "closed"); + removeClass(nav, "opened"); + nav.removeAttribute("style"); + nav.removeAttribute("aria-hidden"); + nav = null; + + removeEvent(window, "resize", this, false); + removeEvent(document.body, "touchmove", this, false); + removeEvent(navToggle, "touchstart", this, false); + removeEvent(navToggle, "touchend", this, false); + removeEvent(navToggle, "mouseup", this, false); + removeEvent(navToggle, "keyup", this, false); + removeEvent(navToggle, "click", this, false); + + if (!opts.customToggle) { + navToggle.parentNode.removeChild(navToggle); + } else { + navToggle.removeAttribute("aria-hidden"); + } + }, + + toggle: function () { + if (hasAnimFinished === true) { + if (!navOpen) { + removeClass(nav, "closed"); + addClass(nav, "opened"); + nav.style.position = opts.openPos; + setAttributes(nav, {"aria-hidden": "false"}); + + navOpen = true; + opts.open(); + } else { + removeClass(nav, "opened"); + addClass(nav, "closed"); + setAttributes(nav, {"aria-hidden": "true"}); + + if (opts.animate) { + hasAnimFinished = false; + setTimeout(function () { + nav.style.position = "absolute"; + hasAnimFinished = true; + }, opts.transition + 10); + } else { + nav.style.position = "absolute"; + } + + navOpen = false; + opts.close(); + } + } + }, + + handleEvent: function (e) { + var evt = e || window.event; + + switch (evt.type) { + case "touchstart": + this._onTouchStart(evt); + break; + case "touchmove": + this._onTouchMove(evt); + break; + case "touchend": + case "mouseup": + this._onTouchEnd(evt); + break; + case "click": + this._preventDefault(evt); + break; + case "keyup": + this._onKeyUp(evt); + break; + case "resize": + this._resize(evt); + break; + } + }, + + // Private methods + _init: function () { + addClass(nav, "nav-collapse"); + addClass(nav, "closed"); + hasAnimFinished = true; + navOpen = false; + + this._createToggle(); + this._transitions(); + this._resize(); + + addEvent(window, "resize", this, false); + addEvent(document.body, "touchmove", this, false); + addEvent(navToggle, "touchstart", this, false); + addEvent(navToggle, "touchend", this, false); + addEvent(navToggle, "mouseup", this, false); + addEvent(navToggle, "keyup", this, false); + addEvent(navToggle, "click", this, false); + + // Init callback + opts.init(); + }, + + _createStyles: function () { + if (!styleElement.parentNode) { + styleElement.type = "text/css"; + document.getElementsByTagName("head")[0].appendChild(styleElement); + } + }, + + _removeStyles: function () { + if (styleElement.parentNode) { + styleElement.parentNode.removeChild(styleElement); + } + }, + + _createToggle: function () { + if (!opts.customToggle) { + var toggle = document.createElement("a"); + toggle.innerHTML = opts.label; + setAttributes(toggle, { + "href": "#", + "class": "nav-toggle" + }); + + if (opts.insert === "after") { + nav.parentNode.insertBefore(toggle, nav.nextSibling); + } else { + nav.parentNode.insertBefore(toggle, nav); + } + + navToggle = toggle; + } else { + var toggleEl = opts.customToggle.replace("#", ""); + + if (document.getElementById(toggleEl)) { + navToggle = document.getElementById(toggleEl); + } else if (document.querySelector(toggleEl)) { + navToggle = document.querySelector(toggleEl); + } else { + throw new Error("The custom nav toggle you are trying to select doesn't exist"); + } + } + }, + + _preventDefault: function(e) { + if (e.preventDefault) { + e.preventDefault(); + e.stopPropagation(); + } else { + e.returnValue = false; + } + }, + + _onTouchStart: function (e) { + e.stopPropagation(); + this.startX = e.touches[0].clientX; + this.startY = e.touches[0].clientY; + this.touchHasMoved = false; + removeEvent(navToggle, "mouseup", this, false); + }, + + _onTouchMove: function (e) { + if (Math.abs(e.touches[0].clientX - this.startX) > 10 || + Math.abs(e.touches[0].clientY - this.startY) > 10) { + this.touchHasMoved = true; + } + }, + + _onTouchEnd: function (e) { + this._preventDefault(e); + if (!this.touchHasMoved) { + if (e.type === "touchend") { + this.toggle(e); + // Prevent click on the underlying menu on Android 2.3 + var that = this; + nav.addEventListener("click", that._preventDefault, true); + setTimeout(function () { + nav.removeEventListener("click", that._preventDefault, true); + }, opts.transition + 100); + return; + } else { + var evt = e || window.event; + // If it isn't a right click + if (!(evt.which === 3 || evt.button === 2)) { + this.toggle(e); + } + } + } + }, + + _onKeyUp: function (e) { + var evt = e || window.event; + if (evt.keyCode === 13) { + this.toggle(e); + } + }, + + _transitions: function () { + if (opts.animate) { + var objStyle = nav.style, + transition = "max-height " + opts.transition + "ms"; + + objStyle.WebkitTransition = transition; + objStyle.MozTransition = transition; + objStyle.OTransition = transition; + objStyle.transition = transition; + } + }, + + _calcHeight: function () { + var savedHeight = 0; + for (var i = 0; i < nav.inner.length; i++) { + savedHeight += nav.inner[i].offsetHeight; + } + var innerStyles = ".nav-collapse.opened{max-height:" + savedHeight + "px}"; + + if (styleElement.styleSheet) { + styleElement.styleSheet.cssText = innerStyles; + } else { + styleElement.innerHTML = innerStyles; + } + + innerStyles = ""; + }, + + _resize: function () { + if (window.getComputedStyle(navToggle, null).getPropertyValue("display") !== "none") { + setAttributes(navToggle, {"aria-hidden": "false"}); + + // If the navigation is hidden + if (nav.className.match(/(^|\s)closed(\s|$)/)) { + setAttributes(nav, {"aria-hidden": "true"}); + nav.style.position = "absolute"; + } + + this._createStyles(); + this._calcHeight(); + } else { + setAttributes(navToggle, {"aria-hidden": "true"}); + setAttributes(nav, {"aria-hidden": "false"}); + nav.style.position = opts.openPos; + this._removeStyles(); + } + } + + }; + return new ResponsiveNav(el, options); +}; \ No newline at end of file