Source: Utils/utils.js

/**
 * @class
 * @classdesc Plugin with utils methods.
 * @name Utils
 * @memberof ATInternet.Tracker.Plugins
 * @type {function}
 * @param parent {object} Instance of the Tag used
 * @description
 * This plugin shares specific feature methods to our helper plugins.
 * For example plugins Page, Clicks and OnSiteAds have common usages.
 * @public
 */
window['ATInternet']['Tracker']['Plugins']['Utils'] = function (parent) {
    "use strict";
    var self = this;

    // storage for the querystrings processed, key is the hash of the querystring, value is an object with all querystring parameters
    var _queryStringValues = {};

    /**
     * Get the value of a queryString variable
     * @name getQueryStringValue
     * @memberof ATInternet.Tracker.Plugins.Utils#
     * @function
     * @param name {string} Variable that you want to get
     * @param str {string} String in which we will look the wanted variable (considered as queryString format)
     * @return string|null|undefined {string|null|undefined} This method returns a string if the variable exists with a value,
     * it returns null if the variable is not present (or not correct for a queryString) or
     * it returns undefined if the variable exists but doesn't have any value (ex : '&variable=')
     * @public
     */
    self['getQueryStringValue'] = function (name, str) {
        var hash = window['ATInternet']['Utils']['hashcode'](str).toString();
        if (!_queryStringValues[hash]) {
            _queryStringValues[hash] = {};
            var regex = new RegExp('[&#?]{1}([^&=#?]*)=([^&#]*)?', 'g'),
                match = regex.exec(str);
            if (match !== null) {
                while (match !== null) {
                    _queryStringValues[hash][match[1]] = match[2];
                    match = regex.exec(str);
                }
            }
        }
        if (_queryStringValues[hash].hasOwnProperty(name)) {
            return _queryStringValues[hash][name];
        } else {
            return null;
        }
    };

    /**
     * Serialize to JSON format and encode the string before returning it (encodeURIComponent)
     * @name customObjectToString
     * @memberof ATInternet.Tracker.Plugins.Utils#
     * @function
     * @param customObject {object} Javascript object we nee to transform into a JSON encoded string
     * @return {string}
     * @public
     */
    self['customObjectToString'] = function (customObject) {
        return encodeURIComponent(window['ATInternet']['Utils']['jsonSerialize'](customObject));
    };

    /**
     * Check an iterative property in an object and build a specific string from it
     * @name manageChapters
     * @memberof ATInternet.Tracker.Plugins.Utils#
     * @function
     * @param tagObject {object} Object containing properties to check
     * @param key {string} Key word to check
     * @param length {number} Number of occurence possible
     * @return {string}
     * @example
     * <pre>
     * var myObject = {
     *     chapter1:'one',
     *     chapter2:'two'
     * }
     * var chapters = manageChapters(myObject, 'chapter', 2);
     * // chapters = 'one::two::'
     * </pre>
     * @public
     */
    self['manageChapters'] = function (tagObject, key, length) {
        var config = parent.getConfig('ignoreEmptyChapterValue');
        var chapt = '';
        if (tagObject) {
            length = parseInt(length, 10);
            for (var i = 1; i < length + 1; i++) {
                var chapterName = tagObject[key + i] || '';
                if (config) {
                    chapt += chapterName ? chapterName + '::' : '';
                } else {
                    chapt += tagObject.hasOwnProperty(key + i) ? chapterName + '::' : '';
                }
            }
        }
        return chapt;
    };

    /**
     * Get document level to use from global configuration or the default one (document.)
     * @name getDocumentLevel
     * @memberof ATInternet.Tracker.Plugins.Utils#
     * @function
     * @return {object}
     * @public
     */
    self['getDocumentLevel'] = function () {
        var documentLevel = parent.getConfig('documentLevel');
        if (documentLevel.indexOf('.') < 0) {
            return (window[documentLevel] || document);
        } else {
            var tab = documentLevel.split('.');
            return (window[tab[0]][tab[1]] || document);
        }
    };

    /**
     * Get the current location (URL associated with the document level configured)
     * @name getLocation
     * @memberof ATInternet.Tracker.Plugins.Utils#
     * @function
     * @return {string}
     * @public
     */
    self['getLocation'] = function () {
        var obj = self.getDocumentLevel();
        return obj.location.href;
    };

    //////////////////////////////  dispatch  ///////////////////////////////////

    parent.dispatchIndex = {};
    parent.dispatchStack = [];
    parent.dispatchEventFor = {};
    var ExecWaitingSpecificDispatchCount = 0;

    /**
     * [Function added by plugin {@link ATInternet.Tracker.Plugins.Utils Utils}] Add a helper plugin into a list telling which ones have been used before dispatching
     * @name dispatchSubscribe
     * @memberof ATInternet.Tracker.Tag
     * @inner
     * @function
     * @param helperName {string} Plugin name to add
     * @return {boolean}
     * @private
     */
    parent['dispatchSubscribe'] = function (helperName) {
        if (!parent.dispatchIndex[helperName]) {
            parent.dispatchStack.push(helperName);
            parent.dispatchIndex[helperName] = true;
            return true;
        }
        return false;
    };

    /**
     * [Function added by plugin {@link ATInternet.Tracker.Plugins.Utils Utils}] Return a boolean which tell if the helper plugin concerned is waiting for a dispatch
     * @name dispatchSubscribed
     * @memberof ATInternet.Tracker.Tag
     * @inner
     * @function
     * @param helperName {string} Plugin name to check
     * @return {boolean}
     * @private
     */
    parent['dispatchSubscribed'] = function (helperName) {
        return parent.dispatchIndex[helperName] === true;
    };

    /**
     * [Function added by plugin {@link ATInternet.Tracker.Plugins.Utils Utils}] Add a specific event for dispatching
     * @name addSpecificDispatchEventFor
     * @memberof ATInternet.Tracker.Tag
     * @inner
     * @function
     * @param helperName {string} Plugin name to check
     * @return {boolean}
     * @private
     */
    parent['addSpecificDispatchEventFor'] = function (helperName) {
        if (!parent.dispatchEventFor[helperName]) {
            parent.dispatchEventFor[helperName] = true;
            ExecWaitingSpecificDispatchCount++;
            return true;
        }
        return false;
    };

    /**
     * Test if specific dispatch are being processed
     * @memberof ATInternet.Tracker.Plugins.Utils#
     * @function
     * @return {boolean}
     * @private
     */
    var _IsExecWaitingSpecificDispatch = function () {
        return ExecWaitingSpecificDispatchCount !== 0;
    };

    /**
     * [Function added by plugin {@link ATInternet.Tracker.Plugins.Utils Utils}] Process a specific event for dispatching
     * @name processSpecificDispatchEventFor
     * @memberof ATInternet.Tracker.Tag
     * @inner
     * @function
     * @param helperName {string} Plugin name to check
     * @private
     */
    parent['processSpecificDispatchEventFor'] = function (helperName) {
        if (parent.dispatchEventFor[helperName]) {
            parent.dispatchEventFor[helperName] = false;
            ExecWaitingSpecificDispatchCount--;
            if (ExecWaitingSpecificDispatchCount === 0) {
                parent.dispatchEventFor = {};
                parent['emit']('Tracker:Plugin:SpecificEvent:Exec:Complete', {lvl: 'INFO'});
            }
        }
    };

    /**
     * [Helper added by plugin {@link ATInternet.Tracker.Plugins.Utils Utils}] Dispatch all tags.
     * @name dispatch
     * @memberof ATInternet.Tracker.Tag
     * @inner
     * @function
     * @public
     */
    parent['dispatch'] = function () {
        var _doDispatch = function () {
            while (parent.dispatchStack.length > 0) {
                var name = parent.dispatchStack.pop();
                parent[name]['onDispatch']();
            }
            parent.dispatchIndex = {};
            parent.delContext(undefined, 'customObject');
            /* @if debug */
            parent.debug('Utils:dispatch', 'DEBUG', 'method ended');
            /* @endif */
        };
        var _processDispatch = function () {
            if (!parent.plugins.isExecWaitingLazyloading()) {
                _doDispatch();
            } else {
                // it manages both cases, lazyload plugins can finish loading after some lazyload triggers or the contrary
                parent['onTrigger']('Tracker:Plugin:Lazyload:Exec:Complete', function () {
                    _doDispatch();
                }, true);
            }
        };
        if (!_IsExecWaitingSpecificDispatch()) {
            _processDispatch();
        } else {
            parent['onTrigger']('Tracker:Plugin:SpecificEvent:Exec:Complete', function () {
                _processDispatch();
            }, true);
        }
    };

    /**
     * [Helper added by plugin {@link ATInternet.Tracker.Plugins.Utils Utils}] Dispatch all tags (with automatic redirect management).
     * @name dispatchRedirect
     * @memberof ATInternet.Tracker.Tag
     * @inner
     * @function
     * @param tagObject {object} Tag object, used here to tell how we have to do the redirection (url/target)
     * @return {boolean}
     * @public
     */
    parent['dispatchRedirect'] = function (tagObject) {
        var resultCheck = true;
        if (tagObject && tagObject['elem']) {
            tagObject['elem']['timeoutonly'] = true;
            parent['plugins']['exec']('TechClicks', 'manageClick', [tagObject['elem'], tagObject['event'], tagObject['callback']], function (data) {
                resultCheck = data;
            });
        }
        parent.dispatch();
        return resultCheck;
    };

    //////////////////////////////  dispatch  ///////////////////////////////////

    /* @if test */
    self['getQueryStringValuesHash'] = function () {
        return _queryStringValues
    };
    /* @endif */
};

window['ATInternet']['Tracker']['addPlugin']('Utils');