debian-mirror-gitlab/snowplow-javascript-tracker/src/js/in_queue.js
2020-04-13 14:06:41 +05:30

193 lines
6.3 KiB
JavaScript

/*
* JavaScript tracker for Snowplow: queue.js
*
* Significant portions copyright 2010 Anthon Pang. Remainder copyright
* 2012-2014 Snowplow Analytics Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of Anthon Pang nor Snowplow Analytics Ltd nor the
* names of their contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
;(function() {
var
map = require('lodash/map'),
isUndefined = require('lodash/isUndefined'),
isFunction = require('lodash/isFunction'),
helpers = require('./lib/helpers'),
object = typeof exports !== 'undefined' ? exports : this; // For eventual node.js environment support
/************************************************************
* Proxy object
* - this allows the caller to continue push()'ing to _snaq
* after the Tracker has been initialized and loaded
************************************************************/
object.InQueueManager = function(TrackerConstructor, version, mutSnowplowState, asyncQueue, functionName) {
// Page view ID should be shared between all tracker instances
var trackerDictionary = {};
/**
* Get an array of trackers to which a function should be applied.
*
* @param array names List of namespaces to use. If empty, use all namespaces.
*/
function getNamedTrackers(names) {
var namedTrackers = [];
if (!names || names.length === 0) {
namedTrackers = map(trackerDictionary);
} else {
for (var i = 0; i < names.length; i++) {
if (trackerDictionary.hasOwnProperty(names[i])) {
namedTrackers.push(trackerDictionary[names[i]]);
} else {
helpers.warn('Warning: Tracker namespace "' + names[i] + '" not configured');
}
}
}
if (namedTrackers.length === 0) {
helpers.warn('Warning: No tracker configured');
}
return namedTrackers;
}
/**
* Legacy support for input of the form _snaq.push(['setCollectorCf', 'd34uzc5hjrimh8'])
*
* @param string f Either 'setCollectorCf' or 'setCollectorUrl'
* @param string endpoint
* @param string namespace Optional tracker name
*
* TODO: remove this in 2.1.0
*/
function legacyCreateNewNamespace(f, endpoint, namespace) {
helpers.warn(f + ' is deprecated. Set the collector when a new tracker instance using newTracker.');
var name;
if (isUndefined(namespace)) {
name = 'sp';
} else {
name = namespace;
}
createNewNamespace(name);
trackerDictionary[name][f](endpoint);
}
/**
* Initiate a new tracker namespace
*
* @param string namespace
* @param string endpoint Of the form d3rkrsqld9gmqf.cloudfront.net
*/
function createNewNamespace(namespace, endpoint, argmap) {
argmap = argmap || {};
if (!trackerDictionary.hasOwnProperty(namespace)) {
trackerDictionary[namespace] = new TrackerConstructor(functionName, namespace, version, mutSnowplowState, argmap);
trackerDictionary[namespace].setCollectorUrl(endpoint);
} else {
helpers.warn('Tracker namespace ' + namespace + ' already exists.');
}
}
/**
* Output an array of the form ['functionName', [trackerName1, trackerName2, ...]]
*
* @param string inputString
*/
function parseInputString(inputString) {
var separatedString = inputString.split(':'),
extractedFunction = separatedString[0],
extractedNames = (separatedString.length > 1) ? separatedString[1].split(';') : [];
return [extractedFunction, extractedNames];
}
/**
* apply wrapper
*
* @param array parameterArray An array comprising either:
* [ 'methodName', optional_parameters ]
* or:
* [ functionObject, optional_parameters ]
*/
function applyAsyncFunction() {
var i, j, f, parameterArray, input, parsedString, names, namedTrackers;
// Outer loop in case someone push'es in zarg of arrays
for (i = 0; i < arguments.length; i += 1) {
parameterArray = arguments[i];
// Arguments is not an array, so we turn it into one
input = Array.prototype.shift.call(parameterArray);
// Custom callback rather than tracker method, called with trackerDictionary as the context
if (isFunction(input)) {
input.apply(trackerDictionary, parameterArray);
continue;
}
parsedString = parseInputString(input);
f = parsedString[0];
names = parsedString[1];
if (f === 'newTracker') {
createNewNamespace(parameterArray[0], parameterArray[1], parameterArray[2]);
continue;
}
if ((f === 'setCollectorCf' || f === 'setCollectorUrl') && (!names || names.length === 0)) {
legacyCreateNewNamespace(f, parameterArray[0], parameterArray[1]);
continue;
}
namedTrackers = getNamedTrackers(names);
for (j = 0; j < namedTrackers.length; j++) {
namedTrackers[j][f].apply(namedTrackers[j], parameterArray);
}
}
}
// We need to manually apply any events collected before this initialization
for (var i = 0; i < asyncQueue.length; i++) {
applyAsyncFunction(asyncQueue[i]);
}
return {
push: applyAsyncFunction
};
};
}());