// Equivalent of jQuery .ready document.addEventListener('DOMContentLoaded',function(){

// Initialize variables
var lastScrollTop = window.pageYOffset || document.documentElement.scrollTop; // Scroll position of body

// Listener to resizes
window.onresize = function(event) {
lastScrollTop = window.pageYOffset || document.documentElement.scrollTop;
};

// Helper functions
// Detect offset of element
function getOffset( el ) {
        var _x = 0;
        var _y = 0;
        while( el && !isNaN( el.offsetLeft ) && !isNaN( el.offsetTop ) ) {
                _x += el.offsetLeft - el.scrollLeft;
                _y += el.offsetTop - el.scrollTop;
                el = el.offsetParent;
        }
        return { top: _y, left: _x };
};

// Add class to element => https://www.sitepoint.com/add-remove-css-class-vanilla-js/
function addNewClass(elements, myClass) {
        // if there are no elements, we're done
        if (!elements) { return; }
        // if we have a selector, get the chosen elements
        if (typeof(elements) === 'string') {
                elements = document.querySelectorAll(elements);
        }
        // if we have a single DOM element, make it an array to simplify behavior
        else if (elements.tagName) { elements=[elements]; }
        // add class to all chosen elements
        for (var i=0; i<elements.length; i++) {
                // if class is not already found
                if ( (' '+elements[i].className+' ').indexOf(' '+myClass+' ') < 0 ) {
                // add class
                elements[i].className += ' ' + myClass;
                }
        }
};

// Remove class from element => https://www.sitepoint.com/add-remove-css-class-vanilla-js/
function removeClass(elements, myClass) {
        // if there are no elements, we're done
        if (!elements) { return; }

        // if we have a selector, get the chosen elements
        if (typeof(elements) === 'string') {
                elements = document.querySelectorAll(elements);
        }
        // if we have a single DOM element, make it an array to simplify behavior
        else if (elements.tagName) { elements=[elements]; }
        // create pattern to find class name
        var reg = new RegExp('(^| )'+myClass+'($| )','g');
        // remove class from all chosen elements
        for (var i=0; i<elements.length; i++) {
                elements[i].className = elements[i].className.replace(reg,' ');
        }
}

// Smooth scrolling => https://codepen.io/andylobban/pen/qOLKVW
if ( 'querySelector' in document && 'addEventListener' in window && Array.prototype.forEach ) {
        // Function to animate the scroll
        var smoothScroll = function (anchor, duration) {
        // Calculate how far and how fast to scroll
        var startLocation = window.pageYOffset;
        var endLocation = anchor.offsetTop - 40; // Remove 40 pixels for padding
        var distance = endLocation - startLocation;
        var increments = distance/(duration/16);
        var stopAnimation;
        // Scroll the page by an increment, and check if it's time to stop
        var animateScroll = function () {
                window.scrollBy(0, increments);
                stopAnimation();
        };
// If scrolling down
        if ( increments >= 0 ) {
        // Stop animation when you reach the anchor OR the bottom of the page
                stopAnimation = function () {
                        var travelled = window.pageYOffset;
                        if ( (travelled >= (endLocation - increments)) || ((window.innerHeight + travelled) >= document.body.offsetHeight) ) {
                                clearInterval(runAnimation);
                        }
                };
        }
    // Loop the animation function
    var runAnimation = setInterval(animateScroll, 16);
};
        // Define smooth scroll links
        var scrollToggle = document.querySelectorAll('.scroll');
        // For each smooth scroll link
        [].forEach.call(scrollToggle, function (toggle) {
                // When the smooth scroll link is clicked
                toggle.addEventListener('click', function(e) {
        // Prevent the default link behavior
        e.preventDefault();
        // Get anchor link and calculate distance from the top
        var dataTarget = document.querySelector('.landing__section');
        var dataSpeed = toggle.getAttribute('data-speed');
        // If the anchor exists
        if (dataTarget) {
                // Scroll to the anchor
                        smoothScroll(dataTarget, dataSpeed || 700);
                }
        }, false);
        });
}

        // Listen to scroll position changes
window.addEventListener("scroll",function(){

        // NAVIGATION BAR ON LANDING FIXED
        // If there is a #navConverter element then attach listener to scroll events
        if (document.body.contains(document.getElementById("navConverter"))){
                var lastScrollTop = window.pageYOffset || document.documentElement.scrollTop;
                // if the current body position is less than 20 pixels away from our converter, convert
                if (lastScrollTop > (getOffset( document.getElementById('navConverter') ).top - 60)){ removeClass(document.querySelector('.navbar'),'navbar--extended');} else {addNewClass(document.querySelector('.navbar'),'navbar--extended');}
        }

        // SCROLL TO NEXT ELEMENT ON LANDING
        if (document.body.contains(document.getElementById('scrollToNext'))){
                var lastScrollTop = window.pageYOffset || document.documentElement.scrollTop;
                // if the current body position is less than 20 pixels away from the top, hide the icon
                if (lastScrollTop > 20){ addNewClass(document.getElementById('scrollToNext'),'invisible');} else {removeClass(document.getElementById('scrollToNext'),'invisible');}
        }
});

// Responsive mobile menu
// Create the menu 
if (document.getElementsByClassName("nav__mobile") && document.getElementsByClassName('nav__mobile').length > 0){
        var navElements = document.getElementsByClassName('navbar__menu')[0].innerHTML;
        document.getElementsByClassName('nav__mobile')[0].innerHTML = navElements;
        // Load 
        var nav = responsiveNav(".nav__mobile", { // Selector
                animate: true, // Boolean: Use CSS3 transitions, true or false
                transition: 284, // Integer: Speed of the transition, in milliseconds
                label: "Menu", // String: Label for the navigation toggle
                insert: "before", // String: Insert the toggle before or after the navigation
                customToggle: "toggle", // Selector: Specify the ID of a custom toggle
                openPos: "relative", // String: Position of the opened nav, relative or static
                navClass: "nav__mobile", // String: Default CSS class. If changed, you need to edit the CSS too!
        });
} else {
         addNewClass(document.querySelector('.navbar__menu'),'navbar__menu--noMob');
         addNewClass(document.querySelector('.navbar__menu-mob'), 'navbar__menu-mob--noMob');
};

}); (function(f){if(typeof exports===“object”&&typeof module!==“undefined”){module.exports=f()}else if(typeof define===“function”&&define.amd){define([],f)}else{var g;if(typeof window!==“undefined”){g=window}else if(typeof global!==“undefined”){g=global}else if(typeof self!==“undefined”){g=self}else{g=this}g.flexibility = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n){if(!t){var a=typeof require==“function”&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(“Cannot find module '”o“'”);throw f.code=“MODULE_NOT_FOUND”,f}var l=n={exports:{}};t[0].call(l.exports,function(e){var n=t[1];return s(n?n:e)},l,l.exports,e,t,n,r)}return n.exports}var i=typeof require==“function”&&require;for(var o=0;o);return s})({1:[function(require,module,exports){ module.exports = function alignContent(target) {

var start;
var factor;

if (target.lines.length < 2 || target.alignContent === 'stretch') {
        factor = target.crossSpace / target.lines.length;
        start = 0;

        target.lines.forEach(function (line) {
                line.crossStart = start;
                line.cross += factor;

                start += line.cross;
        });
} else if (target.alignContent === 'flex-start') {
        start = 0;

        target.lines.forEach(function (line) {
                line.crossStart = start;

                start += line.cross;
        });
} else if (target.alignContent === 'flex-end') {
        start = target.crossSpace;

        target.lines.forEach(function (line) {
                line.crossStart = start;

                start += line.cross;
        });
} else if (target.alignContent === 'center') {
        start = target.crossSpace / 2;

        target.lines.forEach(function (line) {
                line.crossStart = start;

                start += line.cross;
        });
} else if (target.alignContent === 'space-between') {
        factor = target.crossSpace / (target.lines.length - 1);
        start = 0;

        target.lines.forEach(function (line) {
                line.crossStart = start;

                start += line.cross + factor;
        });
} else if (target.alignContent === 'space-around') {
        factor = target.crossSpace * 2 / (target.lines.length * 2);
        start = factor / 2;

        target.lines.forEach(function (line) {
                line.crossStart = start;

                start += line.cross + factor;
        });
} else if (target.alignContent === 'stretch') {
        factor = target.crossSpace / target.lines.length;
        start = 0;

        target.lines.forEach(function (line) {
                line.crossStart = start;
                line.cross += factor;

                start += line.cross;
        });
}

};

},{}],2:[function(require,module,exports){ module.exports = function alignItems(target) {

target.lines.forEach(function (line) {
        line.children.forEach(function (child) {
                if (child.alignSelf === 'flex-start') {
                        child.crossStart = line.crossStart;
                } else if (child.alignSelf === 'flex-end') {
                        child.crossStart = line.crossStart + line.cross - child.crossAround;
                } else if (child.alignSelf === 'center') {
                        child.crossStart = line.crossStart + (line.cross - child.crossAround) / 2;
                } else if (child.alignSelf === 'stretch') {
                        child.crossStart = line.crossStart;
                        child.crossAround = line.cross;
                }
        });
});

};

},{}],3:[function(require,module,exports){ module.exports = function flexDirection(target, targetFlexDirection, targetAlignItems) {

var clientRect = target.node.getBoundingClientRect();

if (targetFlexDirection === 'row' || targetFlexDirection === 'row-reverse') {
        target.mainAxis  = 'inline';
        target.crossAxis = 'block';

        if (typeof target.main === 'number' || typeof target.cross === 'number') {
                if (target.flexDirection === 'row' || targetFlexDirection === 'row-reverse') {
                        target.width  = target.main;
                        target.height = target.cross;
                } else {
                        target.width  = target.cross;
                        target.height = target.main;
                }
        }

        target.main  = target.width;
        target.cross = target.height;

        target.mainClient  = clientRect.width  || target.node.offsetWidth;
        target.crossClient = clientRect.height || target.node.offsetHeight;

        target.mainBefore  = target.marginLeft;
        target.mainAfter   = target.marginRight;
        target.crossBefore = target.marginTop;
        target.crossAfter  = target.marginBottom;
} else {
        target.mainAxis  = 'block';
        target.crossAxis = 'inline';

        target.main  = target.height;
        target.cross = target.width;

        if (typeof target.main === 'number' || typeof target.cross === 'number') {
                if (target.flexDirection === 'column' || targetFlexDirection === 'column-reverse') {
                        target.width  = target.cross;
                        target.height = target.main;
                } else {
                        target.width  = target.main;
                        target.height = target.cross;
                }
        }

        target.mainClient  = clientRect.height || target.node.offsetHeight;
        target.crossClient = clientRect.width  || target.node.offsetWidth;

        target.mainBefore  = target.marginTop;
        target.mainAfter   = target.marginBottom;
        target.crossBefore = target.marginLeft;
        target.crossAfter  = target.marginRight;
}

if (typeof target.flexBasis === 'number') {
        target.main = target.flexBasis;
}

if (target.main === 'auto') {
        target.mainAround = target.mainClient;
} else {
        target.mainAround = target.main;
}

if (target.cross === 'auto') {
        target.crossAround = target.crossClient;
} else {
        target.crossAround = target.cross;
}

if (typeof target.mainBefore === 'number') {
        target.mainAround += target.mainBefore;
}

if (typeof target.mainAfter === 'number') {
        target.mainAround += target.mainAfter;
}

if (typeof target.crossBefore === 'number') {
        target.crossAround += target.crossBefore;
}

if (typeof target.crossBefore === 'number') {
        target.crossAround += target.crossBefore;
}

if (target.alignSelf === 'auto') {
        target.alignSelf = targetAlignItems;
}

};

},{}],4:[function(require,module,exports){ module.exports = function flexGrow(line) {

if (line.mainSpace > 0) {
        var growFactor = line.children.reduce(function (lastGrowFactor, child) {
                return lastGrowFactor + child.flexGrow;
        }, 0);

        if (growFactor > 0) {
                line.children.forEach(function (child) {
                        child.mainAround += child.flexGrow / growFactor * line.mainSpace;
                });

                line.main = line.children.reduce(function (main, child) {
                        return main + child.mainAround;
                }, 0);

                line.mainSpace = 0;
        }
}

};

},{}],5:[function(require,module,exports){ module.exports = function flexShrink(line) {

if (line.mainSpace < 0) {
        var shrinkFactor = line.children.reduce(function (lastShrinkFactor, child) {
                return lastShrinkFactor + child.flexShrink;
        }, 0);

        if (shrinkFactor > 0) {
                line.children.forEach(function (child) {
                        child.mainAround += child.flexShrink / shrinkFactor * line.mainSpace;
                });

                line.main = line.children.reduce(function (main, child) {
                        return main + child.mainAround;
                }, 0);

                line.mainSpace = 0;
        }
}

};

},{}],6:[function(require,module,exports){ module.exports = function flexboxLines(target) {

var line;

target.lines = [line = {
        main:  0,
        cross: 0,
        children: []
}];

target.children.forEach(function (child) {
        if (
                target.flexWrap === 'nowrap' ||
                line.children.length === 0 ||
                target.mainAround >= line.main + child.mainAround
        ) {
                line.main += child.mainAround;
                line.cross = Math.max(line.cross, child.crossAround);
        } else {
                target.lines.push(line = {
                        main:  child.mainAround,
                        cross: child.crossAround,
                        children: []
                });
        }

        line.children.push(child);
});

};

},{}],7:[function(require,module,exports){ module.exports = function flexbox(target) {

target.descendants.forEach(function (descendant) {
        module.exports(descendant);
});

if (target.display === 'flex') {
        target.children.forEach(function (child) {
                require('./flex-direction')(child, target.flexDirection, target.alignItems);
        });
} else {
        return target;
}

require('./order')(target);
require('./flex-direction')(target, target.flexDirection, target.alignItems);
require('./flexbox-lines')(target);

if (target.main === 'auto') {
        target.main = Math.max(target.mainAround, target.lines.reduce(function (main, line) {
                return Math.max(main, line.main);
        }, 0));

        if (target.flexDirection === 'row') {
                target.mainAround = target.mainClient + target.mainBefore + target.mainAfter;
        } else {
                target.mainAround = target.main + target.mainBefore + target.mainAfter;
        }
}

if (target.cross === 'auto') {
        target.cross = target.lines.reduce(function (cross, line) {
                return cross + line.cross;
        }, 0);

        if (target.flexDirection === 'column') {
                target.crossAround = target.crossClient + target.crossBefore + target.crossAfter;
        } else {
                target.crossAround = target.cross + target.crossBefore + target.crossAfter;
        }

        target.crossSpace = target.crossAround - target.cross;
} else {
        target.crossSpace = target.cross - target.lines.reduce(function (cross, line) {
                return cross + line.cross;
        }, 0);
}

require('./align-content')(target);

target.lines.forEach(function (line) {
        line.mainSpace = target.main - line.main;

        require('./flex-grow')(line);
        require('./flex-shrink')(line);
        require('./margin-main')(line);
        require('./margin-cross')(line);
        require('./justify-content')(line, target.justifyContent);
});

require('./align-items')(target);

return target;

};

},{“./align-content”:1,“./align-items”:2,“./flex-direction”:3,“./flex-grow”:4,“./flex-shrink”:5,“./flexbox-lines”:6,“./justify-content”:8,“./margin-cross”:9,“./margin-main”:10,“./order”:11}],8:[function(require,module,exports){ module.exports = function justifyContent(line, targetJustifyContent) {

var start;
var factor;

if (targetJustifyContent === 'flex-start') {
        start = 0;

        line.children.forEach(function (child) {
                child.mainStart = start;

                start += child.mainAround;
        });
} else if (targetJustifyContent === 'flex-end') {
        start = line.mainSpace;

        line.children.forEach(function (child) {
                child.mainStart = start;

                start += child.mainAround;
        });
} else if (targetJustifyContent === 'center') {
        start = line.mainSpace / 2;

        line.children.forEach(function (child) {
                child.mainStart = start;

                start += child.mainAround;
        });
} else if (targetJustifyContent === 'space-between') {
        factor = line.mainSpace / (line.children.length - 1);

        start = 0;

        line.children.forEach(function (child) {
                child.mainStart = start;

                start += child.mainAround + factor;
        });
} else if (targetJustifyContent === 'space-around') {
        factor = line.mainSpace * 2 / (line.children.length * 2);
        start = factor / 2;

        line.children.forEach(function (child) {
                child.mainStart = start;

                start += child.mainAround + factor;
        });
}

};

},{}],9:[function(require,module,exports){ module.exports = function marginCross(line) {

line.children.forEach(function (child) {
        var count = 0;

        if (child.crossBefore === 'auto') {
                ++count;
        }

        if (child.crossAfter === 'auto') {
                ++count;
        }

        var childSpace = line.cross - child.crossAround;

        if (child.crossBefore === 'auto') {
                child.crossBefore = childSpace / count;

                child.crossAround += child.crossBefore;
        }

        if (child.crossAfter === 'auto') {
                child.crossAfter = childSpace / count;

                child.crossAround += child.crossAfter;
        }
});

};

},{}],10:[function(require,module,exports){ module.exports = function marginCross(line) {

var count = 0;

line.children.forEach(function (child) {
        if (child.mainBefore === 'auto') {
                ++count;
        }

        if (child.mainAfter === 'auto') {
                ++count;
        }
});

if (count > 0) {
        line.children.forEach(function (child) {
                if (child.mainBefore === 'auto') {
                        child.mainBefore = line.mainSpace / count;

                        child.mainAround += child.mainBefore;
                }

                if (child.mainAfter === 'auto') {
                        child.mainAfter = line.mainSpace / count;

                        child.mainAround += child.mainAfter;
                }
        });

        line.mainSpace = 0;
}

};

},{}],11:[function(require,module,exports){ module.exports = function order(target) {

target.children.sort(function (childA, childB) {
        return childA.order - childB.order || childA.index - childB.index;
});

};

},{}],12:[function(require,module,exports){ module.exports = function getFlexStyles(target, data, isFlexChild) {

var style = Object.assign(data, {
        alignContent: 'stretch',
        alignItems: 'stretch',
        alignSelf: 'auto',
        display: 'inline',
        flexBasis: 'auto',
        flexDirection: 'row',
        flexGrow:   0,
        flexShrink: 1,
        flexWrap: 'nowrap',
        justifyContent: 'flex-start',
        height: 'auto',
        marginTop:    0,
        marginRight:  0,
        marginLeft:   0,
        marginBottom: 0,
        maxHeight: 'none',
        maxWidth: 'none',
        minHeight: 0,
        minWidth: 0,
        order: 0,
        position: 'static',
        width: 'auto'
});

if (target.hasAttribute('data-style')) {
        target.setAttribute('style', target.getAttribute('data-style'));
} else {
        target.setAttribute('data-style', target.getAttribute('style') || '');
}

var attr = (target.getAttribute('data-style') || '') + ';' + (target.getAttribute('data-flex') || '');
var re = /([^\s:;]+)\s*:\s*([^;]+?)\s*(;|$)/g;
var decl;

while (decl = re.exec(attr)) {
        var name = decl[1].toLowerCase().replace(/-[a-z]/g, function (match) {
                return match.slice(1).toUpperCase();
        });

        style[name] = parseFloat(decl[2]);

        if (isNaN(style[name])) {
                style[name] = decl[2];
        }
}

if (isFlexChild) {
        target.style.display  = 'inline-block';
        target.style.position = 'absolute';
}

var rect = target.getBoundingClientRect();

style.clientWidth  = rect.width || target.offsetWidth;
style.clientHeight = rect.height || target.offsetHeight;

return style;

};

},{}],13:[function(require,module,exports){ /*! Flexibility 2.0.0 | MIT Licensed | github.com/10up/flexibility */

module.exports = function flexibility(target) {

var data1 = module.exports.walk(target);

var data2 = module.exports.flexbox(data1);

var data3 = module.exports.write(data2);

return data3;

};

module.exports.flexbox = require('./flexbox'); module.exports.getFlexStyles = require('./getFlexStyles'); module.exports.walk = require('./walk'); module.exports.write = require('./write');

// module.exports.process = require('./process'); // module.exports.support = require('./support');

},{“./flexbox”:7,“./getFlexStyles”:12,“./walk”:14,“./write”:15}],14:[function(require,module,exports){ var getFlexStyles = require('../getFlexStyles');

module.exports = function walk(target, ancestorData, isFlexChild) {

var flexContainerRE = /(^|;)\s*display\s*:\s*(inline-)?flex\s*(;|$)/i;
var isFlexContainer = flexContainerRE.test(target.getAttribute('data-flex'));
var data = {
        node: target,
        children: [],
        descendants: []
};

if (isFlexContainer) {
        if (ancestorData !== undefined) {
                ancestorData.descendants.push(data);
        }
}

if (isFlexContainer || !ancestorData) {
        ancestorData = data;
}

Array.prototype.forEach.call(target.childNodes, function (childNode) {
        if (isFlexContainer && childNode.nodeType === 3 && childNode.nodeValue.trim()) {
                var oldNode = childNode;

                childNode = target.insertBefore(document.createElement('flex-item'), oldNode);

                childNode.appendChild(oldNode);
        }

        if (childNode.nodeType === 1) {
                var childData = module.exports(childNode, ancestorData, isFlexContainer);

                if (isFlexContainer) {
                        data.children.push(childData);
                }
        }
});

if (isFlexContainer || isFlexChild) {
        getFlexStyles(target, data, isFlexChild);
}

return data;

};

},{“../getFlexStyles”:12}],15:[function(require,module,exports){ module.exports = function write(target) {

target.descendants.filter(function (descendant) {
        return target.children.indexOf(descendant) === -1;
}).forEach(function (descendant) {
        module.exports(descendant);
});

if (!target.display) {
        return;
}

var style = target.node.style;

if ('mainStart' in target) {
        style.position = 'absolute';

        if (target.mainAxis === 'inline') {
                style.left = target.mainStart  + 'px';
                style.top  = target.crossStart + 'px';

                style.marginTop    = target.crossBefore + 'px';
                style.marginRight  = target.mainAfter   + 'px';
                style.marginBottom = target.crossAfter  + 'px';
                style.marginLeft   = target.mainBefore  + 'px';
        } else {
                style.left = target.crossStart + 'px';
                style.top  = target.mainStart  + 'px';

                style.marginTop    = target.mainBefore  + 'px';
                style.marginRight  = target.crossAfter  + 'px';
                style.marginBottom = target.mainAfter   + 'px';
                style.marginLeft   = target.crossBefore + 'px';
        }

        if (target.mainAxis === 'inline') {
                style.width  = target.mainAround  - target.mainBefore - target.mainAfter + 'px';
                style.height = target.crossAround - target.crossBefore - target.crossAfter + 'px';
        } else {
                if (target.cross === 'auto') {
                        style.width = target.crossClient - target.crossBefore - target.crossAfter + 'px';
                } else {
                        style.width = target.crossAround - target.crossBefore - target.crossAfter + 'px';
                }

                if (target.main === 'auto') {
                        style.height = target.mainClient - target.mainBefore - target.mainAfter + 'px';
                } else {
                        style.height = target.mainAround - target.mainBefore - target.mainAfter + 'px';
                }
        }
} else {
        if (!style.position) {
                style.position = 'relative';
        }

        if (target.mainAxis === 'inline') {
                style.width = target.mainAround - target.mainBefore - target.mainAfter + 'px';
                style.height = target.crossAround - target.crossBefore - target.crossAfter + 'px';
        } else {
                style.width = target.crossAround - target.crossBefore - target.crossAfter + 'px';
                style.height = target.mainAround - target.mainBefore - target.mainAfter + 'px';
        }
}

if (target.children) {
        target.children.forEach(function (child) {
                module.exports(child);
        });
}

};

},{}]},{},[13])(13) }); /*! responsive-nav.js 1.0.39

* https://github.com/viljamis/responsive-nav.js
* http://responsive-nav.com
*
* Copyright (c) 2015 @viljamis
* Available under the MIT license
Licensed under the MIT license.

Copyright © 2013 Viljami Salminen, viljamis.com/

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

*/

/* global Event */ (function (document, window, index) {

// Index is used to keep multiple navs on the same page namespaced

"use strict";

var responsiveNav = function (el, options) {

  var computed = !!window.getComputedStyle;

  /**
   * getComputedStyle polyfill for old browsers
   */
  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;
    };
  }
  /* exported addEvent, removeEvent, getChildren, setAttributes, addClass, removeClass, forEach */

  /**
   * Add Event
   * fn arg can be an object or a function, thanks to handleEvent
   * read more at: http://www.thecssninja.com/javascript/handleevent
   *
   * @param  {element}  element
   * @param  {event}    event
   * @param  {Function} fn
   * @param  {boolean}  bubbling
   */
  var 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);
        }
      }
    },

    /**
     * Remove Event
     *
     * @param  {element}  element
     * @param  {event}    event
     * @param  {Function} fn
     * @param  {boolean}  bubbling
     */
    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);
        }
      }
    },

    /**
     * Get the children of any element
     *
     * @param  {element}
     * @return {array} Returns matching elements in an array
     */
    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;
    },

    /**
     * Sets multiple attributes at once
     *
     * @param {element} element
     * @param {attrs}   attrs
     */
    setAttributes = function (el, attrs) {
      for (var key in attrs) {
        el.setAttribute(key, attrs[key]);
      }
    },

    /**
     * Adds a class to any element
     *
     * @param {element} element
     * @param {string}  class
     */
    addClass = function (el, cls) {
      if (el.className.indexOf(cls) !== 0) {
        el.className += " " + cls;
        el.className = el.className.replace(/(^\s*)|(\s*$)/g,"");
      }
    },

    /**
     * Remove a class from any element
     *
     * @param  {element} element
     * @param  {string}  class
     */
    removeClass = function (el, cls) {
      var reg = new RegExp("(\\s|^)" + cls + "(\\s|$)");
      el.className = el.className.replace(reg, " ").replace(/(^\s*)|(\s*$)/g,"");
    },

    /**
     * forEach method that passes back the stuff we need
     *
     * @param  {array}    array
     * @param  {Function} callback
     * @param  {scope}    scope
     */
    forEach = function (array, callback, scope) {
      for (var i = 0; i < array.length; i++) {
        callback.call(scope, i, array[i]);
      }
    };

  var nav,
    opts,
    navToggle,
    styleElement = document.createElement("style"),
    htmlEl = document.documentElement,
    hasAnimFinished,
    isMobile,
    navOpen;

  var ResponsiveNav = function (el, options) {
      var i;

      /**
       * Default options
       * @type {Object}
       */
      this.options = {
        animate: true,                    // Boolean: Use CSS3 transitions, true or false
        transition: 284,                  // Integer: Speed of the transition, in milliseconds
        label: "Menu",                    // String: Label for the navigation toggle
        insert: "before",                 // String: Insert the toggle before or after the navigation
        customToggle: "",                 // Selector: Specify the ID of a custom toggle
        closeOnNavClick: false,           // Boolean: Close the navigation when one of the links are clicked
        openPos: "relative",              // String: Position of the opened nav, relative or static
        navClass: "nav-collapse",         // String: Default CSS class. If changed, you need to edit the CSS too!
        navActiveClass: "js-nav-active",  // String: Class that is added to <html> element when nav is active
        jsClass: "js",                    // String: 'JS enabled' class which is added to <html> element
        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(htmlEl, this.options.jsClass);

      // Wrapper
      this.wrapperEl = el.replace("#", "");

      // Try selecting ID first
      if (document.getElementById(this.wrapperEl)) {
        this.wrapper = document.getElementById(this.wrapperEl);

      // If element with an ID doesn't exist, use querySelector
      } else if (document.querySelector(this.wrapperEl)) {
        this.wrapper = document.querySelector(this.wrapperEl);

      // If element doesn't exists, stop here.
      } else {
        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 = {

    /**
     * Unattaches events and removes any classes that were added
     */
    destroy: function () {
      this._removeStyles();
      removeClass(nav, "closed");
      removeClass(nav, "opened");
      removeClass(nav, opts.navClass);
      removeClass(nav, opts.navClass + "-" + this.index);
      removeClass(htmlEl, opts.navActiveClass);
      nav.removeAttribute("style");
      nav.removeAttribute("aria-hidden");

      removeEvent(window, "resize", this, false);
      removeEvent(window, "focus", 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");
      }
    },

    /**
     * Toggles the navigation open/close
     */
    toggle: function () {
      if (hasAnimFinished === true) {
        if (!navOpen) {
          this.open();
        } else {
          this.close();
        }
      }
    },

    /**
     * Opens the navigation
     */
    open: function () {
      if (!navOpen) {
        removeClass(nav, "closed");
        addClass(nav, "opened");
        addClass(htmlEl, opts.navActiveClass);
        addClass(navToggle, "active");
        nav.style.position = opts.openPos;
        setAttributes(nav, {"aria-hidden": "false"});
        navOpen = true;
        opts.open();
      }
    },

    /**
     * Closes the navigation
     */
    close: function () {
      if (navOpen) {
        addClass(nav, "closed");
        removeClass(nav, "opened");
        removeClass(htmlEl, opts.navActiveClass);
        removeClass(navToggle, "active");
        setAttributes(nav, {"aria-hidden": "true"});

        // If animations are enabled, wait until they finish
        if (opts.animate) {
          hasAnimFinished = false;
          setTimeout(function () {
            nav.style.position = "absolute";
            hasAnimFinished = true;
          }, opts.transition + 10);

        // Animations aren't enabled, we can do these immediately
        } else {
          nav.style.position = "absolute";
        }

        navOpen = false;
        opts.close();
      }
    },

    /**
     * Resize is called on window resize and orientation change.
     * It initializes the CSS styles and height calculations.
     */
    resize: function () {

      // Resize watches navigation toggle's display state
      if (window.getComputedStyle(navToggle, null).getPropertyValue("display") !== "none") {

        isMobile = true;
        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 {

        isMobile = false;
        setAttributes(navToggle, {"aria-hidden": "true"});
        setAttributes(nav, {"aria-hidden": "false"});
        nav.style.position = opts.openPos;
        this._removeStyles();
      }
    },

    /**
     * Takes care of all even handling
     *
     * @param  {event} event
     * @return {type} returns the type of event that should be used
     */
    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 "focus":
      case "resize":
        this.resize(evt);
        break;
      }
    },

    /**
     * Initializes the widget
     */
    _init: function () {
      this.index = index++;

      addClass(nav, opts.navClass);
      addClass(nav, opts.navClass + "-" + this.index);
      addClass(nav, "closed");
      hasAnimFinished = true;
      navOpen = false;

      this._closeOnNavClick();
      this._createToggle();
      this._transitions();
      this.resize();

      /**
       * On IE8 the resize event triggers too early for some reason
       * so it's called here again on init to make sure all the
       * calculated styles are correct.
       */
      var self = this;
      setTimeout(function () {
        self.resize();
      }, 20);

      addEvent(window, "resize", this, false);
      addEvent(window, "focus", 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 here
       */
      opts.init();
    },

    /**
     * Creates Styles to the <head>
     */
    _createStyles: function () {
      if (!styleElement.parentNode) {
        styleElement.type = "text/css";
        document.getElementsByTagName("head")[0].appendChild(styleElement);
      }
    },

    /**
     * Removes styles from the <head>
     */
    _removeStyles: function () {
      if (styleElement.parentNode) {
        styleElement.parentNode.removeChild(styleElement);
      }
    },

    /**
     * Creates Navigation Toggle
     */
    _createToggle: function () {

      // If there's no toggle, let's create one
      if (!opts.customToggle) {
        var toggle = document.createElement("a");
        toggle.innerHTML = opts.label;
        setAttributes(toggle, {
          "href": "#",
          "class": "nav-toggle"
        });

        // Determine where to insert the toggle
        if (opts.insert === "after") {
          nav.parentNode.insertBefore(toggle, nav.nextSibling);
        } else {
          nav.parentNode.insertBefore(toggle, nav);
        }

        navToggle = toggle;

      // There is a toggle already, let's use that one
      } 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");
        }
      }
    },

    /**
     * Closes the navigation when a link inside is clicked.
     */
    _closeOnNavClick: function () {
      if (opts.closeOnNavClick) {
        var links = nav.getElementsByTagName("a"),
          self = this;
        forEach(links, function (i, el) {
          addEvent(links[i], "click", function () {
            if (isMobile) {
              self.toggle();
            }
          }, false);
        });
      }
    },

    /**
     * Prevents the default functionality.
     *
     * @param  {event} event
     */
    _preventDefault: function(e) {
      if (e.preventDefault) {
        if (e.stopImmediatePropagation) {
          e.stopImmediatePropagation();
        }
        e.preventDefault();
        e.stopPropagation();
        return false;

      // This is strictly for old IE
      } else {
        e.returnValue = false;
      }
    },

    /**
     * On touch start we get the location of the touch.
     *
     * @param  {event} event
     */
    _onTouchStart: function (e) {
      if (!Event.prototype.stopImmediatePropagation) {
        this._preventDefault(e);
      }
      this.startX = e.touches[0].clientX;
      this.startY = e.touches[0].clientY;
      this.touchHasMoved = false;

      /**
       * Remove mouseup event completely here to avoid
       * double triggering the event.
       */
      removeEvent(navToggle, "mouseup", this, false);
    },

    /**
     * Check if the user is scrolling instead of tapping.
     *
     * @param  {event} event
     */
    _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;
      }
    },

    /**
     * On touch end toggle the navigation.
     *
     * @param  {event} event
     */
    _onTouchEnd: function (e) {
      this._preventDefault(e);
      if (!isMobile) {
        return;
      }

      // If the user isn't scrolling
      if (!this.touchHasMoved) {

        // If the event type is touch
        if (e.type === "touchend") {
          this.toggle();
          return;

        // Event type was click, not touch
        } else {
          var evt = e || window.event;

          // If it isn't a right click, do toggling
          if (!(evt.which === 3 || evt.button === 2)) {
            this.toggle();
          }
        }
      }
    },

    /**
     * For keyboard accessibility, toggle the navigation on Enter
     * keypress too.
     *
     * @param  {event} event
     */
    _onKeyUp: function (e) {
      var evt = e || window.event;
      if (evt.keyCode === 13) {
        this.toggle();
      }
    },

    /**
     * Adds the needed CSS transitions if animations are enabled
     */
    _transitions: function () {
      if (opts.animate) {
        var objStyle = nav.style,
          transition = "max-height " + opts.transition + "ms";

        objStyle.WebkitTransition =
        objStyle.MozTransition =
        objStyle.OTransition =
        objStyle.transition = transition;
      }
    },

    /**
     * Calculates the height of the navigation and then creates
     * styles which are later added to the page <head>
     */
    _calcHeight: function () {
      var savedHeight = 0;
      for (var i = 0; i < nav.inner.length; i++) {
        savedHeight += nav.inner[i].offsetHeight;
      }

      var innerStyles = "." + opts.jsClass + " ." + opts.navClass + "-" + this.index + ".opened{max-height:" + savedHeight + "px !important} ." + opts.jsClass + " ." + opts.navClass + "-" + this.index + ".opened.dropdown-active {max-height:9999px !important}";

      if (styleElement.styleSheet) {
        styleElement.styleSheet.cssText = innerStyles;
      } else {
        styleElement.innerHTML = innerStyles;
      }

      innerStyles = "";
    }

  };

  /**
   * Return new Responsive Nav
   */
  return new ResponsiveNav(el, options);

};

if (typeof module !== "undefined" && module.exports) {
  module.exports = responsiveNav;
} else {
  window.responsiveNav = responsiveNav;
}

}(document, window, 0));