Source: Tracker/callbacks.js

/**
 * @class
 * @classdesc Callbacks Management.
 * @name CallbacksManager
 * @param tag {object} Instance of the Tag used
 * @public
 */
var CallbacksManager = function (tag) {
    'use strict';

    var self = this;
    var callbacksToProcess = {};
    var callbacksLoaded = {};

    /**
     * Process callbacks
     * @memberof CallbacksManager#
     * @function
     * @private
     */
    var _process = function () {
        var configuration = tag.getConfig('callbacks');
        // Define callbacks to process
        if (typeof configuration !== 'undefined' && configuration.include instanceof Array) {
            for (var i = 0; i < configuration.include.length; i++) {
                if (ATInternet.Callbacks && ATInternet.Callbacks.hasOwnProperty(configuration.include[i])) {
                    callbacksToProcess[configuration.include[i]] = {
                        'function': ATInternet.Callbacks[configuration.include[i]]
                    };
                    if (!ATInternet.Tracker.callbackProtos[configuration.include[i]]) {
                        ATInternet.Tracker.callbackProtos[configuration.include[i]] = callbacksToProcess[configuration.include[i]];
                    }
                }
            }
        } else {
            for (var name in ATInternet.Callbacks) {
                if (ATInternet.Callbacks.hasOwnProperty(name)) {
                    callbacksToProcess[name] = {
                        'function': ATInternet.Callbacks[name]
                    };
                    if (!ATInternet.Tracker.callbackProtos[name]) {
                        ATInternet.Tracker.callbackProtos[name] = callbacksToProcess[name];
                    }
                }
            }
        }
        // Remove callbacks to exclude
        if (typeof configuration !== 'undefined' && configuration.exclude instanceof Array) {
            for (var j = 0; j < configuration.exclude.length; j++) {
                delete callbacksToProcess[configuration.exclude[j]];
            }
        }
        // Execute valid callbacks
        for (var key in callbacksToProcess) {
            if (callbacksToProcess.hasOwnProperty(key) && callbacksToProcess[key]) {
                self.load(key, callbacksToProcess[key]['function']);
            }
        }
    };

    /**
     * Process callback events
     * @memberof CallbacksManager#
     * @function
     * @private
     */
    var _processEvent = function (e) {
        if (e.name) {
            // Define if callback can be processed
            var toProcess = true;
            var configuration = tag.getConfig('callbacks');
            if (typeof configuration !== 'undefined') {
                if (configuration.include instanceof Array && ATInternet.Utils.arrayIndexOf(configuration.include, e.name) === -1) {
                    toProcess = false;
                }
                if (configuration.exclude instanceof Array && ATInternet.Utils.arrayIndexOf(configuration.exclude, e.name) !== -1) {
                    toProcess = false;
                }
            }
            if (ATInternet.Callbacks && ATInternet.Callbacks.hasOwnProperty(e.name)) {
                var callbackToAdd = {};
                callbackToAdd[e.name] = {
                    'function': ATInternet.Callbacks[e.name]
                };
                if (toProcess) {
                    self.load(e.name, callbackToAdd[e.name]['function']);
                }
                if (!ATInternet.Tracker.callbackProtos[e.name]) {
                    ATInternet.Tracker.callbackProtos[e.name] = callbackToAdd[e.name];
                }
            }
        }
    };

    /**
     * Load a callback.
     * @name load
     * @memberof CallbacksManager#
     * @function
     * @public
     * @param name {string} Callback's name
     * @param Callback {function} Callback's code
     * @returns Object {object} Instance of the Tag used
     */
    self.load = function (name, Callback) {
        if (typeof (Callback) === 'function') {
            callbacksLoaded[name] = new Callback(tag);
            tag.emit('Tracker:Callback:Load:' + name + ':Ok', {
                lvl: 'INFO',
                details: {obj: Callback}
            });
        } else {
            tag.emit('Tracker:Callback:Load:' + name + ':Error', {
                lvl: 'ERROR',
                msg: 'not a function',
                details: {obj: Callback}
            });
        }
        return tag;
    };

    /**
     * Create an instance of each callback declared.
     * @name init
     * @memberof CallbacksManager#
     * @function
     * @public
     */
    self.init = function () {
        if (!!tag.getConfig('activateCallbacks')) {
            // Run process for loaded callbacks
            _process();
            // Attach event in order to process asynchronous callbacks
            ATInternet.Utils.addCallbackEvent(_processEvent);
        }
    };

    /**
     * Delete the callback management event
     * @name init
     * @memberof CallbacksManager#
     * @function
     * @public
     */
    self.removeCallbackEvent = function () {
        ATInternet.Utils.removeCallbackEvent(_processEvent);
    };

    // For unit tests on private elements !!!
    /* @if test */
    self.callbacksToProcess = callbacksToProcess;
    self.callbacksLoaded = callbacksLoaded;
    /* @endif */
};