conveyal/modeify

View on GitHub
client/components/pazguille/scrolling/0.1.0/index.js

Summary

Maintainability
A
35 mins
Test Coverage
/**
 * Module dependencies
 */
var on = (window.addEventListener !== undefined) ? 'addEventListener' : 'attachEvent',
    off = (window.removeEventListener !== undefined) ? 'removeEventListener' : 'detachEvent',
    scrollEvent = (on !== 'addEventListener') ? 'onscroll' : 'scroll',
    scrolled = false,
    requestAnimFrame = (function () {
        return window.requestAnimationFrame ||
            window.webkitRequestAnimationFrame ||
            window.mozRequestAnimationFrame ||
            function (callback) {
                window.setTimeout(callback, 1000 / 60);
            };
    }()),
    scrolledElement,
    scroll;


/**
 * Captures the scroll event and the element who emits it.
 * @function
 * @private
 */
function captureScroll(e) {
    // No changing, exit
    if (!scrolled) {
        scrolled = true;
        scrolledElement = this;
        eve = e || window.e;


        /**
         * requestAnimationFrame
         */
        requestAnimFrame(update);
    }
}

/**
 * If the scroll event exist, it will execute the scrolledElement listeners.
 * @function
 * @private
 */
function update() {

    var i = 0,
        listeners = scroll._collection[scrolledElement].listeners,
        len = listeners.length;

    for (i; i < len; i += 1) {
        listeners[i].call(scrolledElement, eve);
    }

    scrolledElement = undefined;

    // Change scroll status
    scrolled = false;
}

/**
 * Scroll Constructor.
 * @constructor
 * @returns {scroll} Returns a new instance of Scroll.
 */
function Scroll() {
    this.initialize();
    return this;
}

/**
 * Initializes a new instance of Scroll.
 * @function
 * @returns {scroll} Returns a new instance of Scroll.
 */
Scroll.prototype.initialize = function () {
    this._collection = {};
    return this;
};

/**
 * Adds an el with a listener to the collection.
 * @memberof! Scroll.prototype
 * @function
 * @param {HTMLElement} [el] - A given HTMLElement to add to scroll.
 * @param {Funtion} listener - A given listener to execute when the given el is scrolled.
 * @returns {scroll}
 */
Scroll.prototype.add = function (el, listener) {

    if ('function' === typeof el) {
        listener = el;
        el = window;
    }

    if (this._collection[el] === undefined) {
        this._collection[el] = {
            'listeners': []
        };

        el[on](scrollEvent, captureScroll, false);
    }

    // Add listeners to an el collection
    this._collection[el].listeners.push(listener);

    return this;
};

/**
 * Removes a HTMLElement and its listener from the collection with the given el.
 * @memberof! Scroll.prototype
 * @function
 * @param {HTMLElement} el - A given HTMLElement to remove.
 * @param {Funtion} [listener] - A given listener to remove.
 * @returns {scroll}
 */
Scroll.prototype.remove = function (el, listener) {
    var listeners = this._collection[el].listeners,
        i = 0,
        len = listeners.length;

    if (len !== undefined) {
        for (i; i < len; i += 1) {
            if (listeners[i] === listener) {
                listeners.splice(i, 1);
                break;
            }
        }
    }

    if (listeners.length === 0 || listener === undefined) {
        el[off](scrollEvent, captureScroll, false);
        delete this._collection[el];
    }

    return this;
};

// Defines a new instance of Scroll.
scroll = new Scroll();

/**
 * Adds an el with a listener to the collection.
 * @function
 * @param {HTMLElement} [el] - A given HTMLElement to add to scroll.
 * @param {Funtion} listener - A given listener to execute when the given el is scrolled.
 * @returns {scroll}
 */
function scrolling(el, listener) {
    scroll.add(el, listener);

    return scrolling;
}

/**
 * Removes a HTMLElement and its listener from the collection with the given el.
 * @function
 * @param {HTMLElement} el - A given HTMLElement to remove.
 * @param {Funtion} [listener] - A given listener to remove.
 * @returns {scrolling}
 */
scrolling.remove = function (el, listener) {
    scroll.remove(el, listener);

    return scrolling;
};

/**
 * Expose scrolling
 */
exports = module.exports = scrolling;