<commit_before>(function (root, factory) {
    if (typeof define === "function" && define.amd) {
        define("priorityNav", factory(root));
    } else if (typeof exports === "object") {
        module.exports = factory(root);
    } else {
        root.priorityNav = factory(root);
    }
})(window || this, function (root) {

    "use strict";

    /**
     * Variables
     */
    var priorityNav = {}; // Object for public APIs
    var breaks = []; // Object to store instances with breakpoints where the instances menu item"s didin"t fit.
    var supports = !!document.querySelector && !!root.addEventListener; // Feature test
    var settings = {};
    var instance = 0;
    var count = 0;
    var mainNavWrapper, totalWidth, restWidth, mainNav, navDropdown, navDropdownToggle, dropDownWidth, toggleWrapper;

    /**
     * Default settings
     * @type {{initClass: string, navDropdown: string, navDropdownToggle: string, mainNavWrapper: string, moved: Function, movedBack: Function}}
     */
    var defaults = {
        initClass: "js-priorityNav",
        mainNavWrapper: "nav",
        mainNav: "ul",
        navDropdown: ".nav__dropdown",
        navDropdownToggle: ".nav__dropdown-toggle",
        navDropdownLabel: "more",
        throttleDelay: 50,
        offsetPixels: 0,
        count: true,

        //Callbacks
        moved: function () {
        },
        movedBack: function () {
        }
    };

    /**
     * A simple forEach() implementation for Arrays, Objects and NodeLists
     * @private
     * @param {Array|Object|NodeList} collection Collection of items to iterate
     * @param {Function} callback Callback function for each iteration
     * @param {Array|Object|NodeList} scope Object/NodeList/Array that forEach is iterating over (aka `this`)
     */
    var forEach = function (collection, callback, scope) {
        if (Object.prototype.toString.call(collection) === "[object Object]") {
            for (var prop in collection) {
                if (Object.prototype.hasOwnProperty.call(collection, prop)) {
                    callback.call(scope, collection[prop], prop, collection);
                }
            }
        } else {
            for (var i = 0, len = collection.length; i < len; i++) {
                callback.call(scope, collection[i], i, collection);
            }
        }
    };

    /**
     * Get the closest matching element up the DOM tree
     * @param {Element} elem Starting element
     * @param {String} selector Selector to match against (class, ID, or data attribute)
     * @return {Boolean|Element} Returns false if not match found
     */
    var getClosest = function (elem, selector) {
        var firstChar = selector.charAt(0);
        for (; elem && elem !== document; elem = elem.parentNode) {
            if (firstChar === ".") {
                if (elem.classList.contains(selector.substr(1))) {
                    return elem;
                }
            } else if (firstChar === "#") {
                if (elem.id === selector.substr(1)) {
                    return elem;
                }
            } else if (firstChar === "[") {
                if (elem.hasAttribute(selector.substr(1, selector.length - 2))) {
                    return elem;
                }
            }
        }
        return false;
    };

    /**
     * Merge defaults with user options
     * @private
     * @param {Object} defaults Default settings
     * @param {Object} options User options
     * @returns {Object} Merged values of defaults and options
     */
    var extend = function (defaults, options) {
        var extended = {};
        forEach(defaults, function (value, prop) {
            extended[prop] = defaults[prop];
        });
        forEach(options, function (value, prop) {
            extended[prop] = options[prop];
        });
        return extended;
    };

    /**
     * Debounced resize to throttle execution
     * @param func
     * @param wait
     * @param immediate
     * @returns {Function}
     */
    function debounce(func, wait, immediate) {
        var timeout;
        return function () {
            var context = this, args = arguments;
            var later = function () {
                timeout = null;
                if (!immediate) func.apply(context, args);
            };
            var callNow = immediate && !timeout;
            clearTimeout(timeout);
            timeout = setTimeout(later, wait);
            if (callNow) func.apply(context, args);
        };
    }

    /**
     * Toggle class on element
     * @param el
     * @param className
     */
    var toggleClass = function (el, className) {
        if (el.classList) {
            el.classList.toggle(className);
        } else {
            var classes = el.className.split(" ");
            var existingIndex = classes.indexOf(className);

            if (existingIndex >= 0)
                classes.splice(existingIndex, 1); else
                classes.push(className);

            el.className = classes.join(" ");
        }
    };

    /**
     * Check if dropdown menu is already on page before creating it
     * @param mainNavWrapper
     */
    var prepareHtml = function (_this) {
        /**
         * Create dropdow menu
         * @type {HTMLElement}
         */
        toggleWrapper = document.createElement("span");
        navDropdown = document.createElement("ul");
        navDropdownToggle = document.createElement("button");

        /**
         * Set label for dropdown toggle
         * @type {string}
         */
        navDropdownToggle.innerHTML = settings.navDropdownLabel;

        /**
         * Move elements to the right spot
         */
        _this.insertAfter(toggleWrapper, _this.querySelector(mainNav));
        toggleWrapper.appendChild(navDropdown);
        toggleWrapper.appendChild(navDropdownToggle);

        /**
         * Add classes so we can target elements
         */
        navDropdown.classList.add(settings.navDropdown.substr(1));
        navDropdown.classList.add("priority-nav__dropdown");

        navDropdownToggle.classList.add(settings.navDropdownToggle.substr(1));
        navDropdownToggle.classList.add("priority-nav__dropdown-toggle");

        toggleWrapper.classList.add(settings.navDropdown.substr(1)+"-wrapper");
        toggleWrapper.classList.add("priority-nav__wrapper");

        _this.classList.add("priority-nav");
    };

    /**
     * Get innerwidth without padding
     * @param element
     * @returns {number}
     */
    var getElementContentWidth = function(element) {
        var styles = window.getComputedStyle(element);
        var padding = parseFloat(styles.paddingLeft) +
            parseFloat(styles.paddingRight);

        return element.clientWidth - padding;
    };

    /**
     * Get width
     * @param elem
     * @returns {number}
     */
    var calculateWidths = function (_this) {
        totalWidth = getElementContentWidth(_this);
        //Check if parent is the navwrapper before calculating its width
        if (_this.querySelector(navDropdown).parentNode === _this) {
            dropDownWidth = _this.querySelector(navDropdown).offsetWidth;
        } else {
            dropDownWidth = 0;
        }
        restWidth = getChildrenWidth(_this) + settings.offsetPixels;
    };

    /**
     * Move item to array
     * @param item
     */
    priorityNav.doesItFit = function (_this) {

        /**
         * Check if it is the first run
         */
        var delay = _this.getAttribute("instance") === 0 ? delay : settings.throttleDelay;

        /**
         * Increase instance
         */
        instance++;

        /**
         * Debounced execution of the main logic
         */
        (debounce(function () {

            /**
             * Get the current element"s instance
             * @type {string}
             */
            var identifier = _this.getAttribute("instance");

            /**
             * Update width
             */
            calculateWidths(_this);

            /**
             * Keep executing until all menu items that are overflowing are moved
             */
            while (totalWidth < restWidth && _this.querySelector(mainNav).children.length > 0) {
                //move item to dropdown
                priorityNav.toDropdown(_this, identifier);
                //recalculate widths
                calculateWidths(_this, identifier);
            }

            /**
             * Keep executing until all menu items that are able to move back are moved
             */
            while (totalWidth > breaks[identifier][breaks[identifier].length - 1]) {
                //move item to menu
                priorityNav.toMenu(_this, identifier);
            }

            /**
             * If there are no items in dropdown hide dropdown
             */
            if (breaks[identifier].length < 1) {
                _this.querySelector(navDropdown).classList.remove("show");
            }

            /**
             * Check if we need to show toggle menu button
             */
            showToggle(_this, identifier);

        }, delay ))();
    };

    /**
     * Show/hide toggle button
     */
    var showToggle = function (_this, identifier) {
        if (breaks[identifier].length < 1) {
            _this.querySelector(navDropdownToggle).classList.add("priority-nav-is-hidden");
            _this.querySelector(navDropdownToggle).classList.remove("priority-nav-is-visible");
            _this.classList.remove("priority-nav-has-dropdown");
        } else {
            _this.querySelector(navDropdownToggle).classList.add("priority-nav-is-visible");
            _this.querySelector(navDropdownToggle).classList.remove("priority-nav-is-hidden");
            _this.classList.add("priority-nav-has-dropdown");
        }
    };

    /**
     * Update count on dropdown toggle button
     */
    var updateCount = function (_this, identifier) {
        _this.querySelector(navDropdownToggle).dataset.count = breaks[identifier].length;
    };

    /**
     * Move item to dropdown
     */
    priorityNav.toDropdown = function (_this, identifier) {

        /**
         * move last child of navigation menu to dropdown
         */
        if (_this.querySelector(navDropdown).firstChild && _this.querySelector(mainNav).children.length > 0) {
            _this.querySelector(navDropdown).insertBefore(_this.querySelector(mainNav).lastElementChild, _this.querySelector(navDropdown).firstChild);
        } else if (_this.querySelector(mainNav).children.length > 0) {
            _this.querySelector(navDropdown).appendChild(_this.querySelector(mainNav).lastElementChild);
        }

        /**
         * store breakpoints
         */
        breaks[identifier].push(restWidth);

        /**
         * check if we need to show toggle menu button
         */
        showToggle(_this, identifier);

        /**
         * update count on dropdown toggle button
         */
        if (_this.querySelector(mainNav).children.length > 0 && settings.count) {
            updateCount(_this, identifier);
        }

        /**
         * If item has been moved to dropdown trigger the callback
         */
        settings.moved();
    };

    /**
     * Move item to menu
     */
    priorityNav.toMenu = function (_this, identifier) {

        /**
         * move last child of navigation menu to dropdown
         */
        if (_this.querySelector(navDropdown).children.length > 0) _this.querySelector(mainNav).appendChild(_this.querySelector(navDropdown).firstElementChild);

        /**
         * remove last breakpoint
         */
        breaks[identifier].pop();

        /**
         * Check if we need to show toggle menu button
         */
        showToggle(_this, identifier);

        /**
         * update count on dropdown toggle button
         */
        if (_this.querySelector(mainNav).children.length > 0 && settings.count) {
            updateCount(_this, identifier);
        }

        /**
         * If item has been moved back to the main menu trigger the callback
         */
        settings.movedBack();
    };

    /**
     * Count width of children and return the value
     * @param e
     */
    var getChildrenWidth = function (e) {
        var children = e.childNodes;
        var sum = 0;
        for (var i = 0; i < children.length; i++) {
            if (children[i].nodeType !== 3) {
                if(!isNaN(children[i].offsetWidth)){
                    sum += children[i].offsetWidth;
                }

            }
        }
        return sum;
    };

    /**
     * Bind eventlisteners
     */
    var listeners = function (_this) {

        // Check if an item needs to move
        if(window.attachEvent) {
            window.attachEvent("onresize", function() {
                if(priorityNav.doesItFit)priorityNav.doesItFit(instance, _this);
            });
        }
        else if(window.addEventListener) {
            window.addEventListener("resize", function() {
                if(priorityNav.doesItFit)priorityNav.doesItFit(instance, _this);
            }, true);
        }

        // Toggle dropdown
        _this.querySelector(navDropdownToggle).addEventListener("click", function () {
            toggleClass(_this.querySelector(settings.navDropdown), "show");
            toggleClass(this, "is-open");
            toggleClass(_this, "is-open");
        });

        /*
         * Remove when clicked outside dropdown
         */
        document.addEventListener("click", function (event) {
            if (!getClosest(event.target, settings.navDropdown) && event.target !== _this.querySelector(navDropdownToggle)) {
                _this.querySelector(navDropdown).classList.remove("show");
                _this.querySelector(navDropdownToggle).classList.remove("is-open");
                _this.classList.remove("is-open");
            }
        });

        /**
         * Remove when escape key is pressed
         */
        document.onkeydown = function (evt) {
            evt = evt || window.event;
            if (evt.keyCode === 27) {
                navDropdown.classList.remove("show");
                navDropdownToggle.classList.remove("is-open");
                mainNavWrapper.classList.remove("is-open");
            }
        };
    };

    /**
     * Remove function
     */
    Element.prototype.remove = function() {
        this.parentElement.removeChild(this);
    };

    /*global HTMLCollection */
    NodeList.prototype.remove = HTMLCollection.prototype.remove = function() {
        for(var i = 0, len = this.length; i < len; i++) {
            if(this[i] && this[i].parentElement) {
                this[i].parentElement.removeChild(this[i]);
            }
        }
    };

    /**
     * Destroy the current initialization.
     * @public
     */
    priorityNav.destroy = function () {
        // If plugin isn"t already initialized, stop
        if (!settings) return;
        // Remove feedback class
        document.documentElement.classList.remove(settings.initClass);
        // Remove toggle
        toggleWrapper.remove();
        // Remove settings
        settings = null;
        delete priorityNav.init;
        delete priorityNav.doesItFit;
    };

    /**
     * insertAfter function
     * @param n
     * @param r
     */
    Node.prototype.insertAfter = function(n,r) {this.insertBefore(n,r.nextSibling);};

    /**
     * Initialize Plugin
     * @public
     * @param {Object} options User settings
     */
    priorityNav.init = function (options) {

        // Feature test.
        if (!supports){
            console.warn("This browser doesn't support priorityNav");
            return;
        }

        /**
         * Merge user options with defaults
         * @type {Object}
         */
        settings = extend(defaults, options || {});

        /**
         * Store nodes
         * @type {NodeList}
         */
        var elements = document.querySelectorAll(settings.mainNavWrapper);

        /**
         * Loop over every instance and reference _this
         */
        forEach(elements, function(_this){

            /**
             * Create breaks array
             * @type {number}
             */
            breaks[count] = [];

            /**
             * Set the instance number as data attribute
             */
            _this.setAttribute("instance", count++);

            /**
             * Store the wrapper element
             */
            mainNavWrapper = _this;
            if (!mainNavWrapper) {
                console.warn("couldn't find the specified mainNavWrapper element");
                return;
            }

            /**
             * Store the menu elementStore the menu element
             */
            mainNav = settings.mainNav;
            if (!_this.querySelector(mainNav)) {
                console.warn("couldn't find the specified mainNav element");
                return;
            }

            /**
             * Check if we need to create the dropdown elements
             */
            prepareHtml(_this);

            /**
             * Store the dropdown element
             */
            navDropdown = settings.navDropdown;
            if (!_this.querySelector(navDropdown)) {
                console.warn("couldn't find the specified navDropdown element");
                return;
            }

            /**
             * Store the dropdown toggle element
             */
            navDropdownToggle = settings.navDropdownToggle;
            if (!_this.querySelector(navDropdownToggle)) {
                console.warn("couldn't find the specified navDropdownToggle element");
                return;
            }

            /**
             * Event listeners
             */
            listeners(_this);

            /**
             * Start first check
             */
            priorityNav.doesItFit(_this);

        });

        /**
         * Count amount of instances
         */
        instance++;

        /**
         * Add class to HTML element to activate conditional CSS
         */
        document.documentElement.classList.add(settings.initClass);
    };

    /**
     * Public APIs
     */
    return priorityNav;

});<commit_msg>fixed old paramater in function<commit_after>(function (root, factory) {
    if (typeof define === "function" && define.amd) {
        define("priorityNav", factory(root));
    } else if (typeof exports === "object") {
        module.exports = factory(root);
    } else {
        root.priorityNav = factory(root);
    }
})(window || this, function (root) {

    "use strict";

    /**
     * Variables
     */
    var priorityNav = {}; // Object for public APIs
    var breaks = []; // Object to store instances with breakpoints where the instances menu item"s didin"t fit.
    var supports = !!document.querySelector && !!root.addEventListener; // Feature test
    var settings = {};
    var instance = 0;
    var count = 0;
    var mainNavWrapper, totalWidth, restWidth, mainNav, navDropdown, navDropdownToggle, dropDownWidth, toggleWrapper;

    /**
     * Default settings
     * @type {{initClass: string, navDropdown: string, navDropdownToggle: string, mainNavWrapper: string, moved: Function, movedBack: Function}}
     */
    var defaults = {
        initClass: "js-priorityNav",
        mainNavWrapper: "nav",
        mainNav: "ul",
        navDropdown: ".nav__dropdown",
        navDropdownToggle: ".nav__dropdown-toggle",
        navDropdownLabel: "more",
        throttleDelay: 50,
        offsetPixels: 0,
        count: true,

        //Callbacks
        moved: function () {
        },
        movedBack: function () {
        }
    };

    /**
     * A simple forEach() implementation for Arrays, Objects and NodeLists
     * @private
     * @param {Array|Object|NodeList} collection Collection of items to iterate
     * @param {Function} callback Callback function for each iteration
     * @param {Array|Object|NodeList} scope Object/NodeList/Array that forEach is iterating over (aka `this`)
     */
    var forEach = function (collection, callback, scope) {
        if (Object.prototype.toString.call(collection) === "[object Object]") {
            for (var prop in collection) {
                if (Object.prototype.hasOwnProperty.call(collection, prop)) {
                    callback.call(scope, collection[prop], prop, collection);
                }
            }
        } else {
            for (var i = 0, len = collection.length; i < len; i++) {
                callback.call(scope, collection[i], i, collection);
            }
        }
    };

    /**
     * Get the closest matching element up the DOM tree
     * @param {Element} elem Starting element
     * @param {String} selector Selector to match against (class, ID, or data attribute)
     * @return {Boolean|Element} Returns false if not match found
     */
    var getClosest = function (elem, selector) {
        var firstChar = selector.charAt(0);
        for (; elem && elem !== document; elem = elem.parentNode) {
            if (firstChar === ".") {
                if (elem.classList.contains(selector.substr(1))) {
                    return elem;
                }
            } else if (firstChar === "#") {
                if (elem.id === selector.substr(1)) {
                    return elem;
                }
            } else if (firstChar === "[") {
                if (elem.hasAttribute(selector.substr(1, selector.length - 2))) {
                    return elem;
                }
            }
        }
        return false;
    };

    /**
     * Merge defaults with user options
     * @private
     * @param {Object} defaults Default settings
     * @param {Object} options User options
     * @returns {Object} Merged values of defaults and options
     */
    var extend = function (defaults, options) {
        var extended = {};
        forEach(defaults, function (value, prop) {
            extended[prop] = defaults[prop];
        });
        forEach(options, function (value, prop) {
            extended[prop] = options[prop];
        });
        return extended;
    };

    /**
     * Debounced resize to throttle execution
     * @param func
     * @param wait
     * @param immediate
     * @returns {Function}
     */
    function debounce(func, wait, immediate) {
        var timeout;
        return function () {
            var context = this, args = arguments;
            var later = function () {
                timeout = null;
                if (!immediate) func.apply(context, args);
            };
            var callNow = immediate && !timeout;
            clearTimeout(timeout);
            timeout = setTimeout(later, wait);
            if (callNow) func.apply(context, args);
        };
    }

    /**
     * Toggle class on element
     * @param el
     * @param className
     */
    var toggleClass = function (el, className) {
        if (el.classList) {
            el.classList.toggle(className);
        } else {
            var classes = el.className.split(" ");
            var existingIndex = classes.indexOf(className);

            if (existingIndex >= 0)
                classes.splice(existingIndex, 1); else
                classes.push(className);

            el.className = classes.join(" ");
        }
    };

    /**
     * Check if dropdown menu is already on page before creating it
     * @param mainNavWrapper
     */
    var prepareHtml = function (_this) {
        /**
         * Create dropdow menu
         * @type {HTMLElement}
         */
        toggleWrapper = document.createElement("span");
        navDropdown = document.createElement("ul");
        navDropdownToggle = document.createElement("button");

        /**
         * Set label for dropdown toggle
         * @type {string}
         */
        navDropdownToggle.innerHTML = settings.navDropdownLabel;

        /**
         * Move elements to the right spot
         */
        _this.insertAfter(toggleWrapper, _this.querySelector(mainNav));
        toggleWrapper.appendChild(navDropdown);
        toggleWrapper.appendChild(navDropdownToggle);

        /**
         * Add classes so we can target elements
         */
        navDropdown.classList.add(settings.navDropdown.substr(1));
        navDropdown.classList.add("priority-nav__dropdown");

        navDropdownToggle.classList.add(settings.navDropdownToggle.substr(1));
        navDropdownToggle.classList.add("priority-nav__dropdown-toggle");

        toggleWrapper.classList.add(settings.navDropdown.substr(1)+"-wrapper");
        toggleWrapper.classList.add("priority-nav__wrapper");

        _this.classList.add("priority-nav");
    };

    /**
     * Get innerwidth without padding
     * @param element
     * @returns {number}
     */
    var getElementContentWidth = function(element) {
        var styles = window.getComputedStyle(element);
        var padding = parseFloat(styles.paddingLeft) +
            parseFloat(styles.paddingRight);

        return element.clientWidth - padding;
    };

    /**
     * Get width
     * @param elem
     * @returns {number}
     */
    var calculateWidths = function (_this) {
        totalWidth = getElementContentWidth(_this);
        //Check if parent is the navwrapper before calculating its width
        if (_this.querySelector(navDropdown).parentNode === _this) {
            dropDownWidth = _this.querySelector(navDropdown).offsetWidth;
        } else {
            dropDownWidth = 0;
        }
        restWidth = getChildrenWidth(_this) + settings.offsetPixels;
    };

    /**
     * Move item to array
     * @param item
     */
    priorityNav.doesItFit = function (_this) {

        /**
         * Check if it is the first run
         */
        var delay = _this.getAttribute("instance") === 0 ? delay : settings.throttleDelay;

        /**
         * Increase instance
         */
        instance++;

        /**
         * Debounced execution of the main logic
         */
        (debounce(function () {

            /**
             * Get the current element"s instance
             * @type {string}
             */
            var identifier = _this.getAttribute("instance");

            /**
             * Update width
             */
            calculateWidths(_this);

            /**
             * Keep executing until all menu items that are overflowing are moved
             */
            while (totalWidth < restWidth && _this.querySelector(mainNav).children.length > 0) {
                //move item to dropdown
                priorityNav.toDropdown(_this, identifier);
                //recalculate widths
                calculateWidths(_this, identifier);
            }

            /**
             * Keep executing until all menu items that are able to move back are moved
             */
            while (totalWidth > breaks[identifier][breaks[identifier].length - 1]) {
                //move item to menu
                priorityNav.toMenu(_this, identifier);
            }

            /**
             * If there are no items in dropdown hide dropdown
             */
            if (breaks[identifier].length < 1) {
                _this.querySelector(navDropdown).classList.remove("show");
            }

            /**
             * Check if we need to show toggle menu button
             */
            showToggle(_this, identifier);

        }, delay ))();
    };

    /**
     * Show/hide toggle button
     */
    var showToggle = function (_this, identifier) {
        if (breaks[identifier].length < 1) {
            _this.querySelector(navDropdownToggle).classList.add("priority-nav-is-hidden");
            _this.querySelector(navDropdownToggle).classList.remove("priority-nav-is-visible");
            _this.classList.remove("priority-nav-has-dropdown");
        } else {
            _this.querySelector(navDropdownToggle).classList.add("priority-nav-is-visible");
            _this.querySelector(navDropdownToggle).classList.remove("priority-nav-is-hidden");
            _this.classList.add("priority-nav-has-dropdown");
        }
    };

    /**
     * Update count on dropdown toggle button
     */
    var updateCount = function (_this, identifier) {
        _this.querySelector(navDropdownToggle).dataset.count = breaks[identifier].length;
    };

    /**
     * Move item to dropdown
     */
    priorityNav.toDropdown = function (_this, identifier) {

        /**
         * move last child of navigation menu to dropdown
         */
        if (_this.querySelector(navDropdown).firstChild && _this.querySelector(mainNav).children.length > 0) {
            _this.querySelector(navDropdown).insertBefore(_this.querySelector(mainNav).lastElementChild, _this.querySelector(navDropdown).firstChild);
        } else if (_this.querySelector(mainNav).children.length > 0) {
            _this.querySelector(navDropdown).appendChild(_this.querySelector(mainNav).lastElementChild);
        }

        /**
         * store breakpoints
         */
        breaks[identifier].push(restWidth);

        /**
         * check if we need to show toggle menu button
         */
        showToggle(_this, identifier);

        /**
         * update count on dropdown toggle button
         */
        if (_this.querySelector(mainNav).children.length > 0 && settings.count) {
            updateCount(_this, identifier);
        }

        /**
         * If item has been moved to dropdown trigger the callback
         */
        settings.moved();
    };

    /**
     * Move item to menu
     */
    priorityNav.toMenu = function (_this, identifier) {

        /**
         * move last child of navigation menu to dropdown
         */
        if (_this.querySelector(navDropdown).children.length > 0) _this.querySelector(mainNav).appendChild(_this.querySelector(navDropdown).firstElementChild);

        /**
         * remove last breakpoint
         */
        breaks[identifier].pop();

        /**
         * Check if we need to show toggle menu button
         */
        showToggle(_this, identifier);

        /**
         * update count on dropdown toggle button
         */
        if (_this.querySelector(mainNav).children.length > 0 && settings.count) {
            updateCount(_this, identifier);
        }

        /**
         * If item has been moved back to the main menu trigger the callback
         */
        settings.movedBack();
    };

    /**
     * Count width of children and return the value
     * @param e
     */
    var getChildrenWidth = function (e) {
        var children = e.childNodes;
        var sum = 0;
        for (var i = 0; i < children.length; i++) {
            if (children[i].nodeType !== 3) {
                if(!isNaN(children[i].offsetWidth)){
                    sum += children[i].offsetWidth;
                }

            }
        }
        return sum;
    };

    /**
     * Bind eventlisteners
     */
    var listeners = function (_this) {

        // Check if an item needs to move
        if(window.attachEvent) {
            window.attachEvent("onresize", function() {
                if(priorityNav.doesItFit)priorityNav.doesItFit(_this);
            });
        }
        else if(window.addEventListener) {
            window.addEventListener("resize", function() {
                if(priorityNav.doesItFit)priorityNav.doesItFit(_this);
            }, true);
        }

        // Toggle dropdown
        _this.querySelector(navDropdownToggle).addEventListener("click", function () {
            toggleClass(_this.querySelector(settings.navDropdown), "show");
            toggleClass(this, "is-open");
            toggleClass(_this, "is-open");
        });

        /*
         * Remove when clicked outside dropdown
         */
        document.addEventListener("click", function (event) {
            if (!getClosest(event.target, settings.navDropdown) && event.target !== _this.querySelector(navDropdownToggle)) {
                _this.querySelector(navDropdown).classList.remove("show");
                _this.querySelector(navDropdownToggle).classList.remove("is-open");
                _this.classList.remove("is-open");
            }
        });

        /**
         * Remove when escape key is pressed
         */
        document.onkeydown = function (evt) {
            evt = evt || window.event;
            if (evt.keyCode === 27) {
                navDropdown.classList.remove("show");
                navDropdownToggle.classList.remove("is-open");
                mainNavWrapper.classList.remove("is-open");
            }
        };
    };

    /**
     * Remove function
     */
    Element.prototype.remove = function() {
        this.parentElement.removeChild(this);
    };

    /*global HTMLCollection */
    NodeList.prototype.remove = HTMLCollection.prototype.remove = function() {
        for(var i = 0, len = this.length; i < len; i++) {
            if(this[i] && this[i].parentElement) {
                this[i].parentElement.removeChild(this[i]);
            }
        }
    };

    /**
     * Destroy the current initialization.
     * @public
     */
    priorityNav.destroy = function () {
        // If plugin isn"t already initialized, stop
        if (!settings) return;
        // Remove feedback class
        document.documentElement.classList.remove(settings.initClass);
        // Remove toggle
        toggleWrapper.remove();
        // Remove settings
        settings = null;
        delete priorityNav.init;
        delete priorityNav.doesItFit;
    };

    /**
     * insertAfter function
     * @param n
     * @param r
     */
    Node.prototype.insertAfter = function(n,r) {this.insertBefore(n,r.nextSibling);};

    /**
     * Initialize Plugin
     * @public
     * @param {Object} options User settings
     */
    priorityNav.init = function (options) {

        // Feature test.
        if (!supports){
            console.warn("This browser doesn't support priorityNav");
            return;
        }

        /**
         * Merge user options with defaults
         * @type {Object}
         */
        settings = extend(defaults, options || {});

        /**
         * Store nodes
         * @type {NodeList}
         */
        var elements = document.querySelectorAll(settings.mainNavWrapper);

        /**
         * Loop over every instance and reference _this
         */
        forEach(elements, function(_this){

            /**
             * Create breaks array
             * @type {number}
             */
            breaks[count] = [];

            /**
             * Set the instance number as data attribute
             */
            _this.setAttribute("instance", count++);

            /**
             * Store the wrapper element
             */
            mainNavWrapper = _this;
            if (!mainNavWrapper) {
                console.warn("couldn't find the specified mainNavWrapper element");
                return;
            }

            /**
             * Store the menu elementStore the menu element
             */
            mainNav = settings.mainNav;
            if (!_this.querySelector(mainNav)) {
                console.warn("couldn't find the specified mainNav element");
                return;
            }

            /**
             * Check if we need to create the dropdown elements
             */
            prepareHtml(_this);

            /**
             * Store the dropdown element
             */
            navDropdown = settings.navDropdown;
            if (!_this.querySelector(navDropdown)) {
                console.warn("couldn't find the specified navDropdown element");
                return;
            }

            /**
             * Store the dropdown toggle element
             */
            navDropdownToggle = settings.navDropdownToggle;
            if (!_this.querySelector(navDropdownToggle)) {
                console.warn("couldn't find the specified navDropdownToggle element");
                return;
            }

            /**
             * Event listeners
             */
            listeners(_this);

            /**
             * Start first check
             */
            priorityNav.doesItFit(_this);

        });

        /**
         * Count amount of instances
         */
        instance++;

        /**
         * Add class to HTML element to activate conditional CSS
         */
        document.documentElement.classList.add(settings.initClass);
    };

    /**
     * Public APIs
     */
    return priorityNav;

});<|endoftext|>


<commit_before>L.Proj4js = {};

L.Proj4js._isProj4Proj = function(a) {
	return typeof a['projName'] !== 'undefined';
}

L.Proj4js.Projection = L.Class.extend({
	initialize: function(a, def) {
		if (L.Proj4js._isProj4Proj(a)) {
			this._proj = a;
		} else {
			var code = a;
			Proj4js.defs[code] = def;
			this._proj = new Proj4js.Proj(code);
		}
	},

	project: function (latlng) {
		var point = new L.Point(latlng.lng, latlng.lat);
		return Proj4js.transform(Proj4js.WGS84, this._proj, point);
	},

	unproject: function (point, unbounded) {
		var point2 = Proj4js.transform(this._proj, Proj4js.WGS84, point.clone());
		return new L.LatLng(point2.y, point2.x, unbounded);
	}
});

L.Proj4js.CRS = L.Class.extend({
	includes: L.CRS,

	options: {
		transformation: new L.Transformation(1, 0, -1, 0)
	},

	initialize: function(a, b, c) {
		var code, proj, def, options;

		if (L.Proj4js._isProj4Proj(a)) {
			proj = a;
			code = proj.srsCode;
			options = b;

			this.projection = new L.Proj4js.Projection(proj);
		} else {
			code = a;
			def = b;
			options = c;
			this.projection = new L.Proj4js.Projection(code, def);
		}

		L.Util.setOptions(options);
		this.code = code;
		this.transformation = this.options.transformation;

		if (options) {
			if (options.origin) {
				this.transformation =
					new L.Transformation(1, -options.origin[0],
						-1, options.origin[1]);
			}

			if (options.scales) {
				this.scale = function(zoom) {
					return options.scales[zoom];
				}
			} else if (options.resolutions) {
				this.scale = function(zoom) {
					return 1 / options.resolutions[zoom];
				}
			}
		}
	},
});

L.Proj4js.CRS.TMS = L.Proj4js.CRS.extend({
	initialize: function(a, b, c, d) {
		if (L.Proj4js._isProj4Proj(a)) {
			var proj = a,
				projectedBounds = b,
				options = c;
			L.Proj4js.CRS.prototype.initialize(proj, options);
		} else {
			var code = a,
				def = b,
				projectedBounds = c,
				options = d;
			L.Proj4js.CRS.prototype.initialize(code, def, options);
		}

		options.origin = [projectedBounds[0], projectedBounds[3]];
		this.projectedBounds = projectedBounds;
	},
});

L.Proj4js.TileLayer = {};

L.Proj4js.TileLayer.TMS = L.TileLayer.extend({
	options: {
		tms: true,
		continuousWorld: true,
	},

	initialize: function(urlTemplate, crs, options) {
		if (!(crs instanceof L.Proj4js.CRS.TMS)) {
			throw new Error("CRS is not L.Proj4js.CRS.TMS.");
		}

		L.TileLayer.prototype.initialize.call(this, urlTemplate, options);
		this.crs = crs;

		// Verify grid alignment
		for (var i = this.options.minZoom; i < this.options.maxZoom; i++) {
			var gridHeight = (this.crs.projectedBounds[3] - this.crs.projectedBounds[1]) /
				this._projectedTileSize(i);
			if (Math.abs(gridHeight - Math.round(gridHeight)) > 1e-3) {
				throw new Error("Projected bounds does not match grid at zoom " + i);
			}
		}
	},

	getTileUrl: function(tilePoint) {
		var gridHeight =
			Math.round((this.crs.projectedBounds[3] - this.crs.projectedBounds[1]) /
			this._projectedTileSize(this._map.getZoom()));

		// TODO: relies on some of TileLayer's internals
		return L.Util.template(this._url, L.Util.extend({
			s: this._getSubdomain(tilePoint),
			z: this._getZoomForUrl(),
			x: tilePoint.x,
			y: gridHeight - tilePoint.y - 1
		}, this.options));
	},

	_projectedTileSize: function(zoom) {
		return (this.options.tileSize / this.crs.scale(zoom));
	}
});

if (typeof module !== 'undefined') module.exports = L.Proj4js;

if (typeof L !== 'undefined' && typeof L.CRS !== 'undefined') {
	// This is left here for backwards compatibility
	L.CRS.proj4js = (function () {
		return function (code, def, transformation, options) {
			if (transformation) options.transformation = transformation;

			return new L.Proj4js.CRS(code, def, options);
		};
	}());
}
<commit_msg>Added default if options aren't passed to CRS constructor.<commit_after>L.Proj4js = {};

L.Proj4js._isProj4Proj = function(a) {
	return typeof a['projName'] !== 'undefined';
}

L.Proj4js.Projection = L.Class.extend({
	initialize: function(a, def) {
		if (L.Proj4js._isProj4Proj(a)) {
			this._proj = a;
		} else {
			var code = a;
			Proj4js.defs[code] = def;
			this._proj = new Proj4js.Proj(code);
		}
	},

	project: function (latlng) {
		var point = new L.Point(latlng.lng, latlng.lat);
		return Proj4js.transform(Proj4js.WGS84, this._proj, point);
	},

	unproject: function (point, unbounded) {
		var point2 = Proj4js.transform(this._proj, Proj4js.WGS84, point.clone());
		return new L.LatLng(point2.y, point2.x, unbounded);
	}
});

L.Proj4js.CRS = L.Class.extend({
	includes: L.CRS,

	options: {
		transformation: new L.Transformation(1, 0, -1, 0)
	},

	initialize: function(a, b, c) {
		var code, proj, def, options;

		if (L.Proj4js._isProj4Proj(a)) {
			proj = a;
			code = proj.srsCode;
			options = b || {};

			this.projection = new L.Proj4js.Projection(proj);
		} else {
			code = a;
			def = b;
			options = c || {};
			this.projection = new L.Proj4js.Projection(code, def);
		}

		L.Util.setOptions(options);
		this.code = code;
		this.transformation = this.options.transformation;

		if (options) {
			if (options.origin) {
				this.transformation =
					new L.Transformation(1, -options.origin[0],
						-1, options.origin[1]);
			}

			if (options.scales) {
				this.scale = function(zoom) {
					return options.scales[zoom];
				}
			} else if (options.resolutions) {
				this.scale = function(zoom) {
					return 1 / options.resolutions[zoom];
				}
			}
		}
	},
});

L.Proj4js.CRS.TMS = L.Proj4js.CRS.extend({
	initialize: function(a, b, c, d) {
		if (L.Proj4js._isProj4Proj(a)) {
			var proj = a,
				projectedBounds = b,
				options = c;
			L.Proj4js.CRS.prototype.initialize(proj, options);
		} else {
			var code = a,
				def = b,
				projectedBounds = c,
				options = d;
			L.Proj4js.CRS.prototype.initialize(code, def, options);
		}

		options.origin = [projectedBounds[0], projectedBounds[3]];
		this.projectedBounds = projectedBounds;
	},
});

L.Proj4js.TileLayer = {};

L.Proj4js.TileLayer.TMS = L.TileLayer.extend({
	options: {
		tms: true,
		continuousWorld: true,
	},

	initialize: function(urlTemplate, crs, options) {
		if (!(crs instanceof L.Proj4js.CRS.TMS)) {
			throw new Error("CRS is not L.Proj4js.CRS.TMS.");
		}

		L.TileLayer.prototype.initialize.call(this, urlTemplate, options);
		this.crs = crs;

		// Verify grid alignment
		for (var i = this.options.minZoom; i < this.options.maxZoom; i++) {
			var gridHeight = (this.crs.projectedBounds[3] - this.crs.projectedBounds[1]) /
				this._projectedTileSize(i);
			if (Math.abs(gridHeight - Math.round(gridHeight)) > 1e-3) {
				throw new Error("Projected bounds does not match grid at zoom " + i);
			}
		}
	},

	getTileUrl: function(tilePoint) {
		var gridHeight =
			Math.round((this.crs.projectedBounds[3] - this.crs.projectedBounds[1]) /
			this._projectedTileSize(this._map.getZoom()));

		// TODO: relies on some of TileLayer's internals
		return L.Util.template(this._url, L.Util.extend({
			s: this._getSubdomain(tilePoint),
			z: this._getZoomForUrl(),
			x: tilePoint.x,
			y: gridHeight - tilePoint.y - 1
		}, this.options));
	},

	_projectedTileSize: function(zoom) {
		return (this.options.tileSize / this.crs.scale(zoom));
	}
});

if (typeof module !== 'undefined') module.exports = L.Proj4js;

if (typeof L !== 'undefined' && typeof L.CRS !== 'undefined') {
	// This is left here for backwards compatibility
	L.CRS.proj4js = (function () {
		return function (code, def, transformation, options) {
			if (transformation) options.transformation = transformation;

			return new L.Proj4js.CRS(code, def, options);
		};
	}());
}
<|endoftext|>


<commit_before>(function (factory) {
	var L, proj4;
	if (typeof define === 'function' && define.amd) {
		// AMD
		define(['leaflet', 'proj4'], factory);
	} else if (typeof module !== 'undefined') {
		// Node/CommonJS
		L = require('leaflet');
		proj4 = require('proj4');
		module.exports = factory(L, proj4);
	} else {
		// Browser globals
		if (typeof window.L === 'undefined' || typeof window.proj4 === 'undefined')
			throw 'Leaflet and proj4 must be loaded first';
		factory(window.L, window.proj4);
	}
}(function (L, proj4) {

	L.Proj = {};

	L.Proj._isProj4Obj = function(a) {
		return (typeof a.inverse !== 'undefined' &&
			typeof a.forward !== 'undefined');
	};

	L.Proj.Projection = L.Class.extend({
		initialize: function(code, def, bounds) {
			var isP4 = L.Proj._isProj4Obj(code);
			this._proj = isP4 ? code : this._projFromCodeDef(code, def);
			this.bounds = isP4 ? def : bounds;
		},

		project: function (latlng) {
			var point = this._proj.forward([latlng.lng, latlng.lat]);
			return new L.Point(point[0], point[1]);
		},

		unproject: function (point, unbounded) {
			var point2 = this._proj.inverse([point.x, point.y]);
			return new L.LatLng(point2[1], point2[0], unbounded);
		},

		_projFromCodeDef: function(code, def) {
			if (def) {
				proj4.defs(code, def);
			} else if (proj4.defs[code] === undefined) {
				var urn = code.split(':');
				if (urn.length > 3) {
					code = urn[urn.length - 3] + ':' + urn[urn.length - 1];
				}
				if (proj4.defs[code] === undefined) {
					throw 'No projection definition for code ' + code;
				}
			}

			return proj4(code);
		}
	});

	L.Proj.CRS = L.Class.extend({
		includes: L.CRS,

		options: {
			transformation: new L.Transformation(1, 0, -1, 0)
		},

		initialize: function(a, b, c) {
			var code,
			    proj,
			    def,
			    options;

			if (L.Proj._isProj4Obj(a)) {
				proj = a;
				code = proj.srsCode;
				options = b || {};

				this.projection = new L.Proj.Projection(proj, options.bounds);
			} else {
				code = a;
				def = b;
				options = c || {};
				this.projection = new L.Proj.Projection(code, def, options.bounds);
			}

			L.Util.setOptions(this, options);
			this.code = code;
			this.transformation = this.options.transformation;

			if (this.options.origin) {
				this.transformation =
					new L.Transformation(1, -this.options.origin[0],
						-1, this.options.origin[1]);
			}

			if (this.options.scales) {
				this._scales = this.options.scales;
			} else if (this.options.resolutions) {
				this._scales = [];
				for (var i = this.options.resolutions.length - 1; i >= 0; i--) {
					if (this.options.resolutions[i]) {
						this._scales[i] = 1 / this.options.resolutions[i];
					}
				}
			}

			this.infinite = !this.options.bounds;
		},

		scale: function(zoom) {
			return this._scales[zoom];
		},
	});

	L.Proj.GeoJSON = L.GeoJSON.extend({
		initialize: function(geojson, options) {
			if (geojson.crs && geojson.crs.type === 'name') {
				var crs = new L.Proj.CRS(geojson.crs.properties.name);
				options = options || {};
				options.coordsToLatLng = function(coords) {
					var point = L.point(coords[0], coords[1]);
					return crs.projection.unproject(point);
				};
			}
			L.GeoJSON.prototype.initialize.call(this, geojson, options);
		}
	});

	L.Proj.geoJson = function(geojson, options) {
		return new L.Proj.GeoJSON(geojson, options);
	};

	return L.Proj;
}));
<commit_msg>Naïve fix for non-integer zoomlevels in CRS.scale; interpolation results in discontinuities<commit_after>(function (factory) {
	var L, proj4;
	if (typeof define === 'function' && define.amd) {
		// AMD
		define(['leaflet', 'proj4'], factory);
	} else if (typeof module !== 'undefined') {
		// Node/CommonJS
		L = require('leaflet');
		proj4 = require('proj4');
		module.exports = factory(L, proj4);
	} else {
		// Browser globals
		if (typeof window.L === 'undefined' || typeof window.proj4 === 'undefined')
			throw 'Leaflet and proj4 must be loaded first';
		factory(window.L, window.proj4);
	}
}(function (L, proj4) {

	L.Proj = {};

	L.Proj._isProj4Obj = function(a) {
		return (typeof a.inverse !== 'undefined' &&
			typeof a.forward !== 'undefined');
	};

	L.Proj.Projection = L.Class.extend({
		initialize: function(code, def, bounds) {
			var isP4 = L.Proj._isProj4Obj(code);
			this._proj = isP4 ? code : this._projFromCodeDef(code, def);
			this.bounds = isP4 ? def : bounds;
		},

		project: function (latlng) {
			var point = this._proj.forward([latlng.lng, latlng.lat]);
			return new L.Point(point[0], point[1]);
		},

		unproject: function (point, unbounded) {
			var point2 = this._proj.inverse([point.x, point.y]);
			return new L.LatLng(point2[1], point2[0], unbounded);
		},

		_projFromCodeDef: function(code, def) {
			if (def) {
				proj4.defs(code, def);
			} else if (proj4.defs[code] === undefined) {
				var urn = code.split(':');
				if (urn.length > 3) {
					code = urn[urn.length - 3] + ':' + urn[urn.length - 1];
				}
				if (proj4.defs[code] === undefined) {
					throw 'No projection definition for code ' + code;
				}
			}

			return proj4(code);
		}
	});

	L.Proj.CRS = L.Class.extend({
		includes: L.CRS,

		options: {
			transformation: new L.Transformation(1, 0, -1, 0)
		},

		initialize: function(a, b, c) {
			var code,
			    proj,
			    def,
			    options;

			if (L.Proj._isProj4Obj(a)) {
				proj = a;
				code = proj.srsCode;
				options = b || {};

				this.projection = new L.Proj.Projection(proj, options.bounds);
			} else {
				code = a;
				def = b;
				options = c || {};
				this.projection = new L.Proj.Projection(code, def, options.bounds);
			}

			L.Util.setOptions(this, options);
			this.code = code;
			this.transformation = this.options.transformation;

			if (this.options.origin) {
				this.transformation =
					new L.Transformation(1, -this.options.origin[0],
						-1, this.options.origin[1]);
			}

			if (this.options.scales) {
				this._scales = this.options.scales;
			} else if (this.options.resolutions) {
				this._scales = [];
				for (var i = this.options.resolutions.length - 1; i >= 0; i--) {
					if (this.options.resolutions[i]) {
						this._scales[i] = 1 / this.options.resolutions[i];
					}
				}
			}

			this.infinite = !this.options.bounds;
		},

		scale: function(zoom) {
			var iZoom = Math.floor(zoom),
				baseScale,
				nextScale,
				scaleDiff,
				zDiff;
			if (zoom === iZoom) {
				return this._scales[zoom];
			} else {
				// Non-integer zoom, interpolate
				baseScale = this._scales[iZoom];
				nextScale = this._scales[iZoom + 1];
				scaleDiff = nextScale - baseScale;
				zDiff = (zoom - iZoom);
				return baseScale + scaleDiff * Math.pow(zDiff, nextScale / baseScale);
			}
		},
	});

	L.Proj.GeoJSON = L.GeoJSON.extend({
		initialize: function(geojson, options) {
			if (geojson.crs && geojson.crs.type === 'name') {
				var crs = new L.Proj.CRS(geojson.crs.properties.name);
				options = options || {};
				options.coordsToLatLng = function(coords) {
					var point = L.point(coords[0], coords[1]);
					return crs.projection.unproject(point);
				};
			}
			L.GeoJSON.prototype.initialize.call(this, geojson, options);
		}
	});

	L.Proj.geoJson = function(geojson, options) {
		return new L.Proj.GeoJSON(geojson, options);
	};

	return L.Proj;
}));
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2012 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

// This file requires the functions defined in test_functions.js.

var gFingerprints = [];

// Public interface.

/**
 * Starts capturing frames from a video tag. The algorithm will fingerprint a
 * a frame every now and then. After calling this function and running for a
 * while (at least 200 ms) you will be able to call isVideoPlaying to see if
 * we detected any video.
 *
 * @param {string} videoElementId The video element to analyze.
 * @param {string} canvasId A canvas element to write fingerprints into.
 * @param {int}    width The video element's width.
 * @param {int}    width The video element's height.
 *
 * @return {string} Returns ok-started to PyAuto.
 */
//
function startDetection(videoElementId, canvasId, width, height) {
  var video = document.getElementById(videoElementId);
  var canvas = document.getElementById(canvasId);
  var NUM_FINGERPRINTS_TO_SAVE = 5;

  setInterval(function() {
    var context = canvas.getContext('2d');
    captureFrame_(video, context, width, height);
    gFingerprints.push(fingerprint_(context, width, height));
    if (gFingerprints.length > NUM_FINGERPRINTS_TO_SAVE) {
      gFingerprints.shift();
    }
  }, 100);

  returnToTest('ok-started');
}

/**
 * Checks if we have detected any video so far.
 *
 * @return {string} video-playing if we detected video, otherwise
 *                  video-not-playing.
 */
function isVideoPlaying() {
  // Video is considered to be playing if at least one finger print has changed
  // since the oldest fingerprint. Even small blips in the pixel data will cause
  // this check to pass. We only check for rough equality though to account for
  // rounding errors.
  try {
    if (gFingerprints.length > 1) {
      if (!allElementsRoughlyEqualTo_(gFingerprints, gFingerprints[0])) {
        returnToTest('video-playing');
        return;
      }
    }
  } catch (exception) {
    throw failTest('Failed to detect video: ' + exception.message);
  }
  returnToTest('video-not-playing');
}

// Internals.

/** @private */
function allElementsRoughlyEqualTo_(elements, element_to_compare) {
  if (elements.length == 0)
    return false;
  for (var i = 0; i < elements.length; i++) {
    if (Math.abs(elements[i] - element_to_compare) > 3) {
      return false;
    }
  }
  return true;
}

/** @private */
function captureFrame_(video, canvasContext, width, height) {
  canvasContext.drawImage(video, 0, 0, width, height);
}

/** @private */
function fingerprint_(canvasContext, width, height) {
  var imageData = canvasContext.getImageData(0, 0, width, height);
  var pixels = imageData.data;

  var fingerprint = 0;
  for (var i = 0; i < pixels.length; i++) {
    fingerprint += pixels[i];
  }
  return fingerprint;
}<commit_msg>Raise difference tolerance for video_detector.js<commit_after>/**
 * Copyright (c) 2012 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

// This file requires the functions defined in test_functions.js.

var gFingerprints = [];

// Public interface.

/**
 * Starts capturing frames from a video tag. The algorithm will fingerprint a
 * a frame every now and then. After calling this function and running for a
 * while (at least 200 ms) you will be able to call isVideoPlaying to see if
 * we detected any video.
 *
 * @param {string} videoElementId The video element to analyze.
 * @param {string} canvasId A canvas element to write fingerprints into.
 * @param {int}    width The video element's width.
 * @param {int}    width The video element's height.
 *
 * @return {string} Returns ok-started to PyAuto.
 */
//
function startDetection(videoElementId, canvasId, width, height) {
  var video = document.getElementById(videoElementId);
  var canvas = document.getElementById(canvasId);
  var NUM_FINGERPRINTS_TO_SAVE = 5;

  setInterval(function() {
    var context = canvas.getContext('2d');
    captureFrame_(video, context, width, height);
    gFingerprints.push(fingerprint_(context, width, height));
    if (gFingerprints.length > NUM_FINGERPRINTS_TO_SAVE) {
      gFingerprints.shift();
    }
  }, 100);

  returnToTest('ok-started');
}

/**
 * Checks if we have detected any video so far.
 *
 * @return {string} video-playing if we detected video, otherwise
 *                  video-not-playing.
 */
function isVideoPlaying() {
  // Video is considered to be playing if at least one finger print has changed
  // since the oldest fingerprint. Even small blips in the pixel data will cause
  // this check to pass. We only check for rough equality though to account for
  // rounding errors.
  try {
    if (gFingerprints.length > 1) {
      if (!allElementsRoughlyEqualTo_(gFingerprints, gFingerprints[0])) {
        returnToTest('video-playing');
        return;
      }
    }
  } catch (exception) {
    throw failTest('Failed to detect video: ' + exception.message);
  }
  returnToTest('video-not-playing');
}

// Internals.

/** @private */
function allElementsRoughlyEqualTo_(elements, element_to_compare) {
  if (elements.length == 0)
    return false;

  var PIXEL_DIFF_TOLERANCE = 100;
  for (var i = 0; i < elements.length; i++) {
    if (Math.abs(elements[i] - element_to_compare) > PIXEL_DIFF_TOLERANCE) {
      return false;
    }
  }
  return true;
}

/** @private */
function captureFrame_(video, canvasContext, width, height) {
  canvasContext.drawImage(video, 0, 0, width, height);
}

/** @private */
function fingerprint_(canvasContext, width, height) {
  var imageData = canvasContext.getImageData(0, 0, width, height);
  var pixels = imageData.data;

  var fingerprint = 0;
  for (var i = 0; i < pixels.length; i++) {
    fingerprint += pixels[i];
  }
  return fingerprint;
}
<|endoftext|>


<commit_before>/*
 * Andraia
 * A lightweight javascript MVC framework for building simple mobile apps.
 * https://github.com/grevory/andraia-js-mobile-framework
 *
 * Copyright (c) 2014 Gregory Pike
 * Licensed under the MIT license.
 */

/* Use the following comments to define global variables for tests */
/* global $:false */
/* global console:false */
/* global window:false */
/* global PageSlider:false */
/* global _:false */
/* global Handlebars:false */
/* global Mustache:false */
/* global EJS:false */
/* global FastClick:false */

function Andraia(elementContainerId, userSettings) {

  // Variables prefixed with underscores (_) are used throughout the app
  // but are not accessible outside of Andraia
  var _self = this,
      // Settings vars
      _defaultSettings = {}, _settings = {},
      // The ID value of the element container
      _getElementId = null,
      // The PageSlide var
      _slider = null,
      // Loading templates
      _loadTemplate = null, _loadedTemplate = '',
      // Templating vars
      _templateEngine = null, _templateHeader = '', _templateFooter = '',
      // Data and controller vars
      _data = null, _controller = null, _bindings = [],
      // Error vars
      _error = null, _debugError = null;

  _defaultSettings = {
    // The directory for storing templates to be loaded as views
    'templateDirectory': 'templates/',
    // PageSlider is a script for hardware-accelerated CSS transitions
    'enablePageslider': true,
    // PageSlide uses FastClick
    'enableFastclick': true,
    // Use an automatic router by default
    // Turn it off to use your own
    'enableRouter': true,
    // Maximum number of hashes to be stored in history
    // We don't want to store too much in memory
    'maxHistory': 8,
    // Could be Underscore, Handlebars, Mustache,
    'templateEngine': '',
    // How fast pages transition
    'pageTransitionSpeed': 0.25
  };

  $.extend(_settings, _defaultSettings, userSettings);

  // Data in memory
  this.controllers = {};
  this.models = {};
  this.helpers = {};
  this.templateData = {};

  // Adds a hash to an element ID if it is not there for jQuery selectors
  _getElementId = function(id) {
    if (id.charAt(0) !== '#') {
      return '#' + id;
    }
    return id;
  };

  if (_settings.enableRouter) {
    var _history = [];
  }

  // Handle _errors in the app
  this.error = function(errorMessage, debugMessage) {
    if (!errorMessage) {
      return _error;
    }
    _error = errorMessage;
    _debugError = debugMessage;
    console.error(debugMessage || errorMessage);
    // alert(_errorMessage);
  };

  // Model
  // A generic function for handling models
  this.model = function(modelName, modelFunction) {

    var modelLoaded = null;

    if ($.isFunction(modelFunction)) {
      _self.models[modelName] = modelFunction;
    }

    if (!modelFunction && $.isFunction(_self.models[modelName])) {
      modelLoaded = new _self.models[modelName](_self.helpers);
      return modelLoaded;
    }
  };

  // Add a model to memory
  // Shortcut to model()
  this.registerModel = function(modelName, modelFunction) {
    return _self.model(modelName, modelFunction);
  };

  // Grab the model for your app
  this.loadModel = function(modelName) {
    return _self.model(modelName);
  };

  // Check to see if a model is already loaded
  this.hasModel = function(modelName) {
    return !!_self.models[modelName];
  };

  // Add helpers to memory for reusable functions
  this.registerHelper = function(name, helperFunction) {
    if ($.type(name) !== "string") {
      return _self._error('Could not register helper. The name is not a string.');
    }

    if ($.type(helperFunction) !== "function") {
      return _self._error('Could not register helper. The function is not a function.');
    }

    _self.helpers[name] = helperFunction;
  };

  // This is where we store laoded templates
  _loadTemplate = function(id) {
    var _elementId = _getElementId(id),
        deferred = $.Deferred();

    if ($(_elementId).size() > 0) {
      // Load the template into memory
      _loadedTemplate = $(_elementId).html();

      deferred.resolve();
      return deferred;
    }

    // Example URL: templates/newView.html
    $.get(_settings.templateDirectory + _elementId.substr(1) + '.html', function(html) {
      _loadedTemplate = html;
      $('body').append('<script id="'+_elementId.substr(1)+'" type="text/html">'+html+'</script>');
      deferred.resolve();
    });

    return deferred;
  };

  this.registerView = function(viewName, controllerFunction, data) {

    viewName = _getElementId(viewName);

    // If the action item is a function then it must be a controller.
    // Add the controller function to memory
    if ($.isFunction(controllerFunction)){ // && ($(_self.controllers).size() < 1 || !$.isFunction(_self.controllers[viewName]))) {
      _self.controllers[viewName] = controllerFunction;
    }

    if (!!data) {
      _self.templateData[viewName] = data;
    }
  };

  function loadController(viewName) {
    // Check to see if there is a controller for this view and then load it
    if ($(_self.controllers).size() > 0 && $.isFunction(_self.controllers[viewName])) {
      _controller = new _self.controllers[viewName](_self.helpers);
    }

    // If there is a data returned from the controller we assume it is meant to be used for template
    if (!$.isEmptyObject(_controller)) {
      return _controller;
    }
    // There was no data from the controller but their might be data registered for this view
    return _self.templateData[viewName];
  }

  this.bind = function(selector, bindType, callbackFtn) {
    _bindings.push({
      'selector': selector,
      'bindType': bindType,
      'callbackFtn': callbackFtn
    });
  };

  function resetBindings() {
    this.bindings = [];
  }

  // Shortcut to view specifically for loading a view
  this.loadView = function(viewName) {
    viewName = _getElementId(viewName);

    if (_settings.enableRouter) {
      // Change the hash on load if necessary
      if (!_self.router.currentPage || _self.router.currentPage !== viewName) {
        window.location.hash = viewName;
      }
      // If this is the first load and no hashchange is needed, start the history
      else if (!!_history && !_history.length) {
        _history.push(viewName);
      }
    }

    if (_settings.enablePageslider && $.isFunction(PageSlider) && !_slider) {
      _slider = new PageSlider($(elementContainerId));
    }

    // Load the template. When the template is loaded we will apply any
    // templating as necessary and load the controller for the view
    _loadTemplate(viewName).done(function() {

      resetBindings();

      _data = _self.templateData[viewName];
      if ($.isFunction(_data)) {
        _data = _data();
        _self.templateData[viewName] = _data;
      }

      // Run the templating engine on the template using any user-defined data
      _loadedTemplate = _self.template(_loadedTemplate, _data);

      // Slide the page to this view
      if (!!_slider) {
        _slider.slidePage($(_loadedTemplate), "left");
      } else {
        $(elementContainerId).html(_loadedTemplate);
      }

      loadController(viewName);

      // $(elementContainerId).html(_self.template($(elementContainerId).html(), _data));

      $.each(_bindings, function(id, binding) {
        $(binding.selector).unbind(binding.bindType + '.' + viewName);
        $(binding.selector).bind(binding.bindType + '.' + viewName, binding.callbackFtn);
      });
    });
  };

  // Define how the template is to be rendered.
  _templateEngine = function(template, data) {

    if (!data) {
      return template;
    }

    var compiled;

    function isEngine(engineType) {
      // Get the lowercase version of the template engine name (for consistency)
      var usersTemplateEngine = _settings.templateEngine.toLowerCase();
      // Check for this engine type in the users selected template engine
      // E.g. search for "mustache in Mustache.js"
      return usersTemplateEngine.indexOf(engineType) >= 0;
    }

    // Use Underscore's templating
    if (typeof _ !== "undefined" && $.isFunction(_) && isEngine('underscore')) {
      compiled = _.template(template);
      return compiled(data);
    }

    // Use Handlebar's templating
    if (typeof Handlebars !== "undefined" && isEngine('handlebars')) {
      compiled = Handlebars.compile(template);
      template = compiled(data);
    }

    // Use Mustache's templating
    if (typeof Mustache !== "undefined" && isEngine('mustache')) {
      template = Mustache.render(template, data);
    }

    if (typeof EJS !== "undefined" && isEngine('ejs')) {
      template = new EJS({text: template}).render(data);
    }

    return template;
  };

  // A generic function for handling templates
  this.template = function(template, data) {
    // Set the template engine if a function is passed
    if ($.isFunction(template)) {
      _templateEngine = template;
      return;
    }

    if (!_templateEngine) {
      _self._error('No template engine loaded');
    }

    if (!template) {
      return '';
    }

    template = '<div>' + _templateHeader + _templateEngine(template) + _templateFooter + '</div>';

    if (!data) {
      return template;
    }

    return _templateEngine(template, data);
  };

  // A shortcut for adding templating to the app
  this.registerTemplating = function(templateFunction) {
    return _self.template(templateFunction);
  };

  var extractTemplate = function(htmlString) {
    // Convert header HTML to string
    htmlString = "" + htmlString;

    if (htmlString.indexOf('.html') > -1) {
      _self._error('This option is not yet available. Cannot load header or footer template from external file.');
      return console.log('Go get template');
    }

    // If there are no HTML tags and the headerHtml string is the id of an element let's get the HTML of that element
    if (htmlString.indexOf('<') < 0 && $(_getElementId(htmlString)).size() > 0) {
      htmlString = $(_getElementId(htmlString)).html();
    }

    return htmlString;
  };

  this.registerTemplateHeader = function(headerHtml) {
    _templateHeader = extractTemplate(headerHtml);
  };

  this.registerTemplateFooter = function(footerHtml) {
    _templateFooter = extractTemplate(footerHtml);
  };

  if (!elementContainerId) {
    elementContainerId = 'body';
  }
  else {
    elementContainerId = _getElementId(elementContainerId);
  }

  if (_settings.enableFastclick) {
    window.addEventListener('load', function () {
      new FastClick(window.document.body);
    }, false);
  }

  this.router = {
    currentPage: window.location.hash,
    changePage: function (pageId) {
      pageId = _getElementId(pageId);

      _self.router.addToHistory(pageHash);

      // If there is no current page we do not want to load the view until the app is ready.
      if (!!_self.router.currentPage) {
        _self.loadView(pageId);
      }

      if (!_self.router.currentPage || _self.router.currentPage === pageId) {
        window.location.hash = pageId;
      }

      _self.router.currentPage = pageId;
    },
    addToHistory: function(pageHash) {
      if (_history.length >= _settings.maxHistory) {
        _history = _history.slice(1);
      }
      _history.push(pageHash);
    },
    goBack: function() {
      // If there is no history to go back don't bother trying to change the page
      if (!_history || !_history.length || _history.length <= 1) {
        return;
      }
      // We get -2 of the length because we want the last item in history and
      // JS arrays are 0-indexed
      window.location.hash = _history[_history.length - 2];
    }
  };

  if (_settings.enableRouter) {
    var pageHash = '';

    window.addEventListener('hashchange', function () {
      var changePage = _self.router.changePage;
      pageHash = window.location.hash;
      if (!!pageHash) {
        changePage(pageHash);
      }
    });
  }

  if (_settings.pageTransitionSpeed !== _defaultSettings.pageTransitionSpeed) {
    // Add styles to overwrite the page transition speed at the end of the head
    // The default is 0.25.
    // Don't bother with the overwrite if the user is using the default
    $('head').append(' ' +
      '<style>' +
      '  .page.transition {' +
      '    -webkit-transition-duration: ' + _settings.pageTransitionSpeed + 's;' +
      '    transition-duration: ' + _settings.pageTransitionSpeed + 's;' +
      '  }' +
      '</style>');
  }
}
<commit_msg>Remove public data from memory<commit_after>/*
 * Andraia
 * A lightweight javascript MVC framework for building simple mobile apps.
 * https://github.com/grevory/andraia-js-mobile-framework
 *
 * Copyright (c) 2014 Gregory Pike
 * Licensed under the MIT license.
 */

/* Use the following comments to define global variables for tests */
/* global $:false */
/* global console:false */
/* global window:false */
/* global PageSlider:false */
/* global _:false */
/* global Handlebars:false */
/* global Mustache:false */
/* global EJS:false */
/* global FastClick:false */

function Andraia(elementContainerId, userSettings) {

  // Variables prefixed with underscores (_) are used throughout the app
  // but are not accessible outside of Andraia
  var _self = this,
    // Settings vars
    _defaultSettings = {}, _settings = {},
    // The ID value of the element container
    _getElementId = null,
    // The PageSlide var
    _slider = null,
    // Loading templates
    _loadTemplate = null, _loadedTemplate = '',
    // Templating vars
    _templateEngine = null, _templateHeader = '', _templateFooter = '',
    // Data stored in memory for the MVC
    _controllers = {}, _models = {}, _helpers = {}, _templateData = {},
    // Data and controller vars
    _data = null, _controller = null, _bindings = [],
    // Error vars
    _error = null, _debugError = null;

  _defaultSettings = {
    // The directory for storing templates to be loaded as views
    'templateDirectory': 'templates/',
    // PageSlider is a script for hardware-accelerated CSS transitions
    'enablePageslider': true,
    // PageSlide uses FastClick
    'enableFastclick': true,
    // Use an automatic router by default
    // Turn it off to use your own
    'enableRouter': true,
    // Maximum number of hashes to be stored in history
    // We don't want to store too much in memory
    'maxHistory': 8,
    // Could be Underscore, Handlebars, Mustache,
    'templateEngine': '',
    // How fast pages transition
    'pageTransitionSpeed': 0.25
  };

  $.extend(_settings, _defaultSettings, userSettings);

  // Adds a hash to an element ID if it is not there for jQuery selectors
  _getElementId = function(id) {
    if (id.charAt(0) !== '#') {
      return '#' + id;
    }
    return id;
  };

  if (_settings.enableRouter) {
    var _history = [];
  }

  // Handle _errors in the app
  this.error = function(errorMessage, debugMessage) {
    if (!errorMessage) {
      return _error;
    }
    _error = errorMessage;
    _debugError = debugMessage;
    console.error(debugMessage || errorMessage);
    // alert(_errorMessage);
  };

  // Model
  // A generic function for handling models
  this.model = function(modelName, modelFunction) {

    var modelLoaded = null;

    if ($.isFunction(modelFunction)) {
      _models[modelName] = modelFunction;
    }

    if (!modelFunction && $.isFunction(_models[modelName])) {
      modelLoaded = new _models[modelName](_helpers);
      return modelLoaded;
    }
  };

  // Add a model to memory
  // Shortcut to model()
  this.registerModel = function(modelName, modelFunction) {
    return _self.model(modelName, modelFunction);
  };

  // Grab the model for your app
  this.loadModel = function(modelName) {
    return _self.model(modelName);
  };

  // Check to see if a model is already loaded
  this.hasModel = function(modelName) {
    return !!_models[modelName];
  };

  // Add helpers to memory for reusable functions
  this.registerHelper = function(name, helperFunction) {
    if ($.type(name) !== "string") {
      return _self._error('Could not register helper. The name is not a string.');
    }

    if ($.type(helperFunction) !== "function") {
      return _self._error('Could not register helper. The function is not a function.');
    }

    _helpers[name] = helperFunction;
  };

  // This is where we store laoded templates
  _loadTemplate = function(id) {
    var _elementId = _getElementId(id),
        deferred = $.Deferred();

    if ($(_elementId).size() > 0) {
      // Load the template into memory
      _loadedTemplate = $(_elementId).html();

      deferred.resolve();
      return deferred;
    }

    // Example URL: templates/newView.html
    $.get(_settings.templateDirectory + _elementId.substr(1) + '.html', function(html) {
      _loadedTemplate = html;
      $('body').append('<script id="'+_elementId.substr(1)+'" type="text/html">'+html+'</script>');
      deferred.resolve();
    });

    return deferred;
  };

  this.registerView = function(viewName, controllerFunction, data) {

    viewName = _getElementId(viewName);

    // If the action item is a function then it must be a controller.
    // Add the controller function to memory
    if ($.isFunction(controllerFunction)){
      _controllers[viewName] = controllerFunction;
    }

    if (!!data) {
      _templateData[viewName] = data;
    }
  };

  function loadController(viewName) {
    // Check to see if there is a controller for this view and then load it
    if ($(_controllers).size() > 0 && $.isFunction(_controllers[viewName])) {
      _controller = new _controllers[viewName](_helpers);
    }

    // If there is a data returned from the controller we assume it is meant to be used for template
    if (!$.isEmptyObject(_controller)) {
      return _controller;
    }
    // There was no data from the controller but their might be data registered for this view
    return _templateData[viewName];
  }

  this.bind = function(selector, bindType, callbackFtn) {
    _bindings.push({
      'selector': selector,
      'bindType': bindType,
      'callbackFtn': callbackFtn
    });
  };

  function resetBindings() {
    this.bindings = [];
  }

  // Shortcut to view specifically for loading a view
  this.loadView = function(viewName) {
    viewName = _getElementId(viewName);

    if (_settings.enableRouter) {
      // Change the hash on load if necessary
      if (!_self.router.currentPage || _self.router.currentPage !== viewName) {
        window.location.hash = viewName;
      }
      // If this is the first load and no hashchange is needed, start the history
      else if (!!_history && !_history.length) {
        _history.push(viewName);
      }
    }

    if (_settings.enablePageslider && $.isFunction(PageSlider) && !_slider) {
      _slider = new PageSlider($(elementContainerId));
    }

    // Load the template. When the template is loaded we will apply any
    // templating as necessary and load the controller for the view
    _loadTemplate(viewName).done(function() {

      resetBindings();

      _data = _templateData[viewName];
      if ($.isFunction(_data)) {
        _data = _data();
        _templateData[viewName] = _data;
      }

      // Run the templating engine on the template using any user-defined data
      _loadedTemplate = _self.template(_loadedTemplate, _data);

      // Slide the page to this view
      if (!!_slider) {
        _slider.slidePage($(_loadedTemplate), "left");
      } else {
        $(elementContainerId).html(_loadedTemplate);
      }

      loadController(viewName);

      // $(elementContainerId).html(_self.template($(elementContainerId).html(), _data));

      $.each(_bindings, function(id, binding) {
        $(binding.selector).unbind(binding.bindType + '.' + viewName);
        $(binding.selector).bind(binding.bindType + '.' + viewName, binding.callbackFtn);
      });
    });
  };

  // Define how the template is to be rendered.
  _templateEngine = function(template, data) {

    if (!data) {
      return template;
    }

    var compiled;

    function isEngine(engineType) {
      // Get the lowercase version of the template engine name (for consistency)
      var usersTemplateEngine = _settings.templateEngine.toLowerCase();
      // Check for this engine type in the users selected template engine
      // E.g. search for "mustache in Mustache.js"
      return usersTemplateEngine.indexOf(engineType) >= 0;
    }

    // Use Underscore's templating
    if (typeof _ !== "undefined" && $.isFunction(_) && isEngine('underscore')) {
      compiled = _.template(template);
      return compiled(data);
    }

    // Use Handlebar's templating
    if (typeof Handlebars !== "undefined" && isEngine('handlebars')) {
      compiled = Handlebars.compile(template);
      template = compiled(data);
    }

    // Use Mustache's templating
    if (typeof Mustache !== "undefined" && isEngine('mustache')) {
      template = Mustache.render(template, data);
    }

    if (typeof EJS !== "undefined" && isEngine('ejs')) {
      template = new EJS({text: template}).render(data);
    }

    return template;
  };

  // A generic function for handling templates
  this.template = function(template, data) {
    // Set the template engine if a function is passed
    if ($.isFunction(template)) {
      _templateEngine = template;
      return;
    }

    if (!_templateEngine) {
      _self._error('No template engine loaded');
    }

    if (!template) {
      return '';
    }

    template = '<div>' + _templateHeader + _templateEngine(template) + _templateFooter + '</div>';

    if (!data) {
      return template;
    }

    return _templateEngine(template, data);
  };

  // A shortcut for adding templating to the app
  this.registerTemplating = function(templateFunction) {
    return _self.template(templateFunction);
  };

  var extractTemplate = function(htmlString) {
    // Convert header HTML to string
    htmlString = "" + htmlString;

    if (htmlString.indexOf('.html') > -1) {
      _self._error('This option is not yet available. Cannot load header or footer template from external file.');
      return console.log('Go get template');
    }

    // If there are no HTML tags and the headerHtml string is the id of an element let's get the HTML of that element
    if (htmlString.indexOf('<') < 0 && $(_getElementId(htmlString)).size() > 0) {
      htmlString = $(_getElementId(htmlString)).html();
    }

    return htmlString;
  };

  this.registerTemplateHeader = function(headerHtml) {
    _templateHeader = extractTemplate(headerHtml);
  };

  this.registerTemplateFooter = function(footerHtml) {
    _templateFooter = extractTemplate(footerHtml);
  };

  if (!elementContainerId) {
    elementContainerId = 'body';
  }
  else {
    elementContainerId = _getElementId(elementContainerId);
  }

  if (_settings.enableFastclick) {
    window.addEventListener('load', function () {
      new FastClick(window.document.body);
    }, false);
  }

  this.router = {
    currentPage: window.location.hash,
    changePage: function (pageId) {
      pageId = _getElementId(pageId);

      _self.router.addToHistory(pageHash);

      // If there is no current page we do not want to load the view until the app is ready.
      if (!!_self.router.currentPage) {
        _self.loadView(pageId);
      }

      if (!_self.router.currentPage || _self.router.currentPage === pageId) {
        window.location.hash = pageId;
      }

      _self.router.currentPage = pageId;
    },
    addToHistory: function(pageHash) {
      if (_history.length >= _settings.maxHistory) {
        _history = _history.slice(1);
      }
      _history.push(pageHash);
    },
    goBack: function() {
      // If there is no history to go back don't bother trying to change the page
      if (!_history || !_history.length || _history.length <= 1) {
        return;
      }
      // We get -2 of the length because we want the last item in history and
      // JS arrays are 0-indexed
      window.location.hash = _history[_history.length - 2];
    }
  };

  if (_settings.enableRouter) {
    var pageHash = '';

    window.addEventListener('hashchange', function () {
      var changePage = _self.router.changePage;
      pageHash = window.location.hash;
      if (!!pageHash) {
        changePage(pageHash);
      }
    });
  }

  if (_settings.pageTransitionSpeed !== _defaultSettings.pageTransitionSpeed) {
    // Add styles to overwrite the page transition speed at the end of the head
    // The default is 0.25.
    // Don't bother with the overwrite if the user is using the default
    $('head').append(' ' +
      '<style>' +
      '  .page.transition {' +
      '    -webkit-transition-duration: ' + _settings.pageTransitionSpeed + 's;' +
      '    transition-duration: ' + _settings.pageTransitionSpeed + 's;' +
      '  }' +
      '</style>');
  }
}
<|endoftext|>


<commit_before>exports.getCountry = function (value) {
    "use strict";

	var country = "";

    if ( (country = value.match(/,?\([A-Z]{2}\)$/g)) === null ) {
        country = "00";
    } else {
        country = value.match(/,?\([A-Z]{2}\)$/g).toString().replace(',','').replace('(', '').replace(')', '');   // => US
    }

    return country;
};

exports.getFullName = function ( value ) {
    "use strict";

	var fullName = "";

    if ( (fullName = value.match(/^[^\d]*,/gi)) === null ) {
            fullName = value.match(/^[^,]*,/gi).toString().trim().replace(/,$/gi, '');
    } else {
        fullName = value.match(/^[^\d]*,/gi).toString().trim().replace(/,$/gi, '');  //Full name of Inventor / Agent...
    }

    return fullName;
};

exports.getValueSingleChild = function( value, key ) {
    "use strict";

	var isKeyADate = ( key === 'PublicationDate' || key === 'FilingDate' );

    if (isKeyADate) {
        var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'June', 'July', 'Aug', 'Sept', 'Oct', 'Nov', 'Dec'];
        var day = value.match(/[^ ]*,/gi).toString().replace(',', '');
        var mon = value.match(/^[A-za-z]{3} /gi).toString().trim();
        var month = months.indexOf(mon) + 1;
        var year = value.match(/[0-9]{4}$/gi);

        value = day + '/' + month + '/' + year;
    }

    return value;
};

exports.range = function (low, high, step) {
  // From: http://phpjs.org/functions
  // +   original by: Waldo Malqui Silva
  // *     example 1: range ( 0, 12 );
  // *     returns 1: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
  // *     example 2: range( 0, 100, 10 );
  // *     returns 2: [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
  // *     example 3: range( 'a', 'i' );
  // *     returns 3: ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']
  // *     example 4: range( 'c', 'a' );
  // *     returns 4: ['c', 'b', 'a']
  var matrix = [];
  var inival, endval, plus;
  var walker = step || 1;
  var chars = false;

  if (!isNaN(low) && !isNaN(high)) {
    inival = low;
    endval = high;
  } else if (isNaN(low) && isNaN(high)) {
    chars = true;
    inival = low.charCodeAt(0);
    endval = high.charCodeAt(0);
  } else {
    inival = (isNaN(low) ? 0 : low);
    endval = (isNaN(high) ? 0 : high);
  }

  plus = ((inival > endval) ? false : true);
  if (plus) {
    while (inival <= endval) {
      matrix.push(((chars) ? String.fromCharCode(inival) : inival));
      inival += walker;
    }
  } else {
    while (inival >= endval) {
      matrix.push(((chars) ? String.fromCharCode(inival) : inival));
      inival -= walker;
    }
  }

  return matrix;
}<commit_msg>Changing the date format<commit_after>exports.getCountry = function (value) {
    "use strict";

	var country = "";

    if ( (country = value.match(/,?\([A-Z]{2}\)$/g)) === null ) {
        country = "00";
    } else {
        country = value.match(/,?\([A-Z]{2}\)$/g).toString().replace(',','').replace('(', '').replace(')', '');   // => US
    }

    return country;
};

exports.getFullName = function ( value ) {
    "use strict";

	var fullName = "";

    if ( (fullName = value.match(/^[^\d]*,/gi)) === null ) {
            fullName = value.match(/^[^,]*,/gi).toString().trim().replace(/,$/gi, '');
    } else {
        fullName = value.match(/^[^\d]*,/gi).toString().trim().replace(/,$/gi, '');  //Full name of Inventor / Agent...
    }

    return fullName;
};

exports.getValueSingleChild = function( value, key ) {
    "use strict";

	var isKeyADate = ( key === 'PublicationDate' || key === 'FilingDate' );

    if (isKeyADate) {
        var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'June', 'July', 'Aug', 'Sept', 'Oct', 'Nov', 'Dec'];
        var day = value.match(/[^ ]*,/gi).toString().replace(',', '');
        var mon = value.match(/^[A-za-z]{3} /gi).toString().trim();
        var month = months.indexOf(mon) + 1;
        var year = value.match(/[0-9]{4}$/gi);

        value = year + '/' + month + '/' + day;
    }

    return value;
};

exports.range = function (low, high, step) {
  // From: http://phpjs.org/functions
  // +   original by: Waldo Malqui Silva
  // *     example 1: range ( 0, 12 );
  // *     returns 1: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
  // *     example 2: range( 0, 100, 10 );
  // *     returns 2: [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
  // *     example 3: range( 'a', 'i' );
  // *     returns 3: ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']
  // *     example 4: range( 'c', 'a' );
  // *     returns 4: ['c', 'b', 'a']
  var matrix = [];
  var inival, endval, plus;
  var walker = step || 1;
  var chars = false;

  if (!isNaN(low) && !isNaN(high)) {
    inival = low;
    endval = high;
  } else if (isNaN(low) && isNaN(high)) {
    chars = true;
    inival = low.charCodeAt(0);
    endval = high.charCodeAt(0);
  } else {
    inival = (isNaN(low) ? 0 : low);
    endval = (isNaN(high) ? 0 : high);
  }

  plus = ((inival > endval) ? false : true);
  if (plus) {
    while (inival <= endval) {
      matrix.push(((chars) ? String.fromCharCode(inival) : inival));
      inival += walker;
    }
  } else {
    while (inival >= endval) {
      matrix.push(((chars) ? String.fromCharCode(inival) : inival));
      inival -= walker;
    }
  }

  return matrix;
}<|endoftext|>


<commit_before>import { createStore as _createStore, applyMiddleware, compose } from 'redux';
import createMiddleware from './middleware/clientMiddleware';
import { routerMiddleware } from 'react-router-redux';
import thunk from 'redux-thunk';
import devTools from 'remote-redux-devtools';
import createLogger from 'redux-logger';

export default function createStore(history, client, data) {
  // Sync dispatched route actions to the history
  const reduxRouterMiddleware = routerMiddleware(history);

  const middleware = [
    thunk,
    createMiddleware(client),
    reduxRouterMiddleware
  ];

  let finalCreateStore;
  if (__DEVELOPMENT__ && __CLIENT__ && __DEVTOOLS__) {
    const { persistState } = require('redux-devtools');
    // const DevTools = require('../containers/DevTools/DevTools');
    middleware.push(createLogger({
      duration: true,
      diff: true,
      collapsed: true
    }));
    finalCreateStore = compose(
      applyMiddleware(...middleware),
      devTools({
        name: 'farts',
        hostname: 'localhost',
        port: 8000,
        realtime: true,
        filters: {
          blacklist: ['SET_WINDOW', 'SET_SCROLL', 'SET_CONTAINER_WIDTH']
        }
      }),
      persistState(window.location.href.match(/[?&]debug_session=([^&]+)\b/))
    )(_createStore);
  } else {
    finalCreateStore = applyMiddleware(...middleware)(_createStore);
  }

  const reducer = require('./modules/reducer');
  const store = finalCreateStore(reducer, data);

  if (__DEVELOPMENT__ && module.hot) {
    module.hot.accept('./modules/reducer', () => {
      store.replaceReducer(require('./modules/reducer'));
    });
  }

  return store;
}
<commit_msg>Added dev tooling<commit_after>import { createStore as _createStore, applyMiddleware, compose } from 'redux';
import createMiddleware from './middleware/clientMiddleware';
import { routerMiddleware } from 'react-router-redux';
import thunk from 'redux-thunk';
import devTools from 'remote-redux-devtools';
import createLogger from 'redux-logger';

export default function createStore(history, client, data) {
  // Sync dispatched route actions to the history
  const reduxRouterMiddleware = routerMiddleware(history);

  const middleware = [
    thunk,
    createMiddleware(client),
    reduxRouterMiddleware
  ];

  let finalCreateStore;
  if (__CLIENT__ && __DEVTOOLS__) {
    const { persistState } = require('redux-devtools');
    // const DevTools = require('../containers/DevTools/DevTools');
    middleware.push(createLogger({
      duration: true,
      diff: true,
      collapsed: true
    }));
    finalCreateStore = compose(
      applyMiddleware(...middleware),
      devTools({
        name: 'farts',
        hostname: 'localhost',
        port: 8000,
        realtime: true,
        filters: {
          blacklist: ['SET_WINDOW', 'SET_SCROLL', 'SET_CONTAINER_WIDTH']
        }
      }),
      persistState(window.location.href.match(/[?&]debug_session=([^&]+)\b/))
    )(_createStore);
  } else {
    finalCreateStore = applyMiddleware(...middleware)(_createStore);
  }

  const reducer = require('./modules/reducer');
  const store = finalCreateStore(reducer, data);

  if (__DEVELOPMENT__ && module.hot) {
    module.hot.accept('./modules/reducer', () => {
      store.replaceReducer(require('./modules/reducer'));
    });
  }

  return store;
}
<|endoftext|>


<commit_before>import DS from 'ember-data';

var Prompt = DS.Model.extend({
  content: DS.attr('string'),
  blanks: DS.hasMany('blank'),  //e.g. we collect info about your _blank_
  response: DS.attr('string'), //what going in the blank, e.g. "location"
  step: DS.attr('integer')
});

Prompt.reopenClass({
  FIXTURES: [
  {'id': 1, 'step': 1, 'content': 'My business is called'}
  ]
});

export default Prompt;
<commit_msg>some dummy fixture prompts.<commit_after>import DS from 'ember-data';

let Prompt = DS.Model.extend({
  step: DS.belongsTo('step'),

  question: DS.attr('string'), //our prompt
  answer: DS.attr('string'), // their answer
  clause: DS.attr('string')
});

let data = [
	{step: 1, prompts: ['My business is called %businessName'] },
	{step: 2, prompts: ['How will the weather be tomorrow? %weather'] },
	{step: 3, prompts: ['Do you use google adsense? %goodle-adsense', 'Do you use Amazon Web Services? %amazon'] },
	{step: 4, prompts: ['Where do you store the data collected? %data-collected']}
]

//Turn the data above into the format that ember fixtures wants
var fixtures = [];
var id_number = 0;

for (let step of data) {
	id_number +=1;
	let step_number = step.step;
	let prompts = step.prompts;
	for (let question of prompts) {
		fixtures.push({id: id_number, question: question, step: step_number});
	}
}

console.log(fixtures);

Prompt.reopenClass({
	FIXTURES: fixtures
});

export default Prompt;
<|endoftext|>


<commit_before>/*
 * Class for fetching tube status by parsing an RSS feed from tubeupdates.com
 * This code is cribbed heavily from the Feeds class from the Palm News sample
 * app from the WebOS O'Reilly book.
 */

var Status = Class.create ({
    emptyList: [
        {
            line:"bakerloo",
            status:"unknown",
            details:"none"
        },
        {
            line:"central",
            status:"unknown",
            details:"none"
        },
        {
            line:"circle",
            status:"unknown",
            details:"none"
        },
        {
            line:"district",
            status:"unknown",
            details:"none"
        },
        {
            line:"hammersmith & city",
            status:"unknown",
            details:"none"
        },
        {
            line:"jubilee",
            status:"unknown",
            details:"none"
        },
        {
            line:"metropolitan",
            status:"unknown",
            details:"none"
        },
        {
            line:"northern",
            status:"unknown",
            details:"none"
        },
        {
            line:"picadilly",
            status:"unknown",
            details:"none"
        },
        {
            line:"victoria",
            status:"unknown",
            details:"none"
        },
        {
            line:"waterloo & city",
            status:"unknown",
            details:"none"
        }
    ],

    initialize: function() {
        this.list = this.emptyList;
        this.statusUrl = "http://tubeupdates.com/rss/all.xml";
        this.lastUpdated = "";
    },

    updateStatus: function() {
        Mojo.Log.info("Fetching tube status");

        var request = new Ajax.request(this.statusUrl, {
            method: "get",
            evalJSON: "false",
            onSuccess: this.updateStatusSuccess.bind(this),
            onFailure: this.updateStatusFailure.bind(this)
        });
    },

    updateStatusFailure: function(transport) {
        var t = new Template("Status fetch failed with #{status}.");
        var m = new t.evaluate(transport);

        Mojo.Log.info(m);
    }//,

    // updateStatusSuccess: function(transport) {
    //     Mojo.Log.info("Status fetched, now to process");

    //     // work around occasional XML errors
    //     if (transport.responseXML == null && transport.responseText !== null) {
    //         Mojo.log.info("Request not XML, converting");
    //         transport.responseXML = new DOMParser().parseFromString
    //         (transport.responseText, "text/xml");
    //     }

    //     this.processStatus(transport);
    // },

    // processStatus: function(trasnport) {
    //     var statusList = [];
    //     var items = transport.responseXML.getElementsByTagName("item");
    //     for (i=0;i<items.length; i++) {
    //         statusList[i] = {
    //             title: unescape(items[i].getElementByTagName("title").item(0).textContent),
    //             text: items[i].getElementsByTagName("description").item(0).textContent,
    //             url: items[i].getElementsByTagName("link").item(0).textContent
    //         };
    //     }

    //     /*
    //      * Iterate items and pull the line name, status and details out and
    //      * update this.list with line, status and details
    //      * Need to process title for line and status, details are in description
    //      */

    //     // Set the last update
    //     this.lastUpdate = new Date();
    // }
});
<commit_msg>Switch to using the REST API for status updates<commit_after>/*
 * Class for fetching tube status by parsing an RSS feed from tubeupdates.com
 * This code is cribbed heavily from the Feeds class from the Palm News sample
 * app from the WebOS O'Reilly book.
 */

var Status = Class.create ({
    dummyList: [
        {
            line:"bakerloo",
            status:"unknown",
            details:"none"
        },
        {
            line:"central",
            status:"unknown",
            details:"none"
        },
        {
            line:"circle",
            status:"unknown",
            details:"none"
        },
        {
            line:"district",
            status:"unknown",
            details:"none"
        },
        {
            line:"hammersmith & city",
            status:"unknown",
            details:"none"
        },
        {
            line:"jubilee",
            status:"unknown",
            details:"none"
        },
        {
            line:"metropolitan",
            status:"unknown",
            details:"none"
        },
        {
            line:"northern",
            status:"unknown",
            details:"none"
        },
        {
            line:"picadilly",
            status:"unknown",
            details:"none"
        },
        {
            line:"victoria",
            status:"unknown",
            details:"none"
        },
        {
            line:"waterloo & city",
            status:"unknown",
            details:"none"
        }
    ],

    initialize: function() {
        this.list = this.dummyList;
        this.statusUrl = "http://api.tubeupdates.com";
        this.lastUpdated = "";
    },

    updateStatus: function() {
        Mojo.Log.info("Fetching tube status from " + this.statusUrl);

        var request = new Ajax.Request(this.statusUrl, {
            method: "get",
            evalJSON: "false",
            parameters: "method=get.status&lines=all&format=xml",
            onSuccess: this.updateStatusSuccess.bind(this),
            onFailure: this.updateStatusFailure.bind(this)
        });
    },

    updateStatusFailure: function(transport) {
        var t = new Template("Status fetch failed with #{status}.");
        var m = new t.evaluate(transport);

        Mojo.Log.info(m);
    },

    updateStatusSuccess: function(transport) {
        Mojo.Log.info("Success");

        // work around occasional XML errors
        if (transport.responseXML == null && transport.responseText !== null) {
            Mojo.log.info("Request not XML, converting");
            transport.responseXML = new DOMParser().parseFromString(
                transport.responseText, "text/xml");
        }

        this.processStatus(transport);
    },

    processStatus: function(transport) {
        var lines = $(transport.responseXML).getElementsByTagName("line");
        var stati = [];

        Mojo.Log.info("Processing status\n" + transport.responseXML);
        Mojo.Log.info("Response is: " + lines);

        /*
         * Iterate the returned lines XML and pull out the data into our
         * this.list
         */

        Mojo.Log.info("Response has " + lines.length + " items");
        for (var i = 0; i < lines.length; i++) {
            stati[i] = {
                line:lines[i].getElementsByTagName("name").item(0).textContent,
                status:lines[i].getElementsByTagName("status").item(0).textContent,
                details:lines[i].getElementsByTagName("messages").item(0).textContent
            };
        }

        // Set the last update
        this.list = stati;
        this.lastUpdate = new Date();
    }
});
<|endoftext|>