/*
    json2.js
    2014-02-04

    Public Domain.

    NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.

    See http://www.JSON.org/js.html


    This code should be minified before deployment.
    See http://javascript.crockford.com/jsmin.html

    USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
    NOT CONTROL.


    This file creates a global JSON object containing two methods: stringify
    and parse.

        JSON.stringify(value, replacer, space)
            value       any JavaScript value, usually an object or array.

            replacer    an optional parameter that determines how object
                        values are stringified for objects. It can be a
                        function or an array of strings.

            space       an optional parameter that specifies the indentation
                        of nested structures. If it is omitted, the text will
                        be packed without extra whitespace. If it is a number,
                        it will specify the number of spaces to indent at each
                        level. If it is a string (such as '\t' or '&nbsp;'),
                        it contains the characters used to indent at each level.

            This method produces a JSON text from a JavaScript value.

            When an object value is found, if the object contains a toJSON
            method, its toJSON method will be called and the result will be
            stringified. A toJSON method does not serialize: it returns the
            value represented by the name/value pair that should be serialized,
            or undefined if nothing should be serialized. The toJSON method
            will be passed the key associated with the value, and this will be
            bound to the value

            For example, this would serialize Dates as ISO strings.

                Date.prototype.toJSON = function (key) {
                    function f(n) {
                        // Format integers to have at least two digits.
                        return n < 10 ? '0' + n : n;
                    }

                    return this.getUTCFullYear()   + '-' +
                         f(this.getUTCMonth() + 1) + '-' +
                         f(this.getUTCDate())      + 'T' +
                         f(this.getUTCHours())     + ':' +
                         f(this.getUTCMinutes())   + ':' +
                         f(this.getUTCSeconds())   + 'Z';
                };

            You can provide an optional replacer method. It will be passed the
            key and value of each member, with this bound to the containing
            object. The value that is returned from your method will be
            serialized. If your method returns undefined, then the member will
            be excluded from the serialization.

            If the replacer parameter is an array of strings, then it will be
            used to select the members to be serialized. It filters the results
            such that only members with keys listed in the replacer array are
            stringified.

            Values that do not have JSON representations, such as undefined or
            functions, will not be serialized. Such values in objects will be
            dropped; in arrays they will be replaced with null. You can use
            a replacer function to replace those with JSON values.
            JSON.stringify(undefined) returns undefined.

            The optional space parameter produces a stringification of the
            value that is filled with line breaks and indentation to make it
            easier to read.

            If the space parameter is a non-empty string, then that string will
            be used for indentation. If the space parameter is a number, then
            the indentation will be that many spaces.

            Example:

            text = JSON.stringify(['e', {pluribus: 'unum'}]);
            // text is '["e",{"pluribus":"unum"}]'


            text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
            // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'

            text = JSON.stringify([new Date()], function (key, value) {
                return this[key] instanceof Date ?
                    'Date(' + this[key] + ')' : value;
            });
            // text is '["Date(---current time---)"]'


        JSON.parse(text, reviver)
            This method parses a JSON text to produce an object or array.
            It can throw a SyntaxError exception.

            The optional reviver parameter is a function that can filter and
            transform the results. It receives each of the keys and values,
            and its return value is used instead of the original value.
            If it returns what it received, then the structure is not modified.
            If it returns undefined then the member is deleted.

            Example:

            // Parse the text. Values that look like ISO date strings will
            // be converted to Date objects.

            myData = JSON.parse(text, function (key, value) {
                var a;
                if (typeof value === 'string') {
                    a =
/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
                    if (a) {
                        return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
                            +a[5], +a[6]));
                    }
                }
                return value;
            });

            myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
                var d;
                if (typeof value === 'string' &&
                        value.slice(0, 5) === 'Date(' &&
                        value.slice(-1) === ')') {
                    d = new Date(value.slice(5, -1));
                    if (d) {
                        return d;
                    }
                }
                return value;
            });


    This is a reference implementation. You are free to copy, modify, or
    redistribute.
*/

/*jslint evil: true, regexp: true */

/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
    call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
    getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
    lastIndex, length, parse, prototype, push, replace, slice, stringify,
    test, toJSON, toString, valueOf
*/


// Create a JSON object only if one does not already exist. We create the
// methods in a closure to avoid creating global variables.

if (typeof JSON !== 'object') {
    JSON = {};
}

(function () {
    'use strict';

    function f(n) {
        // Format integers to have at least two digits.
        return n < 10 ? '0' + n : n;
    }

    if (typeof Date.prototype.toJSON !== 'function') {

        Date.prototype.toJSON = function () {

            return isFinite(this.valueOf())
                ? this.getUTCFullYear()     + '-' +
                    f(this.getUTCMonth() + 1) + '-' +
                    f(this.getUTCDate())      + 'T' +
                    f(this.getUTCHours())     + ':' +
                    f(this.getUTCMinutes())   + ':' +
                    f(this.getUTCSeconds())   + 'Z'
                : null;
        };

        String.prototype.toJSON      =
            Number.prototype.toJSON  =
            Boolean.prototype.toJSON = function () {
                return this.valueOf();
            };
    }

    var cx,
        escapable,
        gap,
        indent,
        meta,
        rep;


    function quote(string) {

// If the string contains no control characters, no quote characters, and no
// backslash characters, then we can safely slap some quotes around it.
// Otherwise we must also replace the offending characters with safe escape
// sequences.

        escapable.lastIndex = 0;
        return escapable.test(string) ? '"' + string.replace(escapable, function (a) {
            var c = meta[a];
            return typeof c === 'string'
                ? c
                : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
        }) + '"' : '"' + string + '"';
    }


    function str(key, holder) {

// Produce a string from holder[key].

        var i,          // The loop counter.
            k,          // The member key.
            v,          // The member value.
            length,
            mind = gap,
            partial,
            value = holder[key];

// If the value has a toJSON method, call it to obtain a replacement value.

        if (value && typeof value === 'object' &&
                typeof value.toJSON === 'function') {
            value = value.toJSON(key);
        }

// If we were called with a replacer function, then call the replacer to
// obtain a replacement value.

        if (typeof rep === 'function') {
            value = rep.call(holder, key, value);
        }

// What happens next depends on the value's type.

        switch (typeof value) {
        case 'string':
            return quote(value);

        case 'number':

// JSON numbers must be finite. Encode non-finite numbers as null.

            return isFinite(value) ? String(value) : 'null';

        case 'boolean':
        case 'null':

// If the value is a boolean or null, convert it to a string. Note:
// typeof null does not produce 'null'. The case is included here in
// the remote chance that this gets fixed someday.

            return String(value);

// If the type is 'object', we might be dealing with an object or an array or
// null.

        case 'object':

// Due to a specification blunder in ECMAScript, typeof null is 'object',
// so watch out for that case.

            if (!value) {
                return 'null';
            }

// Make an array to hold the partial results of stringifying this object value.

            gap += indent;
            partial = [];

// Is the value an array?

            if (Object.prototype.toString.apply(value) === '[object Array]') {

// The value is an array. Stringify every element. Use null as a placeholder
// for non-JSON values.

                length = value.length;
                for (i = 0; i < length; i += 1) {
                    partial[i] = str(i, value) || 'null';
                }

// Join all of the elements together, separated with commas, and wrap them in
// brackets.

                v = partial.length === 0
                    ? '[]'
                    : gap
                    ? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']'
                    : '[' + partial.join(',') + ']';
                gap = mind;
                return v;
            }

// If the replacer is an array, use it to select the members to be stringified.

            if (rep && typeof rep === 'object') {
                length = rep.length;
                for (i = 0; i < length; i += 1) {
                    if (typeof rep[i] === 'string') {
                        k = rep[i];
                        v = str(k, value);
                        if (v) {
                            partial.push(quote(k) + (gap ? ': ' : ':') + v);
                        }
                    }
                }
            } else {

// Otherwise, iterate through all of the keys in the object.

                for (k in value) {
                    if (Object.prototype.hasOwnProperty.call(value, k)) {
                        v = str(k, value);
                        if (v) {
                            partial.push(quote(k) + (gap ? ': ' : ':') + v);
                        }
                    }
                }
            }

// Join all of the member texts together, separated with commas,
// and wrap them in braces.

            v = partial.length === 0
                ? '{}'
                : gap
                ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}'
                : '{' + partial.join(',') + '}';
            gap = mind;
            return v;
        }
    }

// If the JSON object does not yet have a stringify method, give it one.

    if (typeof JSON.stringify !== 'function') {
        escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
        meta = {    // table of character substitutions
            '\b': '\\b',
            '\t': '\\t',
            '\n': '\\n',
            '\f': '\\f',
            '\r': '\\r',
            '"' : '\\"',
            '\\': '\\\\'
        };
        JSON.stringify = function (value, replacer, space) {

// The stringify method takes a value and an optional replacer, and an optional
// space parameter, and returns a JSON text. The replacer can be a function
// that can replace values, or an array of strings that will select the keys.
// A default replacer method can be provided. Use of the space parameter can
// produce text that is more easily readable.

            var i;
            gap = '';
            indent = '';

// If the space parameter is a number, make an indent string containing that
// many spaces.

            if (typeof space === 'number') {
                for (i = 0; i < space; i += 1) {
                    indent += ' ';
                }

// If the space parameter is a string, it will be used as the indent string.

            } else if (typeof space === 'string') {
                indent = space;
            }

// If there is a replacer, it must be a function or an array.
// Otherwise, throw an error.

            rep = replacer;
            if (replacer && typeof replacer !== 'function' &&
                    (typeof replacer !== 'object' ||
                    typeof replacer.length !== 'number')) {
                throw new Error('JSON.stringify');
            }

// Make a fake root object containing our value under the key of ''.
// Return the result of stringifying the value.

            return str('', {'': value});
        };
    }


// If the JSON object does not yet have a parse method, give it one.

    if (typeof JSON.parse !== 'function') {
        cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
        JSON.parse = function (text, reviver) {

// The parse method takes a text and an optional reviver function, and returns
// a JavaScript value if the text is a valid JSON text.

            var j;

            function walk(holder, key) {

// The walk method is used to recursively walk the resulting structure so
// that modifications can be made.

                var k, v, value = holder[key];
                if (value && typeof value === 'object') {
                    for (k in value) {
                        if (Object.prototype.hasOwnProperty.call(value, k)) {
                            v = walk(value, k);
                            if (v !== undefined) {
                                value[k] = v;
                            } else {
                                delete value[k];
                            }
                        }
                    }
                }
                return reviver.call(holder, key, value);
            }


// Parsing happens in four stages. In the first stage, we replace certain
// Unicode characters with escape sequences. JavaScript handles many characters
// incorrectly, either silently deleting them, or treating them as line endings.

            text = String(text);
            cx.lastIndex = 0;
            if (cx.test(text)) {
                text = text.replace(cx, function (a) {
                    return '\\u' +
                        ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
                });
            }

// In the second stage, we run the text against regular expressions that look
// for non-JSON patterns. We are especially concerned with '()' and 'new'
// because they can cause invocation, and '=' because it can cause mutation.
// But just to be safe, we want to reject all unexpected forms.

// We split the second stage into 4 regexp operations in order to work around
// crippling inefficiencies in IE's and Safari's regexp engines. First we
// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
// replace all simple value tokens with ']' characters. Third, we delete all
// open brackets that follow a colon or comma or that begin the text. Finally,
// we look to see that the remaining characters are only whitespace or ']' or
// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.

            if (/^[\],:{}\s]*$/
                    .test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
                        .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
                        .replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {

// In the third stage we use the eval function to compile the text into a
// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
// in JavaScript: it can begin a block or an object literal. We wrap the text
// in parens to eliminate the ambiguity.

                j = eval('(' + text + ')');

// In the optional fourth stage, we recursively walk the new structure, passing
// each name/value pair to a reviver function for possible transformation.

                return typeof reviver === 'function'
                    ? walk({'': j}, '')
                    : j;
            }

// If the text is not JSON parseable, then a SyntaxError is thrown.

            throw new SyntaxError('JSON.parse');
        };
    }
}());
/* JSONPath 0.8.0 - XPath for JSON
 *
 * Copyright (c) 2007 Stefan Goessner (goessner.net)
 * Licensed under the MIT (MIT-LICENSE.txt) licence.
 */

var isNode = false;
(function(exports, require) {

// Keep compatibility with old browsers
if (!Array.isArray) {
  Array.isArray = function(vArg) {
   return Object.prototype.toString.call(vArg) === "[object Array]";
  };
}

if ( 'function' !== typeof Array.prototype.reduce ) {
  Array.prototype.reduce = function( callback /*, initialValue*/ ) {
    if ( null === this || 'undefined' === typeof this ) {
      throw new TypeError(
         'Array.prototype.reduce called on null or undefined' );
    }
    if ( 'function' !== typeof callback ) {
      return;
    }
    var t = Object( this ), len = t.length >>> 0, k = 0, value;
    if ( arguments.length >= 2 ) {
      value = arguments[1];
    } else {
      while ( k < len && ! k in t ) k++; 
      if ( k >= len )
        throw new TypeError('Reduce of empty array with no initial value');
      value = t[ k++ ];
    }
    for ( ; k < len ; k++ ) {
      if ( k in t ) {
         value = callback( value, t[k], k, t );
      }
    }
    return value;
  };
}

// Production steps of ECMA-262, Edition 5, 15.4.4.19
// Reference: http://es5.github.com/#x15.4.4.19
if (!Array.prototype.map) {

  Array.prototype.map = function (callback, thisArg) {

    var T, A, k;

    if (this == null) {
      throw new TypeError(" this is null or not defined");
    }

    // 1. Let O be the result of calling ToObject passing the |this| value as the argument.
    var O = Object(this);

    // 2. Let lenValue be the result of calling the Get internal method of O with the argument "length".
    // 3. Let len be ToUint32(lenValue).
    var len = O.length >>> 0;

    // 4. If IsCallable(callback) is false, throw a TypeError exception.
    // See: http://es5.github.com/#x9.11
    if (typeof callback !== "function") {
      return;
    }

    // 5. If thisArg was supplied, let T be thisArg; else let T be undefined.
    if (arguments.length > 1) {
      T = thisArg;
    }

    // 6. Let A be a new array created as if by the expression new Array( len) where Array is
    // the standard built-in constructor with that name and len is the value of len.
    A = new Array(len);

    // 7. Let k be 0
    k = 0;

    // 8. Repeat, while k < len
    while (k < len) {

      var kValue, mappedValue;

      // a. Let Pk be ToString(k).
      //   This is implicit for LHS operands of the in operator
      // b. Let kPresent be the result of calling the HasProperty internal method of O with argument Pk.
      //   This step can be combined with c
      // c. If kPresent is true, then
      if (k in O) {

        // i. Let kValue be the result of calling the Get internal method of O with argument Pk.
        kValue = O[k];

        // ii. Let mappedValue be the result of calling the Call internal method of callback
        // with T as the this value and argument list containing kValue, k, and O.
        mappedValue = callback.call(T, kValue, k, O);

        // iii. Call the DefineOwnProperty internal method of A with arguments
        // Pk, Property Descriptor {Value: mappedValue, Writable: true, Enumerable: true, Configurable: true},
        // and false.

        // In browsers that support Object.defineProperty, use the following:
        // Object.defineProperty( A, k, { value: mappedValue, writable: true, enumerable: true, configurable: true });

        // For best browser support, use the following:
        A[k] = mappedValue;
      }
      // d. Increase k by 1.
      k++;
    }

    // 9. return A
    return A;
  };
}


if (!Array.prototype.filter) {
   Array.prototype.filter = function(fun /*, thisArg */) {
      if (this === void 0 || this === null)
      throw new TypeError();

      var t = Object(this);
      var len = t.length >>> 0;
      if (typeof fun !== "function"){
        return;
      }

      var res = [];
      var thisArg = arguments.length >= 2 ? arguments[1] : void 0;
      for (var i = 0; i < len; i++) {
         if (i in t) {
           var val = t[i];

           // NOTE: Technically this should Object.defineProperty at
           //       the next index, as push can be affected by
           //       properties on Object.prototype and Array.prototype.
           //       But that method's new, and collisions should be
           //       rare, so use the more-compatible alternative.
           if (fun.call(thisArg, val, i, t)) 
             res.push(val);
         }
      }

      return res;
   };
}

// Make sure to know if we are in real node or not (the `require` variable
// could actually be require.js, for example.
var isNode = typeof module !== 'undefined' && !!module.exports;

var vm = isNode ?
    require('vm') : {
      runInNewContext: function(expr, context) { with (context) return eval(expr); }
    };
exports.eval = jsonPath;

var cache = {};

function push(arr, elem) { arr = arr.slice(); arr.push(elem); return arr; }
function unshift(elem, arr) { arr = arr.slice(); arr.unshift(elem); return arr; }

function jsonPath(obj, expr, arg) {
   var P = {
      resultType: arg && arg.resultType || "VALUE",
      flatten: arg && arg.flatten || false,
      wrap: (arg && arg.hasOwnProperty('wrap')) ? arg.wrap : true,
      sandbox: (arg && arg.sandbox) ? arg.sandbox : {},
      normalize: function(expr) {
         if (cache[expr]) return cache[expr];
         var subx = [];
         var normalized = expr.replace(/[\['](\??\(.*?\))[\]']/g, function($0,$1){return "[#"+(subx.push($1)-1)+"]";})
                     .replace(/'?\.'?|\['?/g, ";")
                     .replace(/(;)?(\^+)(;)?/g, function(_, front, ups, back) { return ';' + ups.split('').join(';') + ';'; })
                     .replace(/;;;|;;/g, ";..;")
                     .replace(/;$|'?\]|'$/g, "");
         var exprList = normalized.split(';').map(function(expr) {
            var match = expr.match(/#([0-9]+)/);
            return !match || !match[1] ? expr : subx[match[1]];
         });
         return cache[expr] = exprList;
      },
      asPath: function(path) {
         var x = path, p = "$";
         for (var i=1,n=x.length; i<n; i++)
            p += /^[0-9*]+$/.test(x[i]) ? ("["+x[i]+"]") : ("['"+x[i]+"']");
         return p;
      },
      trace: function(expr, val, path) {
         // no expr to follow? return path and value as the result of this trace branch
         if (!expr.length) return [{path: path, value: val}];

         var loc = expr[0], x = expr.slice(1);
         // the parent sel computation is handled in the frame above using the
         // ancestor object of val
         if (loc === '^') return path.length ? [{path: path.slice(0,-1), expr: x, isParentSelector: true}] : [];

         // we need to gather the return value of recursive trace calls in order to
         // do the parent sel computation.
         var ret = [];
         function addRet(elems) { ret = ret.concat(elems); }

         if (val && val.hasOwnProperty(loc)) // simple case, directly follow property
            addRet(P.trace(x, val[loc], push(path, loc)));
         else if (loc === "*") { // any property
            P.walk(loc, x, val, path, function(m,l,x,v,p) {
               addRet(P.trace(unshift(m, x), v, p)); });
         }
         else if (loc === "..") { // all chid properties
            addRet(P.trace(x, val, path));
            P.walk(loc, x, val, path, function(m,l,x,v,p) {
               if (typeof v[m] === "object")
                  addRet(P.trace(unshift("..", x), v[m], push(p, m)));
            });
         }
         else if (loc[0] === '(') { // [(expr)]
            addRet(P.trace(unshift(P.eval(loc, val, path[path.length], path),x), val, path));
         }
         else if (loc.indexOf('key')===-1&&loc.indexOf('?(') === 0) { // [?(expr)]
            P.walk(loc, x, val, path, function(m,l,x,v,p) {
               if (P.eval(l.replace(/^\?\((.*?)\)$/,"$1"),v[m],m, path))
                  addRet(P.trace(unshift(m,x),v,p));
            });
         }
         else if (loc.indexOf('key')===-1&&loc.indexOf(',') > -1) { // [name1,name2,...]
            for (var parts = loc.split(','), i = 0; i < parts.length; i++)
               addRet(P.trace(unshift(parts[i], x), val, path));
         }
         else if (val && loc.indexOf('key') === 0) {//Add by Pankaj in order to support key level filtering.
          var pattren=new RegExp(loc.split("'")[1]);
            for (var prop in val) {
            if(val.hasOwnProperty(prop) && pattren.test(prop) ){
            addRet(P.trace(x, val[prop], push(path, prop)));
            }
            }           
         }
         else if (/^(-?[0-9]*):(-?[0-9]*):?([0-9]*)$/.test(loc)) { // [start:end:step]  python slice syntax
            addRet(P.slice(loc, x, val, path));
         }

         // we check the resulting values for parent selections. for parent
         // selections we discard the value object and continue the trace with the
         // current val object
         return ret.reduce(function(all, ea) {
            return all.concat(ea.isParentSelector ? P.trace(ea.expr, val, ea.path) : [ea]);
         }, []);
      },
      walk: function(loc, expr, val, path, f) {
         if (Array.isArray(val))
            for (var i = 0, n = val.length; i < n; i++)
               f(i, loc, expr, val, path);
         else if (typeof val === "object")
            for (var m in val)
               if (val.hasOwnProperty(m))
                  f(m, loc, expr, val, path);
      },
      slice: function(loc, expr, val, path) {
         if (!Array.isArray(val)) return;
         var len = val.length, parts = loc.split(':'),
             start = (parts[0] && parseInt(parts[0])) || 0,
             end = (parts[1] && parseInt(parts[1])) || len,
             step = (parts[2] && parseInt(parts[2])) || 1;
         start = (start < 0) ? Math.max(0,start+len) : Math.min(len,start);
         end   = (end < 0)   ? Math.max(0,end+len)   : Math.min(len,end);
         var ret = [];
         for (var i = start; i < end; i += step)
            ret = ret.concat(P.trace(unshift(i,expr), val, path));
         return ret;
      },
      eval: function(code, _v, _vname, path) {
         if (!$ || !_v) return false;
         if (code.indexOf("@path") > -1) {
            P.sandbox["_path"] = P.asPath(path.concat([_vname]));
            code = code.replace(/@path/g, "_path");
         }
         if (code.indexOf("@") > -1) {
            P.sandbox["_v"] = _v;
            code = code.replace(/@/g, "_v");
         }
         try {
             return vm.runInNewContext(code, P.sandbox);
         }
         catch(e) {
             throw new Error("jsonPath: " + e.message + ": " + code);
         }
      }
   };

   var $ = obj;
   var resultType = P.resultType.toLowerCase();
   if (expr && obj && (resultType == "value" || resultType == "path")) {
      var exprList = P.normalize(expr);
      if (exprList[0] === "$" && exprList.length > 1) exprList.shift();
      var result = P.trace(exprList, obj, ["$"]);
      result = result.filter(function(ea) { return ea && !ea.isParentSelector; });
      if (!result.length) return P.wrap ? [] : false;
      if (result.length === 1 && !P.wrap && !Array.isArray(result[0].value)) return result[0][resultType] || false;
      return result.reduce(function(result, ea) {
         var valOrPath = ea[resultType];
         if (resultType === 'path') valOrPath = P.asPath(valOrPath);
         if (P.flatten && Array.isArray(valOrPath)) {
            result = result.concat(valOrPath);
         } else {
            result.push(valOrPath);
         }
         return result;
      }, []);
   }
}
})(typeof exports === 'undefined' ? this['jsonPath'] = {} : exports, typeof require == "undefined" ? null : require);

(function (global) {
	global.pulse_runtime = {
		'jsonPath' : jsonPath
	};
})(this);

(function (global) {
	global.pulse = {
					  'runtime': {
					    'jsonpath': jsonPath,// jshint ignore:line
					    'omniture': {
					      
					    }
					  },
					  'ptns': {
					    'ads': {
					    	'customPageVar':{
					    		
					    	}
					      
					    },
					    'omniture': {
					      
					    }
					  },
					  'output': {
					    
					  },
					  'placeholder': {
					    
					  }
					  
	};
})(this);
/*
(function (runtime) {
	'use strict';
	
	runtime.direct = function(input){ return input;};
	runtime.execJsonPath = function(object,path)
						  {
						  	if(path==="$..id")
						  	{
						  		return "G6373768098424152601";
						  	}
						  	if(path==="$..ty")
						  	{
						  		return "member";
						  	}
						    return "result";
						  };
	runtime.split = function(inputString,splitter){return inputString.split(splitter);};
	runtime.getCookie = function(cookieName){return "cookie_value";};
	runtime.omniture.t = function(){
								return {"fn":"t","args":[]};
	                     };
    runtime.omniture.tl = function(flag,o,link_name){
								return {"fn":"t","args":[{"t":"st","v":true},{"t":"st","v":"o"},{"t":"st","v":link_name}]};
	                     };
})(this.pulse.runtime);
*/
var _bcc = {};

(function(bc, config) {
    'use strict';

    _bcc = {
  "store": {
    "wait_q": {
      "n": "wait_q",
      "t": "localStorage"
    }
  },
  "tmpls": {  
  },
  "ptns": {
  }
  
};

})(_bcq, _bcc);
var _bcc = _bcc || {};

(function(bc, config) {
    'use strict';
    _bcc["ptns"] = _bcc["ptns"] || {};
    _bcc["ptns"]["wmbeacon"] = {
      "rqTp": "post_limit",
      "opts": [
        [
          "beacon_url_domain",
          ""
        ],
        [
          "beacon_url_path",
          ""
        ],
        [
          "site_domain",
          ""
        ],
        [
          "site_id",
          "uswm"
        ],
        [
          "site_version",
          "d.www.1.0"
        ],
        [
          "tm_version",
          "v0"
        ]
      ],
      "tmpls": {
        
      },
      "ctxs": {
        "AdsHklgWlmrt": {
          "acts": {
            "ADS_PAGINATION": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AdsHklgWlmrt_ADS_PAGINATION",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ADS_HL_ERR": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AdsHklgWlmrt_ADS_HL_ERR",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ADS_IN_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AdsHklgWlmrt_ADS_IN_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ADS_MIDAS_ERR": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AdsHklgWlmrt_ADS_MIDAS_ERR",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ADS_SHOWN": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AdsHklgWlmrt_ADS_SHOWN",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ADS_NOT_AVAILABLE": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AdsHklgWlmrt_ADS_NOT_AVAILABLE",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ADS_CLICK": {
              "returnUrl": true,
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AdsHklgWlmrt_ADS_CLICK",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ADS_CSA_ERR": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AdsHklgWlmrt_ADS_CSA_ERR",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "Account": {
          "acts": {
            "LANDING_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_Account_LANDING_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ACCT_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_Account_ACCT_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "Checkout": {
          "acts": {
            "ON_CHCKOUT_SIGN_IN": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_Checkout_ON_CHCKOUT_SIGN_IN",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ON_NEW_ACCT": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_Checkout_ON_NEW_ACCT",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ON_ALL_PKP": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_Checkout_ON_ALL_PKP",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ON_PAYMENT_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_Checkout_ON_PAYMENT_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "CHCKOUT_WELCOME_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_Checkout_CHCKOUT_WELCOME_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ON_CHG_PKP_LOC": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_Checkout_ON_CHG_PKP_LOC",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ON_FF_CONT": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_Checkout_ON_FF_CONT",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "CHCKOUT_SUM": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_Checkout_CHCKOUT_SUM",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ON_SHP_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_Checkout_ON_SHP_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ON_CHG_SHP": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_Checkout_ON_CHG_SHP",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ON_FF_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_Checkout_ON_FF_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ON_PAYMENT_CHANGE_INIT": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_Checkout_ON_PAYMENT_CHANGE_INIT",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ON_PAYMENT_CHANGE": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_Checkout_ON_PAYMENT_CHANGE",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ON_PICKUP_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_Checkout_ON_PICKUP_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ON_REV_ORDER_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_Checkout_ON_REV_ORDER_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ON_ASSOC_OVERLAY_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_Checkout_ON_ASSOC_OVERLAY_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ON_SHP_CONT": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_Checkout_ON_SHP_CONT",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ON_PICKUP_CONT": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_Checkout_ON_PICKUP_CONT",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ON_ADDR_CHANGE": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_Checkout_ON_ADDR_CHANGE",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ON_ALL_SHP": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_Checkout_ON_ALL_SHP",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ON_NEW_ACCT_INIT": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_Checkout_ON_NEW_ACCT_INIT",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ON_PAYMENT_CONT": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_Checkout_ON_PAYMENT_CONT",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ON_NEW_ACCT_COMPLETE": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_Checkout_ON_NEW_ACCT_COMPLETE",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ON_PAYMENT_CHANGE_TGL": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_Checkout_ON_PAYMENT_CHANGE_TGL",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ON_CHCKOUT_GUEST": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_Checkout_ON_CHCKOUT_GUEST",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "PERFORMANCE_METRICS": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_Checkout_PERFORMANCE_METRICS",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "AccountManage_": {
          "acts": {
            "SETTINGS_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AccountManage__SETTINGS_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "SchoolLists": {
          "acts": {
            "ON_UNIV_LINK": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_SchoolLists_ON_UNIV_LINK",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "AdsCntxtsrchGgl": {
          "acts": {
            "ADS_PAGINATION": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AdsCntxtsrchGgl_ADS_PAGINATION",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ADS_HL_ERR": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AdsCntxtsrchGgl_ADS_HL_ERR",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ADS_IN_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AdsCntxtsrchGgl_ADS_IN_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ADS_MIDAS_ERR": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AdsCntxtsrchGgl_ADS_MIDAS_ERR",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ADS_SHOWN": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AdsCntxtsrchGgl_ADS_SHOWN",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ADS_NOT_AVAILABLE": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AdsCntxtsrchGgl_ADS_NOT_AVAILABLE",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ADS_CLICK": {
              "returnUrl": true,
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AdsCntxtsrchGgl_ADS_CLICK",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ADS_CSA_ERR": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AdsCntxtsrchGgl_ADS_CSA_ERR",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "Thankyou": {
          "acts": {
            "THANK_YOU_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_Thankyou_THANK_YOU_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "PERFORMANCE_METRICS": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_Thankyou_PERFORMANCE_METRICS",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "AdsBanner": {
          "acts": {
            "ADS_HL_ERR": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AdsBanner_ADS_HL_ERR",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ADS_IN_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AdsBanner_ADS_IN_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ADS_MIDAS_ERR": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AdsBanner_ADS_MIDAS_ERR",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ADS_SHOWN": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AdsBanner_ADS_SHOWN",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ADS_PAGINATION": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AdsBanner_ADS_PAGINATION",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ADS_NOT_AVAILABLE": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AdsBanner_ADS_NOT_AVAILABLE",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ADS_CLICK": {
              "returnUrl": true,
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AdsBanner_ADS_CLICK",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ADS_CSA_ERR": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AdsBanner_ADS_CSA_ERR",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "Header": {
          "acts": {
            "ON_UNIV_LINK": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_Header_ON_UNIV_LINK",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "ValueOfTheDay": {
          "acts": {
            "VOD_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_ValueOfTheDay_VOD_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "PERFORMANCE_METRICS": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_ValueOfTheDay_PERFORMANCE_METRICS",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "OneHG": {
          "acts": {
            "CONFIRM_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_OneHG_CONFIRM_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "REVIEW_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_OneHG_REVIEW_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "LANDING_VIEW_ERR": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_OneHG_LANDING_VIEW_ERR",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "LANDING_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_OneHG_LANDING_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "PERFORMANCE_METRICS": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_OneHG_PERFORMANCE_METRICS",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "GrpChoicePage": {
          "acts": {
            "GRPNG_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_GrpChoicePage_GRPNG_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "AdsMultiWlmrt": {
          "acts": {
            "ADS_PAGINATION": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AdsMultiWlmrt_ADS_PAGINATION",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ADS_HL_ERR": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AdsMultiWlmrt_ADS_HL_ERR",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ADS_IN_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AdsMultiWlmrt_ADS_IN_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ADS_MIDAS_ERR": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AdsMultiWlmrt_ADS_MIDAS_ERR",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ADS_SHOWN": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AdsMultiWlmrt_ADS_SHOWN",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ADS_NOT_AVAILABLE": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AdsMultiWlmrt_ADS_NOT_AVAILABLE",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ADS_CLICK": {
              "returnUrl": true,
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AdsMultiWlmrt_ADS_CLICK",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ADS_CSA_ERR": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AdsMultiWlmrt_ADS_CSA_ERR",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "CartHelper": {
          "acts": {
            "ON_ATC": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_CartHelper_ON_ATC",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "AccountManage": {
          "acts": {
            "ACCT_MANAGE_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AccountManage_ACCT_MANAGE_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "SETTINGS_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AccountManage_SETTINGS_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "AdsWlmrtWlmrt": {
          "acts": {
            "ADS_PAGINATION": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AdsWlmrtWlmrt_ADS_PAGINATION",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ADS_HL_ERR": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AdsWlmrtWlmrt_ADS_HL_ERR",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ADS_IN_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AdsWlmrtWlmrt_ADS_IN_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ADS_MIDAS_ERR": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AdsWlmrtWlmrt_ADS_MIDAS_ERR",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ADS_SHOWN": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AdsWlmrtWlmrt_ADS_SHOWN",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ADS_NOT_AVAILABLE": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AdsWlmrtWlmrt_ADS_NOT_AVAILABLE",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ADS_CLICK": {
              "returnUrl": true,
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AdsWlmrtWlmrt_ADS_CLICK",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ADS_CSA_ERR": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AdsWlmrtWlmrt_ADS_CSA_ERR",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "MerchModule_": {
          "acts": {
            "ON_UNIV_LINK": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_MerchModule__ON_UNIV_LINK",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "": {
          "acts": {
            "PERFORMANCE_METRICS": {
              "mp": [
                {
                  "rt": "mp",
                  "rn": "",
                  "rr": {
                    "fn": "mappingTemplate",
                    "args": [
                      {
                        "t": "st",
                        "v": "pctx_pv"
                      }
                    ]
                  }
                }
              ]
            }
          }
        },
        "PAC": {
          "acts": {
            "ON_CHCKOUT": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_PAC_ON_CHCKOUT",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "ShoppingCart": {
          "acts": {
            "ON_CHCKOUT": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_ShoppingCart_ON_CHCKOUT",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "SHOPCART_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_ShoppingCart_SHOPCART_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "PERFORMANCE_METRICS": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_ShoppingCart_PERFORMANCE_METRICS",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "Irs_": {
          "acts": {
            "INIT": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_Irs__INIT",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "BOOTSTRAP": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_Irs__BOOTSTRAP",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "PLACEMENT": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_Irs__PLACEMENT",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ADD_TO_CART": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_Irs__ADD_TO_CART",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "PAGINATION": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_Irs__PAGINATION",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "PRODUCT_INTEREST": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_Irs__PRODUCT_INTEREST",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "QUICKLOOK": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_Irs__QUICKLOOK",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "ProductPage": {
          "acts": {
            "PRODUCT_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_ProductPage_PRODUCT_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ON_UNIV_LINK": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_ProductPage_ON_UNIV_LINK",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "ErrorPage": {
          "acts": {
            "ERRORPAGE_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_ErrorPage_ERRORPAGE_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "Expo_": {
          "acts": {
            "ON_EXPO": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_Expo__ON_EXPO",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "EXPO_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_Expo__EXPO_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "Account_": {
          "acts": {
            "NEW_ACCT_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_Account__NEW_ACCT_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "SIGN_IN_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_Account__SIGN_IN_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "SIGN_OUT_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_Account__SIGN_OUT_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "PSWD_FRGT_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_Account__PSWD_FRGT_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "PSWD_RESET_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_Account__PSWD_RESET_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "LocalStore": {
          "acts": {
            "STORE_DETAIL_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_LocalStore_STORE_DETAIL_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "STORE_DETAIL_ERR": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_LocalStore_STORE_DETAIL_ERR",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "PERFORMANCE_METRICS": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_LocalStore_PERFORMANCE_METRICS",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "SearchResults": {
          "acts": {
            "SEARCH_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_SearchResults_SEARCH_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "PERFORMANCE_METRICS": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_SearchResults_PERFORMANCE_METRICS",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "SpotLight_": {
          "acts": {
            "SPOTLIGHT_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_SpotLight__SPOTLIGHT_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "PrintList": {
          "acts": {
            "PRINT_LIST_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_PrintList_PRINT_LIST_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "Browse": {
          "acts": {
            "ON_TITLE_SELECT": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_Browse_ON_TITLE_SELECT",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ON_IMAGE_SELECT": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_Browse_ON_IMAGE_SELECT",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "BROWSE_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_Browse_BROWSE_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "PERFORMANCE_METRICS": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_Browse_PERFORMANCE_METRICS",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "Collection": {
          "acts": {
            "COLLECTION_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_Collection_COLLECTION_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "PERFORMANCE_METRICS": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_Collection_PERFORMANCE_METRICS",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "AdsProdlistGgl": {
          "acts": {
            "ADS_PAGINATION": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AdsProdlistGgl_ADS_PAGINATION",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ADS_HL_ERR": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AdsProdlistGgl_ADS_HL_ERR",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ADS_IN_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AdsProdlistGgl_ADS_IN_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ADS_MIDAS_ERR": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AdsProdlistGgl_ADS_MIDAS_ERR",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ADS_SHOWN": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AdsProdlistGgl_ADS_SHOWN",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ADS_NOT_AVAILABLE": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AdsProdlistGgl_ADS_NOT_AVAILABLE",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ADS_CLICK": {
              "returnUrl": true,
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AdsProdlistGgl_ADS_CLICK",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ADS_CSA_ERR": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AdsProdlistGgl_ADS_CSA_ERR",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "Topic": {
          "acts": {
            "TOPIC_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_Topic_TOPIC_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "BuyTogether": {
          "acts": {
            "BUYTOGETHER_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_BuyTogether_BUYTOGETHER_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "AccountOrder_": {
          "acts": {
            "ORDER_LIST_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AccountOrder__ORDER_LIST_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ORDER_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AccountOrder__ORDER_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "StoreFinder": {
          "acts": {
            "STORE_FINDER_ERR": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_StoreFinder_STORE_FINDER_ERR",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "STORE_FINDER_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_StoreFinder_STORE_FINDER_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "PERFORMANCE_METRICS": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_StoreFinder_PERFORMANCE_METRICS",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "CategoryListings": {
          "acts": {
            "CATEGORY_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_CategoryListings_CATEGORY_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "PERFORMANCE_METRICS": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_CategoryListings_PERFORMANCE_METRICS",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ON_UNIV_LINK": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_CategoryListings_ON_UNIV_LINK",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "HomePage": {
          "acts": {
            "PERFORMANCE_METRICS": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_HomePage_PERFORMANCE_METRICS",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "FIRST_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_HomePage_FIRST_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "HOMEPAGE_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_HomePage_HOMEPAGE_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ON_UNIV_LINK": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_HomePage_ON_UNIV_LINK",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "AdsShopGgl": {
          "acts": {
            "ADS_PAGINATION": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AdsShopGgl_ADS_PAGINATION",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ADS_HL_ERR": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AdsShopGgl_ADS_HL_ERR",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ADS_IN_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AdsShopGgl_ADS_IN_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ADS_MIDAS_ERR": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AdsShopGgl_ADS_MIDAS_ERR",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ADS_SHOWN": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AdsShopGgl_ADS_SHOWN",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ADS_NOT_AVAILABLE": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AdsShopGgl_ADS_NOT_AVAILABLE",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ADS_CLICK": {
              "returnUrl": true,
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AdsShopGgl_ADS_CLICK",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ADS_CSA_ERR": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AdsShopGgl_ADS_CSA_ERR",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "CreateBabyRegistry": {
          "acts": {
            "CREATE_BB_REG_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_CreateBabyRegistry_CREATE_BB_REG_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "CREATE_BB_REG_ERR": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_CreateBabyRegistry_CREATE_BB_REG_ERR",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "CreateWeddingRegistry": {
          "acts": {
            "CREATE_W_REG_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_CreateWeddingRegistry_CREATE_W_REG_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "CREATE_W_REG_ERR": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_CreateWeddingRegistry_CREATE_W_REG_ERR",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "ManageBabyRegistry": {
          "acts": {
            "MANAGE_BB_REG_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_ManageBabyRegistry_MANAGE_BB_REG_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "MANAGE_BB_REG_ERR": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_ManageBabyRegistry_MANAGE_BB_REG_ERR",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "ManageWeddingRegistry": {
          "acts": {
            "MANAGE_W_REG_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_ManageWeddingRegistry_MANAGE_W_REG_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "MANAGE_W_REG_ERR": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_ManageWeddingRegistry_MANAGE_W_REG_ERR",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "AdsCntxtsrchYahoo": {
          "acts": {
            "ADS_SHOWN": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AdsCntxtsrchYahoo_ADS_SHOWN",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ADS_IN_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AdsCntxtsrchYahoo_ADS_IN_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ADS_NOT_AVAILABLE": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AdsCntxtsrchYahoo_ADS_NOT_AVAILABLE",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ADS_PAGINATION": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AdsCntxtsrchYahoo_ADS_PAGINATION",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ADS_MIDAS_ERR": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AdsCntxtsrchYahoo_ADS_MIDAS_ERR",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ADS_CSA_ERR": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AdsCntxtsrchYahoo_ADS_CSA_ERR",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ADS_HL_ERR": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AdsCntxtsrchYahoo_ADS_HL_ERR",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ADS_CLICK": {
              "returnUrl": true,
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AdsCntxtsrchYahoo_ADS_CLICK",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "GrpNonChoicePage": {
          "acts": {
            "GRPNG_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_GrpNonChoicePage_GRPNG_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "AccountSigin": {
          "acts": {
            "SIGN_IN_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AccountSigin_SIGN_IN_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "SIGN_IN_ERR": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AccountSigin_SIGN_IN_ERR",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "DisplayBabyRegistry": {
          "acts": {
            "DISPLAY_BB_REG_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_DisplayBabyRegistry_DISPLAY_BB_REG_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "PrintBabyRegistry": {
          "acts": {
            "PRINT_BB_REG_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_PrintBabyRegistry_PRINT_BB_REG_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "DisplayWeddingRegistry": {
          "acts": {
            "DISPLAY_W_REG_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_DisplayWeddingRegistry_DISPLAY_W_REG_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "ChecklistWeddingRegistry": {
          "acts": {
            "CHECKLIST_W_REG_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_ChecklistWeddingRegistry_CHECKLIST_W_REG_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "PrintWeddingRegistry": {
          "acts": {
            "PRINT_W_REG_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_PrintWeddingRegistry_PRINT_W_REG_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "AccountReturns_": {
          "acts": {
            "RETURNS_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AccountReturns__RETURNS_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "RETURNS_LIST_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AccountReturns__RETURNS_LIST_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "Page_": {
          "acts": {
            "PAGE_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_Page__PAGE_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "CreateAccount": {
          "acts": {
            "NEW_ACCT_ERR": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_CreateAccount_NEW_ACCT_ERR",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "NEW_ACCT_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_CreateAccount_NEW_ACCT_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "AccountCreate": {
          "acts": {
            "ACCT_CREATE_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AccountCreate_ACCT_CREATE_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "AccountOrders": {
          "acts": {
            "ACCT_ORDER_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_AccountOrders_ACCT_ORDER_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "ChecklistBabyRegistry": {
          "acts": {
            "CHECKLIST_BB_REG_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_ChecklistBabyRegistry_CHECKLIST_BB_REG_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "ConfirmBabyRegistry": {
          "acts": {
            "CONFIRM_CREATE_BB_REG_ERR": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_ConfirmBabyRegistry_CONFIRM_CREATE_BB_REG_ERR",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "CONFIRM_CREATE_BB_REG_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_ConfirmBabyRegistry_CONFIRM_CREATE_BB_REG_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "ConfirmWeddingRegistry": {
          "acts": {
            "CONFIRM_CREATE_W_REG_ERR": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_ConfirmWeddingRegistry_CONFIRM_CREATE_W_REG_ERR",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "CONFIRM_CREATE_W_REG_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_ConfirmWeddingRegistry_CONFIRM_CREATE_W_REG_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "DisplayList_": {
          "acts": {
            "DISPLAY_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_DisplayList__DISPLAY_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ON_SOCIALSHARE": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_DisplayList__ON_SOCIALSHARE",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "FindBabyRegistry": {
          "acts": {
            "FIND_BB_REG_ERR": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_FindBabyRegistry_FIND_BB_REG_ERR",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "FIND_BB_REG_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_FindBabyRegistry_FIND_BB_REG_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "FindList_": {
          "acts": {
            "FIND_ERROR": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_FindList__FIND_ERROR",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "FIND_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_FindList__FIND_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "ON_FIND": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_FindList__ON_FIND",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "FindWeddingRegistry": {
          "acts": {
            "FIND_W_REG_ERR": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_FindWeddingRegistry_FIND_W_REG_ERR",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "FIND_W_REG_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_FindWeddingRegistry_FIND_W_REG_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "LandingBabyRegistry": {
          "acts": {
            "LANDING_BB_REG_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_LandingBabyRegistry_LANDING_BB_REG_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "LandingWeddingRegistry": {
          "acts": {
            "LANDING_W_REG_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_LandingWeddingRegistry_LANDING_W_REG_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "ListFind": {
          "acts": {
            "FIND_UNI_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_ListFind_FIND_UNI_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "ManageList": {
          "acts": {
            "MANAGE_LIST_ERR": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_ManageList_MANAGE_LIST_ERR",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "MANAGE_LIST_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_ManageList_MANAGE_LIST_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "PreviewBabyRegistry": {
          "acts": {
            "PREVIEW_BB_REG_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_PreviewBabyRegistry_PREVIEW_BB_REG_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "PreviewList": {
          "acts": {
            "PREVIEW_LIST_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_PreviewList_PREVIEW_LIST_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "PreviewWeddingRegistry": {
          "acts": {
            "PREVIEW_W_REG_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_PreviewWeddingRegistry_PREVIEW_W_REG_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "PrintList_": {
          "acts": {
            "PRINT_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_PrintList__PRINT_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "SettingsBabyRegistry": {
          "acts": {
            "SETTINGS_BB_REG_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_SettingsBabyRegistry_SETTINGS_BB_REG_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "SettingsList": {
          "acts": {
            "SETTINGS_LIST_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_SettingsList_SETTINGS_LIST_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "SettingsWeddingRegistry": {
          "acts": {
            "SETTINGS_W_REG_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_SettingsWeddingRegistry_SETTINGS_W_REG_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "SignIn": {
          "acts": {
            "SIGN_IN_ERR": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_SignIn_SIGN_IN_ERR",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "SIGN_IN_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_SignIn_SIGN_IN_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        },
        "Trending": {
          "acts": {
            "PERFORMANCE_METRICS": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_Trending_PERFORMANCE_METRICS",
                    "args": [
                      
                    ]
                  }
                }
              ]
            },
            "TRENDING_VIEW": {
              "mp": [
                {
                  "rt": "pv",
                  "rn": "jsmp",
                  "rr": {
                    "fn": "wmbeacon_Trending_TRENDING_VIEW",
                    "args": [
                      
                    ]
                  }
                }
              ]
            }
          }
        }
      }
    };
})(_bcq, _bcc);
(function (bc) {
	'use strict';

	// -------------------------------------------------- UTILITY FUNCTIONS --------------------------------------------------
	bc.utils.defKey = '_def'; 
	bc.utils.separator = '__';
	bc.utils.pctx = 'PCTX';
	
	bc.utils.isEmptyObj = function(obj) {
		var prop;
	    for(prop in obj) {
	        if(obj.hasOwnProperty(prop))
	            return false;
	    }
	    return true;
	};
	
	/**
	 * @desc Creates a Class Constructor
	 * @desc Inspired from: http://www.htmlgoodies.com/html5/tutorials/create-an-object-oriented-javascript-class-constructor.html#fbid=QlAWBNynR5l
	 * @author Carlos Soto <csoto@walmartlabs.com>
	 * @param {Object} attributes Set of attributes/methods the new Class will have
	 * @return {Object} new Class Constructor
	 */
	bc.utils.createClass = function (attributes) {
		var prop, // iterator
			klass = function () { // New class to be returned    
			this.initialize.apply(this, arguments);          
		};
	  
		// ------------------------------
		// Add the methods/attributes sent as parameters to the new class
		for (prop in attributes) { 
		   if(attributes.hasOwnProperty(prop)){
		   	klass.prototype[prop] = attributes[prop];
		   }
		}
		
		// ------------------------------
		// Set a default initialize function 
		// in case the class doesn't have one
		if (!klass.prototype.initialize) {
			klass.prototype.initialize = function () {};      
		}
		return klass;    
	};
	 
	bc.utils.exceFiltering=function(value,filter){
	    if(typeof value === 'string' && value !== ''){
			value = (typeof filter[value] === 'string') ? filter[value] : value;
	    }
	    return value;
	};
	
	/**
	 * @desc Extends and creates a class from a list of objects
	 * @desc Inspired from: https://bugzilla.mozilla.org/show_bug.cgi?id=433351
	 * @author Carlos Soto <csoto@walmartlabs.com>
	 * @param {Objects} [object1, object2, etc.] List of following objects to merge 
	 * @return {Object} merged Class
	 */
	bc.utils.extend = function () {
		return bc.utils.createClass(bc.utils.merge.apply(this, arguments));
	};

	/**
	 * @desc Transforms an underscore/lower case String to a CamelCase String
	 * @desc Inspired from: http://stackoverflow.com/questions/6660977/convert-hyphens-to-camel-case-camelcase
	 * @author Carlos Soto <csoto@walmartlabs.com>
	 * @param {String} text String to transform
	 * @return {String} camelCased String
	 */
	bc.utils.toCamelCase = function (text, capitalize) {
		if(typeof text !== 'string'){
			return text;
		}
		var result = text.replace(/(\-[a-z])/g, function($1){return $1.toUpperCase().replace('-','');});
		if (capitalize) {
			result = text.charAt(0).toUpperCase() + text.slice(1);
		}
		return result;
	};
	
	/**
	 * @desc Gets a value based on a key in a key-value Array of Arrays, example, returns 'var1' on:
	 * @desc bc.utils.findValueByKey('foo1', [['foo0', 'var0'], ['foo1', 'var1'], ['foo2', 'var2'], ]);
	 * @author Carlos Soto <csoto@walmartlabs.com>
	 * @param {String} text String to transform
	 * @return {String} camelCased String
	 */
	bc.utils.findValueByKey = function (key, arrayOfPairs) {
		var value = '', l, i;
		if (Array.isArray(arrayOfPairs)) {
			l = arrayOfPairs.length;
			for (i = 0; i < l; ++i) {
				if (Array.isArray(arrayOfPairs[i]) && arrayOfPairs[i].length > 1 && arrayOfPairs[i][0] === key) {
					value = arrayOfPairs[i][1];
					break;
				}
			}
		}
		return value;
	};
	
})(_bcq);
(function (bc, config) {
	'use strict';

	function getIEVersion(){
		var ieVersion = -1, 
			re,
			ua = navigator.userAgent;

		if (navigator.appName === 'Microsoft Internet Explorer'){
			re  = new RegExp("MSIE ([0-9]{1,}[\\.0-9]{0,})"); // IE 1-10
		}else if(navigator.appName === 'Netscape'){ 
			re  = new RegExp("Trident/.*rv:([0-9]{1,}[\\.0-9]{0,})"); // IE11+
		}
		
		if (re.exec(ua) !== null){
			ieVersion = parseInt( RegExp.$1, 10);
		}

		return ieVersion;
	}

	//TODO: Remove dependency of config from core util methods

	// -------------------------------------------------- UTILITY FUNCTIONS --------------------------------------------------
	bc.utils.isIE = function (){
	  var ie, ieVersion;
	  try{ 
	  	  ieVersion = getIEVersion();
		  ie = (ieVersion !== -1) ? ieVersion : false;
	  }catch(e){}

	  return ie;
	};
	
	bc.utils.ieUrlLimit = function (){
	  var isIE = bc.utils.isIE();
	  return isIE ? ((isIE < 9) ? 2080 : 4997) : false;	// IE specific logic : for IE4-8 limit is 2083 IE9 onwards limit is 5000
	};

	bc.utils.hasVal = function (v){
		return (typeof v !== 'undefined' && v !== null);
	};
	
	/**
	 * @desc Binds an event to a DOM Object
	 * @desc Inspired from: https://github.com/yahoo/boomerang/blob/master/boomerang.js
	 * @author Carlos Soto <csoto@walmartlabs.com>
	 * @param {Object} el DOM Object
	 * @param {String} event Type of event to which we need to bind the function (click, load, etc.)
	 * @param {Function} fn The function to bind 
	 * @return void
	 */
	bc.utils.bind = function (el, event, fn) {
		if (el.addEventListener) {
			el.addEventListener(event, fn, false);
		} else if(el.attachEvent) {
			el.attachEvent("on" + event, fn);
		}
	};
	
	bc.utils.addCommand = function (context, attributes, isMerge) {
		var attrs = {}, 
			ctx,
			i, len;
		
		ctx = arguments[0];
		
		if (typeof ctx !== 'string') {
			return;
		}
		
		if (arguments.length >= 2 && Array.isArray(arguments[1])) {
			attrs = arguments[1];
			len = attrs.length;
			for(i = 0; i < len; i++){
				bc.utils.addEntry(attrs[i], ctx, isMerge);
			}
		}
		
	};
	
	bc.utils.addEntry = function(dataSet, ctx, isMerge){
		var group, key, data, len,
			k, grpData;
		
		if(!Array.isArray(dataSet) || !bc.utils.hasVal(dataSet[0])){
			return;
		}
		len = dataSet.length;
		if(len > 2 && !bc.utils.hasVal(dataSet[1])){
			return;
		}
		
		ctx = ctx || '';
		
		group = Array.isArray(dataSet[0]) ? dataSet[0] : [dataSet[0]];
		key = dataSet.length > 2 ? (Array.isArray(dataSet[1]) ? dataSet[1] : [dataSet[1]]) : [bc.utils.defKey];
		data = dataSet.length > 2 ? dataSet[2] : dataSet[1];
		
		bc.data[ctx] = bc.data[ctx] || {};
		try{
			group = group.join(bc.utils.separator);
			key = key.join(bc.utils.separator);
			bc.data[ctx][group] = bc.data[ctx][group] || {};
			
			if(isMerge){
				bc.data[ctx][group][key] = bc.utils.mergeData(bc.data[ctx][group][key], data);
			}else{
				bc.data[ctx][group][key] = data;
			}
		}catch(e){
			bc.utils.log('add failed under ctx [' + ctx + '] for group [' + group + ']');
		}
		
		//TODO: To be removed in next release, adding a temp n urgent solution till we get proper fix from Checkout Team
		if((ctx === 'Checkout' || ctx === 'Thankyou') && bc.data[ctx]){
			if(group === 'py'){
				grpData = bc.data[ctx].py;
				for(k in grpData){
					if(grpData.hasOwnProperty(k)){
						grpData[k].em = '';
						grpData[k].cn = '';
					}
				}
			}
			if(group === 'ul'){
				grpData = bc.data[ctx].ul;
				for(k in grpData){
					if(grpData.hasOwnProperty(k)){
						grpData[k].pp = '';
						grpData[k].sp = '';
					}
				}
			}
			if(group === 'pc'){
				grpData = bc.data[ctx].pc;
				for(k in grpData){
					if(grpData.hasOwnProperty(k)){
						grpData[k].em = '';
					}
				}
			}
			if(group === 'al'){
				grpData = bc.data[ctx].al;
				for(k in grpData){
					if(grpData.hasOwnProperty(k)){
						grpData[k].pa = '';
						grpData[k].sa = '';
					}
				}
			}
		}
	};
	
	/**
	 * @desc Add groups for a given context on the Beacon Data Layer
	 * @author Laxmikant Kurhe <lkurhe@walmartlabs.com>
	 * @param {Object} ctxObj from which to create/update data
	 * @param {Object} dataObj with new set of data to be added under a context name
	 * @return {Void}
	 */
	bc.utils.addData = function (ctxObj, dataObj){
		var i;
		if(typeof dataObj !== 'object' || dataObj === null){
			return dataObj;	
		}
		ctxObj = ctxObj || {};
		for(i in dataObj){
			if (dataObj.hasOwnProperty(i)) {
				ctxObj[i] = dataObj[i];
			}
		}
		return ctxObj;
	};
	
	/**
	 * @desc Fetch value for a given attribute, can involve fetching data from nested objects
	 * @author Laxmikant Kurhe <lkurhe@walmartlabs.com>
	 * @param {Mixed} valObject The String identifier to where to store the data
	 * @param {String} attr name of the attribute to be fetched from valObject
	 * @return {Mixed} value for a given attribute 
	 */
	bc.utils.fetchData = function(valObject, attr){
		var i, len;
		if (bc.utils.hasVal(attr) && valObject) {
			attr = typeof attr === 'string' ? attr.split('.') : (typeof attr === 'number' ? attr : []);
			len = attr.length;
			valObject = valObject[attr[0]];
			for(i = 1; i<len; i++){
				if(valObject){
					valObject = valObject[attr[i]];
				}
			}
		}
		return valObject;
	};

	/**
	 * @desc Update attributes for a given context on the Beacon Data Layer
	 * @author Laxmikant Kurhe <lkurhe@walmartlabs.com>
	 * @param {Object} ctxObj from which to create/update data
	 * @param {Object} dataObj with new set of data to be added under a context name
	 * @return {Void}
	 */
	bc.utils.mergeData = function (ctxObj, dataObj){
		var i, ctxObj;
		if(typeof dataObj !== 'undefined' && dataObj !== null){
			ctxObj = ctxObj || {};
		}
		for(i in dataObj){
			if(typeof dataObj[i] === 'object' && ctxObj[i]){
				bc.utils.mergeData(ctxObj[i], dataObj[i]);
			}else{
				if (dataObj.hasOwnProperty(i)) {
					ctxObj[i] = dataObj[i];
				}
			}
		}
		return ctxObj;
	};

	/**
	 * @desc Stores attributes for a given context on the Beacon Data Layer
	 * @author Carlos Soto <csoto@walmartlabs.com>
	 * @param {String} ctx The String identifier to where to store the data
	 * @param {String} attrName name of the attribute to be fetched
	 * @param {Object} attrs attributes available with current tagAction 
	 * @return {Mixed} property set for a given attribute
	 */
	bc.utils.getData = function (ctx, attrName, attrs) {
		var res;
		if (bc.utils.hasVal(ctx)) {
			res = bc.utils.fetchData(bc.data[ctx], attrName);
		}else if(bc.utils.hasVal(attrName)){
			res = bc.utils.fetchData(attrs, attrName);
		}
		return res;
	};
	
	/**
	 * @desc Stores attributes for a given context on the Beacon Data Layer
	 * @author Carlos Soto <csoto@walmartlabs.com>
	 * @param {String} ctx The String identifier to where to store the data
	 * @param {String} attrName name of the attribute to be fetched
	 * @param {Object} attrs attributes available with current tagAction 
	 * @return {Mixed} property set for a given attribute
	 */
	bc.utils.getDataNew = function (ctx, attrName) {
		var res;
		if (bc.utils.hasVal(ctx)) {
			res = bc.utils.fetchData(bc.data[ctx], attrName);
		}else if(bc.utils.hasVal(attrName)){
			res = bc.utils.fetchData(pulse.runtime.pulsePayload, attrName);
		}
		return res;
	};

	bc.utils.readBaseEntry = function(actData, group, key, ctx){
		var i, len, 
			j, keyLen, keyArr;
		actData = actData || {};
		
		try{
			len = group.length;
			if(len > 1){
				keyLen = key.length;
				for(i = 0; i < len; i++){
					if(key.length === 1 && key[0] ===bc.utils.defKey){
						actData = bc.utils.readEntry(actData, [group[i]], ctx);
					}else{
						keyArr = [];
						for(j = 0; j < keyLen; j++){
							keyArr.push(key[j][i]);
						}
						actData = bc.utils.readEntry(actData, [group[i], keyArr], ctx);
					}
				}
			}
		}catch(e){
			bc.utils.log('read failed under ctx [' + ctx + '] for group [' + group + ']');
		}
		
		return actData;
	};
	
	bc.utils.readEntry = function(actData, dataSet, ctx, readBase){
		var group, key, data,
			sep = bc.utils.separator,
			i, len;
		
		actData = actData || {};
		
		if(!Array.isArray(dataSet) && dataSet){
			return actData;
		}
		
		group = Array.isArray(dataSet[0]) ? dataSet[0] : [dataSet[0]];
		if(dataSet.length === 1){
			key = [bc.utils.defKey];
		}else if(dataSet.length === 2){
			key = (typeof dataSet[1] === 'string' || typeof dataSet[1] === 'number') ? [dataSet[1]] : 
				  	(Array.isArray(dataSet[1]) ? dataSet[1] : [bc.utils.defKey]);
		}else{
			key = Array.isArray(dataSet[1]) ? dataSet[1] : [dataSet[1]];
		}
		data = (dataSet.length === 2 && key[0] === bc.utils.defKey) ? dataSet[1] : dataSet[2];
		
		actData = actData || {};
		if(readBase){
			actData = bc.utils.readBaseEntry(actData, group, key, ctx);
		}
		
		try{
			group = group.join(bc.utils.separator);
			actData[group] = actData[group] || {};
			
			len = key.length;
			for(i = 0; i < len; i++){
				if(Array.isArray(key[i])){
					actData[group][key[i].join(sep)] = (typeof data === 'undefined') ? bc.utils.getData(ctx, group + '.' + key[i].join(sep)) : data;
				}else{
					actData[group][key[i]] = (typeof data === 'undefined') ? bc.utils.getData(ctx, group + '.' + key[i]) : data;
				}
			}
			
		}catch(e){
			bc.utils.log('read failed under ctx [' + ctx + '] for group [' + group + ']');
		}
		return actData;
	};
	
	bc.utils.actionData = function(actData, attrs, ctx, readBase){
		var i, len;
		
		actData = actData || {};
		
		if(Array.isArray(attrs)){
			len = attrs.length;
			for(i = 0; i < len; i++){
				actData = bc.utils.readEntry(actData, attrs[i], ctx, readBase);
			}
		}
		return actData;
	}; 
	
	bc.utils.rmvEntry = function(dataSet, ctx){
		var group, key, 
			i, len,
			sep = bc.utils.separator;
		
		if(!Array.isArray(dataSet)){
			return;
		}
		
		group = Array.isArray(dataSet[0]) ? dataSet[0] : [dataSet[0]];
		key = dataSet.length > 1 ? (Array.isArray(dataSet[1]) ? dataSet[1] : [dataSet[1]]) : [bc.utils.defKey];
		
		try{
			group = group.join(sep);
			
			len = key.length;
			for(i = 0; i < len; i++){
				if(Array.isArray(key[i])){
					delete bc.data[ctx][group][key[i].join(sep)];
				}else{
					delete bc.data[ctx][group][key[i]];
				}
			}
			
		}catch(e){
			bc.utils.log('Remove failed under ctx [' + ctx + '] for group [' + group + ']');
		}
	};
	
	bc.utils.rmvAllEntry = function(ctx, attrs){
		var i, len;
		
		if(attrs === true){
			//Remove current context altogether with all associated groups
			delete bc.data[ctx];
		}else if (Array.isArray(attrs)) {
			len = attrs.length;
			try{
				for(i = 0; i < len; i++){
					if(Array.isArray(attrs[i])){
						delete bc.data[ctx][attrs[i].join(bc.utils.separator)];
					}else{
						delete bc.data[ctx][attrs[i]];
					}
				}
			}catch(e){
				bc.utils.log('RemoveAll failed under ctx [' + ctx + ']');
			}
		}
	};
	
	bc.utils.rmvCommand = function(ctx, attrs, rmvAll){
		var i, len;

		if (typeof ctx !== 'string') {
			return;
		}
		
		if(rmvAll){
			bc.utils.rmvAllEntry(ctx, attrs);
			return;
		}
		
		if (Array.isArray(attrs)) {
			len = attrs.length;
			for(i = 0; i < len; i++){
				bc.utils.rmvEntry(attrs[i], ctx);
			}
		}
	}; 
	
	/**
	 * @desc Merges the current bc.options with some new ones
	 * @desc Check if setOptions has item_category set, in which case update report suite for s_omni object
	 * @author Laxmikant Kurhe <lkurhe@walmartlabs.com>
	 * @param {Object} options new options to be set
	 * @return {void}
	 */	
	bc.utils.setOptions = function(options){
		bc.utils.merge(bc.options, options);
		//TODO: below code is required only for omniture report suite, try to move it to omniture handler
		if(options && options.item_category){
			bc.utils.reportSuite(bc.options);
			if(typeof s_omni === 'object' && s_omni && typeof s_omni.sa === 'function'){
				s_omni.sa(window.s_account);
			}
		}
	};
	
	/**
	 * @desc fetch omniture report suite from config file and item_category of the page
	 * @desc store this comma sepearated string value under 's_account' variable 
	 * @author Laxmikant Kurhe <lkurhe@walmartlabs.com>
	 * @param {Object} options object 
	 * @return {void}
	 */
	bc.utils.reportSuite = function(options){
		var repId;
		options = options || {};
		// ------------------------------
		// Build the report Suite for Omniture (if enabled)
		if (!!config.ptns.omniture) {
			if(!!config.ptns.omniture.ds){
				bc.utils.log('Tagging for Partner [omniture] is disabled');
			}else{
				// ------------------------------
				// Find the s_account property with the value of the default report suite
				// If no s_account is found, then, disable Omniture as it will not function properly
				repId = bc.utils.buildReportSuite(options.item_category);
				if (repId) {
					window.s_account = repId;
				} else {
					config.ptns.omniture.ds = true;
				}
			}
		}
	};
	
	bc.utils.buildReportSuite = function(repSuites){
		var suites = [], sa, 
			i, len, 
			rpId,omnitureEnums = pulse.runtime.omniture.enums, rpIdFilter = omnitureEnums && omnitureEnums.rpIdFilter || {}; 
		repSuites = Array.isArray(repSuites) ? repSuites : [repSuites];
		// ------------------------------
		// Find the s_account property with the value of the default report suite
		// If no s_account is found, then, disable Omniture as it will not function properly
		sa = bc.utils.findValueByKey('s_account', config.ptns.omniture.opts);
		if (!!sa) {
			suites.push(sa);
			if (Array.isArray(repSuites)) {
				len = repSuites.length;
				for(i = 0; i < len; i++){
					rpId = repSuites[i];
					if(typeof rpId === 'string' && rpId !== ''){
						rpId = (typeof rpIdFilter[rpId] === 'string') ? rpIdFilter[rpId] : rpId;
						rpId = rpId.replace(/[\s\\&]/g, '').toLowerCase();
						// TODO: Remove hardcoded list of rpId exclusions, hardcoded for an urgent release 
						if(rpId === 'autotires'){
							suites.push(sa.replace(/com$/, '') + rpId);
						}else if(rpId === 'photocenter' || rpId === 'pharmacy'){
							suites = [];
							suites.push(sa.replace(/com$/, '') + rpId);
						}else{
							suites.push(rpId);
						}
					}
				}
			}
		}
		return suites.join();
	};
	
	//TODO: Revisit urlMatch and contextRule functions
	/**
	 * @desc provide a regular expression to match for a  value
	 * @author Laxmikant Kurhe <lkurhe@walmartlabs.com>
	 * @param {Array} Array that defines name and type of value to be fetched from available attributes/storages
	 * @param {Object} available attribute object
	 */
	bc.utils.urlMatch = function(args){
		var args = args || [],
			url = document.location.href,
			r;
		if(!args[0]){
			return;
		}
		r = new RegExp(args[0], 'g');
		return (r.test(url) ? args[1] : null);
	};
	
	bc.utils.contextRule = function(){
		var ctxRule,
			i, len, 
			overridenCtx;
		if(typeof bc.context_rule !== 'undefined'){
			return;
		}
		bc.context_rule = {};
		if(config && config.context_rule){
			len = config.context_rule.length;
			for(i = 0; i<len; i++){
				ctxRule = config.context_rule[i];
				if(ctxRule.rr){
					overridenCtx = bc.utils.urlMatch(ctxRule.rr.args);
					if(overridenCtx){
						bc.context_rule[ctxRule.rn] = overridenCtx;
					}
				}
			}
		}
	};
	
	// -------------------------------------------------- UTILITY FUNCTIONS --------------------------------------------------
	/**
	 * @desc create cors request if browser supports 
	 * @author Laxmikant Kurhe <lkurhe@walmartlabs.com>
	 * @param {String} method  
	 * @param {String} url  
	 * @return {Object} xhr
	 */
	bc.utils.corsReq = function(method, url){
		var xhr;
		try{
			xhr = new XMLHttpRequest();
			if ("withCredentials" in xhr) {
				// XHR for Chrome/Firefox/Opera/Safari.
				xhr.open(method, url, true);
				xhr.withCredentials = true;
			} else if (typeof XDomainRequest !== "undefined") {
				// XDomainRequest for IE8 and IE9.
				xhr = new XDomainRequest();
				xhr.open(method, url);

				xhr.ontimeout = function(){};
				xhr.onprogress = function(){};
				xhr.onload = function(){
					bc.utils.log(xhr.responseText);
				};
				xhr.onerror = function(){};
				xhr.timeout = 10000; // Abort the request if it takes more than 10sec
			} else {
				// CORS not supported.
				xhr = null;
			}
		}catch(e){}
		return xhr;
	};
	

	/**
	 * @desc Gets an error object with a code and a message that can be sent to the BE for analysis
	 * @author Carlos Soto <csoto@walmartlabs.com>
	 * @param {String} error_key The name of the error to be sent
	 * @return {Object} error object
	 */	
	bc.utils.getError = function(error_key) {
		var er = {
			code: 0,
			desc: 'Unknown error'
		};
		
		switch(error_key) {
			case 'no-ctx':
				er.code = 1;
				er.desc = 'Invalid Ctx';
				break;
			case 'no-act':
				er.code = 2;
				er.desc = 'Invalid Act';
				break;
			case 'no-rep':
				er.code = 3;
				er.desc = 'No ReportId';
				break;
			default:
				break;
		}
		return er;
	};
	
	bc.utils.isResponsive = function(){
		if(window && window._WML){
			return window._WML.IS_RESPONSIVE;		// Added to capture IS_RESPONSIVE from _WML object 
		}
	};

	// -------------------------------------------------- FUNCTIONS TO GET CLIENT DETAILS --------------------------------------------------
	/**
	 * @desc Get client dimension such as viewport width(vW), height(vH) and screen width(sW), height(sH) 
	 * @author Laxmikant Kurhe <lkurhe@walmartlabs.com>
	 * @return {Object} dimension object
	 */	
	bc.utils.clientDim = function() {
		//TODO: Check if these values can be added under cookie
		var dim = {}, 
			de = document ? document.documentElement : null,
			w = window,
			ws = w ? w.screen : null;
		if(de){
			dim.vw = de.clientWidth;
			dim.vh = de.clientHeight;
		}
		if(ws){
			dim.sw = ws.width;
			dim.sh = ws.height;
		}
		if(w){
			dim.iw = w.innerWidth;
			dim.ih = w.innerHeight;
		}
		return dim;
	};
	
	/**
	 * @desc Get generic details about current page by sniffing page DOM
	 * @author Laxmikant Kurhe <lkurhe@walmartlabs.com>
	 * @return {Object} data object
	 */	
	bc.utils.sniffPage = function() {
		var data = {},
			title = document.getElementsByTagName('title') || {};
		title = title[0] ? title[0].text : '';
		data.tl = title;
		
		return data;
	};

	/**
	 * @desc Get Anivia data if its available under 'WebViewJavascriptBridge'
	 * @desc An object provided by Mobile App web view bridge for web
	 * @return {Object} aniviaMetadata object
	 */
	bc.utils.aniviaMetadata = function() {
		try{
			if(WebViewJavascriptBridge && WebViewJavascriptBridge.analytics){
				return WebViewJavascriptBridge.analytics();
			}else if(Bridge && Bridge.info){
				return Bridge.info();
			}
		}catch(e){}
	};
	
	bc.topics = bc.topics || {};
	bc.topics.NEW_INTERNAL_VIEW = 'new_internal_view';
	
	/**
	 * @desc get the url of previous view to be used as a referrer url for new_internal_view invocation
	 * @desc url will be sent by FE by publishing under topic "new_internal_view"
	 * @return {Object} data object
	 */
	bc.utils.newInternalView = function(data) {
		bc.utils.referrer = (data && data.referrer) ? data.referrer :
								(bc.utils.referrer ? bc.utils.referrer : document.referrer);
	};

    /**
    Test function will remove in next release
    */
	bc.utils.testCachingIssue2 = function() {
		return bc.utils.isIE();
	};
})(_bcq, _bcc);

(function(bc){
	var pubsub = {};
	
	pubsub.topics = {};
	
	pubsub.publish = function(topic){
		var args = [].slice.apply(arguments, [1]),
			subs = pubsub.topics[topic],
			i, len = Array.isArray(subs) ? subs.length : 0;
		for(i = 0; i < len; i++){
			if(subs[i] && subs[i].callback){
				subs[i].callback.apply(subs[i].scope, args);
			}
		}
	};
	
	pubsub.subscribe = function(topic, hdlObject){
		if(!pubsub.topics[topic]){
			pubsub.topics[topic] = [];
		}
		pubsub.topics[topic].push(hdlObject);
	};
	
	bc.pubsub = pubsub;
})(_bcq);
(function(bc, config){
	'use strict';
	// -------------------------------------------------- Commands Definition --------------------------------------------------
	/**
	 * @desc Merges the current bc.options with some new ones
	 * @author Carlos Soto <csoto@walmartlabs.com>
	 * @param {Object} options new options to be set
	 * @return {void}
	 */	
	bc.commands._setOptions = function (options) {
		bc.utils.setOptions.apply(bc, arguments);
	};
	
	/**
	 * @desc definition of the _addData Command 
	 * @desc Adds group attributes to Data Layer Object
	 * @author Laxmikant Kurhe <lkurhe@walmartlabs.com>
	 * @param {String} context namespace about the location of the data
	 * @param {Object} Beacon Attributes [name-value pairs] to be sent to Beacon and transformed into Partner Variables
	 * @return void
	 */
	bc.commands._addData = function (context, attributes) {
		bc.utils.addCommand.apply(bc, arguments);
	};
	
	/**
	 * @desc definition of the _clearData Command 
	 * @desc Adds group attributes to Data Layer Object
	 * @author Laxmikant Kurhe <lkurhe@walmartlabs.com>
	 * @param {String} context namespace about the location of the data
	 * @param {Object} Beacon group, key that needs to be removed
	 * @return void
	 */
	bc.commands._clearData = function (context, attributes) {
		bc.utils.rmvCommand.apply(bc, arguments);
	};
	
	/**
	 * @desc definition of the _clearAllData Command 
	 * @desc Adds group attributes to Data Layer Object
	 * @author Laxmikant Kurhe <lkurhe@walmartlabs.com>
	 * @param {String} context namespace about the location of the data
	 * @param {Object} Beacon group that needs to be removed
	 * @return void
	 */
	bc.commands._clearAllData = function (context, attributes) {
		bc.utils.rmvCommand.apply(bc, [context, attributes, true]);
	};
	
	/**
	 * @desc definition of the tagAction Command 
	 * @desc sends the beacon attributes to each of the partners for it's subsequent tagging.
	 * @author Laxmikant Kurhe <lkurhe@walmartlabs.com>
	 * @param {String} context Optional namespace about the location of the action
	 * @param {String} action Name of the Action to be tagged.
	 * @param {String} report Name of the Report Id for filtering purpose.
	 * @param {Object} attributes Beacon Attributes to be sent to Beacon and transformed into Partner Variables
	 * @return {Array} 
	 */
	bc.commands._tagAction = function (context, action, report, attributes,onlyMappings) {
		var pn, // Partner's Name iterator
			count = [],
			ctx = '',
			dynCtx = '',
			index,
			actDataCtx = '',
			dynamicJoin = false,
			act = '',
			rpt,
			attrs = {},
			capc = {},
			err = {},
			implicitAddData = false,
			disabled = false,
			override = false,
			readBase = true,
			clrGrps,
			pageUrl;
		
		// ------------------------------
		// Find the right arguments depending on the length:
		// < 2 = just action (action)
		// < 3 = no context (action, attributes) or // < 3 = only context and action, no attributes
		// >= 3 = full list (context, action, attributes)
		if (arguments.length < 2) {
			if (typeof arguments[0] === 'string') {
				act = arguments[0];
			}
		} else if (arguments.length < 3) {
			if (typeof arguments[1] === 'object') {
				if (typeof arguments[0] === 'string') {
					act = arguments[0];
				}
				attrs = arguments[1];
			}else{
				if (typeof arguments[0] === 'string') {
					ctx = arguments[0];
				}
				if (typeof arguments[1] === 'string') {
					act = arguments[1];
				}
			}
		} else if (arguments.length < 4) {
			if (typeof arguments[2] === 'object') {
				if (typeof arguments[0] === 'string') {
					ctx = arguments[0];
				}
				if(typeof arguments[1] === 'string'){
					act = arguments[1];
				}
				attrs = arguments[2];
			}else{
				if (typeof arguments[0] === 'string') {
					ctx = arguments[0];
				}
				if (typeof arguments[1] === 'string') {
					act = arguments[1];
				}
				if (typeof arguments[2] === 'string') {
					rpt = arguments[2];
				}
			}
		} else if (arguments.length >= 4) {
			if (typeof arguments[0] === 'string') {
				ctx = arguments[0];
			}
			if (typeof arguments[1] === 'string') {
				act = arguments[1];
			}
			if (typeof arguments[2] === 'string') {
				rpt = arguments[2];
			}
			if (typeof arguments[3] === 'object') {
				attrs = arguments[3];
			}
		}
		
		// -----------------------------	
		// TODO: An EXPO callback is required. EXPO callback is executed directly using global object access.
		// To be re-factored later to remove direct dependency.
		// For every action EXPO callback is executed, 
		// EXPO JS will make sure experiment data will be added only for required actions for other actions do nothing.
		// Any failure is EXPO JS will be silent failures and will not affect Analytics execution
		if(typeof _exp !== 'undefined' && _exp && _exp.bc){
			_exp.bc.apply(_exp, [{'ctx': ctx, 'act': act}]);
		}
		
		ctx = typeof ctx === 'string' ? ctx : '';
		index = ctx.indexOf('_');
		if(index !== -1){
			dynCtx = ctx.substring(index + 1);
			ctx = ctx.substring(0, index + 1);
		}
		
		// -----------------------------	
		// Find out if tagging has been disabled at the Context Level
		try {
			disabled = config.ctxs[ctx].ds;
		} catch (e) {
			disabled = false;
		}
		
		if(disabled){
			bc.utils.log('Tagging disabled for context [' + ctx + ']');
			return;
		}
		
		// Find out if tagging has been disabled at the Action Level
		try {
			disabled = config.ctxs[ctx].acts[act].ds;
		} catch (e) {
			disabled = false;
		}
		
		if(disabled){
			bc.utils.log('Tagging disabled for action [' + act + '] under context [' + ctx + ']');
			return;
		}
		
		try {
			readBase = (config.ctxs[ctx].acts[act].readBase !== false);
		} catch (e) {
			readBase = true;
		}
		
		
		// ------------------------------
		// If the context is not disabled, go ahead and fire the tags
		
		attrs = attrs || {};
		
		if(Array.isArray(attrs)){
			attrs = bc.utils.actionData({}, attrs, ctx+dynCtx, readBase) || {};
		}
		actDataCtx = ctx+dynCtx + '-' + act;
		
		//bc.utils.log('Tagging Context-Action: ["' + ctx + '" - "' + act + '"]');
		
		// -----------------------------	
		// Add the Attributes into the Data Layer, if implicitAddData is set to true
		try {
			implicitAddData = config.ctxs[ctx].acts[act].imAdd;
		} catch (e) {
			implicitAddData = false;
		}
		
		if(implicitAddData){
			//bc.commands._addData(actDataCtx, attrs);
			bc.data = bc.data || {};
			bc.data[actDataCtx] = attrs;
		}
		
		// -----------------------------
		// // Check if the context exists
		// if(!config.ctxs[ctx]){
		// 	bc.utils.log('WARNING - There is no such context defined as [' + ctx + ']');
		// 	err['ctx'] = this.utils.getError('no-ctx');
		// }else if(!config.ctxs[ctx].acts[act]){
		// 	bc.utils.log('WARNING - There is no such action defined as [' + act + '] under given context [' + ctx + ']');
		// 	err['act'] = this.utils.getError('no-act');
		// }else if(!bc.utils.hasVal(rpt) || rpt === ''){
		// 	bc.utils.log('WARNING - No ReportID specified for action defined as [' + act + '] under given context [' + ctx + ']');
		// 	err['rp'] = this.utils.getError('no-rep');
		// }
		
		if(!bc.utils.isEmptyObj(err)){
			attrs.err = err;
		}
		
		// Sniff generic data for pages which are not instrumented
		if(act === 'PERFORMANCE_METRICS'){
			bc.utils.addCommand('PCTX', [['pg', bc.utils.sniffPage()]]);
		}
		
		// ---------------------------
		//Find the Context Override (if exists) at the Context Level
		try {
			override = config.ctxs[ctx].context_override;
		} catch (e) {
			override = false;
		}
		if (override) {
			//TODO: COMPLETE ME!
		}
		// TODO: to be removed soon, added only to ease testing of server side mappings
		bc.utils.rumSeq = typeof(bc.utils.rumSeq) === 'number' ? ++bc.utils.rumSeq : 1;
		// ------------------------------
		// For each of the Partner Handlers, tag the action with all of the data.
		if(bc && onlyMappings !== true){
			if(bc.isMappingsLoaded === false || bc.mappingQueueProcessed === false){
				var tmpData = {
						ctx: ctx+dynCtx,
						act: act,
						rpt: rpt,
						attrs: attrs
					};
				bc.mappingQueue.push(tmpData);
			}
		}
		
		for (pn in bc.handlers) {
			if(bc.handlers.hasOwnProperty(pn)){
				// ------------------------------
				// Also, fetch the Context-Partner-Action-Configuration (capc) from the configuration object
				if(onlyMappings===true && pn === "wmbeacon"){
					continue;
				}
				try {
					capc = config.ptns[pn].ctxs[ctx].acts[act];
				} catch (e) {
					capc = null;
				}
				
				
				// ------------------------------
				// Find out if tagging has been disabled at the Partner Level
				if (!capc && bc.handlers[pn] && bc.handlers[pn].forceTagAction()) {
					//To make sure tagAction gets invoked if there is no context-action-partner-config (capc) entry,
					//For a partner who has forceTagAction set to true
					attrs = bc.handlers[pn].metadata(attrs, ctx+dynCtx, act, rpt);
					count.push(bc.handlers[pn].tagAction(ctx+dynCtx, act, rpt, attrs, capc));
				}else if(capc && !capc.ds){
					attrs = bc.handlers[pn].metadata(attrs, ctx+dynCtx, act, rpt);
					count.push(bc.handlers[pn].tagAction(ctx+dynCtx, act, rpt, attrs, capc));
				}else{
					//bc.utils.log('Partner [' + pn + '] has no task specified, for action [' + act + '] under context [' + ctx + ']');
				}
			}
		}
		
		if (!count.length) {
			bc.utils.log('WARNING - Action [' + act + '] under context [' + ctx + '] was not tagged by any Partners');
		}
		
		// -----------------------------	
		// Find out if any groups need to be cleared out
		try {
			clrGrps = config.ctxs[ctx].acts[act].clr;
		} catch (e) {
			//
		}
		
		if(clrGrps){
			bc.utils.rmvAllEntry(ctx, config.ctxs[ctx].acts[act].clr);
		}
		return count;
	};
	
	/**
	 * @desc definition of the tagOutboundAction Command 
	 * @desc all params are required params in given sequence
	 * @desc get all params, fetch data specified in attributes and store it in sessionStorage
	 * @author Laxmikant Kurhe <lkurhe@walmartlabs.com>
	 * @param {String} context Optional namespace about the location of the action
	 * @param {String} action Name of the Action to be tagged.
	 * @param {String} report Name of the Report Id for filtering purpose.
	 * @param {Object} attributes Beacon Attributes to be sent to Beacon and transformed into Partner Variables
	 * @param {String} linkUrl URL to be triggered after timeout has reached, if no url then pass null
	 * @return {boolean}
	 */
	bc.commands._tagOutboundAction = function (context, action, report, attributes, linkUrl) {
		var index,
			dynCtx = '',
			readBase,
			wait_q = [],
			store,
			data = {},
			i, len = arguments.length,
			url,
			args = [];
		
		if(arguments.length < 5){
			return;
		}
		
		context = typeof context === 'string' ? context : '';
		index = context.indexOf('_');
		if(index !== -1){
			dynCtx = context.substring(index + 1);
			context = context.substring(0, index + 1);
		}
		
		try{
			if(config.ctxs[context].acts[action].triggerNow){
				return bc.commands._tagAction(context, action, report, attributes);
			}
		}catch(err){
			
		}
		
		try {
			readBase = (config.ctxs[context].acts[action].readBase !== false);
		} catch (e) {
			readBase = true;
		}
		
		attributes = attributes || {};
		
		if(Array.isArray(attributes)){
			attributes = bc.utils.actionData({}, attributes, context+dynCtx, readBase) || {};
		}
		
		attributes.opv_id = bc.page_view_id;
		
		data = {
			ctx: context+dynCtx,
			act: action,
			rpt: report,
			attrs: attributes
		};
		
		try{
			store = config.store.wait_q;
			wait_q = _bcq.store.read(store.n, {storage: store.t}) || [];
			wait_q.push(data);
			_bcq.store.write(store.n, wait_q, {storage: store.t});
		}catch(e){
			bc.utils.log('ERROR - _tagOutboundAction failed for [' + action + '] under [' + context + ']');
		}
		return;
	};
	
	/**
	 * @description Infamous "push". Based on the push function from Google Analytics. Receives arrays of commands as parameters
	 * @description and executes a specifc function from the bc.commands namespace if possible
	 * @description inspired from: https://developers.google.com/analytics/devguides/collection/gajs/
	 * @author Carlos Soto <csoto@walmartlabs.com>
	 * @param {Array} an array or list of arrays containing at least the command to be executed
	 * @return void
	 */
	bc.push = function () {
	     
		var args = arguments;
	     
		function the_push () {
	         var i,
	             cmd,
	             name;
	
	         // ------------------------------
	         // Iterate through the arguments as people can add one or more 
	         // commands Make sure that all of the commands are Arrays and 
	         // that have at least one entry (the name of the command)
	         for (i = 0; i < args.length; ++i) {
	             cmd = args[i];
	             if(bc.apiq){
                     bc.apiq.push(cmd);
                 }

                 
	             if (Array.isArray(cmd) && cmd.length) {
	                 // ------------------------------
	                 // Get the name of the command and see if it's a "set" command (like _setAfterTag, or _setBeforeTag).
	                 // If it is, then, remove the "set" string from the name of the command, and then, transform the second character
	                 // to lowercase, so we transform a command from _setAfterTag to _afterTag. Then, replace the default hook that's
	                 // on bc.commands with the new implementation, which should be the second parameter of the command array.
	                 name = cmd[0];
	                 if (name && name !== '_setOptions' && name.search("_set") && cmd.lenth > 1 && typeof cmd[1] === 'function') {
	                     name = name.replace('set', '');
	                     bc.commands[name] = cmd[1];
	                 
	                 // ------------------------------
	                 // if it's not a "set" command, then look for the command un bc.commands, and if it exists,
	                 // then call that function using the rest of the entries of the command array (without the
	                 // command name) as the arguments for that command
	                 } else if (bc.commands.hasOwnProperty(name)) {
	                     bc.commands[name].apply(bc, cmd.slice(1));
	                 }else{
	                 	bc.utils.log('No such command found with name : ' + name);
	                 }
	             }
	         }		
		}
		
	     // ------------------------------
	     // Add a timeout(0) to the "push" functionality (if enabled), so that all of the analytics code goes 
	     // into the queue of the browser's thread so that it gets executed whenever the browser has some spare time
		if (bc.options.push_timeout === true) {
			window.setTimeout(the_push, 0);
		} else {
			the_push();
		}
	};

	bc.mappingPush = function () {
	     
		var args = arguments;
	     
		function the_push () {
	         var i,
	             cmd,
	             name;
	
	         // ------------------------------
	         // Iterate through the arguments as people can add one or more 
	         // commands Make sure that all of the commands are Arrays and 
	         // that have at least one entry (the name of the command)
	         for (i = 0; i < args.length; ++i) {
	             cmd = args[i];
	             if(bc.apiq){
                     bc.apiq.push(cmd);
                 }

                 if(!bc.isMappingsLoaded && !bc.mappingsProcessed){
                     bc.mappingQueue.push(cmd);
                 }
                 else
                 {
                 	if(!bc.mappingsProcessed){
                 		bc.mappingsProcessed=true;
                 		bc.push.apply(bc, bc.mappingQueue);       		
                 	}
                 	
                 }

	             if (Array.isArray(cmd) && cmd.length) {
	                 // ------------------------------
	                 // Get the name of the command and see if it's a "set" command (like _setAfterTag, or _setBeforeTag).
	                 // If it is, then, remove the "set" string from the name of the command, and then, transform the second character
	                 // to lowercase, so we transform a command from _setAfterTag to _afterTag. Then, replace the default hook that's
	                 // on bc.commands with the new implementation, which should be the second parameter of the command array.
	                 name = cmd[0];
	                 if (name && name !== '_setOptions' && name.search("_set") && cmd.lenth > 1 && typeof cmd[1] === 'function') {
	                     name = name.replace('set', '');
	                     bc.commands[name] = cmd[1];
	                 
	                 // ------------------------------
	                 // if it's not a "set" command, then look for the command un bc.commands, and if it exists,
	                 // then call that function using the rest of the entries of the command array (without the
	                 // command name) as the arguments for that command
	                 } else if (bc.commands.hasOwnProperty(name)) {
	                     bc.commands[name].apply(bc, cmd.slice(1));
	                 }else{
	                 	bc.utils.log('No such command found with name : ' + name);
	                 }
	             }
	         }		
		}
		
	     // ------------------------------
	     // Add a timeout(0) to the "push" functionality (if enabled), so that all of the analytics code goes 
	     // into the queue of the browser's thread so that it gets executed whenever the browser has some spare time
		if (bc.options.push_timeout === true) {
			window.setTimeout(the_push, 0);
		} else {
			the_push();
		}
	};
	
	
	/**
	 * @desc definition of the _tagAction method on main _bcq object, to be used only after rum.js is completely downloaded and executed 
	 * @desc same as _tagAction command only difference is this function can return some value
	 * @author Laxmikant Kurhe <lkurhe@walmartlabs.com>
	 * @param {String} context namespace about the location of the action
	 * @param {String} action Name of the Action to be tagged.
	 * @param {String} report Name of the Report Id for filtering purpose.
	 * @param {Object} attributes Beacon Attributes to be sent to Beacon and transformed into Partner Variables
	 * @return void
	 */
	bc._tagAction = function (context, action, report, attributes) {
		var count = bc.commands._tagAction.apply(bc, arguments),
			i, len = Array.isArray(count) ? count.length : 0, urls = [];
		for(i = 0; i < len; i++){
			if(typeof count[i] === 'string' && count[i] !== ''){
				urls.push(count[i]);
			}
		}
		return urls;
	};
	
	/**
	 * @desc definition of the _addData method on main _bcq object, to be used only after rum.js is completely downloaded and executed 
	 * @desc same as _addData command only difference is it will not be sent in _bcq queue rum.js is not loaded
	 * @author Laxmikant Kurhe <lkurhe@walmartlabs.com>
	 * @param {String} context namespace about the location of the data
	 * @param {Object} Beacon Attributes [name-value pairs] to be sent to Beacon and transformed into Partner Variables
	 * @return void
	 */
	bc._addData = function (context, attributes) {
		bc.utils.addCommand.apply(bc, arguments);
	};
	
})(_bcq, _bcc);

/**
 * @copyright (c) 2011, Yahoo! Inc.  All rights reserved.
 * @copyright (c) 2012, Log-Normal, Inc.  All rights reserved.
 * @copyright (c) 2012-2016, SOASTA, Inc. All rights reserved.
 * Copyrights licensed under the BSD License. See the accompanying LICENSE.txt file for terms.
 */

/**
 * @namespace Boomerang
 * @desc
 * boomerang measures various performance characteristics of your user's browsing
 * experience and beacons it back to your server.
 *
 * To use this you'll need a web site, lots of users and the ability to do
 * something with the data you collect.  How you collect the data is up to
 * you, but we have a few ideas.
*/

/**
 * @memberof Boomerang
 * @type {TimeStamp}
 * @desc
 * Measure the time the script started
 * This has to be global so that we don't wait for the entire
 * BOOMR function to download and execute before measuring the
 * time.  We also declare it without `var` so that we can later
 * `delete` it.  This is the only way that works on Internet Explorer
*/
BOOMR_start = new Date().getTime();

/**
 * @function
 * @desc
 * Check the value of document.domain and fix it if incorrect.
 * This function is run at the top of boomerang, and then whenever
 * init() is called.  If boomerang is running within an iframe, this
 * function checks to see if it can access elements in the parent
 * iframe.  If not, it will fudge around with document.domain until
 * it finds a value that works.
 *
 * This allows site owners to change the value of document.domain at
 * any point within their page's load process, and we will adapt to
 * it.
 * @param {string} domain - domain name as retrieved from page url
 */
function BOOMR_check_doc_domain(domain) {
	/*eslint no-unused-vars:0*/
	var test;

	if (!window) {
		return;
	}

	// If domain is not passed in, then this is a global call
	// domain is only passed in if we call ourselves, so we
	// skip the frame check at that point
	if (!domain) {
		// If we're running in the main window, then we don't need this
		if (window.parent === window || !document.getElementById("boomr-if-as")) {
			return;// true;	// nothing to do
		}

		if (window.BOOMR && BOOMR.boomerang_frame && BOOMR.window) {
			try {
				// If document.domain is changed during page load (from www.blah.com to blah.com, for example),
				// BOOMR.window.location.href throws "Permission Denied" in IE.
				// Resetting the inner domain to match the outer makes location accessible once again
				if (BOOMR.boomerang_frame.document.domain !== BOOMR.window.document.domain) {
					BOOMR.boomerang_frame.document.domain = BOOMR.window.document.domain;
				}
			}
			catch (err) {
				if (!BOOMR.isCrossOriginError(err)) {
					BOOMR.addError(err, "BOOMR_check_doc_domain.domainFix");
				}
			}
		}
		domain = document.domain;
	}

	if (domain.indexOf(".") === -1) {
		return;// false;	// not okay, but we did our best
	}

	// 1. Test without setting document.domain
	try {
		test = window.parent.document;
		return;// test !== undefined;	// all okay
	}
	// 2. Test with document.domain
	catch (err) {
		document.domain = domain;
	}
	try {
		test = window.parent.document;
		return;// test !== undefined;	// all okay
	}
	// 3. Strip off leading part and try again
	catch (err) {
		domain = domain.replace(/^[\w\-]+\./, "");
	}

	BOOMR_check_doc_domain(domain);
}

BOOMR_check_doc_domain();


// beaconing section
// the parameter is the window
(function(w) {

	var impl, boomr, d, myurl, createCustomEvent, dispatchEvent, visibilityState, visibilityChange, orig_w = w;

	// This is the only block where we use document without the w. qualifier
	if (w.parent !== w &&
	    document.getElementById("boomr-if-as") &&
	    document.getElementById("boomr-if-as").nodeName.toLowerCase() === "script") {
		w = w.parent;
		myurl = document.getElementById("boomr-if-as").src;
	}

	d = w.document;

	// Short namespace because I don't want to keep typing BOOMERANG
	if (!w.BOOMR) { w.BOOMR = {}; }
	BOOMR = w.BOOMR;
	// don't allow this code to be included twice
	if (BOOMR.version) {
		return;
	}

	BOOMR.version = "pulse_boomerang_v1.0";
	BOOMR.window = w;
	BOOMR.boomerang_frame = orig_w;

	if (!BOOMR.plugins) { BOOMR.plugins = {}; }

	// CustomEvent proxy for IE9 & 10 from https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent
	(function() {
		try {
			if (new w.CustomEvent("CustomEvent") !== undefined) {
				createCustomEvent = function(e_name, params) {
					return new w.CustomEvent(e_name, params);
				};
			}
		}
		catch (ignore) {
			// empty
		}

		try {
			if (!createCustomEvent && d.createEvent && d.createEvent("CustomEvent")) {
				createCustomEvent = function(e_name, params) {
					var evt = d.createEvent("CustomEvent");
					params = params || { cancelable: false, bubbles: false };
					evt.initCustomEvent(e_name, params.bubbles, params.cancelable, params.detail);

					return evt;
				};
			}
		}
		catch (ignore) {
			// empty
		}

		if (!createCustomEvent && d.createEventObject) {
			createCustomEvent = function(e_name, params) {
				var evt = d.createEventObject();
				evt.type = evt.propertyName = e_name;
				evt.detail = params.detail;

				return evt;
			};
		}

		if (!createCustomEvent) {
			createCustomEvent = function() { return undefined; };
		}
	}());

	/**
	 dispatch a custom event to the browser
	 @param e_name	The custom event name that consumers can subscribe to
	 @param e_data	Any data passed to subscribers of the custom event via the `event.detail` property
	 @param async	By default, custom events are dispatched immediately.
			Set to true if the event should be dispatched once the browser has finished its current
			JavaScript execution.
	 */
	dispatchEvent = function(e_name, e_data, async) {
		var ev = createCustomEvent(e_name, {"detail": e_data});
		if (!ev) {
			return;
		}

		function dispatch() {
			try {
				if (d.dispatchEvent) {
					d.dispatchEvent(ev);
				}
				else if (d.fireEvent) {
					d.fireEvent("onpropertychange", ev);
				}
			}
			catch (e) {
				BOOMR.debug("Error when dispatching " + e_name);
			}
		}

		if (async) {
			BOOMR.setImmediate(dispatch);
		}
		else {
			dispatch();
		}
	};

	// visibilitychange is useful to detect if the page loaded through prerender
	// or if the page never became visible
	// http://www.w3.org/TR/2011/WD-page-visibility-20110602/
	// http://www.nczonline.net/blog/2011/08/09/introduction-to-the-page-visibility-api/
	// https://developer.mozilla.org/en-US/docs/Web/Guide/User_experience/Using_the_Page_Visibility_API

	// Set the name of the hidden property and the change event for visibility
	if (typeof document.hidden !== "undefined") { // Opera 12.10 and Firefox 18 and later support
		visibilityState = "visibilityState";
		visibilityChange = "visibilitychange";
	}
	else if (typeof document.mozHidden !== "undefined") {
		visibilityState = "mozVisibilityState";
		visibilityChange = "mozvisibilitychange";
	}
	else if (typeof document.msHidden !== "undefined") {
		visibilityState = "msVisibilityState";
		visibilityChange = "msvisibilitychange";
	}
	else if (typeof document.webkitHidden !== "undefined") {
		visibilityState = "webkitVisibilityState";
		visibilityChange = "webkitvisibilitychange";
	}

	// impl is a private object not reachable from outside the BOOMR object
	// users can set properties by passing in to the init() method
	impl = {
		// properties
		beacon_url: "",
		// beacon request method, either GET, POST or AUTO. AUTO will check the
		// request size then use GET if the request URL is less than MAX_GET_LENGTH chars
		// otherwise it will fall back to a POST request.
		beacon_type: "AUTO",
		//  beacon authorization key value.  Most systems will use the 'Authentication' keyword, but some
		//  some services use keys like 'X-Auth-Token' or other custom keys
		beacon_auth_key: "Authorization",
		//  beacon authorization token.  This is only needed if your are using a POST and
		//  the beacon requires an Authorization token to accept your data
		beacon_auth_token: undefined,
		// strip out everything except last two parts of hostname.
		// This doesn't work well for domains that end with a country tld,
		// but we allow the developer to override site_domain for that.
		// You can disable all cookies by setting site_domain to a falsy value
		site_domain: w.location.hostname.
					replace(/.*?([^.]+\.[^.]+)\.?$/, "$1").
					toLowerCase(),
		//! User's ip address determined on the server.  Used for the BA cookie
		user_ip: "",
		// Whether or not to send beacons on page load
		autorun: true,

		// Whether or not we've sent a page load beacon
		hasSentPageLoadBeacon: false,

		// cookie referrer
		r: undefined,

		// document.referrer
		r2: undefined,

		//! strip_query_string: false,

		//! onloadfired: false,

		//! handlers_attached: false,
		events: {
			"page_ready": [],
			"page_unload": [],
			"before_unload": [],
			"dom_loaded": [],
			"visibility_changed": [],
			"prerender_to_visible": [],
			"before_beacon": [],
			"onbeacon": [],
			"page_load_beacon": [],
			"xhr_load": [],
			"click": [],
			"form_submit": [],
			"onconfig": [],
			"xhr_init": [],
			"spa_init": [],
			"spa_navigation": [],
			"xhr_send": []
		},

		public_events: {
			"before_beacon": "onBeforeBoomerangBeacon",
			"onbeacon": "onBoomerangBeacon",
			"onboomerangloaded": "onBoomerangLoaded"
		},

		listenerCallbacks: {},

		vars: {},

		/**
		 * Variable priority lists:
		 * -1 = first
		 *  1 = last
		 */
		varPriority: {
			"-1": {},
			"1": {}
		},

		errors: {},

		disabled_plugins: {},

		xb_handler: function(type) {
			return function(ev) {
				var target;
				if (!ev) { ev = w.event; }
				if (ev.target) { target = ev.target; }
				else if (ev.srcElement) { target = ev.srcElement; }
				if (target.nodeType === 3) {// defeat Safari bug
					target = target.parentNode;
				}

				// don't capture events on flash objects
				// because of context slowdowns in PepperFlash
				if (target && target.nodeName.toUpperCase() === "OBJECT" && target.type === "application/x-shockwave-flash") {
					return;
				}
				impl.fireEvent(type, target);
			};
		},

		clearEvents: function() {
			var eventName;

			for (eventName in this.events) {
				if (this.events.hasOwnProperty(eventName)) {
					this.events[eventName] = [];
				}
			}
		},

		clearListeners: function() {
			var type, i;

			for (type in impl.listenerCallbacks) {
				if (impl.listenerCallbacks.hasOwnProperty(type)) {
					// remove all callbacks -- removeListener is guaranteed
					// to remove the element we're calling with
					while (impl.listenerCallbacks[type].length) {
						BOOMR.utils.removeListener(
						    impl.listenerCallbacks[type][0].el,
						    type,
						    impl.listenerCallbacks[type][0].fn);
					}
				}
			}

			impl.listenerCallbacks = {};
		},

		fireEvent: function(e_name, data) {
			var i, handler, handlers, handlersLen;

			e_name = e_name.toLowerCase();

			if (!this.events.hasOwnProperty(e_name)) {
				return;// false;
			}

			if (this.public_events.hasOwnProperty(e_name)) {
				dispatchEvent(this.public_events[e_name], data);
			}

			handlers = this.events[e_name];

			// Before we fire any event listeners, let's call real_sendBeacon() to flush
			// any beacon that is being held by the setImmediate.
			if (e_name !== "before_beacon" && e_name !== "onbeacon") {
				BOOMR.real_sendBeacon();
			}

			// only call handlers at the time of fireEvent (and not handlers that are
			// added during this callback to avoid an infinite loop)
			handlersLen = handlers.length;
			for (i = 0; i < handlersLen; i++) {
				try {
					handler = handlers[i];
					handler.fn.call(handler.scope, data, handler.cb_data);
				}
				catch (err) {
					BOOMR.addError(err, "fireEvent." + e_name + "<" + i + ">");
				}
			}

			// remove any 'once' handlers now that we've fired all of them
			for (i = 0; i < handlersLen; i++) {
				if (handlers[i].once) {
					handlers.splice(i, 1);
					handlersLen--;
					i--;
				}
			}

			return;// true;
		},

		spaNavigation: function() {
			// a SPA navigation occured, force onloadfired to true
			impl.onloadfired = true;
		}
	};

	// We create a boomr object and then copy all its properties to BOOMR so that
	// we don't overwrite anything additional that was added to BOOMR before this
	// was called... for example, a plugin.
	boomr = {
		//! t_lstart: value of BOOMR_lstart set in host page
		t_start: BOOMR_start,
		//! t_end: value set in zzz-last-plugin.js

		url: myurl,

		// constants visible to the world
		constants: {
			// SPA beacon types
			BEACON_TYPE_SPAS: ["spa", "spa_hard"],
			// using 2000 here as a de facto maximum URL length based on:
			// http://stackoverflow.com/questions/417142/what-is-the-maximum-length-of-a-url-in-different-browsers
			MAX_GET_LENGTH: 2000
		},

		// Utility functions
		utils: {
			objectToString: function(o, separator, nest_level) {
				var value = [], k;

				if (!o || typeof o !== "object") {
					return o;
				}
				if (separator === undefined) {
					separator = "\n\t";
				}
				if (!nest_level) {
					nest_level = 0;
				}

				if (Object.prototype.toString.call(o) === "[object Array]") {
					for (k = 0; k < o.length; k++) {
						if (nest_level > 0 && o[k] !== null && typeof o[k] === "object") {
							value.push(
								this.objectToString(
									o[k],
									separator + (separator === "\n\t" ? "\t" : ""),
									nest_level - 1
								)
							);
						}
						else {
							if (separator === "&") {
								value.push(encodeURIComponent(o[k]));
							}
							else {
								value.push(o[k]);
							}
						}
					}
					separator = ",";
				}
				else {
					for (k in o) {
						if (Object.prototype.hasOwnProperty.call(o, k)) {
							if (nest_level > 0 && o[k] !== null && typeof o[k] === "object") {
								value.push(encodeURIComponent(k) + "=" +
									this.objectToString(
										o[k],
										separator + (separator === "\n\t" ? "\t" : ""),
										nest_level - 1
									)
								);
							}
							else {
								if (separator === "&") {
									value.push(encodeURIComponent(k) + "=" + encodeURIComponent(o[k]));
								}
								else {
									value.push(k + "=" + o[k]);
								}
							}
						}
					}
				}

				return value.join(separator);
			},

			getCookie: function(name) {
				if (!name) {
					return null;
				}

				name = " " + name + "=";

				var i, cookies;
				cookies = " " + d.cookie + ";";
				if ((i = cookies.indexOf(name)) >= 0) {
					i += name.length;
					cookies = cookies.substring(i, cookies.indexOf(";", i)).replace(/^"/, "").replace(/"$/, "");
					return cookies;
				}
			},

			setCookie: function(name, subcookies, max_age) {
				var value, nameval, savedval, c, exp;

				if (!name || !impl.site_domain) {
					BOOMR.debug("No cookie name or site domain: " + name + "/" + impl.site_domain);
					return false;
				}

				value = this.objectToString(subcookies, "&");
				nameval = name + "=\"" + value + "\"";

				c = [nameval, "path=/", "domain=" + impl.site_domain];
				if (max_age) {
					exp = new Date();
					exp.setTime(exp.getTime() + max_age * 1000);
					exp = exp.toGMTString();
					c.push("expires=" + exp);
				}

				if (nameval.length < 500) {
					d.cookie = c.join("; ");
					// confirm cookie was set (could be blocked by user's settings, etc.)
					savedval = this.getCookie(name);
					if (value === savedval) {
						return true;
					}
					BOOMR.warn("Saved cookie value doesn't match what we tried to set:\n" + value + "\n" + savedval);
				}
				else {
					BOOMR.warn("Cookie too long: " + nameval.length + " " + nameval);
				}

				return false;
			},

			getSubCookies: function(cookie) {
				var cookies_a,
				    i, l, kv,
				    gotcookies = false,
				    cookies = {};

				if (!cookie) {
					return null;
				}

				if (typeof cookie !== "string") {
					BOOMR.debug("TypeError: cookie is not a string: " + typeof cookie);
					return null;
				}

				cookies_a = cookie.split("&");

				for (i = 0, l = cookies_a.length; i < l; i++) {
					kv = cookies_a[i].split("=");
					if (kv[0]) {
						kv.push("");	// just in case there's no value
						cookies[decodeURIComponent(kv[0])] = decodeURIComponent(kv[1]);
						gotcookies = true;
					}
				}

				return gotcookies ? cookies : null;
			},

			removeCookie: function(name) {
				return this.setCookie(name, {}, -86400);
			},

			/**
			 * Cleans up a URL by removing the query string (if configured), and
			 * limits the URL to the specified size.
			 *
			 * @param {string} url URL to clean
			 * @param {number} urlLimit Maximum size, in characters, of the URL
			 *
			 * @returns {string} Cleaned up URL
			 */
			cleanupURL: function(url, urlLimit) {
				if (!url || Object.prototype.toString.call(url) === "[object Array]") {
					return "";
				}

				if (impl.strip_query_string) {
					url = url.replace(/\?.*/, "?qs-redacted");
				}

				if (typeof urlLimit !== "undefined" && url && url.length > urlLimit) {
					// We need to break this URL up.  Try at the query string first.
					var qsStart = url.indexOf("?");
					if (qsStart !== -1 && qsStart < urlLimit) {
						url = url.substr(0, qsStart) + "?...";
					}
					else {
						// No query string, just stop at the limit
						url = url.substr(0, urlLimit - 3) + "...";
					}
				}

				return url;
			},

			hashQueryString: function(url, stripHash) {
				if (!url) {
					return url;
				}
				if (!url.match) {
					BOOMR.addError("TypeError: Not a string", "hashQueryString", typeof url);
					return "";
				}
				if (url.match(/^\/\//)) {
					url = location.protocol + url;
				}
				if (!url.match(/^(https?|file):/)) {
					BOOMR.error("Passed in URL is invalid: " + url);
					return "";
				}
				if (stripHash) {
					url = url.replace(/#.*/, "");
				}
				if (!BOOMR.utils.MD5) {
					return url;
				}
				return url.replace(/\?([^#]*)/, function(m0, m1) { return "?" + (m1.length > 10 ? BOOMR.utils.MD5(m1) : m1); });
			},

			pluginConfig: function(o, config, plugin_name, properties) {
				var i, props = 0;

				if (!config || !config[plugin_name]) {
					return false;
				}

				for (i = 0; i < properties.length; i++) {
					if (config[plugin_name][properties[i]] !== undefined) {
						o[properties[i]] = config[plugin_name][properties[i]];
						props++;
					}
				}

				return (props > 0);
			},
			/**
			 * `filter` for arrays
			 *
			 * @private
			 * @param {Array} array The array to iterate over.
			 * @param {Function} predicate The function invoked per iteration.
			 * @returns {Array} Returns the new filtered array.
			 */
			arrayFilter: function(array, predicate) {
				var result = [];

				if (typeof array.filter === "function") {
					result = array.filter(predicate);
				}
				else {
					var index = -1,
					    length = array.length,
					    value;

					while (++index < length) {
						value = array[index];
						if (predicate(value, index, array)) {
							result[result.length] = value;
						}
					}
				}
				return result;
			},
			/**
			 * @desc
			 * Add a MutationObserver for a given element and terminate after `timeout`ms.
			 * @param el		DOM element to watch for mutations
			 * @param config		MutationObserverInit object (https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver#MutationObserverInit)
			 * @param timeout		Number of milliseconds of no mutations after which the observer should be automatically disconnected
			 * 			If set to a falsy value, the observer will wait indefinitely for Mutations.
			 * @param callback	Callback function to call either on timeout or if mutations are detected.  The signature of this method is:
			 * 				function(mutations, callback_data)
			 * 			Where:
			 * 				mutations is the list of mutations detected by the observer or `undefined` if the observer timed out
			 * 				callback_data is the passed in `callback_data` parameter without modifications
			 *
			 * 						The callback function may return a falsy value to disconnect the observer after it returns, or a truthy value to
			 * 			keep watching for mutations. If the return value is numeric and greater than 0, then this will be the new timeout
			 * 			if it is boolean instead, then the timeout will not fire any more so the caller MUST call disconnect() at some point
			 * @param callback_data	Any data to be passed to the callback function as its second parameter
			 * @param callback_ctx	An object that represents the `this` object of the `callback` method.  Leave unset the callback function is not a method of an object
			 *
			 * @returns {?object} - `null` if a MutationObserver could not be created OR
			 * 		- An object containing the observer and the timer object:
			 * 		  { observer: <MutationObserver>, timer: <Timeout Timer if any> }
			 *
			 * 		The caller can use this to disconnect the observer at any point by calling `retval.observer.disconnect()`
			 * 		Note that the caller should first check to see if `retval.observer` is set before calling `disconnect()` as it may
			 * 		have been cleared automatically.
			 */
			addObserver: function(el, config, timeout, callback, callback_data, callback_ctx) {
				var o = {observer: null, timer: null};

				if (!BOOMR.window || !BOOMR.window.MutationObserver || !callback || !el) {
					return null;
				}

				function done(mutations) {
					var run_again = false;

					if (o.timer) {
						clearTimeout(o.timer);
						o.timer = null;
					}

					if (callback) {
						run_again = callback.call(callback_ctx, mutations, callback_data);

						if (!run_again) {
							callback = null;
						}
					}

					if (!run_again && o.observer) {
						o.observer.disconnect();
						o.observer = null;
					}

					if (typeof run_again === "number" && run_again > 0) {
						o.timer = setTimeout(done, run_again);
					}
				}

				o.observer = new BOOMR.window.MutationObserver(done);

				if (timeout) {
					o.timer = setTimeout(done, o.timeout);
				}

				o.observer.observe(el, config);

				return o;
			},

			addListener: function(el, type, fn) {
				if (el.addEventListener) {
					el.addEventListener(type, fn, false);
				}
				else if (el.attachEvent) {
					el.attachEvent("on" + type, fn);
				}

				// ensure the type arry exists
				impl.listenerCallbacks[type] = impl.listenerCallbacks[type] || [];

				// save a reference to the target object and function
				impl.listenerCallbacks[type].push({ el: el, fn: fn});
			},

			removeListener: function(el, type, fn) {
				var i;

				if (el.removeEventListener) {
					el.removeEventListener(type, fn, false);
				}
				else if (el.detachEvent) {
					el.detachEvent("on" + type, fn);
				}

				if (impl.listenerCallbacks.hasOwnProperty(type)) {
					for (var i = 0; i < impl.listenerCallbacks[type].length; i++) {
						if (fn === impl.listenerCallbacks[type][i].fn &&
						    el === impl.listenerCallbacks[type][i].el) {
							impl.listenerCallbacks[type].splice(i, 1);
							return;
						}
					}
				}
			},

			pushVars: function(form, vars, prefix) {
				var k, i, l = 0, input;

				for (k in vars) {
					if (vars.hasOwnProperty(k)) {
						if (Object.prototype.toString.call(vars[k]) === "[object Array]") {
							for (i = 0; i < vars[k].length; ++i) {
								l += BOOMR.utils.pushVars(form, vars[k][i], k + "[" + i + "]");
							}
						}
						else {
							input = document.createElement("input");
							input.type = "hidden";	// we need `hidden` to preserve newlines. see commit message for more details
							input.name = (prefix ? (prefix + "[" + k + "]") : k);
							input.value = (vars[k] === undefined || vars[k] === null ? "" : vars[k]);

							form.appendChild(input);

							l += encodeURIComponent(input.name).length + encodeURIComponent(input.value).length + 2;
						}
					}
				}

				return l;
			},

			isArray: function(ary) {
				return Object.prototype.toString.call(ary) === "[object Array]";
			},

			inArray: function(val, ary) {
				var i;

				if (typeof val === "undefined" || typeof ary === "undefined" || !ary.length) {
					return false;
				}

				for (i = 0; i < ary.length; i++) {
					if (ary[i] === val) {
						return true;
					}
				}

				return false;
			},

			/**
			 * Get a query parameter value from a URL's query string
			 *
			 * @param {string} param Query parameter name
			 * @param {string|Object} [url] URL containing the query string, or a link object. Defaults to BOOMR.window.location
			 *
			 * @returns {string|null} URI decoded value or null if param isn't a query parameter
			 */
			getQueryParamValue: function(param, url) {
				var l, params, i, kv;
				if (!param) {
					return null;
				}

				if (typeof url === "string") {
					l = BOOMR.window.document.createElement("a");
					l.href = url;
				}
				else if (typeof url === "object" && typeof url.search === "string") {
					l = url;
				}
				else {
					l = BOOMR.window.location;
				}

				// Now that we match, pull out all query string parameters
				params = l.search.slice(1).split(/&/);

				for (i = 0; i < params.length; i++) {
					if (params[i]) {
						kv = params[i].split("=");
						if (kv.length && kv[0] === param) {
							return decodeURIComponent(kv[1].replace(/\+/g, " "));
						}
					}
				}
				return null;
			},

			/**
			 * Generates a pseudo-random UUID (Version 4):
			 * https://en.wikipedia.org/wiki/Universally_unique_identifier
			 *
			 * @returns {string} UUID
			 */
			generateUUID: function() {
				return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) {
					var r = Math.random() * 16 | 0;
					var v = c === "x" ? r : (r & 0x3 | 0x8);
					return v.toString(16);
				});
			},

			/**
			 * Generates a random ID based on the specified number of characters.  Uses
			 * characters a-z0-9.
			 *
			 * @param {number} chars Number of characters (max 40)
			 * @returns {string} Random ID
			 */
			generateId: function(chars) {
				return "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx".substr(0, chars || 40).replace(/x/g, function(c) {
					var c = (Math.random() || 0.01).toString(36);

					// some implementations may return "0" for small numbers
					if (c === "0") {
						return "0";
					}
					else {
						return c.substr(2, 1);
					}
				});
			},

			/**
			 * Attempt to serialize an object, preferring JSURL over JSON.stringify
			 *
			 * @param {Object} value Object to serialize
			 * @returns {string} serialized version of value, empty-string if not possible
			 */
			serializeForUrl: function(value) {
				if (BOOMR.utils.Compression && BOOMR.utils.Compression.jsUrl) {
					return BOOMR.utils.Compression.jsUrl(value);
				}
				if (window.JSON) {
					return JSON.stringify(value);
				}
				// not supported
				BOOMR.debug("JSON is not supported");
				return "";
			}

			/* BEGIN_DEBUG */
			, forEach: function(array, fn, thisArg) {
				if (!BOOMR.utils.isArray(array) || typeof fn !== "function") {
					return;
				}
				var length = array.length;
				for (var i = 0; i < length; i++) {
					if (array.hasOwnProperty(i)) {
						fn.call(thisArg, array[i], i, array);
					}
				}
			}
			/* END_DEBUG */

		}, // closes `utils`

		init: function(config) {
			var i, k,
			    properties = [
				    "beacon_url",
				    "beacon_type",
				    "beacon_auth_key",
				    "beacon_auth_token",
				    "site_domain",
				    "user_ip",
				    "strip_query_string",
				    "secondary_beacons",
				    "autorun",
				    "site_domain"
			    ];

			BOOMR_check_doc_domain();

			if (!config) {
				config = {};
			}

			if (!this.pageId) {
				// generate a random page ID for this page's lifetime
				this.pageId = BOOMR.utils.generateId(8);
			}

			if (config.primary && impl.handlers_attached) {
				return this;
			}

			if (config.log !== undefined) {
				this.log = config.log;
			}
			if (!this.log) {
				this.log = function(/* m,l,s */) {};
			}

			// Set autorun if in config right now, as plugins that listen for page_ready
			// event may fire when they .init() if onload has already fired, and whether
			// or not we should fire page_ready depends on config.autorun.
			if (typeof config.autorun !== "undefined") {
				impl.autorun = config.autorun;
			}

			for (k in this.plugins) {
				if (this.plugins.hasOwnProperty(k)) {
					// config[plugin].enabled has been set to false
					if (config[k] &&
					    config[k].hasOwnProperty("enabled") &&
					    config[k].enabled === false) {
						impl.disabled_plugins[k] = 1;

						if (typeof this.plugins[k].disable === "function") {
							this.plugins[k].disable();
						}

						continue;
					}

					// plugin was previously disabled
					if (impl.disabled_plugins[k]) {

						// and has not been explicitly re-enabled
						if (!config[k] ||
						    !config[k].hasOwnProperty("enabled") ||
						    config[k].enabled !== true) {
							continue;
						}

						if (typeof this.plugins[k].enable === "function") {
							this.plugins[k].enable();
						}

						// plugin is now enabled
						delete impl.disabled_plugins[k];
					}

					// plugin exists and has an init method
					if (typeof this.plugins[k].init === "function") {
						try {
							this.plugins[k].init(config);
						}
						catch (err) {
							BOOMR.addError(err, k + ".init");
						}
					}
				}
			}

			for (i = 0; i < properties.length; i++) {
				if (config[properties[i]] !== undefined) {
					impl[properties[i]] = config[properties[i]];
				}
			}

			if (impl.handlers_attached) {
				return this;
			}

			// The developer can override onload by setting autorun to false
			if (!impl.onloadfired && (config.autorun === undefined || config.autorun !== false)) {
				if (d.readyState && d.readyState === "complete") {
					BOOMR.loadedLate = true;
					this.setImmediate(BOOMR.page_ready_autorun, null, null, BOOMR);
				}
				else {
					if (w.onpagehide || w.onpagehide === null) {
						BOOMR.utils.addListener(w, "pageshow", BOOMR.page_ready_autorun);
					}
					else {
						BOOMR.utils.addListener(w, "load", BOOMR.page_ready_autorun);
					}
				}
			}

			BOOMR.utils.addListener(w, "DOMContentLoaded", function() { impl.fireEvent("dom_loaded"); });
			BOOMR.fireEvent("onconfig", config);
			BOOMR.subscribe("onconfig", function(beaconConfig) {
				if (beaconConfig.beacon_url) {
					impl.beacon_url = beaconConfig.beacon_url;
				}
			});

			BOOMR.subscribe("spa_navigation", impl.spaNavigation, null, impl);

			(function() {
				var forms, iterator;
				if (visibilityChange !== undefined) {
					BOOMR.utils.addListener(d, visibilityChange, function() { impl.fireEvent("visibility_changed"); });

					// save the current visibility state
					impl.lastVisibilityState = BOOMR.visibilityState();

					BOOMR.subscribe("visibility_changed", function() {
						var visState = BOOMR.visibilityState();

						// record the last time each visibility state occurred
						BOOMR.lastVisibilityEvent[visState] = BOOMR.now();
						BOOMR.debug("Visibility changed from " + impl.lastVisibilityState + " to " + visState);

						// if we transitioned from prerender to hidden or visible, fire the prerender_to_visible event
						if (impl.lastVisibilityState === "prerender" &&
						    visState !== "prerender") {
							// note that we transitioned from prerender on the beacon for debugging
							BOOMR.addVar("vis.pre", "1");

							// let all listeners know
							impl.fireEvent("prerender_to_visible");
						}

						impl.lastVisibilityState = visState;
					});
				}

				BOOMR.utils.addListener(d, "mouseup", impl.xb_handler("click"));

				forms = d.getElementsByTagName("form");
				for (iterator = 0; iterator < forms.length; iterator++) {
					BOOMR.utils.addListener(forms[iterator], "submit", impl.xb_handler("form_submit"));
				}

				if (!w.onpagehide && w.onpagehide !== null) {
					// This must be the last one to fire
					// We only clear w on browsers that don't support onpagehide because
					// those that do are new enough to not have memory leak problems of
					// some older browsers
					BOOMR.utils.addListener(w, "unload", function() { BOOMR.window = w = null; });
				}
			}());

			impl.handlers_attached = true;
			return this;
		},

		/**
		 * Attach a callback to the onload event if the onload has not
		 * been fired yet
		 *
		 * @param {function} cb - Callback to run when onload fires or page is visible (pageshow)
		 */
		attach_page_ready: function(cb) {
			if (d.readyState && d.readyState === "complete") {
				this.setImmediate(cb, null, null, BOOMR);
			}
			else {
				if (w.onpagehide || w.onpagehide === null) {
					BOOMR.utils.addListener(w, "pageshow", cb);
				}
				else {
					BOOMR.utils.addListener(w, "load", cb);
				}
			}
		},

		/**
		 * Sends the page_ready beacon only if 'autorun' is still true after init
		 * is called.
		 */
		page_ready_autorun: function(ev) {
			if (impl.autorun) {
				BOOMR.page_ready(ev);
			}
		},

		// The page dev calls this method when they determine the page is usable.
		// Only call this if autorun is explicitly set to false
		page_ready: function(ev) {
			if (!ev) { ev = w.event; }
			if (!ev) { ev = { name: "load" }; }
			if (impl.onloadfired) {
				return this;
			}
			impl.fireEvent("page_ready", ev);
			impl.onloadfired = true;
			return this;
		},

		/**
		 * Determines whether or not the page's `onload` event has fired, or
		 * if `autorun` is false, whether `BOOMR.page_ready()` was called.
		 *
		 * @returns {boolean} True if onload or page_ready() were called
		 */
		onloadFired: function() {
			return impl.onloadfired;
		},

		/**
		 * Defer the function `fn` until the next instant the browser is free from user tasks
		 * @param [Function] fn The callback function.  This function accepts the following arguments:
		 *     - data: The passed in data object
		 *     - cb_data: The passed in cb_data object
		 *     - call stack: An Error object that holds the callstack for when setImmediate was called, used to determine what called the callback
		 * @param [object] data Any data to pass to the callback function
		 * @param [object] cb_data Any passthrough data for the callback function. This differs from `data` when setImmediate is called via an event handler and `data` is the Event object
		 * @param [object] cb_scope The scope of the callback function if it is a method of an object
		 * @returns nothing
		 */
		setImmediate: function(fn, data, cb_data, cb_scope) {
			var cb, cstack;

			// DEBUG: This is to help debugging, we'll see where setImmediate calls were made from
			if (typeof Error !== "undefined") {
				cstack = new Error();
				cstack = cstack.stack ? cstack.stack.replace(/^Error/, "Called") : undefined;
			}
			// END-DEBUG

			cb = function() {
				fn.call(cb_scope || null, data, cb_data || {}, cstack);
				cb = null;
			};

			if (w.requestIdleCallback) {
				w.requestIdleCallback(cb);
			}
			else if (w.setImmediate) {
				w.setImmediate(cb);
			}
			else {
				setTimeout(cb, 10);
			}
		},

		/**
		 * Gets the current time in milliseconds since the Unix Epoch (Jan 1 1970).
		 *
		 * In browsers that support DOMHighResTimeStamp, this will be replaced
		 * by a function that adds BOOMR.now() to navigationStart
		 * (with milliseconds.microseconds resolution).
		 *
		 * @returns {Number} Milliseconds since Unix Epoch
		 */
		now: (function() {
			return Date.now || function() { return new Date().getTime(); };
		}()),

		getPerformance: function() {
			try {
				if (BOOMR.window) {
					if ("performance" in BOOMR.window && BOOMR.window.performance) {
						return BOOMR.window.performance;
					}

					// vendor-prefixed fallbacks
					return BOOMR.window.msPerformance || BOOMR.window.webkitPerformance || BOOMR.window.mozPerformance;
				}
			}
			catch (ignore) {
				// empty
			}
		},

		visibilityState: (visibilityState === undefined ? function() { return "visible"; } : function() { return d[visibilityState]; }),

		lastVisibilityEvent: {},

		/**
		 * Registers an event
		 *
		 * @param {string} e_name Event name
		 *
		 * @returns {BOOMR} Boomerang object
		 */
		registerEvent: function(e_name) {
			if (impl.events.hasOwnProperty(e_name)) {
				// already registered
				return this;
			}

			// create a new queue of handlers
			impl.events[e_name] = [];

			return this;
		},

		/**
		 * Disables boomerang from doing anything further:
		 * 1. Clears event handlers (such as onload)
		 * 2. Clears all event listeners
		 */
		disable: function() {
			impl.clearEvents();
			impl.clearListeners();
		},

		/**
		 * Fires an event
		 *
		 * @param {string} e_name Event name
		 * @param {object} data Event payload
		 *
		 * @returns {BOOMR} Boomerang object
		 */
		fireEvent: function(e_name, data) {
			return impl.fireEvent(e_name, data);
		},

		subscribe: function(e_name, fn, cb_data, cb_scope, once) {
			var i, handler, ev;

			e_name = e_name.toLowerCase();

			if (!impl.events.hasOwnProperty(e_name)) {
				// allow subscriptions before they're registered
				impl.events[e_name] = [];
			}

			ev = impl.events[e_name];

			// don't allow a handler to be attached more than once to the same event
			for (i = 0; i < ev.length; i++) {
				handler = ev[i];
				if (handler && handler.fn === fn && handler.cb_data === cb_data && handler.scope === cb_scope) {
					return this;
				}
			}

			ev.push({
				fn: fn,
				cb_data: cb_data || {},
				scope: cb_scope || null,
				once: once || false
			});

			// attaching to page_ready after onload fires, so call soon
			if (e_name === "page_ready" && impl.onloadfired && impl.autorun) {
				this.setImmediate(fn, null, cb_data, cb_scope);
			}

			// Attach unload handlers directly to the window.onunload and
			// window.onbeforeunload events. The first of the two to fire will clear
			// fn so that the second doesn't fire. We do this because technically
			// onbeforeunload is the right event to fire, but all browsers don't
			// support it.  This allows us to fall back to onunload when onbeforeunload
			// isn't implemented
			if (e_name === "page_unload" || e_name === "before_unload") {
				(function() {
					var unload_handler, evt_idx = ev.length;

					unload_handler = function(evt) {
						if (fn) {
							fn.call(cb_scope, evt || w.event, cb_data);
						}

						// If this was the last unload handler, we'll try to send the beacon immediately after it is done
						// The beacon will only be sent if one of the handlers has queued it
						if (e_name === "page_unload" && evt_idx === impl.events[e_name].length) {
							BOOMR.real_sendBeacon();
						}
					};

					if (e_name === "page_unload") {
						// pagehide is for iOS devices
						// see http://www.webkit.org/blog/516/webkit-page-cache-ii-the-unload-event/
						if (w.onpagehide || w.onpagehide === null) {
							BOOMR.utils.addListener(w, "pagehide", unload_handler);
						}
						else {
							BOOMR.utils.addListener(w, "unload", unload_handler);
						}
					}
					BOOMR.utils.addListener(w, "beforeunload", unload_handler);
				}());
			}

			return this;
		},

		addError: function BOOMR_addError(err, src, extra) {
			var str, E = BOOMR.plugins.Errors;

			//
			// Use the Errors plugin if it's enabled
			//
			if (E && E.is_supported()) {
				if (typeof err === "string") {
					E.send({
						message: err,
						extra: extra,
						functionName: src,
						noStack: true
					}, E.VIA_APP, E.SOURCE_BOOMERANG);
				}
				else {
					if (typeof src === "string") {
						err.functionName = src;
					}

					if (typeof extra !== "undefined") {
						err.extra = extra;
					}

					E.send(err, E.VIA_APP, E.SOURCE_BOOMERANG);
				}

				return;
			}

			if (typeof err !== "string") {
				str = String(err);
				if (str.match(/^\[object/)) {
					str = err.name + ": " + (err.description || err.message).replace(/\r\n$/, "");
				}
				err = str;
			}
			if (src !== undefined) {
				err = "[" + src + ":" + BOOMR.now() + "] " + err;
			}
			if (extra) {
				err += ":: " + extra;
			}

			if (impl.errors[err]) {
				impl.errors[err]++;
			}
			else {
				impl.errors[err] = 1;
			}
		},

		isCrossOriginError: function(err) {
			// These are expected for cross-origin iframe access, although the Internet Explorer check will only
			// work for browsers using English.
			return err.name === "SecurityError" ||
				(err.name === "TypeError" && err.message === "Permission denied") ||
				(err.name === "Error" && err.message && err.message.match(/^(Permission|Access is) denied/));
		},

		addVar: function(name, value) {
			if (typeof name === "string") {
				impl.vars[name] = value;
			}
			else if (typeof name === "object") {
				var o = name, k;
				for (k in o) {
					if (o.hasOwnProperty(k)) {
						impl.vars[k] = o[k];
					}
				}
			}
			return this;
		},

		removeVar: function(arg0) {
			var i, params;
			if (!arguments.length) {
				return this;
			}

			if (arguments.length === 1 &&
			    Object.prototype.toString.apply(arg0) === "[object Array]") {
				params = arg0;
			}
			else {
				params = arguments;
			}

			for (i = 0; i < params.length; i++) {
				if (impl.vars.hasOwnProperty(params[i])) {
					delete impl.vars[params[i]];
				}
			}

			return this;
		},

		hasVar: function(name) {
			return impl.vars.hasOwnProperty(name);
		},

		/**
		 * Sets a variable's priority in the beacon URL.
		 * -1 = beginning of the URL
		 * 0  = middle of the URL (default)
		 * 1  = end of the URL
		 *
		 * @param {string} name Variable name
		 * @param {number} pri Priority (-1 or 1)
		 */
		setVarPriority: function(name, pri) {
			if (typeof pri !== "number" || Math.abs(pri) !== 1) {
				return this;
			}

			impl.varPriority[pri][name] = 1;

			return this;
		},

		/**
		 * Sets the Referrers
		 * @param {string} r Referrer from the cookie
		 * @param {string} [r2] Referrer from document.referrer, if different
		 */
		setReferrer: function(r, r2) {
			// cookie referrer
			impl.r = r;

			// document.referrer, if different
			if (r2 && r !== r2) {
				impl.r2 = r2;
			}
			else {
				impl.r2 = undefined;
			}
		},

		requestStart: function(name) {
			var t_start = BOOMR.now();
			BOOMR.plugins.RT.startTimer("xhr_" + name, t_start);

			return {
				loaded: function(data) {
					BOOMR.responseEnd(name, t_start, data);
				}
			};
		},

		/**
		 * Determines is Boomerang can send a beacon.
		 *
		 * Queryies all plugins to see if they implement readyToSend(),
		 * and if so, that they return true;
		 *
		 * If not, the beacon cannot be sent.
		 *
		 * @returns {boolean} True if Boomerang can send a beacon
		 */
		readyToSend: function() {
			var plugin;

			for (plugin in this.plugins) {
				if (this.plugins.hasOwnProperty(plugin)) {
					if (impl.disabled_plugins[plugin]) {
						continue;
					}

					if (typeof this.plugins[plugin].readyToSend === "function" &&
					    this.plugins[plugin].readyToSend() === false) {
						BOOMR.debug("Plugin " + plugin + " is not ready to send");
						return false;
					}
				}
			}

			return true;
		},

		responseEnd: function(name, t_start, data, t_end) {
			// take the now timestamp for start and end, if unspecified, in case we delay this beacon
			t_start = typeof t_start === "number" ? t_start : BOOMR.now();
			t_end = typeof t_end === "number" ? t_end : BOOMR.now();

			// wait until all plugins are ready to send
			if (!BOOMR.readyToSend()) {
				BOOMR.debug("Attempted to call responseEnd before all plugins were Ready to Send, trying again...");

				// try again later
				setTimeout(function() {
					BOOMR.responseEnd(name, t_start, data, t_end);
				}, 1000);

				return;
			}

			// Wait until we've sent the Page Load beacon first
			if (!BOOMR.hasSentPageLoadBeacon() &&
			    !BOOMR.utils.inArray(name.initiator, BOOMR.constants.BEACON_TYPE_SPAS)) {
				// wait for a beacon, then try again
				BOOMR.subscribe("page_load_beacon", function() {
					BOOMR.responseEnd(name, t_start, data, t_end);
				}, null, BOOMR, true);

				return;
			}

			if (typeof name === "object") {
				if (!name.url) {
					BOOMR.debug("BOOMR.responseEnd: First argument must have a url property if it's an object");
					return;
				}

				impl.fireEvent("xhr_load", name);
			}
			else {
				// flush out any queue'd beacons before we set the Page Group
				// and timers
				BOOMR.real_sendBeacon();

				BOOMR.addVar("xhr.pg", name);
				BOOMR.plugins.RT.startTimer("xhr_" + name, t_start);
				impl.fireEvent("xhr_load", {
					name: "xhr_" + name,
					data: data,
					timing: {
						loadEventEnd: t_end
					}
				});
			}
		},

		//
		// uninstrumentXHR and instrumentXHR are stubs that will be replaced
		// by auto-xhr.js if active.
		//
		/**
		 * Undo XMLHttpRequest instrumentation and reset the original
		 */
		uninstrumentXHR: function() {
		},
		/**
		 * Instrument all requests made via XMLHttpRequest to send beacons
		 * This is implemented in plugins/auto-xhr.js
		 */
		instrumentXHR: function() { },

		sendBeacon: function(beacon_url_override) {
			// This plugin wants the beacon to go somewhere else,
			// so update the location
			if (beacon_url_override) {
				impl.beacon_url_override = beacon_url_override;
			}

			if (!impl.beaconQueued) {
				impl.beaconQueued = true;
				BOOMR.setImmediate(BOOMR.real_sendBeacon, null, null, BOOMR);
			}

			return true;
		},

		real_sendBeacon: function() {
			var k, form, url, img, errors = [], params = [], paramsJoined, useImg = 1,
			    varsSent = {}, varsToSend = {}, urlFirst = [], urlLast = [],
			    xhr;

			if (!impl.beaconQueued) {
				return false;
			}

			impl.beaconQueued = false;

			BOOMR.debug("Checking if we can send beacon");

			// At this point someone is ready to send the beacon.  We send
			// the beacon only if all plugins have finished doing what they
			// wanted to do
			for (k in this.plugins) {
				if (this.plugins.hasOwnProperty(k)) {
					if (impl.disabled_plugins[k]) {
						continue;
					}
					if (!this.plugins[k].is_complete()) {
						BOOMR.debug("Plugin " + k + " is not complete, deferring beacon send");
						return false;
					}
				}
			}

			// Sanity test that the browser is still available (and not shutting down)
			if (!window || !window.Image || !window.navigator || !BOOMR.window) {
				BOOMR.debug("DOM not fully available, not sending a beacon");
				return false;
			}

			// For SPA apps, don't strip hashtags as some SPA frameworks use #s for tracking routes
			// instead of History pushState() APIs. Use d.URL instead of location.href because of a
			// Safari bug.
			var isSPA = BOOMR.utils.inArray(impl.vars["http.initiator"], BOOMR.constants.BEACON_TYPE_SPAS);
			var isPageLoad = typeof impl.vars["http.initiator"] === "undefined" || isSPA;

			var pgu = isSPA ? d.URL : d.URL.replace(/#.*/, "");
			impl.vars.pgu = BOOMR.utils.cleanupURL(pgu);

			// Use the current document.URL if it hasn't already been set, or for SPA apps,
			// on each new beacon (since each SPA soft navigation might change the URL)
			if (!impl.vars.u || isSPA) {
				impl.vars.u = impl.vars.pgu;
			}

			if (impl.vars.pgu === impl.vars.u) {
				delete impl.vars.pgu;
			}

			// Add cleaned-up referrer URLs to the beacon, if available
			if (impl.r) {
				impl.vars.r = BOOMR.utils.cleanupURL(impl.r);
			}
			else {
				delete impl.vars.r;
			}

			if (impl.r2) {
				impl.vars.r2 = BOOMR.utils.cleanupURL(impl.r2);
			}
			else {
				delete impl.vars.r2;
			}

			impl.vars.v = BOOMR.version;

			if (BOOMR.visibilityState()) {
				impl.vars["vis.st"] = BOOMR.visibilityState();
				if (BOOMR.lastVisibilityEvent.visible) {
					impl.vars["vis.lv"] = BOOMR.now() - BOOMR.lastVisibilityEvent.visible;
				}
				if (BOOMR.lastVisibilityEvent.hidden) {
					impl.vars["vis.lh"] = BOOMR.now() - BOOMR.lastVisibilityEvent.hidden;
				}
			}

			impl.vars["ua.plt"] = navigator.platform;
			impl.vars["ua.vnd"] = navigator.vendor;

			if (this.pageId) {
				impl.vars.pid = this.pageId;
			}

			if (w !== window) {
				impl.vars["if"] = "";
			}

			for (k in impl.errors) {
				if (impl.errors.hasOwnProperty(k)) {
					errors.push(k + (impl.errors[k] > 1 ? " (*" + impl.errors[k] + ")" : ""));
				}
			}

			if (errors.length > 0) {
				impl.vars.errors = errors.join("\n");
			}

			impl.errors = {};

			// If we reach here, all plugins have completed
			impl.fireEvent("before_beacon", impl.vars);

			// Use the override URL if given
			impl.beacon_url = impl.beacon_url_override || impl.beacon_url;

			// Don't send a beacon if no beacon_url has been set
			// you would do this if you want to do some fancy beacon handling
			// in the `before_beacon` event instead of a simple GET request
			BOOMR.debug("Ready to send beacon: " + BOOMR.utils.objectToString(impl.vars));
			if (!impl.beacon_url) {
				BOOMR.debug("No beacon URL, so skipping.");
				return true;
			}

			//
			// Try to send an IMG beacon if possible (which is the most compatible),
			// otherwise send an XHR beacon if the  URL length is longer than 2,000 bytes.
			//

			// clone the vars object for two reasons: first, so all listeners of
			// onbeacon get an exact clone (in case listeners are doing
			// BOOMR.removeVar), and second, to help build our priority list of vars.
			for (k in impl.vars) {
				if (impl.vars.hasOwnProperty(k)) {
					varsSent[k] = impl.vars[k];
					varsToSend[k] = impl.vars[k];
				}
			}

			// get high- and low-priority variables first, which remove any of
			// those vars from varsToSend
			urlFirst = this.getVarsOfPriority(varsToSend, -1);
			urlLast  = this.getVarsOfPriority(varsToSend, 1);

			// merge the 3 lists
			params = urlFirst.concat(this.getVarsOfPriority(varsToSend, 0), urlLast);
			paramsJoined = params.join("&");

			// if there are already url parameters in the beacon url,
			// change the first parameter prefix for the boomerang url parameters to &
			url = impl.beacon_url + ((impl.beacon_url.indexOf("?") > -1) ? "&" : "?") + paramsJoined;

			if (impl.beacon_type === "POST" || url.length > BOOMR.constants.MAX_GET_LENGTH) {
				// switch to a XHR beacon if the the user has specified a POST OR GET length is too long
				useImg = false;
			}

			BOOMR.removeVar("qt");

			// If we reach here, we've transferred all vars to the beacon URL.
			// The only thing that can stop it now is if we're rate limited
			impl.fireEvent("onbeacon", varsSent);

			// keep track of page load beacons
			if (!impl.hasSentPageLoadBeacon && isPageLoad) {
				impl.hasSentPageLoadBeacon = true;

				// let this beacon go out first
				BOOMR.setImmediate(function() {
					impl.fireEvent("page_load_beacon", varsSent);
				});
			}

			if (params.length === 0) {
				// do not make the request if there is no data
				return this;
			}

			if (!BOOMR.orig_XMLHttpRequest && (!BOOMR.window || !BOOMR.window.XMLHttpRequest)) {
				// if we don't have XHR available, force an image beacon and hope
				// for the best
				useImg = true;
			}

			if (useImg) {
				// just in case Image isn't a valid constructor
				try {
					img = new Image();
				}
				catch (e) {
					BOOMR.debug("Image is not a constructor, not sending a beacon");
					return false;
				}

				img.src = url;

				if (impl.secondary_beacons) {
					for (k = 0; k < impl.secondary_beacons.length; k++) {
						url = impl.secondary_beacons[k] + "?" + paramsJoined;

						img = new Image();
						img.src = url;
					}
				}
			}
			else {
				// Send a form-encoded XHR POST beacon
				xhr = new (BOOMR.window.orig_XMLHttpRequest || BOOMR.orig_XMLHttpRequest || BOOMR.window.XMLHttpRequest)();
				try {
					this.sendXhrPostBeacon(xhr, paramsJoined);
				}
				catch (e) {
					// if we had an exception with the window XHR object, try our IFRAME XHR
					xhr = new BOOMR.boomerang_frame.XMLHttpRequest();
					this.sendXhrPostBeacon(xhr, paramsJoined);
				}
			}

			return true;
		},

		/**
		 * Determines whether or not a Page Load beacon has been sent.
		 *
		 * @returns {boolean} True if a Page Load beacon has been sent.
		 */
		hasSentPageLoadBeacon: function() {
			return impl.hasSentPageLoadBeacon;
		},

		/**
		 * Sends an XHR beacon
		 *
		 * @param {object} xhr XMLHttpRequest object
		 * @param {object} [paramsJoined] XMLHttpRequest.send() argument
		 */
		sendXhrPostBeacon: function(xhr, paramsJoined) {
			xhr.open("POST", impl.beacon_url);

			xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");

			if (typeof impl.beacon_auth_token !== "undefined") {
				if (typeof impl.beacon_auth_key === "undefined") {
					impl.beacon_auth_key = "Authorization";
				}

				xhr.setRequestHeader(impl.beacon_auth_key, impl.beacon_auth_token);
			}

			xhr.send(paramsJoined);
		},

		/**
		 * Gets all variables of the specified priority
		 *
		 * @param {object} vars Variables (will be modified for pri -1 and 1)
		 * @param {number} pri Priority (-1, 0, or 1)
		 *
		 * @return {string[]} Array of URI-encoded vars
		 */
		getVarsOfPriority: function(vars, pri) {
			var name, url = [];

			if (pri !== 0) {
				// if we were given a priority, iterate over that list
				for (name in impl.varPriority[pri]) {
					if (impl.varPriority[pri].hasOwnProperty(name)) {
						// if this var is set, add it to our URL array
						if (vars.hasOwnProperty(name)) {
							url.push(this.getUriEncodedVar(name, vars[name]));

							// remove this name from vars so it isn't also added
							// to the non-prioritized list when pri=0 is called
							delete vars[name];
						}
					}
				}
			}
			else {
				// if we weren't given a priority, iterate over all of the vars
				// that are left (from not being removed via earlier pri -1 or 1)
				for (name in vars) {
					if (vars.hasOwnProperty(name)) {
						url.push(this.getUriEncodedVar(name, vars[name]));
					}
				}
			}

			return url;
		},

		/**
		 * Gets a URI-encoded name/value pair.
		 *
		 * @param {string} name Name
		 * @param {string} value Value
		 *
		 * @returns {string} URI-encoded string
		 */
		getUriEncodedVar: function(name, value) {
			var result = encodeURIComponent(name) +
				"=" +
				(
					value === undefined || value === null ?
						"" :
						encodeURIComponent(value)
				);

			return result;
		},

		/**
		 * Gets the latest ResourceTiming entry for the specified URL
		 * Default sort order is chronological startTime
		 * @param {string} url Resource URL
		 * @param {function} [sort] Sort the entries before returning the last one
		 * @returns {PerformanceEntry|undefined} Entry, or undefined if ResourceTiming is not
		 *          supported or if the entry doesn't exist
		 */
		getResourceTiming: function(url, sort) {
			var entries;

			try {
				if (BOOMR.getPerformance() &&
				    typeof BOOMR.getPerformance().getEntriesByName === "function") {
					entries = BOOMR.getPerformance().getEntriesByName(url);
					if (entries && entries.length) {
						if (typeof sort === "function") {
							entries.sort(sort);
						}
						return entries[entries.length - 1];
					}
				}
			}
			catch (ignore) {
				// empty
			}
		}

	};

	delete BOOMR_start;

	if (typeof BOOMR_lstart === "number") {
		boomr.t_lstart = BOOMR_lstart;
		delete BOOMR_lstart;
	}
	else if (typeof BOOMR.window.BOOMR_lstart === "number") {
		boomr.t_lstart = BOOMR.window.BOOMR_lstart;
	}

	if (typeof BOOMR.window.BOOMR_onload === "number") {
		boomr.t_onload = BOOMR.window.BOOMR_onload;
	}

	(function() {
		var make_logger;

		if (typeof console === "object" && console.log !== undefined) {
			boomr.log = function(m, l, s) { console.log(s + ": [" + l + "] " + m); };
		}

		make_logger = function(l) {
			return function(m, s) {
				this.log(m, l, "boomerang" + (s ? "." + s : ""));
				return this;
			};
		};

		boomr.debug = make_logger("debug");
		boomr.info = make_logger("info");
		boomr.warn = make_logger("warn");
		boomr.error = make_logger("error");
	}());

	// If the browser supports performance.now(), swap that in for BOOMR.now
	try {
		var p = boomr.getPerformance();
		if (p &&
		    typeof p.now === "function" &&
		    /\[native code\]/.test(String(p.now)) &&		// #545 handle bogus performance.now from broken shims
		    p.timing &&
		    p.timing.navigationStart) {
			boomr.now = function() {
				return Math.round(p.now() + p.timing.navigationStart);
			};
		}
	}
	catch (ignore) {
		// empty
	}

	(function() {
		var ident;
		for (ident in boomr) {
			if (boomr.hasOwnProperty(ident)) {
				BOOMR[ident] = boomr[ident];
			}
		}
		if (!BOOMR.xhr_excludes) {
			//! URLs to exclude from automatic XHR instrumentation
			BOOMR.xhr_excludes = {};
		}
	}());

	dispatchEvent("onBoomerangLoaded", { "BOOMR": BOOMR }, true);

}(window));

// end of boomerang beaconing section

/*
 * Copyright (c) 2011, Yahoo! Inc.  All rights reserved.
 * Copyright (c) 2012, Log-Normal, Inc.  All rights reserved.
 * Copyrights licensed under the BSD License. See the accompanying LICENSE.txt file for terms.
 */

// This is the Round Trip Time plugin.  Abbreviated to RT
// the parameter is the window
(function(w) {

/*eslint no-underscore-dangle:0*/

	var d, impl,
	    COOKIE_EXP = 60 * 60 * 24 * 7;


	BOOMR = BOOMR || {};
	BOOMR.plugins = BOOMR.plugins || {};
	if (BOOMR.plugins.RT) {
		return;
	}

	// private object
	impl = {
		onloadfired: false,	//! Set when the page_ready event fires
					//  Use this to determine if unload fires before onload
		unloadfired: false,	//! Set when the first unload event fires
					//  Use this to make sure we don't beacon twice for beforeunload and unload
		visiblefired: false,	//! Set when page becomes visible (Chrome/IE)
					//  Use this to determine if user bailed without opening the tab
		initialized: false,	//! Set when init has completed to prevent double initialization
		complete: false,	//! Set when this plugin has completed
		autorun: true,
		timers: {},		//! Custom timers that the developer can use
					// Format for each timer is { start: XXX, end: YYY, delta: YYY-XXX }
		cookie: "RT",		//! Name of the cookie that stores the start time and referrer
		cookie_exp: COOKIE_EXP,	//! Cookie expiry in seconds (7 days)
		strict_referrer: true,	//! By default, don't beacon if referrers don't match.
					// If set to false, beacon both referrer values and let
					// the back end decide

		navigationType: 0,	// Navigation Type from the NavTiming API.  We mainly care if this was BACK_FORWARD
					// since cookie time will be incorrect in that case
		navigationStart: undefined,
		responseStart: undefined,
		t_start: undefined,	// t_start that came off the cookie
		cached_t_start: undefined,	// cached value of t_start once we know its real value
		cached_xhr_start: undefined,	// cached value of xhr t_start once we know its real value
		t_fb_approx: undefined,	// approximate first byte time for browsers that don't support navtiming
		r: undefined,		// referrer from the cookie
		r2: undefined,		// referrer from document.referer

		// These timers are added directly as beacon variables
		basic_timers: { t_done: 1, t_resp: 1, t_page: 1},

		// Vars that were added to the beacon that we can remove after beaconing
		addedVars: [],

		/**
		 * Merge new cookie `params` onto current cookie, and set `timer` param on cookie to current timestamp
		 * @param params object containing keys & values to merge onto current cookie.  A value of `undefined`
		 *		 will remove the key from the cookie
		 * @param timer  string key name that will be set to the current timestamp on the cookie
		 *
		 * @returns true if the cookie was updated, false if the cookie could not be set for any reason
		 */
		updateCookie: function(params, timer) {
			var t_end, t_start, subcookies, k;

			// Disable use of RT cookie by setting its name to a falsy value
			if (!this.cookie) {
				return false;
			}

			subcookies = BOOMR.utils.getSubCookies(BOOMR.utils.getCookie(this.cookie)) || {};

			if (typeof params === "object") {
				for (k in params) {
					if (params.hasOwnProperty(k)) {
						if (params[k] === undefined) {
							if (subcookies.hasOwnProperty(k)) {
								delete subcookies[k];
							}
						}
						else {
							if (k === "nu" || k === "r") {
								params[k] = BOOMR.utils.hashQueryString(params[k], true);
							}

							subcookies[k] = params[k];
						}
					}
				}
			}

			t_start = BOOMR.now();

			if (timer) {
				subcookies[timer] = t_start;
				impl.lastActionTime = t_start;
			}

			BOOMR.debug("Setting cookie (timer=" + timer + ")\n" + BOOMR.utils.objectToString(subcookies), "rt");
			if (!BOOMR.utils.setCookie(this.cookie, subcookies, this.cookie_exp)) {
				BOOMR.error("cannot set start cookie", "rt");
				return false;
			}

			t_end = BOOMR.now();
			if (t_end - t_start > 50) {
				// It took > 50ms to set the cookie
				// The user Most likely has cookie prompting turned on so
				// t_start won't be the actual unload time
				// We bail at this point since we can't reliably tell t_done
				BOOMR.utils.removeCookie(this.cookie);

				// at some point we may want to log this info on the server side
				BOOMR.error("took more than 50ms to set cookie... aborting: " +
					t_start + " -> " + t_end, "rt");
			}

			return true;
		},

		/**
		 * Read initial values from cookie and clear out cookie values it cares about after reading.
		 * This makes sure that other pages (eg: loaded in new tabs) do not get an invalid cookie time.
		 * This method should only be called from init, and may be called more than once.
		 *
		 * Request start time is the greater of last page beforeunload or last click time
		 * If start time came from a click, we check that the clicked URL matches the current URL
		 * If it came from a beforeunload, we check that cookie referrer matches document.referrer
		 *
		 * If we had a pageHide time or unload time, we use that as a proxy for first byte on non-navtiming
		 * browsers.
		 */
		initFromCookie: function() {
			var url, subcookies;
			subcookies = BOOMR.utils.getSubCookies(BOOMR.utils.getCookie(this.cookie));

			if (!subcookies) {
				return;
			}

			subcookies.s = Math.max(+subcookies.ld || 0, Math.max(+subcookies.ul || 0, +subcookies.cl || 0));

			BOOMR.debug("Read from cookie " + BOOMR.utils.objectToString(subcookies), "rt");

			// If we have a start time, and either a referrer, or a clicked on URL,
			// we check if the start time is usable
			if (subcookies.s && (subcookies.r || subcookies.nu)) {
				this.r = subcookies.r;
				url = BOOMR.utils.hashQueryString(d.URL, true);

				// Either the URL of the page setting the cookie needs to match document.referrer
				BOOMR.debug(this.r + " =?= " + this.r2, "rt");

				// Or the start timer was no more than 15ms after a click or form submit
				// and the URL clicked or submitted to matches the current page's URL
				// (note the start timer may be later than click if both click and beforeunload fired
				// on the previous page)
				BOOMR.debug(subcookies.s + " <? " + (+subcookies.cl + 15), "rt");
				BOOMR.debug(subcookies.nu + " =?= " + url, "rt");

				if (!this.strict_referrer ||
					(subcookies.nu && subcookies.nu === url && subcookies.s < +subcookies.cl + 15) ||
					(subcookies.s === +subcookies.ul && this.r === this.r2)
				) {
					this.t_start = subcookies.s;

					// additionally, if we have a pagehide, or unload event, that's a proxy
					// for the first byte of the current page, so use that wisely
					if (+subcookies.hd > subcookies.s) {
						this.t_fb_approx = parseInt(subcookies.hd, 10);
					}
				}
				else {
					this.t_start = this.t_fb_approx = undefined;
				}
			}

			// Now that we've pulled out the timers, we'll clear them so they don't pollute future calls
			this.updateCookie({
				s: undefined,	// start timer
				r: undefined,	// referrer
				nu: undefined,	// clicked url
				ul: undefined,	// onbeforeunload time
				cl: undefined,	// onclick time
				hd: undefined,	// onunload or onpagehide time
				ld: undefined,	// last load time
				rl: undefined
			});
		},

		/**
		 * Figure out how long boomerang and other URLs took to load using
		 * ResourceTiming if available, or built in timestamps.
		 */
		getBoomerangTimings: function() {
			var res, urls, url, startTime, data;

			function trimTiming(time, st) {
				// strip from microseconds to milliseconds only
				var timeMs = Math.round(time ? time : 0),
				    startTimeMs = Math.round(st ? st : 0);

				timeMs = (timeMs === 0 ? 0 : (timeMs - startTimeMs));

				return timeMs ? timeMs : "";
			}

			if (BOOMR.t_start) {
				// How long does it take Boomerang to load up and execute (fb to lb)?
				BOOMR.plugins.RT.startTimer("boomerang", BOOMR.t_start);
				BOOMR.plugins.RT.endTimer("boomerang", BOOMR.t_end);	// t_end === null defaults to current time

				// How long did it take from page request to boomerang fb?
				BOOMR.plugins.RT.endTimer("boomr_fb", BOOMR.t_start);

				if (BOOMR.t_lstart) {
					// when did the boomerang loader start loading boomerang on the page?
					BOOMR.plugins.RT.endTimer("boomr_ld", BOOMR.t_lstart);
					// What was the network latency for boomerang (request to first byte)?
					BOOMR.plugins.RT.setTimer("boomr_lat", BOOMR.t_start - BOOMR.t_lstart);
				}
			}

			// use window and not w because we want the inner iframe
			try {
				if (window &&
				    "performance" in window &&
				    window.performance &&
				    typeof window.performance.getEntriesByName === "function") {
					urls = { "rt.bmr": BOOMR.url };


					for (url in urls) {
						if (urls.hasOwnProperty(url) && urls[url]) {
							res = window.performance.getEntriesByName(urls[url]);
							if (!res || res.length === 0 || !res[0]) {
								continue;
							}

							res = res[0];

							startTime = trimTiming(res.startTime, 0);
							data = [
								startTime,
								trimTiming(res.responseEnd, startTime),
								trimTiming(res.responseStart, startTime),
								trimTiming(res.requestStart, startTime),
								trimTiming(res.connectEnd, startTime),
								trimTiming(res.secureConnectionStart, startTime),
								trimTiming(res.connectStart, startTime),
								trimTiming(res.domainLookupEnd, startTime),
								trimTiming(res.domainLookupStart, startTime),
								trimTiming(res.redirectEnd, startTime),
								trimTiming(res.redirectStart, startTime)
							].join(",").replace(/,+$/, "");

							BOOMR.addVar(url, data);
							impl.addedVars.push(url);
						}
					}
				}
			}
			catch (e) {
				BOOMR.addError(e, "rt.getBoomerangTimings");
			}
		},

		/**
		 * Check if we're in a prerender state, and if we are, set additional timers.
		 * In Chrome/IE, a prerender state is when a page is completely rendered in an in-memory buffer, before
		 * a user requests that page.  We do not beacon at this point because the user has not shown intent
		 * to view the page.  If the user opens the page, the visibility state changes to visible, and we
		 * fire the beacon at that point, including any timing details for prerendering.
		 *
		 * Sets the `t_load` timer to the actual value of page load time (request initiated by browser to onload)
		 *
		 * @returns true if this is a prerender state, false if not (or not supported)
		 */
		checkPreRender: function() {
			if (BOOMR.visibilityState() !== "prerender") {
				return false;
			}

			// This means that onload fired through a pre-render.  We'll capture this
			// time, but wait for t_done until after the page has become either visible
			// or hidden (ie, it moved out of the pre-render state)
			// http://code.google.com/chrome/whitepapers/pagevisibility.html
			// http://www.w3.org/TR/2011/WD-page-visibility-20110602/
			// http://code.google.com/chrome/whitepapers/prerender.html

			BOOMR.plugins.RT.startTimer("t_load", this.navigationStart);
			BOOMR.plugins.RT.endTimer("t_load");					// this will measure actual onload time for a prerendered page
			BOOMR.plugins.RT.startTimer("t_prerender", this.navigationStart);
			BOOMR.plugins.RT.startTimer("t_postrender");				// time from prerender to visible or hidden

			return true;
		},

		/**
		 * Initialise timers from the NavigationTiming API.  This method looks at various sources for
		 * Navigation Timing, and also patches around bugs in various browser implementations.
		 * It sets the beacon parameter `rt.start` to the source of the timer
		 */
		initFromNavTiming: function() {
			var ti, p, source;

			if (this.navigationStart) {
				return;
			}

			// Get start time from WebTiming API see:
			// https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/NavigationTiming/Overview.html
			// http://blogs.msdn.com/b/ie/archive/2010/06/28/measuring-web-page-performance.aspx
			// http://blog.chromium.org/2010/07/do-you-know-how-slow-your-web-page-is.html
			p = BOOMR.getPerformance();

			if (p && p.navigation) {
				this.navigationType = p.navigation.type;
			}

			if (p && p.timing) {
				ti = p.timing;
			}
			else if (w.chrome && w.chrome.csi && w.chrome.csi().startE) {
				// Older versions of chrome also have a timing API that's sort of documented here:
				// http://ecmanaut.blogspot.com/2010/06/google-bom-feature-ms-since-pageload.html
				// source here:
				// http://src.chromium.org/viewvc/chrome/trunk/src/chrome/renderer/loadtimes_extension_bindings.cc?view=markup
				ti = {
					navigationStart: w.chrome.csi().startE
				};
				source = "csi";
			}
			else if (w.gtbExternal && w.gtbExternal.startE()) {
				// The Google Toolbar exposes navigation start time similar to old versions of chrome
				// This would work for any browser that has the google toolbar installed
				ti = {
					navigationStart: w.gtbExternal.startE()
				};
				source = "gtb";
			}

			if (ti) {
				// Always use navigationStart since it falls back to fetchStart (not with redirects)
				// If not set, we leave t_start alone so that timers that depend
				// on it don't get sent back.  Never use requestStart since if
				// the first request fails and the browser retries, it will contain
				// the value for the new request.
				BOOMR.addVar("rt.start", source || "navigation");
				this.navigationStart = ti.navigationStart || ti.fetchStart || undefined;
				this.responseStart = ti.responseStart || undefined;

				// bug in Firefox 7 & 8 https://bugzilla.mozilla.org/show_bug.cgi?id=691547
				if (navigator.userAgent.match(/Firefox\/[78]\./)) {
					this.navigationStart = ti.unloadEventStart || ti.fetchStart || undefined;
				}
			}
			else {
				BOOMR.warn("This browser doesn't support the WebTiming API", "rt");
			}

			return;
		},

		/**
		 * Validate that the time we think is the load time is correct.  This can be wrong if boomerang was loaded
		 * after onload, so in that case, if navigation timing is available, we use that instead.
		 */
		validateLoadTimestamp: function(t_now, data, ename) {
			var p;

			// beacon with detailed timing information
			if (data && data.timing && data.timing.loadEventEnd) {
				return data.timing.loadEventEnd;
			}
			else if (ename === "xhr" && (!data || !BOOMR.utils.inArray(data.initiator, BOOMR.constants.BEACON_TYPE_SPAS))) {
				// if this is an XHR event, trust the input end "now" timestamp
				return t_now;
			}
			// Boomerang loaded late and...
			else if (BOOMR.loadedLate) {
				p = BOOMR.getPerformance();

				// We have navigation timing,
				if (p && p.timing) {
					// and boomerang loaded after onload fired
					if (p.timing.loadEventStart && p.timing.loadEventStart < BOOMR.t_end) {
						return p.timing.loadEventStart;
					}
				}
				// We don't have navigation timing,
				else {
					// So we'll just use the time when boomerang was added to the page
					// Assuming that this means boomerang was added in onload.  If we logged the
					// onload timestamp (via loader snippet), use that first.
					return BOOMR.t_onload || BOOMR.t_lstart || BOOMR.t_start || t_now;
				}
			}

			// default to now
			return t_now;
		},

		/**
		 * Set timers appropriate at page load time.  This method should be called from done() only when
		 * the page_ready event fires.  It sets the following timer values:
		 *		- t_resp:	time from request start to first byte
		 *		- t_page:	time from first byte to load
		 *		- t_postrender	time from prerender state to visible state
		 *		- t_prerender	time from navigation start to visible state
		 *
		 * @param ename  The Event name that initiated this control flow
		 * @param t_done The timestamp when the done() method was called
		 * @param data   Event data passed in from the caller.  For xhr beacons, this may contain detailed timing information
		 *
		 * @returns true if timers were set, false if we're in a prerender state, caller should abort on false.
		 */
		setPageLoadTimers: function(ename, t_done, data) {
			var t_resp_start, t_fetch_start, p, navSt;

			if (ename !== "xhr") {
				impl.initFromCookie();
				impl.initFromNavTiming();

				if (impl.checkPreRender()) {
					return false;
				}
			}

			if (ename === "xhr") {
				if (data.timers) {
					// If we were given a list of timers, set those first
					for (var timerName in data.timers) {
						if (data.timers.hasOwnProperty(timerName)) {
							BOOMR.plugins.RT.setTimer(timerName, data.timers[timerName]);
						}
					}
				}
				else if (data && data.timing) {
					// Use details from XHR object to figure out responce latency and page time. Use
					// responseEnd (instead of responseStart) since it's not until responseEnd
					// that the browser can consume the data, and responseEnd is the only guarateed
					// timestamp with cross-origin XHRs if ResourceTiming is enabled.

					t_fetch_start = data.timing.fetchStart;

					if (typeof t_fetch_start === "undefined" || data.timing.responseEnd >= t_fetch_start) {
						t_resp_start = data.timing.responseEnd;
					}
				}
			}
			else if (impl.responseStart) {
				// Use NavTiming API to figure out resp latency and page time
				// t_resp will use the cookie if available or fallback to NavTiming

				// only use if the time looks legit (after navigationStart)
				if (impl.responseStart >= impl.cached_t_start) {
					t_resp_start = impl.responseStart;
				}
			}
			else if (impl.timers.hasOwnProperty("t_page")) {
				// If the dev has already started t_page timer, we can end it now as well
				BOOMR.plugins.RT.endTimer("t_page");
			}
			else if (impl.t_fb_approx) {
				// If we have an approximate first byte time from the cookie, use it
				t_resp_start = impl.t_fb_approx;
			}

			if (t_resp_start) {
				// if we have a fetch start as well, set the specific timestamps instead of from rt.start
				if (t_fetch_start) {
					BOOMR.plugins.RT.setTimer("t_resp", t_fetch_start, t_resp_start);
				}
				else {
					BOOMR.plugins.RT.endTimer("t_resp", t_resp_start);
				}

				// t_load is the actual time load completed if using prerender
				if (ename === "load" && impl.timers.t_load) {
					BOOMR.plugins.RT.setTimer("t_page", impl.timers.t_load.end - t_resp_start);
				}
				else {
					//
					// Ensure that t_done is after t_resp_start.  If not, set a var so we
					// knew there was an inversion.  This can happen due to bugs in NavTiming
					// clients, where responseEnd happens after all other NavTiming events.
					//
					if (t_done < t_resp_start) {
						BOOMR.addVar("t_page.inv", 1);
					}
					else {
						BOOMR.plugins.RT.setTimer("t_page", t_done - t_resp_start);
					}
				}
			}

			// If a prerender timer was started, we can end it now as well
			if (ename === "load" && impl.timers.hasOwnProperty("t_postrender")) {
				BOOMR.plugins.RT.endTimer("t_postrender");
				BOOMR.plugins.RT.endTimer("t_prerender");
			}

			return true;
		},

		/**
		 * Writes a bunch of timestamps onto the beacon that help in request tracing on the server
		 * - rt.tstart: The value of t_start that we determined was appropriate
		 * - rt.nstart: The value of navigationStart if different from rt.tstart
		 * - rt.cstart: The value of t_start from the cookie if different from rt.tstart
		 * - rt.bstart: The timestamp when boomerang started
		 * - rt.blstart:The timestamp when boomerang was added to the host page
		 * - rt.end:    The timestamp when the t_done timer ended
		 *
		 * @param t_start The value of t_start that we plan to use
		 */
		setSupportingTimestamps: function(t_start) {
			if (t_start) {
				BOOMR.addVar("rt.tstart", t_start);
			}
			if (typeof impl.navigationStart === "number" && impl.navigationStart !== t_start) {
				BOOMR.addVar("rt.nstart", impl.navigationStart);
			}
			if (typeof impl.t_start === "number" && impl.t_start !== t_start) {
				BOOMR.addVar("rt.cstart", impl.t_start);
			}
			BOOMR.addVar("rt.bstart", BOOMR.t_start);
			if (BOOMR.t_lstart) {
				BOOMR.addVar("rt.blstart", BOOMR.t_lstart);
			}
			BOOMR.addVar("rt.end", impl.timers.t_done.end);	// don't just use t_done because dev may have called endTimer before we did
		},

		/**
		 * Determines the best value to use for t_start.
		 * If called from an xhr call, then use the start time for that call
		 * Else, If we have navigation timing, use that
		 * Else, If we have a cookie time, and this isn't the result of a BACK button, use the cookie time
		 * Else, if we have a cached timestamp from an earlier call, use that
		 * Else, give up
		 *
		 * @param ename	The event name that resulted in this call. Special consideration for "xhr"
		 * @param data  Data passed in from the event caller. If the event name is "xhr",
		 *              this should contain the page group name for the xhr call in an attribute called `name`
		 *		and optionally, detailed timing information in a sub-object called `timing`
		 *              and resource information in a sub-object called `resource`
		 *
		 * @returns the determined value of t_start or undefined if unknown
		 */
		determineTStart: function(ename, data) {
			var t_start;
			if (ename === "xhr") {
				if (data && data.name && impl.timers[data.name]) {
					// For xhr timers, t_start is stored in impl.timers.xhr_{page group name}
					// and xhr.pg is set to {page group name}
					t_start = impl.timers[data.name].start;
				}
				else if (data && data.timing && data.timing.requestStart) {
					// For automatically instrumented xhr timers, we have detailed timing information
					t_start = data.timing.requestStart;
				}

				if (typeof t_start === "undefined" && data && BOOMR.utils.inArray(data.initiator, BOOMR.constants.BEACON_TYPE_SPAS)) {
					// if we don't have a start time, set to none so it can possibly be fixed up
					BOOMR.addVar("rt.start", "none");
				}
				else {
					BOOMR.addVar("rt.start", "manual");
				}

				impl.cached_xhr_start = t_start;
			}
			else {
				if (impl.navigationStart) {
					t_start = impl.navigationStart;
				}
				else if (impl.t_start && impl.navigationType !== 2) {
					t_start = impl.t_start;			// 2 is TYPE_BACK_FORWARD but the constant may not be defined across browsers
					BOOMR.addVar("rt.start", "cookie");	// if the user hit the back button, referrer will match, and cookie will match
				}						// but will have time of previous page start, so t_done will be wrong
				else if (impl.cached_t_start) {
					t_start = impl.cached_t_start;
				}
				else {
					BOOMR.addVar("rt.start", "none");
					t_start = undefined;			// force all timers to NaN state
				}

				impl.cached_t_start = t_start;
			}

			BOOMR.debug("Got start time: " + t_start, "rt");
			return t_start;
		},

		page_ready: function() {
			// we need onloadfired because it's possible to reset "impl.complete"
			// if you're measuring multiple xhr loads, but not possible to reset
			// impl.onloadfired
			this.onloadfired = true;
		},

		check_visibility: function() {
			// we care if the page became visible at some point
			if (BOOMR.visibilityState() === "visible") {
				impl.visiblefired = true;
			}
		},

		prerenderToVisible: function() {
			if (impl.onloadfired &&
			    impl.autorun) {
				BOOMR.debug("Transitioned from prerender to " + BOOMR.visibilityState(), "rt");

				// note that we transitioned from prerender on the beacon for debugging
				BOOMR.addVar("vis.pre", "1");

				// send a beacon
				BOOMR.plugins.RT.done(null, "visible");
			}
		},

		page_unload: function(edata) {
			BOOMR.debug("Unload called when unloadfired = " + this.unloadfired, "rt");
			if (!this.unloadfired) {
				// run done on abort or on page_unload to measure session length
				BOOMR.plugins.RT.done(edata, "unload");
			}

			// set cookie for next page
			// We use document.URL instead of location.href because of a bug in safari 4
			// where location.href is URL decoded
			this.updateCookie({ "r": d.URL }, edata.type === "beforeunload" ? "ul" : "hd");


			this.unloadfired = true;
		},

		_iterable_click: function(name, element, etarget, value_cb) {
			var value;
			if (!etarget) {
				return;
			}
			BOOMR.debug(name + " called with " + etarget.nodeName, "rt");
			while (etarget && etarget.nodeName.toUpperCase() !== element) {
				etarget = etarget.parentNode;
			}
			if (etarget && etarget.nodeName.toUpperCase() === element) {
				BOOMR.debug("passing through", "rt");

				// user event, they may be going to another page
				// if this page is being opened in a different tab, then
				// our unload handler won't fire, so we need to set our
				// cookie on click or submit
				value = value_cb(etarget);
				this.updateCookie({ "nu": value }, "cl");
				BOOMR.addVar("nu", BOOMR.utils.cleanupURL(value));
				impl.addedVars.push("nu");
			}
		},

		onclick: function(etarget) {
			impl._iterable_click("Click", "A", etarget, function(t) { return t.href; });
		},

		onerror: function() {
			if (this.onloadfired) {
				// allow error beacons to send outside of page load without adding
				// RT variables to the beacon
				impl.complete = true;
			}
		},

		onsubmit: function(etarget) {
			impl._iterable_click("Submit", "FORM", etarget, function(t) {
				var v = t.getAttribute("action") || d.URL || "";
				return v.match(/\?/) ? v : v + "?";
			});
		},

		onconfig: function(config) {
			if (config.beacon_url) {
				impl.beacon_url = config.beacon_url;
			}

			if (config.RT) {
				if (config.RT.oboError && !isNaN(config.RT.oboError) && config.RT.oboError > impl.oboError) {
					impl.oboError = config.RT.oboError;
				}

				if (config.RT.loadTime && !isNaN(config.RT.loadTime) && config.RT.loadTime > impl.loadTime) {
					impl.loadTime = config.RT.loadTime;

					if (!isNaN(impl.timers.t_done.delta)) {
						impl.loadTime += impl.timers.t_done.delta;
					}
				}
			}
		},

		domloaded: function() {
			BOOMR.plugins.RT.endTimer("t_domloaded");
		},

		clear: function() {
			BOOMR.removeVar("rt.start");
			if (impl.addedVars && impl.addedVars.length > 0) {
				BOOMR.removeVar(impl.addedVars);
				impl.addedVars = [];
			}
		},

		spaNavigation: function() {
			// a SPA navigation occured, force onloadfired to true
			impl.onloadfired = true;
		}
	};

	BOOMR.plugins.RT = {
		// Methods

		init: function(config) {
			BOOMR.debug("init RT", "rt");
			if (w !== BOOMR.window) {
				w = BOOMR.window;
			}

			// protect against undefined window/document
			if (!w || !w.document) {
				return;
			}

			d = w.document;

			BOOMR.utils.pluginConfig(impl, config, "RT",
						["cookie", "cookie_exp", "session_exp", "strict_referrer"]);

			if (config && typeof config.autorun !== "undefined") {
				impl.autorun = config.autorun;
			}

			// A beacon may be fired automatically on page load or if the page dev fires
			// it manually with their own timers.  It may not always contain a referrer
			// (eg: XHR calls).  We set default values for these cases.
			// This is done before reading from the cookie because the cookie overwrites
			// impl.r
			if (typeof d !== "undefined") {
				impl.r = impl.r2 = BOOMR.utils.hashQueryString(d.referrer, true);
			}

			// Now pull out start time information and session information from the cookie
			// We'll do this every time init is called, and every time we call it, it will
			// overwrite values already set (provided there are values to read out)
			impl.initFromCookie();

			// only initialize once.  we still collect config and check/set cookies
			// every time init is called, but we attach event handlers only once
			if (impl.initialized) {
				return this;
			}

			impl.complete = false;
			impl.timers = {};

			impl.check_visibility();

			BOOMR.subscribe("page_ready", impl.page_ready, null, impl);
			BOOMR.subscribe("visibility_changed", impl.check_visibility, null, impl);
			BOOMR.subscribe("prerender_to_visible", impl.prerenderToVisible, null, impl);
			BOOMR.subscribe("page_ready", this.done, "load", this);
			BOOMR.subscribe("xhr_load", this.done, "xhr", this);
			BOOMR.subscribe("dom_loaded", impl.domloaded, null, impl);
			BOOMR.subscribe("page_unload", impl.page_unload, null, impl);
			BOOMR.subscribe("click", impl.onclick, null, impl);
			BOOMR.subscribe("form_submit", impl.onsubmit, null, impl);
			BOOMR.subscribe("before_beacon", this.addTimersToBeacon, "beacon", this);
			BOOMR.subscribe("onbeacon", impl.clear, null, impl);
			BOOMR.subscribe("onerror", impl.onerror, null, impl);
			BOOMR.subscribe("onconfig", impl.onconfig, null, impl);
			BOOMR.subscribe("spa_navigation", impl.spaNavigation, null, impl);

			// Override any getBeaconURL method to make sure we return the one from the
			// cookie and not the one hardcoded into boomerang
			BOOMR.getBeaconURL = function() { return impl.beacon_url; };

			impl.initialized = true;
			return this;
		},

		startTimer: function(timer_name, time_value) {
			if (timer_name) {
				if (timer_name === "t_page") {
					this.endTimer("t_resp", time_value);
				}
				impl.timers[timer_name] = {start: (typeof time_value === "number" ? time_value : BOOMR.now())};
			}

			return this;
		},

		endTimer: function(timer_name, time_value) {
			if (timer_name) {
				impl.timers[timer_name] = impl.timers[timer_name] || {};
				if (impl.timers[timer_name].end === undefined) {
					impl.timers[timer_name].end =
							(typeof time_value === "number" ? time_value : BOOMR.now());
				}
			}

			return this;
		},

		/**
		 * Clears (removes) the specified timer
		 *
		 * @param {string} timer_name Timer name
		 */
		clearTimer: function(timer_name) {
			if (timer_name) {
				delete impl.timers[timer_name];
			}

			return this;
		},

		setTimer: function(timer_name, time_delta_or_start, timer_end) {
			if (timer_name) {
				if (typeof timer_end !== "undefined") {
					// in this case, we were given three args, the name, start, and end,
					// so time_delta_or_start is the start time
					impl.timers[timer_name] = {
						start: time_delta_or_start,
						end: timer_end,
						delta: timer_end - time_delta_or_start
					};
				}
				else {
					// in this case, we were just given two args, the name and delta
					impl.timers[timer_name] = { delta: time_delta_or_start };
				}
			}

			return this;
		},

		addTimersToBeacon: function(vars, source) {
			var t_name, timer,
			    t_other = [];

			for (t_name in impl.timers) {
				if (impl.timers.hasOwnProperty(t_name)) {
					timer = impl.timers[t_name];

					// if delta is a number, then it was set using setTimer
					// if not, then we have to calculate it using start & end
					if (typeof timer.delta !== "number") {
						if (typeof timer.start !== "number") {
							timer.start = source === "xhr" ? impl.cached_xhr_start : impl.cached_t_start;
						}
						timer.delta = timer.end - timer.start;
					}

					// If the caller did not set a start time, and if there was no start cookie
					// Or if there was no end time for this timer,
					// then timer.delta will be NaN, in which case we discard it.
					if (isNaN(timer.delta)) {
						continue;
					}

					if (impl.basic_timers.hasOwnProperty(t_name)) {
						BOOMR.addVar(t_name, timer.delta);
						impl.addedVars.push(t_name);
					}
					else {
						t_other.push(t_name + "|" + timer.delta);
					}
				}
			}

			if (t_other.length) {
				BOOMR.addVar("t_other", t_other.join(","));
				impl.addedVars.push("t_other");
			}

			if (source === "beacon") {
				impl.timers = {};
				impl.complete = false;	// reset this state for the next call
			}
		},

		// Called when the page has reached a "usable" state.  This may be when the
		// onload event fires, or it could be at some other moment during/after page
		// load when the page is usable by the user
		done: function(edata, ename) {
			BOOMR.debug("Called done: " + ename, "rt");

			var t_start, t_done, t_now = BOOMR.now(),
			    subresource = false;

			// We may have to rerun if this was a pre-rendered page, so set complete to false, and only set to true when we're done
			impl.complete = false;

			t_done = impl.validateLoadTimestamp(t_now, edata, ename);

			if (ename === "load" || ename === "visible" || ename === "xhr") {
				if (!impl.setPageLoadTimers(ename, t_done, edata)) {
					return this;
				}
			}

			if (ename === "load" ||
			    ename === "visible" ||
				(ename === "xhr" && edata && edata.initiator === "spa_hard")) {
				// Only add Boomerang timings to page load and SPA beacons
				impl.getBoomerangTimings();
			}

			t_start = impl.determineTStart(ename, edata);

			// If the dev has already called endTimer, then this call will do nothing
			// else, it will stop the page load timer
			this.endTimer("t_done", t_done);

			// For XHR events, ensure t_done is set with the proper start, end, and
			// delta timestamps.  Until Issue #195 is fixed, if this XHR is firing
			// a beacon very quickly after a previous XHR, the previous XHR might
			// not yet have had time to fire a beacon and clear its own t_done,
			// so the preceeding endTimer() wouldn't have set this XHR's timestamps.
			if (edata && edata.initiator === "xhr") {
				this.setTimer("t_done", edata.timing.requestStart, edata.timing.loadEventEnd);
			}

			// make sure old variables don't stick around
			BOOMR.removeVar(
				"t_done", "t_page", "t_resp", "t_postrender", "t_prerender", "t_load", "t_other",
				"rt.tstart", "rt.nstart", "rt.cstart", "rt.bstart", "rt.end", "rt.subres", "rt.abld",
				"http.errno", "http.method", "xhr.sync"
			);

			impl.setSupportingTimestamps(t_start);

			this.addTimersToBeacon(null, ename);

			BOOMR.setReferrer(impl.r, impl.r2);

			if (ename === "xhr" && edata) {
				if (edata && edata.data) {
					edata = edata.data;
				}
			}

			if (ename === "xhr" && edata) {
				subresource = edata.subresource;

				if (edata.url) {
					BOOMR.addVar("u", BOOMR.utils.cleanupURL(edata.url.replace(/#.*/, "")));
					impl.addedVars.push("u");
				}

				if (edata.status && (edata.status < -1 || edata.status >= 400)) {
					BOOMR.addVar("http.errno", edata.status);
				}

				if (edata.method && edata.method !== "GET") {
					BOOMR.addVar("http.method", edata.method);
				}

				if (edata.headers) {
					BOOMR.addVar("http.hdr", edata.headers);
				}

				if (edata.synchronous) {
					BOOMR.addVar("xhr.sync", 1);
				}

				if (edata.initiator) {
					BOOMR.addVar("http.initiator", edata.initiator);
				}

				impl.addedVars.push("http.errno", "http.method", "http.hdr", "xhr.sync", "http.initiator");
			}

			// This is an explicit subresource
			if (subresource && subresource !== "passive") {
				BOOMR.addVar("rt.subres", 1);
				impl.addedVars.push("rt.subres");
			}

			impl.updateCookie();

			if (ename === "unload") {
				BOOMR.addVar("rt.quit", "");

				if (!impl.onloadfired) {
					BOOMR.addVar("rt.abld", "");
				}

				if (!impl.visiblefired) {
					BOOMR.addVar("rt.ntvu", "");
				}
			}

			impl.complete = true;

			BOOMR.sendBeacon(impl.beacon_url);

			return this;
		},

		is_complete: function() { return impl.complete; },

		/**
		 * @desc
		 * Publicly accessible function to updating implementation private data of the RT plugin on the RT cookie
		 */
		updateCookie: function() {
			impl.updateCookie();
		},

		navigationStart: function() {
			if (!impl.navigationStart) {
				impl.initFromNavTiming();
			}
			return impl.navigationStart;
		}
	};

}(window));
// End of RT plugin

/*
 * Copyright (c), Buddy Brewer.
 */

/**
\file navtiming.js
Plugin to collect metrics from the W3C Navigation Timing API. For more information about Navigation Timing,
see: http://www.w3.org/TR/navigation-timing/
*/

(function() {

	// First make sure BOOMR is actually defined.  It's possible that your plugin is loaded before boomerang, in which case
	// you'll need this.
	BOOMR = BOOMR || {};
	BOOMR.plugins = BOOMR.plugins || {};
	if (BOOMR.plugins.NavigationTiming) {
		return;
	}

	// A private object to encapsulate all your implementation details
	var impl = {
		complete: false,
		sendBeacon: function() {
			this.complete = true;
			BOOMR.sendBeacon();
		},
		xhr_done: function(edata) {
			var p;

			if (edata && edata.initiator === "spa_hard") {
				// Single Page App - Hard refresh: Send page's NavigationTiming data, if
				// available.
				impl.done(edata);
				return;
			}
			else if (edata && edata.initiator === "spa") {
				// Single Page App - Soft refresh: The original hard navigation is no longer
				// relevant for this soft refresh, nor is the "URL" for this page, so don't
				// add NavigationTiming or ResourceTiming metrics.
				impl.sendBeacon();
				return;
			}

			var w = BOOMR.window, res, data = {}, k;

			if (!edata) {
				return;
			}

			if (edata.data) {
				edata = edata.data;
			}

			p = BOOMR.getPerformance();

			// if we previous saved the correct ResourceTiming entry, use it
			if (p && edata.restiming) {
				data = {
					nt_red_st: edata.restiming.redirectStart,
					nt_red_end: edata.restiming.redirectEnd,
					nt_fet_st: edata.restiming.fetchStart,
					nt_dns_st: edata.restiming.domainLookupStart,
					nt_dns_end: edata.restiming.domainLookupEnd,
					nt_con_st: edata.restiming.connectStart,
					nt_con_end: edata.restiming.connectEnd,
					nt_req_st: edata.restiming.requestStart,
					nt_res_st: edata.restiming.responseStart,
					nt_res_end: edata.restiming.responseEnd
				};

				if (edata.restiming.secureConnectionStart) {
					// secureConnectionStart is OPTIONAL in the spec
					data.nt_ssl_st = edata.restiming.secureConnectionStart;
				}

				for (k in data) {
					if (data.hasOwnProperty(k) && data[k]) {
						data[k] += p.timing.navigationStart;

						// don't need to send microseconds
						data[k] = Math.floor(data[k]);
					}
				}
			}

			if (edata.timing) {
				res = edata.timing;
				if (!data.nt_req_st) {
					// requestStart will be 0 if Timing-Allow-Origin header isn't set on the xhr response
					data.nt_req_st = res.requestStart;
				}
				if (!data.nt_res_st) {
					// responseStart will be 0 if Timing-Allow-Origin header isn't set on the xhr response
					data.nt_res_st = res.responseStart;
				}
				if (!data.nt_res_end) {
					data.nt_res_end = res.responseEnd;
				}
				data.nt_domint = res.domInteractive;
				data.nt_domcomp = res.domComplete;
				data.nt_load_st = res.loadEventEnd;
				data.nt_load_end = res.loadEventEnd;
			}

			for (k in data) {
				if (data.hasOwnProperty(k) && !data[k]) {
					delete data[k];
				}
			}

			BOOMR.addVar(data);

			try { impl.addedVars.push.apply(impl.addedVars, Object.keys(data)); }
			catch (ignore) { /* empty */ }

			impl.sendBeacon();
		},

		done: function() {
			var w = BOOMR.window, p, pn, pt, data;

			if (this.complete) {
				return this;
			}

			impl.addedVars = [];

			p = BOOMR.getPerformance();
			if (p && p.timing && p.navigation) {
				BOOMR.info("This user agent supports NavigationTiming.", "nt");
				pn = p.navigation;
				pt = p.timing;
				data = {
					nt_red_cnt: pn.redirectCount,
					nt_nav_type: pn.type,
					nt_nav_st: pt.navigationStart,
					nt_red_st: pt.redirectStart,
					nt_red_end: pt.redirectEnd,
					nt_fet_st: pt.fetchStart,
					nt_dns_st: pt.domainLookupStart,
					nt_dns_end: pt.domainLookupEnd,
					nt_con_st: pt.connectStart,
					nt_con_end: pt.connectEnd,
					nt_req_st: pt.requestStart,
					nt_res_st: pt.responseStart,
					nt_res_end: pt.responseEnd,
					nt_domloading: pt.domLoading,
					nt_domint: pt.domInteractive,
					nt_domcontloaded_st: pt.domContentLoadedEventStart,
					nt_domcontloaded_end: pt.domContentLoadedEventEnd,
					nt_domcomp: pt.domComplete,
					nt_load_st: pt.loadEventStart,
					nt_load_end: pt.loadEventEnd,
					nt_unload_st: pt.unloadEventStart,
					nt_unload_end: pt.unloadEventEnd
				};

				if (pt.secureConnectionStart) {
					// secureConnectionStart is OPTIONAL in the spec
					data.nt_ssl_st = pt.secureConnectionStart;
				}

				if (pt.msFirstPaint) {
					// msFirstPaint is IE9+ http://msdn.microsoft.com/en-us/library/ff974719
					data.nt_first_paint = pt.msFirstPaint;
				}

				BOOMR.addVar(data);

				//
				// Basic browser bug detection for known cases where NavigationTiming
				// timestamps might not be trusted.
				//
				if ((pt.requestStart && pt.navigationStart && pt.requestStart < pt.navigationStart) ||
				    (pt.responseStart && pt.navigationStart && pt.responseStart < pt.navigationStart) ||
				    (pt.responseStart && pt.fetchStart && pt.responseStart < pt.fetchStart) ||
				    (pt.navigationStart && pt.fetchStart < pt.navigationStart) ||
				    (pt.responseEnd && pt.responseEnd > BOOMR.now() + 8.64e+7)) {
					BOOMR.addVar("nt_bad", 1);
					impl.addedVars.push("nt_bad");
				}

				try { impl.addedVars.push.apply(impl.addedVars, Object.keys(data)); }
				catch (ignore) { /* empty */ }
			}

			// XXX Inconsistency warning.  msFirstPaint above is in milliseconds while
			//     firstPaintTime below is in seconds.microseconds.  The server needs to deal with this.

			// This is Chrome only, so will not overwrite nt_first_paint above
			if (w.chrome && w.chrome.loadTimes) {
				pt = w.chrome.loadTimes();
				if (pt) {
					data = {
						nt_spdy: (pt.wasFetchedViaSpdy ? 1 : 0),
						nt_cinf: pt.connectionInfo,
						nt_first_paint: pt.firstPaintTime
					};

					BOOMR.addVar(data);

					try { impl.addedVars.push.apply(impl.addedVars, Object.keys(data)); }
					catch (ignore) { /* empty */ }
				}
			}

			impl.sendBeacon();
		},

		clear: function() {
			if (impl.addedVars && impl.addedVars.length > 0) {
				BOOMR.removeVar(impl.addedVars);
				impl.addedVars = [];
			}
			this.complete = false;
		},

		prerenderToVisible: function() {
			// ensure we add our data to the beacon even if we had added it
			// during prerender (in case another beacon went out in between)
			this.complete = false;

			// add our data to the beacon
			this.done();
		}
	};

	BOOMR.plugins.NavigationTiming = {
		init: function() {
			if (!impl.initialized) {
				// we'll fire on whichever happens first
				BOOMR.subscribe("page_ready", impl.done, null, impl);
				BOOMR.subscribe("prerender_to_visible", impl.prerenderToVisible, null, impl);
				BOOMR.subscribe("xhr_load", impl.xhr_done, null, impl);
				BOOMR.subscribe("before_unload", impl.done, null, impl);
				BOOMR.subscribe("onbeacon", impl.clear, null, impl);

				impl.initialized = true;
			}
			return this;
		},

		is_complete: function() {
			return true;
		}
	};

}());

//Dependencies in sequence
//core.js

(function(bc, config){
	
	bc.store = (function(){
		'use strict';
		var store = {};
		
		store.prefix = '_bc_';
		store.prefixRE = /^_bc_/;
		
		store.support = function(storage){
			if(['localStorage', 'sessionStorage'].indexOf(storage) !== -1 && window[storage] && window[storage].getItem){
				return true;
			}
			bc.utils.log('[' + storage + '] storage is not supported by browser');
			return false;
		};
		
		store.read = function(key, options) {
			var res,
				rem = [],
				storage = window[options.storage],
				i, len, obj,
				now = (new Date().getTime());
			if(!key){
				len = storage.length;
				res = {};
				try{
					for (i = 0; i < len; i++){
						key = storage.key(i);
						obj = JSON.parse(storage.getItem(key));
						if(obj.expires && obj.expires <= now){
							rem.push(key);
						}else{
							res[key.replace(store.prefixRE, '')] = obj.data;
						}
					}
					while(rem.length){
						i = rem.pop();
						if(bc.utils.hasVal(i)){
							storage.removeItem(i);
						}
					}
				}catch(e){}
			}else{
				key = store.prefix + key;
				obj = JSON.parse(storage.getItem(key)) || {};
				if(obj.expires && obj.expires <= now){
					storage.removeItem(key);
				}else{
					res = obj.data;
				}
			}
			return res;
		};
		
		store.write = function(key, value, options){
			var storage = window[options.storage],
				obj,
				now = (new Date().getTime());
			
			key = store.prefix + key;
			
			if(typeof value === 'undefined' || value === null){
				storage.removeItem(key);
			}else{
				obj = JSON.stringify({
						data: value,
						expires: options.expires ? now + options.expires : null
					});
				try {
					storage.setItem(key, obj);
				} catch(err) {
					store.read();
					try {
						storage.setItem(key, obj);
					} catch(e) {
						bc.utils.log('WARNING: Store write operation failed for key [' + key + ']');
					}
				}
			}
		};	
		
		/**
		 * @desc Get cookie value
		 * @desc Which value to fetch from cookie depends on number of parameters passed to this function
		 * @desc arguments length < 1 or single argument 'name' as null or undefined, return all name/value stored in cookie
		 * @desc arguments length < 2, to get all properties name/value from a cookie value with a given 'name'
		 * @desc arguments length < 3, to get a value of a particular 'property' from cookie value with a given 'name'
		 * @desc Anytime 'name' is null or undefined, means return object with all the name/value from cookie
		 * @author Laxmikant Kurhe <lkurhe@walmartlabs.com>
		 * @param {String} name of cookie
		 * @param {String} separator by which property name and value are separated in single cookie value
		 * @param {String} property name to be fetched from cookie value
		 * @return {Mixed} value of cookie based on provided params
		 */
		store.getCookie = function(name, separator, property){
			var i, len,
				ckArr = document.cookie.split(';'),
				ck, ckNm, ckVal, result;
			/*if(arguments.length < 1){
				//Read value for all cookie separated by ';'
			}else if(arguments.length < 2){
				//Read complete value of cookie with given name
			}else if(arguments.length < 3){
				//Read all the properties from cookie with given name and separator
			}else{
				//Read value of a property of a cookie with given name and separator
			}*/
			
			len = ckArr.length;
			for(i = 0; i < len; i++){
				ck = ckArr[i].split('=');
				ckNm = (typeof ck[0] === 'string') ? ck[0] : null;
				if(!arguments.length){
					result = result || {};
					result[ckNm.trim()] = ckArr[i].replace(ckNm+'=', '');
				}else if(ckNm.trim() === name){
					result = ckArr[i].replace(ckNm+'=', '');
					if(arguments.length > 2){
						result = store.fetchPropVal(result, separator, property);
					}else if(arguments.length > 1){
						result = store.fetchPropVal(result, separator);
					}
					break;
				}
			}
			return result;
		};
		
		/**
		 * @desc Fetch property value from format nm1=vl1|nm2=vl2|.. '|' can b eany separator
		 * @desc Whether to read all properties or a specific one depends on number of arguments passed
		 * @desc arguments length < 3 to get all properties name/value from a 'searchStr' based on 'separator'
		 * @desc arguments length < 2, to get all peroperties name/value from a cookie value with a given 'name'
		 * @desc arguments length < 3, to get a value of a particular 'property' from 'searchStr' separated by given 'separator'
		 * @desc Anytime 'property' is null or undefined, means return object with all the name/value properties
		 * @author Laxmikant Kurhe <lkurhe@walmartlabs.com>
		 * @param {String} searchStr to be searched for
		 * @param {String} separator by which property name and value are separated
		 * @param {String} property name to be fetched from given string
		 * @return {Mixed} value based on provided params
		 */
		store.fetchPropVal = function(searchStr, separator, property){
			var prop,
				result,
				i, len;
			if(typeof searchStr !== 'string' || !searchStr || !bc.utils.hasVal(separator)){
				return searchStr;
			}
			
			/*if(arguments.length < 3){
				//Read all properties from 'str' separated by 'sep'
			}else{
				//Read all a particular property from given 'str' separated by 'sep'
			}*/
			
			searchStr = searchStr.split(separator) || [];
			result = result || {};
			len = searchStr.length;
			for(i = 0; i < len; i++){
				prop = (typeof searchStr[i] === 'string') ? searchStr[i].split('=') : [];
				result[prop[0].trim()] = searchStr[i].replace(prop[0]+'=', '');
			}
			if(arguments.length > 2){
				return result[property];
			}
			
			return result;	
		};
		
		/**
		 * @desc Set simple cookie with given options object, cookie format nm1=vl1
		 * @desc All params to function are required params, send 'value' as 'null' to make that cookie expire
		 * @desc If 'value' is null or undefined means make that cookie expire
		 * @desc If 'value' is an object, it will store as stringified JSON
		 * @desc sample options = {domain: 'DomainName', path: 'PATH', expires: 'TimeInMilliSeconds', secure: 'BooleanToSayIsSecure'}
		 * @author Laxmikant Kurhe <lkurhe@walmartlabs.com>
		 * @param {String} name cookie name
		 * @param {Mixed} value cookie value
		 * @param {Object} options which specifies details for domain/expires/path/secure
		 * @return void
		 */
		//TODO: Discuss whether to provide this options - Calculate RISK while updating cookie
		//Is the cookie already available ? are the new expiry, domain, path correct and match with existing cookie options
		//Whats the format of existing cookie ? Is the update following same format
		//Is the cookie following any encoding format? 
		//While updating secure cookie, can not read existing value, In this case complete value has to be updated
		//Can everyone write all cookies ? What are the restrictions to be included here.
		store.setCookie = function(name, value, options) {
			var result, now, exp;
			
			//Keep setCookie params as very strict, all are required
			if(!name || !options){
				bc.utils.log('Not enough information to perform setCookie operation');
				return;
			}
			
			//If value is undefined or null then remove that cookie
			if (!bc.utils.hasVal(value)) {
				value = null;
				exp = new Date(0);
			} else {
				if(typeof options.expires === "number"){
					exp = new Date();
					exp.setTime(exp.getTime() + (options.expires));
				}
			}
			result = name + (bc.utils.hasVal(value) ? "="+value : value) + 
					";path=" + (options.path || "/") + 
					(options.domain ? ";domain=" + options.domain : "") +
					(exp ? ";expires=" + exp.toUTCString() : "") + 
					(options.secure ? ";secure" : ""); 
			
			document.cookie = result; 
		};
		
		/**
		 * @desc Set cookieGroup with given options object, cookie format ckGrpNm1=pts1=vl1|pts2=vl2...
		 * @desc All params to function are required params, to remove a property send 'value' as 'null'
		 * @desc If 'value' is null or undefined means remove that 'property'
		 * @desc If 'value' is an object, it will store as stringified JSON
		 * @desc sample options = {domain: 'DomainName', path: 'PATH', expires: 'TimeInMilliSeconds', secure: 'BooleanToSayIsSecure'}
		 * @author Laxmikant Kurhe <lkurhe@walmartlabs.com>
		 * @param {String} name cookieGroup name
		 * @param {String} property name of property inside cookieGroup
		 * @param {Mixed} value value for given property name
		 * @param {String} separator separate multiple properties using a separator
		 * @param {boolean} encodeVal whether to set val
		 * @return void
		 */
		store.setCookieGroup = function(name, property, value, separator, options) {
			var ckVal, i,
				result;
			
			//Keep setCookieGroup params as very strict, all are required
			if(!name || !property || !separator || !options){
				bc.utils.log('Not enough information to perform setCookiGroup operation');
				return;
			}
				
			ckVal = store.getCookie(name, separator) || {};
			
			if (!bc.utils.hasVal(value)) {
				delete ckVal[property];
			}else {
				ckVal[property] = value;
			}
			
			for(i in ckVal){
				if(ckVal.hasOwnProperty(i)){
					result = result || '';
					result += i + '=' + ckVal[i] + separator;
				}
			}
			if(result){
				result = result.substring(0, (result.length - 1));
			}
			store.setCookie(name, result, options);
		};
		
		/**
		 * @desc Get cookie with given options object, and value
		 * @desc sample options = {domain: 'DomainName', path: 'PATH', expires: 'TimeInMilliSeconds', secure: 'BooleanToSayIsSecure'}
		 * @author Laxmikant Kurhe <lkurhe@walmartlabs.com>
		 * @param {Mixed} value cookie value
		 * @return void
		 */
		store.getBeaconSessCookie = function(prop) {
			var bcs = config.store.bcs || {},
				result = (arguments.length > 0) ? store.getCookie(bcs.n, bcs.sep, prop) : store.getCookie(bcs.n, bcs.sep),
				i;
			if(typeof result === 'string'){
				result =  decodeURIComponent(result);
			}else if(result && typeof result === 'object'){
				for(i in result){
					if(typeof result[i] === 'string'){
						result[i] = decodeURIComponent(result[i]); 
					}
				}
			}
			return result;
		};
		
		/**
		 * @desc Set cookie with given options object, and value
		 * @desc sample options = {domain: 'DomainName', path: 'PATH', expires: 'TimeInMilliSeconds', secure: 'BooleanToSayIsSecure'}
		 * @author Laxmikant Kurhe <lkurhe@walmartlabs.com>
		 * @param {Mixed} value cookie value
		 * @return void
		 */
		store.setBeaconSessCookie = function(prop, value) {
			var bcs = config.store.bcs || {},
				value = bc.utils.hasVal(value) ? encodeURIComponent(value) : value;
			store.setCookieGroup(bcs.n, prop, value, bcs.sep, bcs.opts);
		};
		
		/**
		 * @desc Get cookie with given options object, and value
		 * @desc sample options = {domain: 'DomainName', path: 'PATH', expires: 'TimeInMilliSeconds', secure: 'BooleanToSayIsSecure'}
		 * @author Laxmikant Kurhe <lkurhe@walmartlabs.com>
		 * @param {Mixed} value cookie value
		 * @return void
		 */
		store.getBeaconPersCookie = function(prop) {
			var bcp = config.store.bcp || {},
				result = store.getCookie(bcp.n, bcp.sep),
				i, val_exp,
				t = (new Date()).getTime();
			for(i in result){
				if(result.hasOwnProperty(i)){
					val_exp = result[i].split(bcp.expSep);
					if(val_exp[1] > t){
						result[i] = decodeURIComponent(val_exp[0]);
					}else{
						delete result[i];
					}
				}
			}
			if(arguments.length){
				result = result ? result[prop] : undefined;
			}
			return result;
		};
		
		/**
		 * @desc Set cookie with given options object, and value
		 * @desc sample options = {domain: 'DomainName', path: 'PATH', expires: 'TimeInMilliSeconds', secure: 'BooleanToSayIsSecure'}
		 * @author Laxmikant Kurhe <lkurhe@walmartlabs.com>
		 * @param {String} prop name to be set 
		 * @param {String} value for property
		 * @param {number} exp time for current property
		 * @return void
		 */
		store.setBeaconPersCookie = function(prop, value, exp) {
			var bcp = config.store.bcp || {},
				ckVal,
				result = store.getCookie(bcp.n, bcp.sep),
				exp = (typeof exp === 'number') ? exp : 0,
				i, val_exp,
				t = (new Date()).getTime();
			
			for(i in result){
				if(result.hasOwnProperty(i)){
					val_exp = result[i].split(bcp.expSep);
					if(val_exp[1] <= t){
						delete result[i];
					}	
				}
			}
			if(prop){
				result = result || {};
				if(bc.utils.hasVal(value) && exp){
					exp = (new Date()).getTime() + exp;
					result[prop] = encodeURIComponent(value) + bcp.expSep + exp;
				}else{
					delete result[prop];
				}
			}
			for(i in result){
				if(result.hasOwnProperty(i)){
					ckVal = ckVal || '';
					ckVal += i + '=' + result[i] + bcp.sep;
				}
			}
			if(ckVal){
				ckVal = ckVal.substring(0, (ckVal.length - 1));	
			}
			store.setCookie(bcp.n, ckVal, bcp.opts);
		};
		
		return {
			//HTML5 storage
			//options.storage	= localStorage|sessionStorage
			//options.expires 	= expiry time
			//options is required
			read : function(name, options){
				var key, opt, val;
				if(arguments.length === 1 && typeof arguments[0] === 'object'){
					opt = arguments[0] || {};
				}else{
					key = arguments[0];
					opt = arguments[1] || {};
				}
				if(store.support(opt.storage)){
					val = store.read(key, opt);
				}
				return val;
			},
			
			write : function(name, value, options){
				var options = options || {};
				if(!name){
					bc.utils.log('No [key] found while performing write operation on storage');
					return;
				}
				if(store.support(options.storage)){
					store.write(name, value, options);
				}
			},
			
			//cookie
			//options.expires 	= expiryd date
			//options.path		= path for cookie
			//options.domain	= domain for cookie
			//options.secure	= isSecure for cookie 
			//options is required
			getCookie : store.getCookie,
			setCookie : store.setCookie,
			setCookieGroup : store.setCookieGroup,
			getBeaconSessCookie : store.getBeaconSessCookie,
			setBeaconSessCookie : store.setBeaconSessCookie,
			getBeaconPersCookie : store.getBeaconPersCookie,
			setBeaconPersCookie : store.setBeaconPersCookie
		};
	})();
})(_bcq, _bcc);
//Dependencies in sequence
//core.js
//storage.js


(function(bc){
	'use strict';
	
	bc.Interpreter = {
		/**
		* @module Object Methods
		*/
		/**
		* @module Data Extraction Methods
		*/
		/**
		* @module Resuable Mappings Methods
		*/
		/**
		* @module Assignment Methods
		*/
		/**
		* @module String Methods
		*/
		/**
		* @module Flow Methods
		*/
		/**
		* @module Operator Methods
		*/
		/**
		* @module Array Methods
		*/
		
		initialize : function(templates,filter){
			this.tmpls = templates;

			if(filter!==undefined)
			{
				this.filter=filter;
		    }
		},
		
		//--------------------------- Utility Functions ---------------------------
		/** User Documentation
		 * This functions is for developer use.
		 */
		/** Developer Documentation
		 * @dev_desc Get value based on a specified type, could be static/attribute/url_params/cookie/store
		 * @dev_author Laxmikant Kurhe <lkurhe@walmartlabs.com>
		 * @dev_method getValue
		 * @dev_param {Object} valObj - Object with name and type of value to be fetched
		 * @dev_param {Object} attrs - Attributes available with current tagAction
		 * @dev_param {Object} ph - Placeholders available with current tagAction mapping
		 * @dev_return {String} value
		 */
		getValue : function(valObj, attrs, ph){
			var valObj = valObj || {},
				name = valObj.n,
				type = valObj.t;
			
			switch(type){
				case 'st': 
					//TODO: check if value is undefined then should this function return value as null?
					return valObj.v;
					
				case 'attr': 

					return bc.utils.getData(valObj.c, name, attrs);
					
				case 'ph':
					return bc.utils.fetchData(ph, name);

				case 's_omni':
					return (typeof s_omni !== 'undefined' && s_omni) ? bc.utils.fetchData(s_omni, name) : null;			
			}
			return;
		},
		//
		// ---------------------------------------------------------------------------------------------------
		//
		
		 
		/** User Documentation
		 * This functions is for developer use.
		 */
		/** Developer Documentation
		 * @dev_desc Interpret/execute a given function based on function name and args array
		 * @dev_author Laxmikant Kurhe <lkurhe@walmartlabs.com>
		 * @dev_method interpret
		 * @dev_param {String} fn - Name of function to be executed
		 * @dev_param {Array} args - Array that defines name and type of value to be fetched from available attributes
		 * @dev_param {Object} attrs - Attributes available with current tagAction
		 * @dev_param {Object} ph - Placeholders available with current tagAction mapping
		 * @dev_return {String} Value fetched from available attributes
		 */
		interpret : function(fn, args, attrs, ph){
			var val;
			if(!fn || typeof fn !== "string" || typeof this[fn] !== "function"){
				return;
			}
			return this[fn](args, attrs, ph);
		}
	};
})(_bcq);

(function(bc, mp){
	'use strict';
	
	//--------------------------- Utility Functions ---------------------------
	
	/** Developer Documentation
		 * @dev_desc Get value based on a specified type, could be static/attribute/url_params/cookie/store
		 * @dev_author Laxmikant Kurhe <lkurhe@walmartlabs.com>
		 * @dev_method getValue
		 * @dev_param {Object} valObj - Object with name and type of value to be fetched
		 * @dev_param {Object} attrs - Attributes available with current tagAction
		 * @dev_param {Object} ph - Placeholders available with current tagAction mapping
		 * @dev_return {String} value
		 */
	mp.getValue = function(valObj){
		var valObj = valObj || {},
			name = valObj.n,
			type = valObj.t;
			
		// switch(type){
		// 	case 'st': 
		// 	//TODO: check if value is undefined then should this function return value as null?
		// 	return valObj.v;
					
		// 	case 'attr': 

		// 	return bc.utils.getDataNew(valObj.c, name, attrs);
					
		// 	case 'ph':
		// 	return bc.utils.fetchData(ph, name);
		// }
		return;
	};

	/** User Documentation
	 * This functions is for developer use.
	 */
	mp.conditional = function(args, operator){
		var args = args || [], operator = operator || '',
			len = args.length,
			param1 = args[0],
			param2 = args[1],
			param3 = args[2],
			param4 = args[3],
			result = false;
		if(operator === "NULL"){
			//If operator is NULL then only 3 params will be available
			result = (param1 === null); 
			return (len > 1) ? (result ? param2 : param3) : result; 
		}else if(operator === "hasVal"){
			//If operator is hasVal then only 3 params will be available
			result = bc.utils.hasVal(param1);
			return (len > 1) ? (result ? param2 : param3) : result; 
		}
		switch(operator){
			case "===" 	: result = param1 === param2; 	break;
			case "!==" 	: result = param1 !== param2; 	break;
			case "<" 	: result = param1 < param2; 	break;
			case "<=" 	: result = param1 <= param2; 	break;
			case ">" 	: result = param1 > param2; 	break;
			case ">=" 	: result = param1 >= param2; 	break;
			case "&&" 	: result = param1 && param2; 	break;
			case "||" 	: result = param1 || param2; 	break;
		}
		
		return (len > 2) ? (result ? param3 : param4) : result;
	};
	
	/** User Documentation
	 * This functions is for developer use.
	 */
	mp.numericOperation = function(param1,param2, operator){
		var result;
		try{
			switch(operator){
				case "+" 	: result = (param1 + param2); 	break;
				case "-" 	: result = (param1 - param2); 	break;
			}
		}catch(e){}
		return result;
	};

	/** User Documentation
	 * This functions is for developer use.
	 */
	mp.aggregationOperation = function(input, operator) {
	    var input = input || [],
	        operator = operator || '',
	        result;
	    switch (operator) {
	        case "sum":
	            result = this.sumArray(input);
	            break;
	    }
	    return result;
	};
	
	/** User Documentation
	 * This functions is for developer use.
	 */
	mp.format = function(type, value){
		switch(type){
			case "LOWER_CASE" : value = typeof value === "string" ? value.toLowerCase() : value; break;
			case "UPPER_CASE" : value = typeof value === "string" ? value.toUpperCase() : value; break;
			case "CAMEL_CASE" : value = typeof value === "string" ? bc.utils.toCamelCase(value) : value; break;
		}
		return value;
	};
	
	/** User Documentation
	 * This functions is for developer use.
	 */
	mp.getFormatedDate = function(value, format){
		switch(format){
			case "yyyy-mm-dd" : value = value instanceof Date? value.getFullYear() +"-"+value.getMonth()+"-"+value.getDay(): null; break;
			
		}
		return value;
	};
	
	/** User Documentation
	 * This functions is for developer use.
	 */
	mp.buildArr = function(args, checkVal){
		var args = args || [],
			i, len, arr = [], val;
		len = args.length;
		for(i = 0; i < len ; i++){
			val = args[i];
			if(checkVal && bc.utils.hasVal(val)){
				arr.push(val);
			}else if(!checkVal){
				arr.push(val);
			}
		}
		return arr;
	};
	
	/** User Documentation
	 * This functions is for developer use.
	 */
	mp.sumArray = function(input) {
	    var sum = 0;
	    for (var i = 0, len = input.length; i < len; i++) {
	        sum += input[i];
	    }
	    return sum;
	};

	//
	// -------------------------------------------------- Data Group specific --------------------------------------------------
	//
	
	/** User Documentation
	 * User function
	 */
	mp.getObj = function(attrsName, ctxName){
		var val,
			args = args || [],
			grp = attrsName,
			ctx = ctxName;
		if(!bc.utils.hasVal(grp)){
			return;
		}
		
		grp = Array.isArray(grp) ? grp.join(bc.utils.separator) : grp;
		val = bc.utils.getDataNew(ctx, grp);

		return val;
	};
	
	/** User Documentation
	 * User function
	*/
	mp.getObjByKey = function(attributeGrp,keyArray,context){
		var val,
			args = args || [],
			grp = attributeGrp || {},
			keyArr = keyArray || [],
			ctx = context,
			key, i, len;
		if(!bc.utils.hasVal(grp)){
			return;
		}
		grp = Array.isArray(grp) ? grp.join(bc.utils.separator) : grp;
		keyArr = Array.isArray(keyArr) ? keyArr : [keyArr];
		len = keyArr.length;
		
		if(len === 1){
			key = keyArr[0];
			key = Array.isArray(key) ? key.join(bc.utils.separator) : key;
			val = bc.utils.getDataNew(ctx, grp + '.' + key);
		}else if(len > 1){
			val = {};
			for(i = 0; i < len; i++){
				key = keyArr[i];
				key = Array.isArray(key) ? key.join(bc.utils.separator) : key;
				val[key] = bc.utils.getDataNew(ctx, grp + '.' + key);
			}
		}
		return val;
	};
	
	/** User Documentation
	 * This functions is for developer use.
	 */
	mp.getObjFirst = function(attrsName, ctxName){
		var val, k, 
			grp = this.getObj(attrsName, ctxName);
		if(typeof grp === 'object'){
			for(k in grp){
				if(grp.hasOwnProperty(k)){
					val = val || {};
					val[k] = grp[k];
					return val;
				}
			}
		}
		return val;
	};
	
	/** User Documentation
	 * @desc Get Object with only first entry from given group, remove key and return only the actual data
	 * @method getObjFirstData
	 * @param {String} key - The name of the key from which to extract the first group
	 * @example
	 * // given: se = {"_def": {"id": "123", "nm": "George"}}
	 * getObjFirstData("se")
	 * // Returns {"id": "123", "nm": "George"}
	 * @return {Object} Data from first entry in a given group 
	**/
	mp.getObjFirstData = function(attrsName, ctxName){
		//args will be an object 

		return this.getFirst(this.getObjFirst(attrsName, ctxName));
	};
	
	/** User Documentation
	 * User function
	*/ 
	mp.getFirstData = function(obj){
		var obj = obj || {};
		return this.getFirst(obj);
	};
	
	/** User Documentation
	 * This functions is for developer use.
	 */
	mp.getFirst = function(obj){
		var k;
		if(typeof obj === 'object'){
			for(k in obj){
				if(obj.hasOwnProperty(k)){
					return obj[k];
				}
			}
		}
		return;
	};
	
	/** User Documentation
	 * User function
	 */
	mp.getKeys = function(obj, filter){
		var k, result = [];
		obj =obj || {};
		filter = typeof filter === 'string' ? new RegExp(filter) : null;
		for(k in obj){
			if(obj.hasOwnProperty(k)){
				if(filter && filter.test(k)){
					result.push(k);
				}else if(!filter){
					result.push(k);
				}
			}
		}
		return result;
	};
	
	/** User Documentation
	 * User function
	 */
	mp.iterateOn = function(obj,property){
		var grp = obj,
			result = [],
			k, val;
		
		for(k in grp){
			if(grp.hasOwnProperty(k)){
				val = bc.utils.fetchData(grp[k], property);
				if(bc.utils.hasVal(val)){
					result.push(val);
				}	
			}
		}
		return result;
	};
	
	/** User Documentation
	 * This functions is for developer use.
	 */
	mp.getMultipleAttr = function(args){
		var args = args || [],
			grp, result = [],
			entry,
			i, len, k, val;
		grp = args[0];
		len = args.length;
		for(k in grp){
			if(grp.hasOwnProperty(k)){
				entry = [];
				if(grp[k]){
					for(i = 1; i < len ; i++){
						entry.push(grp[k][args[i]]);
					}
				}
				result.push(entry);
			}
		}
		return result;
	};

	/** User Documentation
	 * This functions is for developer use.
	 */
	mp.mapValue = function(args){
		var args = args || [];
		return this.map(args[0], args[1]);
	};

	/** User Documentation
	 * This functions is for developer use.
	 */
	mp.map = function (val, filterValue) {
		if (filterValue && val) {
	        if (this[filterValue] !== undefined && typeof this[filterValue] === 'function') {
	            return this[filterValue](val, this["omniture"]["enums"][filterValue]);
	        } else {
	            return bc.utils.exceFiltering(val, this["omniture"]["enums"][filterValue]);
	        }
	    } else {
	        return val;
	    }
	};

	/** User Documentation
	 * @desc Checks the property exists and returns it
	 * @method getProperty
	 * @param {Object} attribute - Object in which to check for the property in question.
	 * @param {String} property - String of the property name to look for in the attribute passed
	 * @example
	 * pulse.runtime.getProperty(pulse.placeholder.er, "id");
	 * @return {Object} Returns the Object of the property if it exists
	 * @example
	 * pulse.runtime.getProperty(pulse.placeholder.cd, "dim,iw");
	 * @return {Object} Returns the Object of the property if it exists
	*/
	mp.getProperty = function (attribute, property) {
		var params = property.split(".");
		var parentObj = null;
		var returnValue;

		if (attribute && params.length > 0) {
			parentObj = attribute;
			for (var i = 0; i < params.length; ++i) {
				if (parentObj.hasOwnProperty(params[i])) {
					if (typeof parentObj[params[i]] === "object" && !Array.isArray(parentObj[params[i]])) {
						parentObj = parentObj[params[i]];
						returnValue = null;
					}
				}
				else {
					parentObj = null;
					break;
				}
			}
			if(parentObj !== null) {
				returnValue = parentObj[params[params.length-1]];
			}
		}
		return returnValue;
	};


	//
	// -------------------------------------------------- Template specific --------------------------------------------------
	//
	
	/** User Documentation
	 * @desc Find mappings from given mapping template
	 * @method mappingTemplate
	 * @param {String} template - Mapping template to be used
	 * @param {Boolean} [isGeneric] - True or False
	 * @example
	 * mappingTemplate("search_texts_usdl")
	 * @example
	 * mappingTemplate("search_groups_usdl", true);
	 * @return {Object} object fetched from mapping template
	 */
	/*mp.mappingTemplate = function(args){
		var val,
			args = args || [],
			template = this.getValue(args[0]),
			isGeneric = this.getValue(args[1]),
			tmpl = (isGeneric && this.genTmpls) ? this.genTmpls[template] : ((!isGeneric && this.tmpls) ? this.tmpls[template]: null);
		return typeof tmpl === 'object' ? tmpl.mp: null;
	};
	
	
	//
	// -------------------------------------------------- Generic mapping functions --------------------------------------------------
	//
	
	
	/** User Documentation
	 * @desc Direct mapping of a string or variable from available attributes
	 * @method direct
	 * @param {String} args - Value in variable or a sting value to be used
	 * @example
		 * direct("string")
		 * // Returns "string"
		 * @example 
		 * // Given that the placeholder variable "se" contains {"id": "123", "nm": "George"}
		 * direct({ph}se.id)
		 * // Returns "123"
		 * @example
		 * // Given that the attribute "ctx" exists and is equal to "ProductPage"
		 * direct({at}u)
		 * //returns "ProductPage"
	 * @return {String} The string that will be assigned to a variable
	 */
	mp.direct = function(val){
		return val;
	};
	
	mp.createEmptyObject = function(){
		return {};
	};

	/** User Documentation
	 * @desc Gets object or creates a new empty Object with the property name passed.
	 * @method getObject
	 * @param {String} propertyName - String of the property name of the requestedObj
	 * @example
	 * getObject("obj");
	 * // If pulse.placeholder.obj does NOT exist
	 * // Returns {}
	 * @example
	 * getObject("obj");
	 * // If pulse.placeholder.obj does exist.
	 * // pulse.placeholder.obj = {"a":1, "b":2}
	 * // Returns {"a":1, "b":2}
	 * @return {String} The string that will be assigned to a variable
	 */
	mp.getObject = function(propertyName){
		if (pulse.placeholder.hasOwnProperty(propertyName)) {
			return pulse.placeholder[propertyName];
		}
		else {
			return {};
		}
	};
	/** User Documentation
	 * @desc Template mapping of variable from available attributes 
	 * @method template
	 * @param {String} args - Defined the template to map using available attribute
	 * @example
	 * // Given "id" is a placeholder variable contaning the value "123"
	 * template("Numbers {{s1}}", {ph}id)
	 * // Returns "Numbers 123"
	 * @return {String} value fetched from available attributes using the template defined
	 */
	mp.template = function(){
		var args = arguments || [],
			tpl = args[0],
			val,
			i, len = args.length,
			rg;
		if(typeof tpl === 'string'){
			for(i = 1; i < len; i++){
				val = args[i];
				val= val !== undefined ? val : '';
				rg = new RegExp('{{s' + i + '}}', 'g');
				tpl = tpl.replace(rg, val);
			}
		}
		return tpl;
	};
	
	/** User Documentation
	 * @desc Check if given attribute has non null non undefined value
	 * @method hasValue 
	 * @param {String} args - Attribute to check for 
	 * @example
	 * // Given the following place holder variable: se = {"id": "123", "nm": "George"}
	 * hasValue({ph}se.id)
	 * // Returns True
	 * @example 
	 * // Given the attribute "se" exists 
	 * hasValue({at}se)
	 * // Returns True
	 * @return {boolean} Returns True if attribute exists False otherwise
	 */
	mp.hasValue = function(obj, val1, val2){
		var params = [];
		Array.prototype.push.apply(params, arguments);
		return this.conditional(params, "hasVal");
	};
	
	//
	// -------------------------------------------------- Operator mapping functions --------------------------------------------------
	//
	

	/** User Documentation
	 * @desc Equals condition, if (param1 === param2) is true then assign value of param3 else param4
	 * @method equals
	 * @param {String|Number} param1 - First part of the condition if (param1 === param2)
	 * @param {String|Number} param2 - Second part of the condition if (param1 === param2)
	 * @param {String} param3 - if the condition is True this value will be returned
	 * @param {String} param4 - if the condition is NOT True this value will be returned
	 * @example
	 * equals({ph}pl.dt,"grid","GRID","LIST")
	 * // if pl.dt is equal to "grid" returns "GRID"
	 * // if pl.dt is NOT equal to "grid" returns "LIST"
	 * @return {String} Value resulting from the evaluation of the condition. Returns either param3 or param4
	 */
	mp.equals = function(param1, param2, param3, param4) {
		var params = [];
		Array.prototype.push.apply(params, arguments);
		return this.conditional(params, "===");
	};
	
	/** User Documentation
	 * @desc NotEquals condition, if (param1 !== param2) is true then assign value of param3 else param4
	 * @method notEquals
	 * @param {String|Number} param1 - First part of the condition if (param1 !== param2)
	 * @param {String|Number} param2 - Second part of the condition if (param1 !== param2)
	 * @param {String} param3 - if the condition is True this value will be returned
	 * @param {String} param4 - if the condition is NOT True this value will be returned
	 * @example
	 * notEquals({ph}pl.dt,"grid","GRID","LIST")
	 * // if pl.dt is NOT equal to "grid" returns "GRID"
	 * // if pl.dt is NOT equal to "grid" returns "LIST"
	 * @return {String} Value resulting from the evaluation of the condition. Returns either param3 or param4
	 */
	mp.notEquals = function(param1, param2, param3, param4){
		var params = [];
		params.push(param1);
		params.push(param2);
		params.push(param3===undefined?true:param3);
		params.push(param4===undefined?false:param4);
		return this.conditional(params, "!==");
	};
	
	/** User Documentation
	 * @desc Greater Than condition, if (param1 > param2) is true then assign value of param3 else param4
	 * @method greaterThan
	 * @param {Number} param1 - First part of the condition if (param1 > param2)
	 * @param {Number} param2 - Second part of the condition if (param1 > param2)
	 * @param {String} param3 - if the condition is True this value will be returned
	 * @param {String} param4 - if the condition is NOT True this value will be returned
	 * @example
	 * // Given that the attribute x holds a number
	 * greaterThan({at}x, 5,"GRID","LIST")
	 * // if x is greater than 5 returns "GRID"
	 * // if x is NOT greater than 5 returns "LIST"
	 * @return {String} Value resulting from the evaluation of the condition. Returns either param3 or param4
	 */
	mp.greaterThan = function(param1, param2, param3, param4){
		var params = [];
		params.push(param1);
		params.push(param2);
		params.push(param3===undefined?true:param3);
		params.push(param4===undefined?false:param4);
		return this.conditional(params, ">");
	};
	
	/** User Documentation
	 * @desc Greater Than Or Equals To condition, if (param1 >= param2) is true then assign value of param3 else param4
	 * @method greaterThanOrEqual
	 * @param {Number} param1 - First part of the condition if (param1 >= param2)
	 * @param {Number} param2 - Second part of the condition if (param1 >= param2)
	 * @param {String} param3 - if the condition is True this value will be returned
	 * @param {String} param4 - if the condition is NOT True this value will be returned
	 * @example
	 * // Given that the attribute x holds a number
	 * greaterThanOrEqual({at}x, 5,"GRID","LIST")
	 * // if x is greater than or equal to 5 returns "GRID"
	 * // if x is NOT greater than or equal to 5 returns "LIST"
	 * @return {String} Value resulting from the evaluation of the condition. Returns either param3 or param4
	 */
	mp.greaterThanOrEqual = function(param1, param2, param3, param4){
		var params = [];
		params.push(param1);
		params.push(param2);
		params.push(param3===undefined?true:param3);
		params.push(param4===undefined?false:param4);
		return this.conditional(params, ">=");
	};
	
	/** User Documentation
	 * @desc Less Than condition, if (param1 < param2) is true then assign value of param3 else param4
	 * @method lessThan
	 * @param {Number} param1 - First part of the condition if (param1 < param2)
	 * @param {Number} param2 - Second part of the condition if (param1 < param2)
	 * @param {String} param3 - if the condition is True this value will be returned
	 * @param {String} param4 - if the condition is NOT True this value will be returned
	 * @example
	 * // Given that the attribute x holds a number
	 * lessThan({at}x, 5,"GRID","LIST")
	 * // if x is lessThan 5 returns "GRID"
	 * // if x is NOT lessThan 5 returns "LIST"
	 * @return {String} Value resulting from the evaluation of the condition. Returns either param3 or param4
	 */
	mp.lessThan = function(param1, param2, param3, param4){
		var params = [];
		params.push(param1);
		params.push(param2);
		params.push(param3===undefined?true:param3);
		params.push(param4===undefined?false:param4);
		return this.conditional(params, "<");
	};
	
	/** User Documentation
	 * @desc Less Than Or Equals To condition, if (param1 <= param2) is true then assign value of param3 else param4
	 * @method lessThanOrEqual
	 * @param {Number} param1 - First part of the condition if (param1 <= param2)
	 * @param {Number} param2 - Second part of the condition if (param1 <= param2)
	 * @param {String} param3 - if the condition is True this value will be returned
	 * @param {String} param4 - if the condition is NOT True this value will be returned
	 * @example
	 * // Given that the attribute x holds a number
	 * lessThanOrEqual({at}x, 5,"GRID","LIST")
	 * // if x is less than or equal to 5 returns "GRID"
	 * // if x is NOT less than or equal to 5 returns "LIST"
	 * @return {String} Value resulting from the evaluation of the condition. Returns either param3 or param4
	 */
	mp.lessThanOrEqual = function(param1, param2, param3, param4){
		var params = [];
		params.push(param1);
		params.push(param2);
		params.push(param3===undefined?true:param3);
		params.push(param4===undefined?false:param4);
		return this.conditional(params, "<=");
	};
	
	/** User Documentation
	 * @desc Logial AND (&&) condition, if (param1 && param2) is true then assign value of param3 else param4
	 * @method logicalAND
	 * @param {Boolean} param1 - First part of the condition if (param1 && param2)
	 * @param {Boolean} param2 - Second part of the condition if (param1 && param2)
	 * @param {String} param3 - if the condition is True this value will be returned
	 * @param {String} param4 - if the condition is NOT True this value will be returned
	 * @example
	 * // Given the attribute "athena" containing the boolean value true
	 * logicalAND({at}athena, false, "yes", "no")
	 * // Returns the string "no"
	 * @return {String} Value resulting from the evaluation of the condition. Returns either param3 or param4
	 */
	mp.logicalAND = function(param1, param2, param3, param4){
		var params = [];
		params.push(param1);
		params.push(param2);
		params.push(param3===undefined?true:param3);
		params.push(param4===undefined?false:param4);
		return this.conditional(params, "&&");
	};
	
	/** User Documentation
	 * @desc Logial OR (||) condition, if (param1 || param2) is true then assign value of param3 else param4
	 * @method logicalOR
	 * @param {Boolean} param1 - First part of the condition if (param1 || param2)
	 * @param {Boolean} param2 - Second part of the condition if (param1 || param2)
	 * @param {String} param3 - if the condition is True this value will be returned
	 * @param {String} param4 - if the condition is NOT True this value will be returned
	 * @example
	 * // Given the attribute "athena" containing the boolean value true
	 * logicalOR({at}athena, false, "yes", "no")
	 * // Returns the string "yes"
	 * @return {String} Value resulting from the evaluation of the condition. Returns either param3 or param4
	 */
	mp.logicalOR = function(param1, param2, param3, param4){
		var params = [];
		params.push(param1);
		params.push(param2);
		params.push(param3===undefined?true:param3);
		params.push(param4===undefined?false:param4);
		return this.conditional(params, "||");
	};
	
	/** User Documentation
	 * This functions is for developer use.
	 */
	mp.isNull = function(obj){
		var params = [];
		params.push(obj);
		return this.conditional(params, "NULL");
	};
	
	/** User Documentation
	 * @desc Subtracts the value of param2 from param1
	 * @method decrement
	 * @param {Number} param1 - The first operand of the substraction. (param1 - param2)
	 * @param {Number} param2 - The second operand of the substraction. (param1 - param2)
	 * @example 
	 * decrement(10, 2)
	 * // Returns 8
	 * @return {Number} The value resulting from the substraction param1 - param2
	 */
	mp.decrement = function(param1, param2){
		
		return this.numericOperation(param1,param2, "-");
	};
	
	/** User Documentation
	 * @desc Addition of the values param1 and param2
	 * @method increment
	 * @param {Number} param1 - The first operand of the addition. (param1 + param2)
	 * @param {Number} param2 - The second operand of the addition. (param1 + param2)
	 * @example 
	 * increment(10, 2)
	 * // Returns 12
	 * @return {Number} The value resulting from the substraction param1 - param2
	 */
	mp.increment = function(param1, param2){
		
		return this.numericOperation(param1,param2, "+");
	};
	
	//
	// -------------------------------------------------- Formatting mapping functions --------------------------------------------------
	//
	
	
	/** User Documentation
	 * @desc Formats value to lowercase
	 * @method lowerCase
	 * @param {String} stg - String to be converted to lower case
	 * @example
	 * // Given "id" is a placeholder variable contaning the value "WALMART"
	 * lowerCase({ph}id)
	 * // Returns the string "walmart"
	 * @return {String} Returns the calling string value converted to lower case.
	 */
	mp.lowerCase = function(inputStr){
		return this.format("LOWER_CASE", inputStr ? inputStr : null);
	};
	
	/** User Documentation
	 * @desc Formats value to lowercase
	 * @method upperCase
	 * @param {String} stg - String to be converted to upper case
	 * @example
	 * // Given "id" is a placeholder variable contaning the value "walmart"
	 * upperCase({ph}id)
	 * // Returns the string "WALMART"
	 * @return {String} Returns the calling string value converted to upper case.
	 */
	mp.upperCase = function(inputStr){
		return this.format("UPPER_CASE", inputStr ? inputStr : null);
	};
	
	/** User Documentation
	 * @desc Formats value to camelCase
	 * @method camelCase
	 * @param {String} stg - String to be converted to camel case
	 * @return {String} Returns the calling string value converted to camel case.
	 */
	mp.camelCase = function(inputStr){
		return this.format("CAMEL_CASE", inputStr ? inputStr : null);
	};

	/** User Documentation
	 * This functions is for developer use.
	 */
	mp.formatDate = function(val, format){
		var val = val || null, date = new Date(val),
		format = format || "yyyy-mm-dd";
		return val ? this.getFormatedDate(date, format) : val;
	};

	/** User Documentation
	 * @desc Retrieves the matches matching a string against a regular expression and returns results
	 * @param {String} re - String of the regular expression to be used
	 * @param {String} stg - String to matched against
	 * @return {String} Match from execution result
	 */
	mp.match = function(){
		var args = [],str,reArr,arr=[],re,i,len;
		Array.prototype.push.apply(args, arguments);
		str=args[0];
		reArr = Array.isArray(args[1]) ? args[1] : [args[1]];
		len = reArr.length;
		if(typeof str !== 'string'){
			return;
		}
		for(i = 0; i < len; i++){
			arr[i] = reArr[i];
		}
		re = new RegExp(arr.join("|"));
		return str.match(re);
	};
	
	/** User Documentation
	 * This functions is for developer use.
	 */
	mp.concat = function(args){
		var args = args || [], 
			val,
			result,
			i, len = args.length;
		for(i = 0; i < len; i++){
			val = args[i];
			if(typeof val !== 'undefined' && val !== null){
				result = result ? result : ''; 
				result += (typeof val !== 'string' ? val + '' : val);
			}
		}
		return result;
	};
	
	/** User Documentation
	 * @desc Evaluate over multiple conditions
	 * @method switchCase
	 * @param {Boolean} [boolean=True] - True or False. Condition should be match to this value
	 * @param {String} expression1 - Fixed value to be compared in the conditions
	 * @param {String} expression2 - Value to be compared to expression1 in first condition, if(expression1 == expression2)
	 * @param {String} result1 - Will return this value if result of condition is equal to boolean.
	 * @param {String} expression3 - Value to be compared to expression1 in second condition, if(expression1 == expression3)
	 * @param {String} result2 - Will return this value if result of condition is equal to boolean.
	 * @param {String} [default] - Will return this value if result of condition not equal to boolean and there are no more conditions.
	 * @example 
	 * switchCase(er.ht, 404, template("Connect {{s1}} {{s2}}",er.ms, erText), 500, template("Please Accept Our Apology {{s1}} {{s2}}",er.ms, erText), null)
	 * // if (er.ht == 404) { 
		 * // Returns "Connect " + er.ms + erText;
		 * // } else if (er.ht == 500) {
		 * // Returns "Please Accept Our Apology " + er.ms +  erText;
		 * // }
	 * @example 
	 * switchCase(true,{ph}uc_storeAvailSel,direct({ph}stItemsTxt),  {ph}uc_onlineSel,  direct({ph}onlineItemsTxt),  direct({ph}allItemsTxt));
	 * // if (uc_storeAvailSel == stItemsTxt) { 
		 * // Returns uc_onlineSel
		 * // } else if (uc_storeAvailSel == onlineItemsTxt) {
		 * // Returns allItemsTxt
		 * // }
	 * @return {String} Value fetched from available attributes as a result of conditions
	 */
	mp.switchCase = function(){
		var args = arguments || [],
			condition, defCase, switchCase, result,
			i, len,isDefExist;
		condition = args[0];
		isDefExist = (args.length%2===0);
		if(isDefExist){
			result = args[args.length - 1];			// take the default value
		}
		len = isDefExist?args.length-1:args.length;
		for(i = 1; i< len; i=i+2){
			if(condition === args[i]){
				return args[i+1];
			}
		}
		return result;
	};
	
	//
	// -------------------------------------------------- String specific --------------------------------------------------
	//
	
	/** User Documentation
	 * This functions is for developer use.
	 */
	mp.splitFilter = function(val, separator, ind){
		return (typeof val === 'string') ? 
					(typeof ind === 'number' ? val.split(separator)[ind] : val.split(separator)) : val;
	};
	
	/** User Documentation
	 * @desc Split string on the basis of seprator provided
	 * @method split
	 * @param {String} val - String that will be separated
	 * @param {String} separator - Separator to be used 
	 * @param {String} filter - Filter to be used
	 * @return {Array} value fetched from available attributes and split on the basis of seprator provided
	 */
	/*mp.split = function(args){
		var args = args || [],
			val = args[0],
			separator = args[1] || '/',
			filter = args[2],
			i, len, result;
			if(typeof val === 'string'){
				result = this.splitFilter(val, separator, filter);
			}else if(Array.isArray(val)){
				len = val.length;
				result = [];
				for(i = 0; i < len; i++){
					result.push(this.splitFilter(val[i], separator, filter));
				}
			}
		return result;
	};*/
	
	/** User Documentation
	 * @desc sub string from main string on the basis of length provided
	 * @author Pankaj Manghnani<pmanghn@walmartlabs.com>
	 * @param {Array} arr - Array that defines name and type of value to be fetched from available attributes
	 * @param {Object} attrs - attributes available with current tagAction
	 * @param {Object} ph - placeholders available with current tagAction mapping
	 * @return {String[]} value fetched from available attributes and split on the basis of seprator provided
	 */
	mp.subString = function(val,len1,len2){
		return val && len1 && len1<val.length ?len2? len2+len1<=val.length? val.substring(len1,len2):val:val.substring(0,len1) : val;
	};


	//
	// -------------------------------------------------- Array specific --------------------------------------------------
	//
	
	
	/** User Documentation
	 * @desc Join elements of an array using a separator
	 * @method join
	 * @param {Array} args - The array of elements to be joined
	 * @param {String} separator - The separator to be used to join the elements of the array
	 * @example
	 * // Given the placeholder variable "arr" contains the array ["1", "2", "3"]
	 * join({ph}arr, "-")
	 * // Returns "1-2-3"
	 * @return {String} The string resulting from joining the elements in an array
	 */
	mp.join = function(arr,separator){
			separator = separator || ',';
		return Array.isArray(arr) ? arr.join(separator) : arr;
	};
	
	/** User Documentation
	 * @desc Find if array has a particular elements in it
	 * @method arrayHas
	 * @param {Array} arr - Array that will be examined
	 * @param {String} strg - Element to look for within the array
	 * @return {Boolean} Returns True if the element exists within the array otherwise False
	 */
	mp.arrayHas = function(arr,elm){
		return (Array.isArray(arr) && (arr.indexOf(elm) > -1)) ? true : false;
	};
	
	/** User Documentation
	 * @desc Returns the length of the array 
	 * @method arrayLength
	 * @param {Array} arr - The array to determine its length
	 * @return {Number} Returns the length of the array
	 */
	mp.arrayLength = function(arr){
		return (Array.isArray(arr)) ? arr.length : -1;
	};
	
	/** User Documentation
	 * @desc Return an array consisting of given elements
	 * @method buildArray
	 * @param {...String} args - String to be used to create the array
	 * @example 
	 * // Given the place holder variable "se"= {"id": "123", "nm": "abcd"} 
	 * // Given attribute "x" holds the number 5
	 * buildArray({ph}se.id, {ph}se.nm, {at}x)
	 * // Returns the array ["123","abcd", 5]
	 * @return {Array} Array constructed from given elements
	 */
	mp.buildArray = function(args){
		return this.buildArr(args, false);
	};
	
	/** User Documentation
	 * @desc Return an array consisting of given elements which are non null non undefined
	 * @method buildValidArray
	 * @param {...String} args - String to be used to create the array
	 * @example
	 * // Given the place holder variable "se"= {"id": "123", "nm": "abcd"} 
	 * // Given attribute "x" holds the number 5
	 * // Given attribute "r" is undefined 
	 * buildValidArray({ph}se.id, {ph}se.nm, {at}r, {at}x)
	 * // Returns the array ["123","abcd", 5]
	 * @return {Array} Array constructed from given elements which are non null non undefined
	 */
	mp.buildValidArray = function(){
        var arr = [];
        Array.prototype.push.apply(arr, arguments);
		return this.buildArr(arr, true);
	};
	
	/** User Documentation
	 * @desc Find if given array has proper elements or not, like array with [undefined, null] or [[], []] will return false
	 * @method arrayHasElm
	 * @param {Array} arr - Array to be checked for NULL, undefined or empty strings
	 * @return {Boolean} Will return False if Array has elements that are NULL, undefined or empty string
	 */
	mp.arrayHasElm = function(arr){
		var i, len;
		if(Array.isArray(arr)){
			len = arr.length;
			for(i = 0; i< len; i++){
				if(Array.isArray(arr[i]) && arr[i].length > 0){
					return true;
				}else if(!Array.isArray(arr[i]) && bc.utils.hasVal(arr[i])){
					return true;
				}
			}
		}
		return false;
	};
	
	/** User Documentation
	 * @desc Push one or more elements to an existing array
	 * @method pushToArray
	 * @param {Array} args - Array on which the elements will be pushed
	 * @param {Object} element - Element to be push to the array
	 * @return {Array} array with new elements pushed to original array 
	 */
	mp.pushToArray = function(){
		var args = arguments || [],
			arr = args[0],
			i, len;
		if(!Array.isArray(arr)){
			return arr;
		}
		len = args.length;
		for(i=1; i<len; i++){
			arr.push(args[i]);
		}
		return arr;
	};
	
	/** User Documentation
	 * @desc Get last element from array
	 * @method lastArrayElm
	 * @param {Array} arr - Array from which the last element is to be extracted
	 * @return {Object} Last element from array 
	 */
	mp.lastArrayElm = function(arr){
		var arr = arr || [];		
		return this.nthArrayElm(arr,"last");
	};
	
	/** User Documentation
	 * @desc Get first element from array
	 * @method firstArrayElm
	 * @param {Array} arr - Array from which the first element is to be extracted
	 * @return {Object} First element from array 
	 */
	mp.firstArrayElm = function(arr){
		var arr = arr || [];
		// args.push({"t":"st","v":0});				
		return this.nthArrayElm(arr, 0);
	};

	/** User Documentation
	 * @desc Get nth element from array
	 * @method nthArrayElm
	 * @param {Array} arr - The array from which to extract the nth element
	 * @param {Number} index - The index of the element to be extracted
	 * @return {Object} nth element from array 
	 */
	mp.nthArrayElm = function(arr, index){
		var arr = arr,
			index = index;
		if(Array.isArray(arr)){
			if(arr.length >index){
			return arr[index];
		    }
		    else if(index==="last")
		    {
		     return arr[arr.length-1];	
		    }
		}
		return;
	};

    /** User Documentation
	 * This functions is for developer use.
	 */
    mp.getUniques = function(args){
      	var arr = args || [];
      	return this.getUniquesArray(arr);
    };
	
	/** User Documentation
	 * User function
	 */
	mp.forEach = function() {

	    var args = [];
	    Array.prototype.push.apply(args, arguments);
	    var object = args[0],
	        funcName = args[1],
	        needUnique = args[2],
	        joinBy = args[3],
	        funcArgs = args.slice(4),
	        funcArgsValues=[],
	        results = [],
	        data, output;
	        
	    if(funcArgs&&funcArgs.length>0)
	    {
	    	for (var a = 0, len = funcArgs.length; a < len; ++a)
	    	{
	    		funcArgsValues.push(funcArgs[a]);
	    	} 
	    }

	    if (typeof object === "object" || Array.isArray(object)) {
	        if (Array.isArray(object)) {
	            for (var i = 0, l = object.length; i < l; ++i) {
	                data = object[i];
	                funcArgsValues.unshift(data);
	                output = (this[funcName]).apply(this, funcArgsValues);
	                if (output) {
	                    results.push(output);
	                }
	                funcArgsValues.shift();
	            }
	        } else {
	            for (var key in object) {
	                if (object.hasOwnProperty(key)) {
	                    
	                    data = object[key]||{};
	           		   	data._key =  key;
	                    
	                    funcArgsValues.unshift(data);
	                    output = (this[funcName]).apply(this, funcArgsValues);
	                    if (output) {
	                        results.push(output);
	                    }
	                    funcArgsValues.shift();
	                }
	            }

	        }
	        if (needUnique) {
	            if (needUnique === "groupBy") {
	                results = this.getGroupByObject(results);
	            } else {
	                results = this.getUniquesArray(results);
	            }
	        }
	        if (joinBy) {
	            return results.join(joinBy);
	        } else {
	            return results.join();
	        }

	    } else {
	        return null;
	    }
	};

	/** User Documentation
	 * This functions is for developer use.
	 */
	mp.getUniquesArray = function(inputArray) {
		var arr = inputArray,
		u = {}, uniqueArr = [];
      	for(var i = 0, l = arr.length; i < l; ++i){
      		if(u.hasOwnProperty(arr[i])) {
      			continue;
      		}
      		uniqueArr.push(arr[i]);
      		u[arr[i]] = 1;
      	}

      	return uniqueArr;
	};

	/** User Documentation
	 * This functions is for developer use.
	 */
	mp.getGroupByObject = function(inputArray) {
	    var arr = inputArray,
	        groupByObj = {},
	        uniqueArr = [];
	    for (var i = 0, l = arr.length; i < l; ++i) {
	        if (groupByObj.hasOwnProperty(arr[i])) {
	            groupByObj[arr[i]]++;
	        } else {
	            groupByObj[arr[i]] = 1;
	        }
	    }
	    for (var key in groupByObj) {
	        if (groupByObj.hasOwnProperty(key)) {
	            uniqueArr.push(groupByObj[key] > 1 ? key + "[" + groupByObj[key] + "]" : key);
	        }
	    }
	    return uniqueArr;
	};


	//
	// -------------------------------------------------- URL --------------------------------------------------
	//


	/** User Documentation
	 * User function
	 */
	mp.buildURL = function(baseUrl,params){
		baseUrl = baseUrl || '';
		if(params){
			baseUrl += ('?' + bc.utils.urlSerialize(params));
		}
		return baseUrl;
	};

	/** User Documentation
	 * This functions is for developer use.
	 */
	mp.decodeURIComponent = function(value){
		if(value){
			try{
				value = decodeURIComponent(value);
			}catch(e){}
		}
		return value;
	};
	
	//
	// -------------------------------------------------- JSONPath --------------------------------------------------
	//
	
	/** User Documentation
	 * This functions is for developer use.
	 */
	mp.execJsonPath = function (dataObj, path, aggr) {
	    var args = args || [],
	        obj = dataObj,
	        path = path,
	        aggregation = aggr,
	        res;
	    if (pulse_runtime.jsonPath && obj && path) {
	        res = pulse_runtime.jsonPath.eval(obj, path); // jshint ignore:line
	    }
	    if (aggregation) {
	        res = this.aggregationOperation(res, aggregation);
	    }
	    return res;
	};


	/**
	* ------------------------------------------------------------------------------------------------------
	* ------------------------------------------- New Methods ----------------------------------------------
	* ------------------------------------------------------------------------------------------------------
	*/

	/**
	* ------------------------------------------- String Methods -------------------------------------------
	* @module String Methods
	*/

// string.toLowerCase
	/** User Documentation
	 * @memberof module:String Methods
	 * @desc Formats the string to lowercase
	 * @method toLowerCase
	 * @param {String} str - String to be converted to lower case
	 * @example
	 * pulse.runtime.toLowerCase("WALMART");
	 * // Returns the string "walmart"
	 * @return {String} Returns the calling string value converted to lower case.
	 */
	mp.toLowerCase = function(str) {
		if (str && typeof str === 'string') {
			return str.toLowerCase();
		}
		else {
			return;
		}
	};

//NOT A SAM'S METHOD
	/** User Documentation
	 * @memberof module:String Methods
	 * @desc Formats the string to upperCase
	 * @method toUpperCase
	 * @param {String} str - String to be converted to upper case
	 * @example
	 * pulse.runtime.toUpperCase("walmart");
	 * // Returns the string "WALMART"
	 * @return {String} Returns the calling string value converted to upper case.
	 */
	mp.toUpperCase = function(str) {
		if (str && typeof str === 'string') {
			return str.toUpperCase();
		}
		else {
			return;
		}
	};

// THIS METHOD IS COMMENTED OUT BECAUSE FUNCTION NAME ALREADY EXISTS IN OLD FUNCTIONALITY
// string.match (should also support regular expression)
	/** User Documentation
	 * @memberof module:String Methods
	 * @desc Retrieves the matches matching a string against a regular expression and returns results
	 * @method match
	 * @param {String} stg - String to matched against
	 * @param {String} re - String of the regular expression to be used
	 * @example
	 * pulse.runtime.match("abcde", "de");
	 * // Returns the string "de"
	 * @example
	 * pulse.runtime.match("abc", "de");
	 * // Returns null
	 * @return {String} Match from execution result
	 */
	// mp.match = function(str, re) {
	// 	if(typeof str !== 'string' || typeof re !== 'string') {
	// 		return;
	// 	}
	// 	re = new RegExp(re);
	// 	return str.match(re);
	// };

// THIS METHOD IS COMMENTED OUT BECAUSE FUNCTION NAME ALREADY EXISTS IN OLD FUNCTIONALITY
// string.split
	/** User Documentation
	 * @memberof module:String Methods
	 * @desc Split string on the basis of seprator provided
	 * @method split
	 * @param {String} str - String that will be separated
	 * @param {String} separator - Separator to be used
	 * @param {number} limit - Instance of separator at which to stop
	 * @example
	 * pulse.runtime.split("Module_ProductPage","_");
	 * // Returns the array ["Module", "ProductPage"]
	 * @example
	 * pulse.runtime.split("This is a string"," ", 2);
	 * // Returns the array ["This", "is"]
	 * @return {Array} Value fetched from available attributes and split on the basis of seprator provided
	 */
	mp.split = function(input, separator, limit) {
		var result,len,i;
		if (typeof input === 'string' && typeof separator === 'string') {
			result = this.splitFilter(input, separator, limit);
			//return (limit && typeof limit === 'number') ? input.split(separator, limit) : input.split(separator);
		}
		else if(Array.isArray(input)){
			len = input.length;
			result = [];
			for(i = 0; i < len; i++){
				result.push(this.splitFilter(input[i], separator, limit));
			}
			
		}
		return result;
	};

// THIS METHOD IS COMMENTED OUT BECAUSE FUNCTION NAME ALREADY EXISTS IN OLD FUNCTIONALITY
//NOT A SAM'S METHOD
	/** User Documentation
	 * @memberof module:String Methods
	 * @desc Template mapping of variable from available attributes
	 * @method template
	 * @param {String} tmpl - Defined the template to map.
	 * @param {...String} str - String with which to substitute within the template
	 * @example
	 * pulse.placeholder["id"] = "123";
	 * pulse.runtime.template("Numbers {{s1}}", pulse.placeholder.id);
	 * // Returns "Numbers 123"
	 * @return {String} value fetched from available attributes using the template defined
	 */
	// mp.template = function(tmpl, str) {
	// 	if(typeof tmpl === 'string') {
	// 		for(var i = 1; i < arguments.length; i++) {
	// 			var substitution = arguments[i] !== undefined ? arguments[i] : '';
	// 			re = new RegExp('{{s' + i + '}}', 'g');
	// 			tmpl = tmpl.replace(re, substitution);
	// 		}
	// 	}
	// 	return tmpl;
	// };

// string.substr
	/** User Documentation
	 * @memberof module:String Methods
	 * @desc Returns a segment of a string beginning at the specified index through the specified number of characters.
	 * @method substr
	 * @param {String} str - The string from which to extract a segment.
	 * @param {Number} beginningIndex - The index of where to begin the extraction.
	 * @param {Number} strLength - The number of characters to extract starting from "beginningIndex".
	 * @example
	 * pulse.runtime.substr("Hello World", 2, 3);
	 * // Returns "llo"
	 * @return {String} Returns the segment string extracted from "str".
	 */
	mp.substr = function(str, beginningIndex, strLength) {
		return ((typeof(str) === "string") && (typeof(beginningIndex) === "number") && (typeof(strLength) === "number")) ? str.substr(beginningIndex, strLength) : "";
	};

// string.trim
	/** User Documentation
	 * @memberof module:String Methods
	 * @desc Strips any whitespace Characters at the beginning or end of a string.
	 * @method trim
	 * @param {String} str - The string to be trimmed.
	 * @example
	 * pulse.runtime.trim("  Hello  ");
	 * // Returns "Hello"
	 * @return {String} Returns the input string without any whitespaces at the beginning or end.
	 */
	mp.trim = function(str) {
		return (typeof(str) === "string") ? str.trim() : "";
	};

// string.parseInt
	/** User Documentation
	 * @memberof module:String Methods
	 * @desc Parses a string and returns an integer.
	 * @method parseInt
	 * @param {String} str - The string to be parsed
	 * @param {Number} [radix] - Numeral system to be used
	 * @example
	 * pulse.runtime.parseInt("40 days");
	 * // Returns 40
	 * @example
	 * pulse.runtime.parseInt("40", 16);
	 * // Returns 64 (hexadecimal 40 is 64 decimal)
	 * @return {Number} Returns the number parsed from the string "str".
	 */
	mp.parseInt = function(str, radix) {
		radix = radix || null;
		return (typeof(str) === "string") ? parseInt(str, radix) : undefined;
	};

// string.parseFloat
	/** User Documentation
	 * @memberof module:String Methods
	 * @desc Parses a string and returns a floating point number.
	 * @method parseFloat
	 * @param {String} str - The string to be parsed
	 * @example
	 * pulse.runtime.parseFloat("40 days");
	 * // Returns 40
	 * @example
	 * pulse.runtime.parseFloat("40.78");
	 * // Returns 40.78
	 * @return {Number} Returns the number parsed from the string "str".
	 */
	mp.parseFloat = function(str) {
		return (typeof(str) === "string") ? parseFloat(str) : undefined;
	};

// nonstring.toString
	/** User Documentation
	 * @memberof module:String Methods
	 * @desc Returns a string representing the specified object
	 * @method toString
	 * @param {*} obj - The object to be converted to a string.
	 * @param {Number} [radix] - The numerical base system to use if the object passed is a number.
	 * @example
	 * pulse.runtime.toString(24);
	 * // Returns "24"
	 * @example
	 * pulse.runtime.toString([1,2]);
	 * // Returns "1,2"
	 * @example
	 * pulse.runtime.toString(9, 2);
	 * // Returns "1001"
	 * @return {Number} Returns the string representing the specified object
	 */
	mp.toString = function(obj, radix) {
		if (typeof(obj) === "number") {
			radix = radix || undefined;
			return obj.toString(radix);
		}
		else {
			return obj.toString();
		}
	};

// string.substring. This function is only unique because it is not camelcased. subString exists.
	/** User Documentation
	 * @memberof module:String Methods
	 * @desc Returns a segment of a string beginning at the specified index through the specified number of characters.
	 * @method substring
	 * @param {String} str - The string from which to  extract a segment.
	 * @param {Number} beginningIndex - The offset of the first character to include.
	 * @param {Number} endIndex - The offset of the first charcter to not include.
	 * @example
	 * pulse.runtime.substring("Hello World", 2, 5);
	 * // Returns "llo"
	 * @return {String} Returns the segment string extracted from "str".
	 */
	mp.substring = function(str, beginningIndex, endIndex) {
		return ((typeof(str) === "string") && (typeof(beginningIndex) === "number") && (typeof(endIndex) === "number")) ? str.substring(beginningIndex, endIndex) : "";
	};

// string.replace (should also support regular expression)

	/**
	* ------------------------------------------- Array Methods -------------------------------------------
	* @module Array Methods
	*/

// THIS METHOD IS COMMENTED OUT BECAUSE FUNCTION NAME ALREADY EXISTS IN OLD FUNCTIONALITY
// Array.join
	/** User Documentation
	 * @memberof module:Array Methods
	 * @desc Join elements of an array into a string using a separator
	 * @method join
	 * @param {Array} arr - The array of elements to be joined
	 * @param {String} [separator] - The separator to be used to join the elements of the array
	 * @example
	 * pulse.runtime.join([1,2])
	 * // Returns "1,2"
	 * @example
	 * pulse.runtime.join([1,2], "/")
	 * // Returns "1/2"
	 * @return {String} The string resulting from joining the elements in an array
	 */
	// mp.join = function(arr, separator) {
	// 	if (Array.isArray(arr)) {
	// 		separator = separator || ",";
	// 		return arr.join(separator);
	// 	}
	// 	return;
	// };

// variable.isArray
	/** User Documentation
	 * @memberof module:Array Methods
	 * @desc Determines if the parameter passed is an array.
	 * @method isArray
	 * @param {Array} value - The parameter passed to be examined.
	 * @example
	 * pulse.runtime.isArray([1,2])
	 * // Returns true
	 * @example
	 * pulse.runtime.isArray({"a":1, "b":2})
	 * // Returns false
	 * @return {Boolean} Returns a true if value is an array.
	 */
	mp.isArray = function(value) {
		return Array.isArray(value);
	};

// array.pop
	/** User Documentation
	 * @memberof module:Array Methods
	 * @desc Removes the last element at the end of an array
	 * @method pop
	 * @param {Array} arr - Array from which to remove the last element.
	 * @example
	 * pulse.placeholder["arr"] = [1,2];
	 * pulse.runtime.pop(pulse.placeholder.arr);
	 * // Returns 2
	 * // pulse.placeholder.arr is now equal to [1]
	 * @example
	 * pulse.placeholder["arr"] = [1,2,3,4,5];
	 * pulse.runtime.pop(pulse.placeholder.arr);
	 * // Returns 5
	 * // pulse.placeholder.arr is now equal to [1,2,3,4]
	 * @return {Array} Returns the last element in the array. The array passed has been mutated.
	 */
	mp.pop = function(arr) {
		if (Array.isArray(arr)) {
			return arr.pop();
		}
		else {
			return;
		}
	};

// array.push
	/** User Documentation
	 * @memberof module:Array Methods
	 * @desc Pushes one or more elements to the end of an array
	 * @method push
	 * @param {Array} arr - Array to which elements will be added.
	 * @param {...*} [elm] - Elements to be added at the end of the array "arr"
	 * @example
	 * pulse.placeholder["arr"] = [1,2];
	 * pulse.runtime.push(pulse.placeholder.arr, 4);
	 * // Returns 3
	 * // pulse.placeholder.arr is now equal to [1,2,4]
	 * @example
	 * pulse.placeholder["arr"] = [1];
	 * pulse.runtime.push(pulse.placeholder.arr, 2, 4);
	 * // Returns 3
	 * // pulse.placeholder.arr is now equal to [1,2,4]
	 * @return {Number} Returns the number of elements in the array. The array passed has been mutated.
	 */
	mp.push = function(arr, elm) {
		if (Array.isArray(arr)) {
			for (var i = 1; i < arguments.length; i++) {
				arr.push(arguments[i]);
			}
			return arr.length;
		}
		else {
			return;
		}
	};

// array.shift
	/** User Documentation
	 * @memberof module:Array Methods
	 * @desc Removes the first element at the beginning of an array
	 * @method shift
	 * @param {Array} arr - Array from which to remove the first element.
	 * @example
	 * pulse.placeholder["arr"] = [2,3];
	 * pulse.runtime.shift(pulse.placeholder.arr);
	 * // Returns 2
	 * // pulse.placeholder.arr is now equal to [3]
	 * @example
	 * pulse.placeholder["arr"] = [1,2,3,4,5];
	 * pulse.runtime.shift(pulse.placeholder.arr);
	 * // Returns 1
	 * // pulse.placeholder.arr is now equal to [2,3,4,5]
	 * @return {Array} Returns the first element of the array. The array passed has been mutated.
	 */
	mp.shift = function(arr) {
		if (Array.isArray(arr)) {
			return arr.shift();
		}
		else {
			return;
		}
	};

// array.unshift
	/** User Documentation
	 * @memberof module:Array Methods
	 * @desc Adds one or more elements to the beginning of an array
	 * @method unshift
	 * @param {Array} arr - Array to which elements will be added.
	 * @param {...*} [elm] - Elements to be added at the begining of the array "arr"
	 * @example
	 * pulse.placeholder["arr"] = [1,2];
	 * pulse.runtime.unshift(pulse.placeholder.arr, 3)
	 * // Returns 3
	 * // pulse.placeholder.arr is now equal to [4,1,2]
	 * @example
	 * pulse.placeholder["arr"] = [1];
	 * pulse.runtime.unshift(pulse.placeholder.arr, 2, 3)
	 * // Returns 3
	 * // pulse.placeholder.arr is now equal to [3,2,1]
	 * @return {Array} Returns the number of elements in the array. The array passed has been mutated.
	 */
	mp.unshift = function(arr, elm) {
		if (Array.isArray(arr)) {
			for (var i = 1; i < arguments.length; i++) {
				arr.unshift(arguments[i]);
			}
			return arr.length;
		}
		else {
			return;
		}
	};

// array.splice
	/** User Documentation
	 * @memberof module:Array Methods
	 * @desc Returns a segment of an array outlined by a starting index and number of elements.
	 * @method splice
	 * @param {String} value - The array from which the segment will be extracted
	 * @param {Number} beginningIndex - The index at which to begin the extraction.
	 * @param {Number} numOfElm - The number of elements of the array to extract
	 * @example
	 * pulse.runtime.splice(["a","b","c","d","e","f","g"], 4, 3);
	 * // Returns ["e","f","g"]
	 * @return {Array} Returns an array that is a segment of "value" with "numOfElm" elements, starting at "beginningIndex".
	 */
	mp.splice = function (value, beginningIndex, numOfElm) {
		if (arguments.length === 3 &&
			(typeof beginningIndex === "number") &&
			(typeof numOfElm === "number") &&
			(Array.isArray(value))) {

			return value.splice(beginningIndex, numOfElm);
		}
		else {
			return;
		}
	};

// array.sort
	/* User Documentation
	 * @memberof module:Array Methods
	 * @desc Returns an array arranged either in ascending or descending order.
	 * @method sort
	 * @param {Array} arr - Array to be sorted
	 * @example
	 * pulse.runtime.sort(["cheese", "apple", "bread"])
	 * // Returns ["apple", "bread", "cheese"]
	 * @example
	 * pulse.runtime.sort(["cheese", "apple", "bread"], "descending")
	 * // Returns ["cheese", "bread", "apple"]
	 * @example
	 * pulse.runtime.sort([27, 1, 9 , 5]);
	 * // Returns [1, 5, 9, 27]
	 * @return {Array} Returns the sorted array
	 */
	mp.sort = function(arr) {
		if (Array.isArray(arr)) {
			return arr.sort();
		}
		else {
			return;
		}
	};

	/**
	* ------------------------------------------- String and Array Common Methods -------------------------------------------
	* @module String and Array Methods
	*/

// length
	/** User Documentation
	 * @memberof module:String and Array Methods
	 * @desc Returns the value of the length of a given string or of an array.
	 * @method length
	 * @param {String|Array} value - The string or array to find the length of.
	 * @example
	 * pulse.runtime.length("Hello World");
	 * // Returns 11
	 * @example
	 * pulse.runtime.length([1,2]);
	 * // Returns 2
	 * @return {Number} Returns the value of the length of the string "str".
	 */
	mp.length = function(value) {
		if (value && (typeof value === "string" || Array.isArray(value))) {
			return value.length;
		}
		else {
			return;
		}
	};

// THIS METHOD IS COMMENTED OUT BECAUSE FUNCTION NAME ALREADY EXISTS IN OLD FUNCTIONALITY
// concat
	/** User Documentation
	 * @memberof module:String and Array Methods
	 * @desc Returns the results of concatenation of given values.
	 * @method concat
	 * @param {...Array|String} values - Two or more arrays to concatenate
	 * @example
	 * pulse.runtime.concat("foo", "-", "bar");
	 * // Returns "foo-bar"
	 * @example
	 * pulse.runtime.concat([1,2],[3]);
	 * // Returns [1,2,3]
	 * @example
	 * pulse.runtime.concat([1,2],3);
	 * // Returns [1,2,3]
	 * @example
	 * pulse.runtime.concat(["a","b"], [3,4], ["e","f"]);
	 * // Returns ["a","b",3,4,"e","f"]
	 * @return {Array|String} Returns an array resulting from the concatenation of all values passed
	 */
	// mp.concat = function(values) {
	// 	console.log(arguments[0]);
	// 	if (!Array.isArray(arguments[0]) && typeof arguments[0] !== 'string') {
	// 		return;
	// 	}
	// 	else {
	// 		var results = arguments[0];
	// 		for (var i = 1; i < arguments.length; ++i) {
	// 			results = results.concat(arguments[i]);
	// 		}
	// 		return results;
	// 	}
	// };

// slice
	/** User Documentation
	 * @memberof module:String and Array Methods
	 * @desc Returns a string extracted as a section of another string.
	 * @method slice
	 * @param {String|Array} value - value on which to perform the extraction
	 * @param {Number} beginningIndex - Index where to begin extraction.
	 * @param {Number} endIndex - Index before which to end extraction.
	 * @example
	 * pulse.runtime.slice("Hello World", 0, 2);
	 * // Returns "He"
	 * @example
	 * pulse.runtime.slice("Hello World", 2, 5);
	 * // Returns "llo"
	 * @example
	 * pulse.runtime.slice(["a","b","c","d","e","f","g"]], 0, 2);
	 * // Returns ["a","b"]
	 * @return {String|Array} Returns the string or array extracted from "value" using the indexes.
	 */
	mp.slice = function (value, beginningIndex, endIndex) {
		if (arguments.length === 3 &&
			(typeof beginningIndex === "number") &&
			(typeof endIndex === "number") &&
			((Array.isArray(value)) || (typeof value === "string"))) {

			return value.slice(beginningIndex, endIndex);
		}
		else {
			return;
		}
	};

// indexOf
	/** User Documentation
	 * @memberof module:String and Array Methods
	 * @desc Returns index of the first occurence of a value within a string.
	 * @method indexOf
	 * @param {String} searchString - String on which the search will occur.
	 * @param {String} value - The value to be searched for in the string.
	 * @example
	 * pulse.runtime.indexOf("Hello World", "or");
	 * // Returns 7
	 * @example
	 * pulse.runtime.indexOf([1,2], "1");
	 * // Returns -1
	 * @return {Number} Returns the index of the first occurence of "value" in "searchString".
	 */
	mp.indexOf = function(searchString, value) {
		if ((typeof(searchString) === "string" && typeof(value) === "string") ||
			(Array.isArray(searchString))) {
			return searchString.indexOf(value);
		}
		else {
			return -1;
		}
	};


	/**
	* ------------------------------------------- Comparison Operator Methods -------------------------------------------
	* @module Comparison Operator Methods
	*/

// ==
	/** User Documentation
	 * @memberof module:Comparison Operator Methods
	 * @desc Abstract equals condition, if (param1 == param2) is true then assign value of param3 else param4
	 * @method equalsAbs
	 * @param {*} param1 - First part of the condition if (param1 == param2)
	 * @param {*} param2 - Second part of the condition if (param1 == param2)
	 * @param {*} [param3] - if the condition is True this value will be returned
	 * @param {*} [param4] - if the condition is NOT True this value will be returned
	 * @example
	 * pulse.placeholder["var1"] = 3;
	 * pulse.placeholder["var2"] = "3";
	 * pulse.runtime.equalsAbs(pulse.placeholder.var1, pulse.placeholder.var2);
	 * // Returns true
	 * @example
	 * pulse.placeholder["var1"] = 3;
	 * pulse.placeholder["var2"] = "3";
	 * pulse.runtime.equalsAbs(pulse.placeholder.var1, pulse.placeholder.var2, "foo", "bar");
	 * // Returns "foo"
	 * @return {*} Value resulting from the evaluation of the condition. Returns boolean or either param3 or param4
	 */
	mp.equalsAbs = function(param1, param2, param3, param4) {
		if (param1 && param2) {
			param3 = param3 || true;
			param4 = param4 || false;
			return (param1 === param2) ? param3 : param4;
		}
		else {
			return;
		}
	};

// ===
	/** User Documentation
	 * @memberof module:Comparison Operator Methods
	 * @desc Strict equals condition, if (param1 === param2) is true then assign value of param3 else param4
	 * @method equalsStr
	 * @param {*} param1 - First part of the condition if (param1 === param2)
	 * @param {*} param2 - Second part of the condition if (param1 === param2)
	 * @param {*} [param3] - if the condition is True this value will be returned
	 * @param {*} [param4] - if the condition is NOT True this value will be returned
	 * @example
	 * pulse.placeholder["var1"] = 3;
	 * pulse.placeholder["var2"] = "3";
	 * pulse.runtime.equalsStr(pulse.placeholder.var1, pulse.placeholder.var2);
	 * // Returns false
	 * @example
	 * pulse.placeholder["var1"] = 3;
	 * pulse.placeholder["var2"] = "3";
	 * pulse.runtime.equalsStr(pulse.placeholder.var1, pulse.placeholder.var2, "foo", "bar");
	 * // Returns "bar"
	 * @return {String} Value resulting from the evaluation of the condition. Returns either param3 or param4
	 */
	mp.equalsStr = function(param1, param2, param3, param4) {
		if (param1 && param2) {
			param3 = param3 || true;
			param4 = param4 || false;
			return (param1 === param2) ? param3 : param4;
		}
		else {
			return;
		}
	};


// !=
	/** User Documentation
	 * @memberof module:Comparison Operator Methods
	 * @desc NotEquals abstract condition, if (param1 !== param2) is true then assign value of param3 else param4
	 * @method notequalsAbs
	 * @param {*} param1 - First part of the condition if (param1 != param2)
	 * @param {*} param2 - Second part of the condition if (param1 != param2)
	 * @param {*} [param3] - if the condition is True this value will be returned
	 * @param {*} [param4] - if the condition is NOT True this value will be returned
	 * @example
	 * pulse.placeholder["var1"] = 3;
	 * pulse.placeholder["var2"] = "3";
	 * pulse.runtime.notEqualsAbs(pulse.placeholder.var1, pulse.placeholder.var2);
	 * // Returns false
	 * @example
	 * pulse.placeholder["var1"] = 3;
	 * pulse.placeholder["var2"] = "3";
	 * pulse.runtime.notEqualsAbs(pulse.placeholder.var1, pulse.placeholder.var2, "foo", "bar");
	 * // Returns "bar"
	 * @return {*} Value resulting from the evaluation of the condition. Returns either param3 or param4
	 */
	mp.notEqualsAbs = function(param1, param2, param3, param4) {
		if (param1 && param2) {
			param3 = param3 || true;
			param4 = param4 || false;
			return (param1 !== param2) ? param3 : param4;
		}
		else {
			return;
		}
	};

// !==
	/** User Documentation
	 * @memberof module:Comparison Operator Methods
	 * @desc NotEquals strict condition, if (param1 !== param2) is true then assign value of param3 else param4
	 * @method notEqualsStr
	 * @param {*} param1 - First part of the condition if (param1 !== param2)
	 * @param {*} param2 - Second part of the condition if (param1 !== param2)
	 * @param {*} [param3] - if the condition is True this value will be returned
	 * @param {*} [param4] - if the condition is NOT True this value will be returned
	 * @example
	 * pulse.placeholder["var1"] = 3;
	 * pulse.placeholder["var2"] = "3";
	 * pulse.runtime.notEqualsStr(pulse.placeholder.var1, pulse.placeholder.var2);
	 * // Returns true
	 * @example
	 * pulse.placeholder["var1"] = 3;
	 * pulse.placeholder["var2"] = "3";
	 * pulse.runtime.notEqualsStr(pulse.placeholder.var1, pulse.placeholder.var2, "foo", "bar");
	 * // Returns "foo"
	 * @return {*} Value resulting from the evaluation of the condition. Returns either param3 or param4
	 */
	mp.notEqualsStr = function(param1, param2, param3, param4) {
		if (param1 && param2) {
			param3 = param3 || true;
			param4 = param4 || false;
			return (param1 !== param2) ? param3 : param4;
		}
		else {
			return;
		}
	};

// THIS METHOD IS COMMENTED OUT BECAUSE FUNCTION NAME ALREADY EXISTS IN OLD FUNCTIONALITY
// >
	/** User Documentation
	 * @memberof module:Comparison Operator Methods
	 * @desc Greater Than condition, if (param1 > param2) is true then assign value of param3 else param4
	 * @method greaterThan
	 * @param {*} param1 - First part of the condition if (param1 > param2)
	 * @param {*} param2 - Second part of the condition if (param1 > param2)
	 * @param {*} [param3] - if the condition is True this value will be returned
	 * @param {*} [param4] - if the condition is NOT True this value will be returned
	 * @example
	 * pulse.placeholder["var1"] = 3;
	 * pulse.placeholder["var2"] = 2;
	 * pulse.runtime.greaterThan(pulse.placeholder.var1, pulse.placeholder.var2);
	 * // Returns true
	 * @example
	 * pulse.placeholder["var1"] = 3;
	 * pulse.placeholder["var2"] = 2;
	 * pulse.runtime.greaterThan(pulse.placeholder.var1, pulse.placeholder.var2, "foo", "bar");
	 * // Returns "foo"
	 * @return {*} Value resulting from the evaluation of the condition. Returns either param3 or param4
	 */
	// mp.greaterThan = function(param1, param2, param3, param4) {
	// 	if (param1 && param2) {
	// 		param3 = param3 || true;
	// 		param4 = param4 || false;
	// 		return (param1 > param2) ? param3 : param4;
	// 	}
	// 	else {
	// 		return;
	// 	}
	// };

// THIS METHOD IS COMMENTED OUT BECAUSE FUNCTION NAME ALREADY EXISTS IN OLD FUNCTIONALITY
// >=
	/** User Documentation
	 * @memberof module:Comparison Operator Methods
	 * @desc Greater Than Or Equals To condition, if (param1 >= param2) is true then assign value of param3 else param4
	 * @method greaterThanOrEqual
	 * @param {*} param1 - First part of the condition if (param1 >= param2)
	 * @param {*} param2 - Second part of the condition if (param1 >= param2)
	 * @param {*} param3 - if the condition is True this value will be returned
	 * @param {*} param4 - if the condition is NOT True this value will be returned
	 * @example
	 * pulse.placeholder["var1"] = 3;
	 * pulse.placeholder["var2"] = 2;
	 * pulse.runtime.greaterThanOrEqual(pulse.placeholder.var1, pulse.placeholder.var2);
	 * // Returns true
	 * @example
	 * pulse.placeholder["var1"] = 3;
	 * pulse.placeholder["var2"] = 2;
	 * pulse.runtime.greaterThanOrEqual(pulse.placeholder.var1, pulse.placeholder.var2, "foo", "bar");
	 * // Returns "foo"
	 * @return {*} Value resulting from the evaluation of the condition. Returns either param3 or param4
	 */
	// mp.greaterThanOrEqual = function(param1, param2, param3, param4) {
	// 	if (param1 && param2) {
	// 		param3 = param3 || true;
	// 		param4 = param4 || false;
	// 		return (param1 >= param2) ? param3 : param4;
	// 	}
	// 	else {
	// 		return;
	// 	}
	// };

// THIS METHOD IS COMMENTED OUT BECAUSE FUNCTION NAME ALREADY EXISTS IN OLD FUNCTIONALITY
// <
	/** User Documentation
	 * @memberof module:Comparison Operator Methods
	 * @desc Less Than condition, if (param1 < param2) is true then assign value of param3 else param4
	 * @method lessThan
	 * @param {*} param1 - First part of the condition if (param1 < param2)
	 * @param {*} param2 - Second part of the condition if (param1 < param2)
	 * @param {*} param3 - if the condition is True this value will be returned
	 * @param {*} param4 - if the condition is NOT True this value will be returned
	 * @example
	 * pulse.placeholder["var1"] = 2;
	 * pulse.placeholder["var2"] = 3;
	 * pulse.runtime.lessThan(pulse.placeholder.var1, pulse.placeholder.var2);
	 * // Returns true
	 * @example
	 * pulse.placeholder["var1"] = 2;
	 * pulse.placeholder["var2"] = 3;
	 * pulse.runtime.lessThan(pulse.placeholder.var1, pulse.placeholder.var2, "foo", "bar");
	 * // Returns "foo"
	 * @return {*} Value resulting from the evaluation of the condition. Returns either param3 or param4
	 */
	// mp.lessThan = function(param1, param2, param3, param4) {
	// 	if (param1 && param2) {
	// 		param3 = param3 || true;
	// 		param4 = param4 || false;
	// 		return (param1 < param2) ? param3 : param4;
	// 	}
	// 	else {
	// 		return;
	// 	}
	// };

// THIS METHOD IS COMMENTED OUT BECAUSE FUNCTION NAME ALREADY EXISTS IN OLD FUNCTIONALITY
// <=
	/** User Documentation
	 * @memberof module:Comparison Operator Methods
	 * @desc Less Than Or Equals To condition, if (param1 <= param2) is true then assign value of param3 else param4
	 * @method lessThanOrEqual
	 * @param {*} param1 - First part of the condition if (param1 <= param2)
	 * @param {*} param2 - Second part of the condition if (param1 <= param2)
	 * @param {*} param3 - if the condition is True this value will be returned
	 * @param {*} param4 - if the condition is NOT True this value will be returned
	 * @example
	 * pulse.placeholder["var1"] = 2;
	 * pulse.placeholder["var2"] = 3;
	 * pulse.runtime.lessThanOrEqual(pulse.placeholder.var1, pulse.placeholder.var2);
	 * // Returns true
	 * @example
	 * pulse.placeholder["var1"] = 2;
	 * pulse.placeholder["var2"] = 3;
	 * pulse.runtime.lessThanOrEqual(pulse.placeholder.var1, pulse.placeholder.var2, "foo", "bar");
	 * // Returns "foo"
	 * @return {String} Value resulting from the evaluation of the condition. Returns either param3 or param4
	 */
	// mp.lessThanOrEqual = function(param1, param2, param3, param4) {
	// 	if (param1 && param2) {
	// 		param3 = param3 || true;
	// 		param4 = param4 || false;
	// 		return (param1 <= param2) ? param3 : param4;
	// 	}
	// 	else {
	// 		return;
	// 	}
	// };


	/**
	* ------------------------------------------- Logical Operator Methods -------------------------------------------
	* @module Logical Operator Methods
	*/

// THIS METHOD IS COMMENTED OUT BECAUSE FUNCTION NAME ALREADY EXISTS IN OLD FUNCTIONALITY
// && (And)
	/** User Documentation
	 * @memberof module:Logical Operator Methods
	 * @desc Logial AND (&&) condition, if (param1 && param2) is true then assign value of param3 else param4
	 * @method logicalAND
	 * @param {Boolean} param1 - First part of the condition if (param1 && param2)
	 * @param {Boolean} param2 - Second part of the condition if (param1 && param2)
	 * @param {*} [param3] - if the condition is True this value will be returned
	 * @param {*} [param4] - if the condition is NOT True this value will be returned
	 * @example
	 * pulse.placeholder["var1"] = "true";
	 * pulse.placeholder["var2"] = "false";
	 * pulse.runtime.logicalAND(pulse.placeholder.var1, pulse.placeholder.var2, "foo", "bar");
	 * // Returns "bar"
	 * @example
	 * pulse.placeholder["var1"] = "true";
	 * pulse.placeholder["var2"] = "false";
	 * pulse.runtime.logicalAND(pulse.placeholder.var1, pulse.placeholder.var2);
	 * // Returns false
	 * @return {String} Value resulting from the evaluation of the condition. Returns either param3 or param4
	 */
	// mp.logicalAND = function(param1, param2, param3, param4) {
	// 	param3 = param3 || true;
	// 	param4 = param4 || false;
	// 	if (typeof param1 === "boolean" && typeof param2 === "boolean") {
	// 		return (param1 && param2) ? param3 : param4;
	// 	}
	// 	else {
	// 		return;
	// 	}
	// };

// THIS METHOD IS COMMENTED OUT BECAUSE FUNCTION NAME ALREADY EXISTS IN OLD FUNCTIONALITY
// || (Or)
	/** User Documentation
	 * @memberof module:Logical Operator Methods
	 * @desc Logial OR (||) condition, if (param1 || param2) is true then assign value of param3 else param4 if they exist.
	 * @method logicalOR
	 * @param {Boolean} param1 - First part of the condition if (param1 || param2)
	 * @param {Boolean} param2 - Second part of the condition if (param1 || param2)
	 * @param {*} param3 - if the condition is True this value will be returned
	 * @param {*} param4 - if the condition is NOT True this value will be returned
	 * @example
	 * pulse.placeholder["var1"] = "true";
	 * pulse.placeholder["var2"] = "false";
	 * pulse.runtime.logicalOR(pulse.placeholder.var1, pulse.placeholder.var2, "foo", "bar");
	 * // Returns "foo"
	 * @example
	 * pulse.placeholder["var1"] = "true";
	 * pulse.placeholder["var2"] = "false";
	 * pulse.runtime.logicalOR(pulse.placeholder.var1, pulse.placeholder.var2);
	 * // Returns true
	 * @return Returns a boolean or either param3 or param4
	 */
	// mp.logicalOR = function(param1, param2, param3, param4) {
	// 	param3 = param3 || true;
	// 	param4 = param4 || false;
	// 	if (typeof param1 === "boolean" && typeof param2 === "boolean") {
	// 		return (param1 || param2) ? param3 : param4;
	// 	}
	// 	else {
	// 		return;
	// 	}
	// };

// ! (Not)
	/** User Documentation
	 * @memberof module:Logical Operator Methods
	 * @desc Logial NOT (!) condition
	 * @method logicalNot
	 * @param {Boolean} param - Boolean value to apply the logical NOT.
	 * @example
	 * pulse.placeholder["var"] = "true";
	 * pulse.runtime.logicalNot(pulse.placeholder.var);
	 * // Returns false
	 * @return {Boolean} Returns the opposite boolean value of parameter provided
	 */
	mp.logicalNot = function(param) {
		if (typeof param === "boolean") {
			return (!param);
		}
		else {
			return;
		}
	};

// THIS METHOD IS COMMENTED OUT BECAUSE FUNCTION NAME ALREADY EXISTS IN OLD FUNCTIONALITY
//NOT A SAM'S METHOD
	/** User Documentation
	 * @memberof module:Logical Operator Methods
	 * @desc isNull condition, if (param1 === null) is true then assign value of param3 else param4 if they exist
	 * @method isNull
	 * @param {*} param1 - Value to test if null.
	 * @param {*} [param2] - if the condition is True this value will be returned
	 * @param {*} [param3] - if the condition is NOT True this value will be returned
	 * @example
	 * pulse.placeholder["var"] = "foo";
	 * pulse.runtime.isNull(pulse.placeholder.var, "is null", "is not null");
	 * // Returns the string "is not null"
	 * @example
	 * pulse.placeholder["var"] = null;
	 * pulse.runtime.isNull(pulse.placeholder.var, "is null", "is not null");
	 * // Returns the string "is null"
	 * @example
	 * pulse.placeholder["var"] = null;
	 * pulse.runtime.isNull(pulse.placeholder.var);
	 * // Returns true
	 * @return {*} Value resulting from the evaluation of the condition. Returns boolean if param3 and param4 are not present.
	 */
	// mp.isNull = function(param1, param2, param3) {
	// 	param2 = param2 || true;
	// 	param3 = param3 || false;
	// 	return (param1 === null) ? param2 : param3;
	// };


	/**
	* ------------------------------------------- Numeric Methods -------------------------------------------
	* @module Numeric Methods
	*/

// Number.toFixed
	/** User Documentation
	 * @memberof module:Numeric Methods
	 * @desc Formats a number using fixed-point notation
	 * @method toFixed
	 * @param {Number} num - The number
	 * @param {Number} [decimals] - Number of digits to appear after the decimal point.
	 * @example
	 * pulse.rumtime.toFixed(12345.6789, 2)
	 * // Returns 12345.68
	 * // The last number has been rounded.
	 * @return {String} A string representing the given number using fixed-point notation.
	 */
	mp.toFixed = function(num, decimals) {
		if (num && !isNaN(num)) {
			if (decimals && !isNaN(decimals)) {
				return num.toFixed(decimals);
			}
			else {
				return num.toFixed();
			}
		}
		else {
			return;
		}
	};


	/**
	* ------------------------------------------- Date Methods -------------------------------------------
	* @module Date Methods
	*/

// new Date()
	/** User Documentation
	 * @memberof module:Date Methods
	 * @desc Creates a new Date object.
	 * @method newDate
	 * @param {...Number} [args] - No arguments, an integer value representing time in milliseconds, string value representing a date or multiple integers representing year, month, date, hour, minutes, seconds, miliseconds.
	 * @example
	 * pulse.runtime.newDate();
	 * // Returns a date object representing the current date and time.
	 * @example
	 * pulse.runtime.newDate(-236721600000);
	 * // Returns Mon Jul 02 1962 00:00:00 GMT-0400 (EDT)
	 * @example
	 * pulse.runtime.newDate(1962, 6 ,2);
	 * // Returns Mon Jul 02 1962 00:00:00 GMT-0400 (EDT)
	 * @return {Object} Returns a date object.
	 */
	mp.newDate = function(args) {
		if (!arguments[0]) {
			return new Date();
		}
		else if (isNaN(arguments[0])) {
			var dateString = arguments[0];
			return new Date(dateString);
		}
		else if (!isNaN(arguments[0]) && arguments[1]) {
			var year = arguments[0] || null;
			var month = arguments[1] || null;
			var date = arguments[2] || null;
			var hours = arguments[3] || null;
			var minutes = arguments[4] || null;
			var seconds = arguments[5] || null;
			var milliseconds = arguments[6] || null;
			return new Date(year, month, date, hours, minutes, seconds, milliseconds);
		}
		else {
			return new Date(arguments[0]);
		}
	};

// date.getDate()
	/** User Documentation
	 * @memberof module:Date Methods
	 * @desc Returns a number representing the day of the month from a date object passed.
	 * @method getDate
	 * @param {Object} dateObj - A date object from which to extract the date (day of the month).
	 * @example
	 * pulse.placeholder["walmart"] = pulse.runtime.newDate(1962, 6 ,2);
	 * // pulse.placeholder.walmart is equal to the date object: Mon Jul 02 1962 00:00:00 GMT-0400 (EDT)
	 * pulse.runtime.getDate(pulse.placeholder.walmart);
	 * // Returns 2 (second day of the month)
	 * @return {Number} Returns the number representing the day of the month. Returns undefined if not a date object.
	 */
	mp.getDate = function(dateObj) {
		if (dateObj instanceof Date) {
			return dateObj.getDate();
		}
		else {
			return;
		}
	};

// date.getTime()
	/** User Documentation
	 * @memberof module:Date Methods
	 * @desc Returns the number of milliseconds since 1970/01/01 representing a date object passed.
	 * @method getTime
	 * @param {Object} dateObj - The date object to convert to milliseconds.
	 * @example
	 * pulse.placeholder["walmart"] = pulse.runtime.newDate(-236721600000);
	 * // pulse.placeholder.walmart is equal to the date object: Mon Jul 02 1962 00:00:00 GMT-0400 (EDT)
	 * pulse.runtime.getTime(pulse.placeholder.walmart);
	 * // Returns -236721600000
	 * @return {Number} Returns a number representing the date object passed in milliseconds since 1970/01/01 (negative number if before 1970/01/01). Returns undefined if not a date object.
	 */
	mp.getTime = function(dateObj) {
		if (dateObj instanceof Date) {
			return dateObj.getTime();
		}
		else {
			return;
		}
	};

// date.getDay()
	/** User Documentation
	 * @memberof module:Date Methods
	 * @desc Returns a number representing the day of the week starting at Sunday being 0 from a date object passed.
	 * @method getDay
	 * @param {Object} dateObj - The date object from which to determine the day of the week.
	 * @example
	 * pulse.placeholder["walmart"] = pulse.runtime.newDate(1962, 6 ,2);
	 * // pulse.placeholder.walmart is equal to the date object: Mon Jul 02 1962 00:00:00 GMT-0400 (EDT)
	 * pulse.runtime.getDay(pulse.placeholder.walmart);
	 * // Returns 1 (representing Monday)
	 * @return {Number} Returns a number that represents the day of the week 0 being Sunday, 1 being Monday etc. Returns undefined if not a date object.
	 */
	mp.getDay = function(dateObj) {
		if (dateObj instanceof Date) {
			return dateObj.getDay();
		}
		else {
			return;
		}
	};

// date.getFullYear()
	/** User Documentation
	 * @memberof module:Date Methods
	 * @desc Returns a number representing the year of a date object passed.
	 * @method getFullYear
	 * @param {Object} dateObj - The date object from which to determine the year.
	 * @example
	 * pulse.placeholder["walmart"] = pulse.runtime.newDate(1962, 6 ,2);
	 * // pulse.placeholder.walmart is equal to the date object: Mon Jul 02 1962 00:00:00 GMT-0400 (EDT)
	 * pulse.runtime.getFullYear(pulse.placeholder.walmart);
	 * // Returns 1962
	 * @return {Number} Returns the year of the date object. Returns undefined if not a date object.
	 */
	mp.getFullYear = function(dateObj) {
		if (dateObj instanceof Date) {
			return dateObj.getFullYear();
		}
		else {
			return;
		}
	};

// date.getHours()
	/** User Documentation
	 * @memberof module:Date Methods
	 * @desc Returns a number representing the hours of a date object passed.
	 * @method getHours
	 * @param {Object} dateObj - The date object from which to determine the hour
	 * @example
	 * pulse.placeholder["walmart"] = pulse.runtime.newDate(1962, 6 ,2);
	 * // pulse.placeholder.walmart is equal to the date object: Mon Jul 02 1962 00:00:00 GMT-0400 (EDT)
	 * pulse.runtime.getHours(pulse.placeholder.walmart);
	 * // Returns 0 (as 12am, midnight)
	 * @return {Number} Returns a number associated with the hour of a date object on a 24 hour clock (0-23). Returns undefined if not a date object.
	 */
	mp.getHours = function(dateObj) {
		if (dateObj instanceof Date) {
			return dateObj.getHours();
		}
		else {
			return;
		}
	};

// date.getMilliseconds()
	/** User Documentation
	 * @memberof module:Date Methods
	 * @desc Returns a number representing the milliseconds of a date object passed.
	 * @method getMilliseconds
	 * @param {Object} dateObj - The date object from which to determine the milliseconds.
	 * @example
	 * pulse.placeholder["walmart"] = pulse.runtime.newDate(1962, 6 ,2);
	 * // pulse.placeholder.walmart is equal to the date object: Mon Jul 02 1962 00:00:00 GMT-0400 (EDT)
	 * pulse.runtime.getMilliseconds(pulse.placeholder.walmart);
	 * // Returns 0 (as 0 milliseconds)
	 * @return {Number} Returns a number representing the milliseconds of a date object passed. Returns undefined if not a date object.
	 */
	mp.getMilliseconds = function(dateObj) {
		if (dateObj instanceof Date) {
			return dateObj.getMilliseconds();
		}
		else {
			return;
		}
	};

// date.getMinutes()
	/** User Documentation
	 * @memberof module:Date Methods
	 * @desc Returns a number representing the minutes of a date object passed.
	 * @method getMinutes
	 * @param {Object} dateObj - The date object from which to determine the minutes.
	 * @example
	 * pulse.placeholder["walmart"] = pulse.runtime.newDate(1962, 6 ,2);
	 * // pulse.placeholder.walmart is equal to the date object: Mon Jul 02 1962 00:00:00 GMT-0400 (EDT)
	 * pulse.runtime.getMinutes(pulse.placeholder.walmart);
	 * // Returns 0 (as 0 minutes)
	 * @return {Number} Returns a number representing the minutes of a date object passed. Returns undefined if not a date object.
	 */
	mp.getMinutes = function(dateObj) {
		if (dateObj instanceof Date) {
			return dateObj.getMinutes();
		}
		else {
			return;
		}
	};

// date.getMonth()
	/** User Documentation
	 * @memberof module:Date Methods
	 * @desc Returns a number representing the month of a date object passed.
	 * @method getMonth
	 * @param {Object} dateObj - The date object from which to determine the month.
	 * @example
	 * pulse.placeholder["walmart"] = pulse.runtime.newDate(1962, 6 ,2);
	 * // pulse.placeholder.walmart is equal to the date object: Mon Jul 02 1962 00:00:00 GMT-0400 (EDT)
	 * pulse.runtime.getMonth(pulse.placeholder.walmart);
	 * // Returns 6 (months start at 0 being January)
	 * @return {Number} Returns a number representing the month of a date object passed. Returns undefined if not a date object.
	 */
	mp.getMonth = function(dateObj) {
		if (dateObj instanceof Date) {
			return dateObj.getMonth();
		}
		else {
			return;
		}
	};

// date.getSeconds()
	/** User Documentation
	 * @memberof module:Date Methods
	 * @desc Returns a number representing the seconds of a date object passed.
	 * @method getSeconds
	 * @param {Object} dateObj - The date object from which to determine the seconds
	 * @example
	 * pulse.placeholder["walmart"] = pulse.runtime.newDate(1962, 6 ,2);
	 * // pulse.placeholder.walmart is equal to the date object: Mon Jul 02 1962 00:00:00 GMT-0400 (EDT)
	 * pulse.runtime.getSeconds(pulse.placeholder.walmart);
	 * // Returns 0 (as 0 seconds)
	 * @return {Number} Returns a number representing the seconds of a date object passed. Returns undefined if not a date object.
	 */
	mp.getSeconds = function(dateObj) {
		if (dateObj instanceof Date) {
			return dateObj.getSeconds();
		}
		else {
			return;
		}
	};

// date.getTimezoneOffset
	/** User Documentation
	 * @memberof module:Date Methods
	 * @desc Returns the time zone difference, in minutes, from date object passed to UTC.
	 * @method getTimezoneOffset
	 * @param {Object} dateObj - The date object from which to determine the UTC offset
	 * @example
	 * pulse.placeholder["newDateObject"] = pulse.runtime.newDate();
	 * pulse.runtime.getTimezoneOffset(pulse.placeholder.newDateObject);
	 * // Returns 240 (4 hour offset locally from UTC, 4 * 60)
	 * @return {Number} Returns a number representing the time difference between UTC and date object passed, in minutes.
	 */
	mp.getTimezoneOffset = function(dateObj) {
		if (dateObj instanceof Date) {
			return dateObj.getTimezoneOffset();
		}
		else {
			return;
		}
	};

	/**
	* ------------------------------------------- Type Methods -------------------------------------------
	* @module Type Methods
	*/

// typeof
	/** User Documentation
	 * @memberof module:Type Methods
	 * @desc Returns a string indicating type of the object passed.
	 * @method typeof
	 * @param {*} obj - The obj to determine the type of.
	 * @example
	 * pulse.runtime.typeof("foo");
	 * // Returns "string"
	 * @example
	 * pulse.runtime.typeof(3);
	 * // Returns "number"
	 * @return {String} Returns a string indicating the type of the object passed.
	 */
	mp['typeof'] = function(obj) {
		return typeof obj;
	};

	/**
	* ------------------------------------------- Condition Methods -------------------------------------------
	* @module Condition Methods
	*/

// switch
	/** User Documentation
	 * @memberof module:Condition Methods
	 * @desc Evaluate over multiple conditions
	 * @method switch
	 * @param {*} expression1 - Fixed value to be compared in the conditions.
	 * @param {...Object[]} cases - An array consisting of cases.
	 * @param {*} cases[].expression2 - The expression to be compared to expression1.
	 * @param {*} cases[].result - The result of case switch if condition is true.
	 * @param {*} def - Will return this value if result of condition not true. Default value if non of the cases are met.
	 * @example
	 * pulse.placeholder["id"] = "123";
	 * pulse.runtime.switch(pulse.placeholder.id, [["223", "fist case"]], "NOT first case");
	 * // Returns "NOT first case"
	 * @return {String} Value fetched from available attributes as a result of conditions
	 */
	mp['switch'] = function(expression1, cases, def) {
		for (var i = 0; i < cases.length; ++i) {
			var nextCase = cases[i];
			var expression2 = nextCase[0];
			var resultIfTrue = nextCase[1];
			if (expression1 === expression2) {
				return resultIfTrue;
			}
		}
		return def;
	};

	// TODO:
	// Regular Expressions
	// new RegExp
	
})(_bcq, pulse.runtime);
(function(bc, mp){
	'use strict';
	
	//
	// -------------------------------------------------- URL specific --------------------------------------------------
	//

	/**
	 * @desc Fetch url params map from query string
	 * @desc http://stackoverflow.com/questions/901115/
	 * @return {Object} map containing param name and value from query string
	 */
	mp.getURLParams = function(){
		var match,
			pl = /\+/g,  				// Regex for replacing addition symbol with a space
			search = /([^&=]+)=?([^&]*)/g,
			urlParams = {},
			decode = function (s) { return decodeURIComponent(s.replace(pl, " ")); },
			query  = window.location.search.substring(1);
		while (bc.utils.hasVal(match = search.exec(query))){
		   urlParams[decode(match[1])] = decode(match[2]);
		}
		return urlParams;
	};
	
	/**
	 * @desc Fetch a particular param value from query string
	 * @param {Array} Array that defines name and type of value to be fetched from available attributes
	 * @param {Object} attrs attributes available with current tagAction
	 * @param {Object} ph placeholders available with current tagAction mapping
	 * @return {String} value fetched from available attributes
	 */
	mp.getURLParam = function(qParam){
		var params = mp.getURLParams() || {};
		return qParam ? params[qParam] : params;
	};

	//
	// -------------------------------------------------- Storage specific --------------------------------------------------
	//
	
	/**
	 * @desc Read HTML5 localStorage
	 * @param {Array} Array that defines name and type of value to be fetched from available attributes
	 * @param {Object} attrs attributes available with current tagAction
	 * @param {Object} ph placeholders available with current tagAction mapping
	 * @return {String} value fetched from available attributes
	 */
	mp.readLocalStorage = function(key){
		return bc.store.read(key, {storage: 'localStorage'});
	};
	
	/**
	 * @desc Read HTML5 sessionStorage
	 * @param {Array} Array that defines name and type of value to be fetched from available attributes
	 * @param {Object} attrs attributes available with current tagAction
	 * @param {Object} ph placeholders available with current tagAction mapping
	 * @return {String} value fetched from available attributes
	 */
	mp.readSessionStorage = function(key){
		return bc.store.read(key, {storage: 'sessionStorage'});
	};
	
	/**
	 * @desc Write into HTML5 localStorage
	 * @param {Array} Array that defines name and type of value to be fetched from available attributes
	 * @param {Object} attrs attributes available with current tagAction
	 * @param {Object} ph placeholders available with current tagAction mapping
	 * @return {String} value fetched from available attributes
	 */
	mp.writeLocalStorage = function(key, val, expires){
		return bc.store.write(key, val, {expires: expires, storage: 'localStorage'});
	};
	
	/**
	 * @desc Write into HTML5 sessionStorage
	 * @param {Array} Array that defines name and type of value to be fetched from available attributes
	 * @param {Object} attrs attributes available with current tagAction
	 * @param {Object} ph placeholders available with current tagAction mapping
	 * @return {String} value fetched from available attributes
	 */
	mp.writeSessionStorage = function(key, val, expires){
		return bc.store.write(key, val, {expires: expires, storage: 'sessionStorage'});
	};
	
	
	/**
	 * @desc Get cookie value
	 * @param {Array} Array that defines name and type of value to be fetched from available attributes
	 * @param {Object} attrs attributes available with current tagAction
	 * @param {Object} ph placeholders available with current tagAction mapping
	 * @return {String} value fetched from available attributes
	 */
	mp.getCookie = function(name, separator, property){
		var args = arguments;
		switch(args.length){
			case 2:	 return bc.store.getCookie(args[0], args[1]);
			case 3:	 return bc.store.getCookie(args[0], args[1], args[2]);
			default: return bc.store.getCookie(args[0]); 
		}
		return;
	};
	
	/**
	 * @desc Set cookie value
	 * @param {Array} Array that defines name and type of value to be fetched from available attributes
	 * @param {Object} attrs attributes available with current tagAction
	 * @param {Object} ph placeholders available with current tagAction mapping
	 * @return {String} value fetched from available attributes
	 */
	mp.setCookie = function(name, value, domain, path, expires, secure){
		var options = {};
		options.domain = domain;
		options.path = path;
		options.expires = expires;
		options.secure = secure;
		return bc.store.setCookie(name, value, options);
	};
	
	/**
	 * @desc Set value of a property on cooki group
	 * @param {Array} Array that defines name and type of value to be fetched from available attributes
	 * @param {Object} attrs attributes available with current tagAction
	 * @param {Object} ph placeholders available with current tagAction mapping
	 * @return {String} value fetched from available attributes
	 */
	mp.setCookieGroup = function(name, property, value, separator, domain, path, expires, secure){
		var options = {};
		options.domain = domain;
		options.path = path;
		options.expires = expires;
		options.secure = secure;
		return bc.store.setCookieGroup(name, property, value, separator, options);
	};
	
	//
	// -------------------------------------------------- DOM Specific --------------------------------------------------
	//
	
	/**
	 * @desc Get object or a property out of object using document.querySelector
	 * @desc args[0] will be query selector string, arg[2] will be property to be fetched out of given selector object
	 * @desc if args[1] is not available then object itself will be returned
	 * @param {Array} Array that defines name and type of value to be fetched from available attributes
	 * @param {Object} attrs attributes available with current tagAction
	 * @param {Object} ph placeholders available with current tagAction mapping
	 * @return {Object} value fetched from available attributes
	 */
	mp.querySelector = function(qSelector, property){
		var d = document, 
			res;
		if(d && typeof d.querySelector === 'function'){
			res = d.querySelector(qSelector);
		}
		res = (res && property) ? res[property] : res;
		return res;
	};
	
	/**
	 * @desc Capture client details e.g. screen height/width viewport height/width
	 * @param {Array} Array that defines name and type of value to be fetched from available attributes
	 * @param {Object} attrs attributes available with current tagAction
	 * @param {Object} ph placeholders available with current tagAction mapping
	 * @return {Object} value fetched from available attributes
	 */
	mp.clientDetails = function(){
		return {dim:bc.utils.clientDim()};
	};
	
	//
	// -------------------------------------------------- WM Site Specific --------------------------------------------------
	//
	
	/**
	 * @desc Responsive status from page window._WML.IS_RESPONSIVE
	 * @param {Array} Array that defines name and type of value to be fetched from available attributes
	 * @param {Object} attrs attributes available with current tagAction
	 * @param {Object} ph placeholders available with current tagAction mapping
	 * @return {Object} value fetched from available attributes
	 */
	mp.responsive = function(){
		return bc.utils.isResponsive();
	};
		
})(_bcq, pulse.runtime);
(function(bc, mp) {
    'use strict';

    mp["common"] = mp["common"] || {};
    mp["common"]["enums"] = {};

})(_bcq, pulse.runtime);
(function(bc, mp) {
    'use strict';

    var mappingsInterpreter = {

        common_browse_groups: function(pulsePayload) {
            pulse.runtime.common_search_groups(pulsePayload);
        },

        common_browse_uc: function(pulsePayload) {
            pulse.runtime.common_refine_res_uc(pulsePayload);
            pulse.placeholder["uc_manShelf"] = pulse.runtime.hasValue(pulse.runtime.getProperty(pulse.placeholder.ta, "hi"));
            pulse.placeholder["uc_newManShelf"] = pulse.runtime.hasValue(pulse.runtime.getProperty(pulse.placeholder.ta, "hn"));
            pulse.placeholder["tmp75"] = pulse.runtime.execJsonPath(pulse.runtime.getProperty(pulse.placeholder.nf, "dn"), "$..[0]");
            pulse.placeholder["tmp76"] = pulse.runtime.firstArrayElm(pulse.placeholder.tmp75);
            pulse.placeholder["tmp77"] = pulse.runtime.equals(pulse.placeholder.uc_manShelf, true, pulse.placeholder.tmp76, null);
            pulse.placeholder["manDeptName"] = pulse.runtime.equals(pulse.placeholder.uc_newManShelf, true, pulse.runtime.getProperty(pulse.placeholder.ta, "dn"), pulse.placeholder.tmp77);
            pulse.placeholder["tmp79"] = pulse.runtime.hasValue(pulse.runtime.getProperty(pulse.placeholder.ta, "hn"));
            pulse.placeholder["manShelfName"] = pulse.runtime.equals(pulse.placeholder.tmp79, true, pulse.runtime.getProperty(pulse.placeholder.ta, "hn"), pulse.runtime.getProperty(pulse.placeholder.ta, "dn"));
            pulse.placeholder["uc_defBrowse"] = pulse.runtime.notEquals(pulse.placeholder.uc_manShelf, true, true, false);
            pulse.placeholder["uc_refBrowse"] = pulse.placeholder.newRefSrch;
            pulse.placeholder["tmp83"] = pulse.runtime.arrayLength(pulse.runtime.getProperty(pulse.placeholder.ta, "nn"));
            pulse.placeholder["shelfName"] = pulse.runtime.equals(pulse.placeholder.tmp83, 0, null, pulse.runtime.getProperty(pulse.placeholder.ta, "nn"));
            pulse.placeholder["tmp85"] = pulse.runtime.join(pulse.placeholder.shelfName, ": ");
            pulse.placeholder["tmp86"] = pulse.runtime.buildValidArray(pulse.runtime.getProperty(pulse.placeholder.ta, "dn"), pulse.runtime.getProperty(pulse.placeholder.ta, "cn"), pulse.runtime.getProperty(pulse.placeholder.ta, "sn"));
            pulse.placeholder["tmp87"] = pulse.runtime.join(pulse.placeholder.tmp86, ": ");
            pulse.placeholder["tmp88"] = pulse.runtime.buildValidArray(pulse.placeholder.tmp87, pulse.placeholder.tmp85);
            pulse.placeholder["tmp89"] = pulse.runtime.join(pulse.placeholder.tmp88, ": ");
            pulse.placeholder["tmp90"] = pulse.runtime.template("Seasonal: Online Specials: {{s1}}", pulse.runtime.getProperty(pulse.placeholder.ta, "hi"));
            pulse.placeholder["pageName_ph"] = pulse.runtime.switchCase(true, pulse.placeholder.uc_manShelf, pulse.placeholder.tmp90, pulse.placeholder.tmp89);
            pulse.placeholder["tmp92"] = pulse.runtime.join(pulse.placeholder.shelfName, ": ");
            pulse.placeholder["tmp93"] = pulse.runtime.buildValidArray(pulse.runtime.getProperty(pulse.placeholder.ta, "dn"), pulse.runtime.getProperty(pulse.placeholder.ta, "cn"), pulse.runtime.getProperty(pulse.placeholder.ta, "sn"));
            pulse.placeholder["tmp94"] = pulse.runtime.join(pulse.placeholder.tmp93, ": ");
            pulse.placeholder["tmp95"] = pulse.runtime.buildValidArray(pulse.placeholder.tmp94, pulse.placeholder.tmp92);
            pulse.placeholder["tmp96"] = pulse.runtime.join(pulse.placeholder.tmp95, ": ");
            pulse.placeholder["tmp97"] = pulse.runtime.template("Seasonal: {{s1}}: {{s2}}", pulse.placeholder.manDeptName, pulse.placeholder.manShelfName);
            pulse.placeholder["prop2_ph"] = pulse.runtime.switchCase(true, pulse.placeholder.uc_manShelf, pulse.placeholder.tmp97, pulse.placeholder.tmp96);
            pulse.placeholder["tmp99"] = pulse.runtime.buildValidArray(pulse.runtime.getProperty(pulse.placeholder.ta, "dn"), pulse.runtime.getProperty(pulse.placeholder.ta, "cn"), pulse.runtime.getProperty(pulse.placeholder.ta, "sn"));
            pulse.placeholder["tmp100"] = pulse.runtime.join(pulse.placeholder.tmp99, ": ");
            pulse.placeholder["prop4_ph"] = pulse.runtime.switchCase(true, pulse.placeholder.uc_defBrowse, pulse.placeholder.tmp100, null);
            pulse.placeholder["tmp104"] = pulse.runtime.template("{{s1}}: ref", pulse.placeholder.prop2_ph);
            pulse.placeholder["tmp105"] = pulse.runtime.logicalAND(pulse.placeholder.uc_defBrowse, pulse.placeholder.uc_refBrowse, true, false);
            pulse.placeholder["tmp107"] = pulse.runtime.logicalAND(pulse.placeholder.uc_defBrowse, pulse.placeholder.uc_noRes, true, false);
            pulse.placeholder["prop5_ph"] = pulse.runtime.switchCase(true, pulse.placeholder.tmp107, pulse.placeholder.prop2_ph, pulse.placeholder.tmp105, pulse.placeholder.tmp104, pulse.placeholder.uc_defBrowse, pulse.placeholder.prop2_ph, null);
        },

        common_btv_groups: function(pulsePayload) {
            pulse.placeholder["pr__se__st"] = pulsePayload["pr__se__st"];
            pulse.placeholder["tmp949"] = pulse.runtime.execJsonPath(pulsePayload.pr, "$..[?(String(@.bt).match(/ANCHOR/))]");
            pulse.placeholder["pr"] = pulse.runtime.firstArrayElm(pulse.placeholder.tmp949);
            pulse.placeholder["prKey"] = pulse.runtime.template("$..[key('{{s1}}')]", pulse.runtime.getProperty(pulse.placeholder.pr, "us"));
            pulse.placeholder["tmp952"] = pulse.runtime.execJsonPath(pulsePayload.pr__se, pulse.placeholder.prKey);
            pulse.placeholder["pr__se"] = pulse.runtime.firstArrayElm(pulse.placeholder.tmp952);
            pulse.placeholder["taxoPathPr"] = pulse.placeholder.pr;
        },

        common_bundle_groups: function(pulsePayload) {
            pulse.placeholder["pr__se__st"] = pulsePayload["pr__se__st"];
            pulse.placeholder["tmp281"] = pulse.runtime.execJsonPath(pulsePayload.pr, "$..[?(String(@.ty).match(/BUNDLE/))]");
            pulse.placeholder["pr"] = pulse.runtime.firstArrayElm(pulse.placeholder.tmp281);
            pulse.placeholder["prKey"] = pulse.runtime.template("$..[key('{{s1}}')]", pulse.runtime.getProperty(pulse.placeholder.pr, "us"));
            pulse.placeholder["tmp284"] = pulse.runtime.execJsonPath(pulsePayload.pr__se, pulse.placeholder.prKey);
            pulse.placeholder["pr__se"] = pulse.runtime.firstArrayElm(pulse.placeholder.tmp284);
            pulse.placeholder["taxoPathPr"] = pulse.runtime.getObjFirstData("pr");
        },

        common_bundle_uc: function(pulsePayload) {
            pulse.runtime.common_prod_taxonomy(pulsePayload);
            pulse.placeholder["prop2_ph"] = pulse.runtime.template("{{s1}} Product {{s2}} BUNDLE", pulse.runtime.getProperty(pulse.placeholder.pr, "nm"), pulse.runtime.getProperty(pulse.placeholder.pr, "us"));
        },

        common_cart_groups: function(pulsePayload) {
            pulse.placeholder["ca"] = pulse.runtime.getObjFirstData("ca");
            pulse.placeholder["tmp509"] = pulse.runtime.execJsonPath(pulsePayload.pr__se__ls, "$..[key('__cart$')]");
            pulse.placeholder["pr__se__ls"] = pulse.runtime.firstArrayElm(pulse.placeholder.tmp509);
        },

        common_cart_texts: function(pulsePayload) {
            pulse.placeholder["prop1Text"] = "Cart";
            pulse.runtime.common_er_texts(pulsePayload);
            pulse.placeholder["cartPageNameText"] = "Shopping Cart Cart";
            pulse.placeholder["emptyCartPageNameText"] = "Shopping Cart Empty";
            pulse.placeholder["prop42Text"] = "Checkout";
            pulse.placeholder["shpPkpExpText"] = "Shipping Options Expansion View";
        },

        common_cart_uc: function(pulsePayload) {
            pulse.placeholder["uc_emptyCart"] = pulse.runtime.equals(pulse.runtime.getProperty(pulse.placeholder.ca, "tq"), 0, true, false);
            pulse.placeholder["pageName_ph"] = pulse.runtime.equals(pulse.placeholder.uc_emptyCart, true, pulse.placeholder.emptyCartPageNameText, pulse.placeholder.cartPageNameText);
            pulse.placeholder["prop2_ph"] = pulse.placeholder.pageName_ph;
        },

        common_cat_groups: function(pulsePayload) {
            pulse.placeholder["ta"] = pulse.runtime.getObjFirstData("ta");
            pulse.placeholder["sr"] = pulse.runtime.getObjFirstData("sr");
        },

        common_cat_uc: function(pulsePayload) {
            pulse.runtime.common_taxonomy_uc(pulsePayload);
            pulse.placeholder["tmp148"] = pulse.runtime.notEquals(pulse.runtime.getProperty(pulse.placeholder.sr, "qt"), "", true, false);
            pulse.placeholder["tmp149"] = pulse.runtime.hasValue(pulse.runtime.getProperty(pulse.placeholder.sr, "qt"));
            pulse.placeholder["uc_search"] = pulse.runtime.logicalAND(pulse.placeholder.tmp149, pulse.placeholder.tmp148);
            pulse.placeholder["tmp151"] = pulse.runtime.buildValidArray(pulse.runtime.getProperty(pulse.placeholder.ta, "dn"), pulse.runtime.getProperty(pulse.placeholder.ta, "cn"), pulse.runtime.getProperty(pulse.placeholder.ta, "sn"));
            pulse.placeholder["tmp152"] = pulse.runtime.join(pulse.placeholder.tmp151, ": ");
            pulse.placeholder["prop2_ph"] = pulse.runtime.switchCase(true, pulse.placeholder.uc_search, "Search - browse redirect", pulse.placeholder.tmp152);
            pulse.placeholder["tmp155"] = pulse.runtime.buildValidArray(pulse.runtime.getProperty(pulse.placeholder.ta, "dn"), pulse.runtime.getProperty(pulse.placeholder.ta, "cn"), pulse.runtime.getProperty(pulse.placeholder.ta, "sn"));
            pulse.placeholder["tmp156"] = pulse.runtime.join(pulse.placeholder.tmp155, ": ");
            pulse.placeholder["tmp157"] = pulse.runtime.logicalOR(pulse.placeholder.uc_dept, pulse.placeholder.uc_cat, true, false);
            pulse.placeholder["tmp158"] = pulse.runtime.notEquals(pulse.placeholder.tmp157, true, true, false);
            pulse.placeholder["prop4_ph"] = pulse.runtime.switchCase(true, pulse.placeholder.tmp158, pulse.placeholder.tmp156, null);
            pulse.placeholder["tmp160"] = pulse.runtime.buildValidArray(pulse.runtime.getProperty(pulse.placeholder.ta, "dn"), pulse.runtime.getProperty(pulse.placeholder.ta, "cn"), pulse.runtime.getProperty(pulse.placeholder.ta, "sn"));
            pulse.placeholder["tmp161"] = pulse.runtime.join(pulse.placeholder.tmp160, ": ");
            pulse.placeholder["tmp162"] = pulse.runtime.logicalOR(pulse.placeholder.uc_dept, pulse.placeholder.uc_cat, true, false);
            pulse.placeholder["tmp163"] = pulse.runtime.logicalOR(pulse.placeholder.tmp162, pulse.placeholder.uc_subcat, true, false);
            pulse.placeholder["tmp164"] = pulse.runtime.notEquals(pulse.placeholder.tmp163, true, true, false);
            pulse.placeholder["prop5_ph"] = pulse.runtime.switchCase(true, pulse.placeholder.tmp164, pulse.placeholder.tmp161, null);
        },

        common_checkout_acct_err_uc: function(pulsePayload) {
            pulse.runtime.common_checkout_tahoe(pulsePayload);
            pulse.placeholder["tmp667"] = pulse.runtime.buildValidArray(pulse.placeholder.tahoe, pulse.placeholder.checkoutText, pulse.placeholder.loginText, pulse.placeholder.erText);
            pulse.placeholder["pageName_ph"] = pulse.runtime.join(pulse.placeholder.tmp667, ":");
            pulse.placeholder["prop2_ph"] = pulse.placeholder.pageName_ph;
        },

        common_checkout_acct_uc: function(pulsePayload) {
            pulse.runtime.common_checkout_tahoe(pulsePayload);
            pulse.placeholder["tmp663"] = pulse.runtime.buildValidArray(pulse.placeholder.tahoe, pulse.placeholder.checkoutText, pulse.placeholder.loginText);
            pulse.placeholder["pageName_ph"] = pulse.runtime.join(pulse.placeholder.tmp663, ":");
            pulse.placeholder["prop2_ph"] = pulse.placeholder.pageName_ph;
        },

        common_checkout_addr_err_uc: function(pulsePayload) {
            pulse.runtime.common_checkout_ffmethods(pulsePayload);
            pulse.runtime.common_checkout_shpaddr(pulsePayload);
            pulse.runtime.common_checkout_tahoe(pulsePayload);
            pulse.placeholder["tmp750"] = pulse.runtime.buildValidArray(pulse.placeholder.checkoutText, pulse.placeholder.ffDetailsText);
            pulse.placeholder["tmp751"] = pulse.runtime.join(pulse.placeholder.tmp750, ":");
            pulse.placeholder["tmp752"] = pulse.runtime.buildValidArray(pulse.placeholder.tahoeText, pulse.placeholder.checkoutText, pulse.placeholder.prfAddrText);
            pulse.placeholder["tmp753"] = pulse.runtime.join(pulse.placeholder.tmp752, ":");
            pulse.placeholder["pageNamePrefix"] = pulse.runtime.equals(true, pulse.placeholder.uc_tahoe, pulse.placeholder.tmp753, pulse.placeholder.tmp751);
            pulse.placeholder["tmp755"] = pulse.runtime.buildValidArray(pulse.placeholder.pageNamePrefix, pulse.placeholder.addShpText, pulse.placeholder.erText);
            pulse.placeholder["tmp756"] = pulse.runtime.join(pulse.placeholder.tmp755, ":");
            pulse.placeholder["tmp757"] = pulse.runtime.buildValidArray(pulse.placeholder.pageNamePrefix, pulse.placeholder.upShpText, pulse.placeholder.erText);
            pulse.placeholder["tmp758"] = pulse.runtime.join(pulse.placeholder.tmp757, ":");
            pulse.placeholder["pageName_ph"] = pulse.runtime.equals(true, pulse.placeholder.uc_updateShpAdd, pulse.placeholder.tmp758, pulse.placeholder.tmp756);
            pulse.placeholder["tmp760"] = pulse.runtime.buildValidArray(pulse.placeholder.pageName_ph, pulse.placeholder.userText);
            pulse.placeholder["prop2_ph"] = pulse.runtime.join(pulse.placeholder.tmp760, ":");
        },

        common_checkout_addr_uc: function(pulsePayload) {
            pulse.runtime.common_checkout_ffmethods(pulsePayload);
            pulse.runtime.common_checkout_shpaddr(pulsePayload);
            pulse.runtime.common_checkout_tahoe(pulsePayload);
            pulse.placeholder["tmp735"] = pulse.runtime.buildValidArray(pulse.placeholder.checkoutText, pulse.placeholder.ffDetailsText);
            pulse.placeholder["tmp736"] = pulse.runtime.join(pulse.placeholder.tmp735, ":");
            pulse.placeholder["tmp737"] = pulse.runtime.buildValidArray(pulse.placeholder.tahoeText, pulse.placeholder.checkoutText, pulse.placeholder.prfAddrText);
            pulse.placeholder["tmp738"] = pulse.runtime.join(pulse.placeholder.tmp737, ":");
            pulse.placeholder["pageNamePrefix"] = pulse.runtime.equals(true, pulse.placeholder.uc_tahoe, pulse.placeholder.tmp738, pulse.placeholder.tmp736);
            pulse.placeholder["tmp740"] = pulse.runtime.buildValidArray(pulse.placeholder.pageNamePrefix, pulse.placeholder.addShpText);
            pulse.placeholder["tmp741"] = pulse.runtime.join(pulse.placeholder.tmp740, ":");
            pulse.placeholder["tmp742"] = pulse.runtime.buildValidArray(pulse.placeholder.pageNamePrefix, pulse.placeholder.upShpText);
            pulse.placeholder["tmp743"] = pulse.runtime.join(pulse.placeholder.tmp742, ":");
            pulse.placeholder["pageName_ph"] = pulse.runtime.equals(true, pulse.placeholder.uc_updateShpAdd, pulse.placeholder.tmp743, pulse.placeholder.tmp741);
            pulse.placeholder["tmp745"] = pulse.runtime.buildValidArray(pulse.placeholder.pageName_ph, pulse.placeholder.userText);
            pulse.placeholder["prop2_ph"] = pulse.runtime.join(pulse.placeholder.tmp745, ":");
        },

        common_checkout_addr_valid_err_uc: function(pulsePayload) {
            pulse.runtime.common_checkout_tahoe(pulsePayload);
            pulse.placeholder["tmp763"] = pulse.runtime.buildValidArray(pulse.placeholder.checkoutText, pulse.placeholder.ffDetailsText);
            pulse.placeholder["tmp764"] = pulse.runtime.join(pulse.placeholder.tmp763, ":");
            pulse.placeholder["tmp765"] = pulse.runtime.buildValidArray(pulse.placeholder.tahoeText, pulse.placeholder.checkoutText, pulse.placeholder.prfAddrText);
            pulse.placeholder["tmp766"] = pulse.runtime.join(pulse.placeholder.tmp765, ":");
            pulse.placeholder["pageNamePrefix"] = pulse.runtime.equals(true, pulse.placeholder.uc_tahoe, pulse.placeholder.tmp766, pulse.placeholder.tmp764);
            pulse.placeholder["tmp768"] = pulse.runtime.buildValidArray(pulse.placeholder.pageNamePrefix, pulse.placeholder.addValidText, pulse.placeholder.erText);
            pulse.placeholder["pageName_ph"] = pulse.runtime.join(pulse.placeholder.tmp768, ":");
            pulse.placeholder["tmp770"] = pulse.runtime.buildValidArray(pulse.placeholder.pageName_ph, pulse.placeholder.userText);
            pulse.placeholder["prop2_ph"] = pulse.runtime.join(pulse.placeholder.tmp770, ":");
        },

        common_checkout_allpkp_uc: function(pulsePayload) {
            pulse.placeholder["tmp788"] = pulse.runtime.buildValidArray(pulse.placeholder.checkoutText, pulse.placeholder.ffDetailsText, pulse.placeholder.pkpLocText);
            pulse.placeholder["pageName_ph"] = pulse.runtime.join(pulse.placeholder.tmp788, ":");
            pulse.placeholder["tmp790"] = pulse.runtime.buildValidArray(pulse.placeholder.pageName_ph, pulse.placeholder.userText);
            pulse.placeholder["prop2_ph"] = pulse.runtime.join(pulse.placeholder.tmp790, ":");
        },

        common_checkout_er_groups: function(pulsePayload) {
            pulse.placeholder["tmp183"] = pulse.runtime.getObjFirstData("er", "Checkout");
            pulse.placeholder["tmp184"] = pulse.runtime.getObjFirstData("er");
            pulse.placeholder["tmp185"] = pulse.runtime.hasValue(pulsePayload.er);
            pulse.placeholder["er"] = pulse.runtime.switchCase(true, pulse.placeholder.tmp185, pulse.placeholder.tmp184, pulse.placeholder.tmp183);
        },

        common_checkout_ff_err_uc: function(pulsePayload) {
            pulse.placeholder["tmp698"] = pulse.runtime.buildValidArray(pulse.placeholder.checkoutText, pulse.placeholder.ffMthdText, pulse.placeholder.erText);
            pulse.placeholder["pageName_ph"] = pulse.runtime.join(pulse.placeholder.tmp698, ":");
            pulse.placeholder["tmp700"] = pulse.runtime.buildValidArray(pulse.placeholder.pageName_ph, pulse.placeholder.userText);
            pulse.placeholder["prop2_ph"] = pulse.runtime.join(pulse.placeholder.tmp700, ":");
        },

        common_checkout_ff_uc: function(pulsePayload) {
            pulse.placeholder["tmp694"] = pulse.runtime.buildValidArray(pulse.placeholder.checkoutText, pulse.placeholder.ffMthdText);
            pulse.placeholder["pageName_ph"] = pulse.runtime.join(pulse.placeholder.tmp694, ":");
            pulse.placeholder["tmp696"] = pulse.runtime.buildValidArray(pulse.placeholder.pageName_ph, pulse.placeholder.userText);
            pulse.placeholder["prop2_ph"] = pulse.runtime.join(pulse.placeholder.tmp696, ":");
        },

        common_checkout_ffmethods: function(pulsePayload) {
            pulse.placeholder["tmp647"] = pulse.runtime.hasValue(pulsePayload.fl);
            pulse.placeholder["tmp648"] = pulse.runtime.switchCase(true, pulse.placeholder.tmp647, pulsePayload.fl, pulsePayload.fl);
            pulse.placeholder["tmp649"] = pulse.runtime.execJsonPath(pulse.placeholder.tmp648, "$..[?(String(@.pn).match(/S2H/))]");
            pulse.placeholder["shpOptions"] = pulse.runtime.firstArrayElm(pulse.placeholder.tmp649);
            pulse.placeholder["tmp651"] = pulse.runtime.hasValue(pulsePayload.fl);
            pulse.placeholder["tmp652"] = pulse.runtime.switchCase(true, pulse.placeholder.tmp651, pulsePayload.fl, pulsePayload.fl);
            pulse.placeholder["tmp653"] = pulse.runtime.execJsonPath(pulse.placeholder.tmp652, "$..[?(String(@.pn).match(/S2S/))]");
            pulse.placeholder["pkpOptions"] = pulse.runtime.firstArrayElm(pulse.placeholder.tmp653);
            pulse.placeholder["tmp657"] = pulse.runtime.hasValue(pulse.placeholder.pkpOptions);
            pulse.placeholder["tmp658"] = pulse.runtime.equals(pulse.placeholder.tmp657, true, true, false);
            pulse.placeholder["tmp659"] = pulse.runtime.hasValue(pulse.placeholder.shpOptions);
            pulse.placeholder["tmp660"] = pulse.runtime.equals(pulse.placeholder.tmp659, true, true, false);
            pulse.placeholder["uc_mixed"] = pulse.runtime.logicalAND(pulse.placeholder.tmp660, pulse.placeholder.tmp658);
        },

        common_checkout_forgotpassword_err_uc: function(pulsePayload) {
            pulse.runtime.common_checkout_tahoe(pulsePayload);
            pulse.placeholder["tmp675"] = pulse.runtime.buildValidArray(pulse.placeholder.tahoe, pulse.placeholder.checkoutText, pulse.placeholder.forgotPasswordText, pulse.placeholder.erText);
            pulse.placeholder["pageName_ph"] = pulse.runtime.join(pulse.placeholder.tmp675, ":");
            pulse.placeholder["prop2_ph"] = pulse.placeholder.pageName_ph;
        },

        common_checkout_forgotpassword_uc: function(pulsePayload) {
            pulse.runtime.common_checkout_tahoe(pulsePayload);
            pulse.placeholder["tmp671"] = pulse.runtime.buildValidArray(pulse.placeholder.tahoe, pulse.placeholder.checkoutText, pulse.placeholder.forgotPasswordText);
            pulse.placeholder["pageName_ph"] = pulse.runtime.join(pulse.placeholder.tmp671, ":");
            pulse.placeholder["prop2_ph"] = pulse.placeholder.pageName_ph;
        },

        common_checkout_groups: function(pulsePayload) {
            pulse.placeholder["tmp573"] = pulse.runtime.getObjFirstData("ca", "Checkout");
            pulse.placeholder["tmp574"] = pulse.runtime.getObjFirstData("ca");
            pulse.placeholder["tmp575"] = pulse.runtime.hasValue(pulsePayload.ca);
            pulse.placeholder["ca"] = pulse.runtime.switchCase(true, pulse.placeholder.tmp575, pulse.placeholder.tmp574, pulse.placeholder.tmp573);
            pulse.placeholder["tmp577"] = pulse.runtime.getObjFirstData("cu", "Checkout");
            pulse.placeholder["tmp578"] = pulse.runtime.getObjFirstData("cu");
            pulse.placeholder["tmp579"] = pulse.runtime.hasValue(pulsePayload.cu);
            pulse.placeholder["cu"] = pulse.runtime.switchCase(true, pulse.placeholder.tmp579, pulse.placeholder.tmp578, pulse.placeholder.tmp577);
            pulse.placeholder["tmp581"] = pulse.runtime.getObjFirstData("ad", "Checkout");
            pulse.placeholder["tmp582"] = pulse.runtime.getObjFirstData("ad");
            pulse.placeholder["tmp583"] = pulse.runtime.hasValue(pulsePayload.ad);
            pulse.placeholder["ad"] = pulse.runtime.switchCase(true, pulse.placeholder.tmp583, pulse.placeholder.tmp582, pulse.placeholder.tmp581);
            pulse.placeholder["tmp585"] = pulse.runtime.getObjFirstData("yl", "Checkout");
            pulse.placeholder["tmp586"] = pulse.runtime.getObjFirstData("yl");
            pulse.placeholder["tmp587"] = pulse.runtime.hasValue(pulsePayload.yl);
            pulse.placeholder["yl"] = pulse.runtime.switchCase(true, pulse.placeholder.tmp587, pulse.placeholder.tmp586, pulse.placeholder.tmp585);
            pulse.placeholder["tmp589"] = pulse.runtime.getObjFirstData("py", "Checkout");
            pulse.placeholder["tmp590"] = pulse.runtime.getObjFirstData("py");
            pulse.placeholder["tmp591"] = pulse.runtime.hasValue(pulsePayload.py);
            pulse.placeholder["py"] = pulse.runtime.switchCase(true, pulse.placeholder.tmp591, pulse.placeholder.tmp590, pulse.placeholder.tmp589);
        },

        common_checkout_newacct_err_uc: function(pulsePayload) {
            pulse.runtime.common_checkout_tahoe(pulsePayload);
            pulse.placeholder["tmp687"] = pulse.runtime.buildValidArray(pulse.placeholder.tahoe, pulse.placeholder.checkoutText, pulse.placeholder.createAcctText, pulse.placeholder.erText);
            pulse.placeholder["pageName_ph"] = pulse.runtime.join(pulse.placeholder.tmp687, ":");
            pulse.placeholder["prop2_ph"] = pulse.placeholder.pageName_ph;
        },

        common_checkout_passwordreset_err_uc: function(pulsePayload) {
            pulse.runtime.common_checkout_tahoe(pulsePayload);
            pulse.placeholder["tmp683"] = pulse.runtime.buildValidArray(pulse.placeholder.tahoe, pulse.placeholder.checkoutText, pulse.placeholder.passwordResetText, pulse.placeholder.erText);
            pulse.placeholder["pageName_ph"] = pulse.runtime.join(pulse.placeholder.tmp683, ":");
            pulse.placeholder["prop2_ph"] = pulse.placeholder.pageName_ph;
        },

        common_checkout_passwordreset_uc: function(pulsePayload) {
            pulse.runtime.common_checkout_tahoe(pulsePayload);
            pulse.placeholder["tmp679"] = pulse.runtime.buildValidArray(pulse.placeholder.tahoe, pulse.placeholder.checkoutText, pulse.placeholder.passwordResetText);
            pulse.placeholder["pageName_ph"] = pulse.runtime.join(pulse.placeholder.tmp679, ":");
            pulse.placeholder["prop2_ph"] = pulse.placeholder.pageName_ph;
        },

        common_checkout_pay_change_err_uc: function(pulsePayload) {
            pulse.runtime.common_checkout_tahoe(pulsePayload);
            pulse.runtime.common_checkout_er_groups(pulsePayload);
            pulse.runtime.common_er_uc(pulsePayload);
            pulse.placeholder["tmp814"] = pulse.runtime.buildValidArray(pulse.placeholder.tahoe, pulse.placeholder.checkoutText, pulse.placeholder.pyText, pulse.placeholder.erText);
            pulse.placeholder["pageName_ph"] = pulse.runtime.join(pulse.placeholder.tmp814, ":");
            pulse.placeholder["tmp816"] = pulse.runtime.buildValidArray(pulse.placeholder.pageName_ph, pulse.placeholder.userText);
            pulse.placeholder["prop2_ph"] = pulse.runtime.join(pulse.placeholder.tmp816, ":");
        },

        common_checkout_pay_err_uc: function(pulsePayload) {
            pulse.runtime.common_checkout_tahoe(pulsePayload);
            pulse.runtime.common_checkout_er_groups(pulsePayload);
            pulse.runtime.common_er_uc(pulsePayload);
            pulse.placeholder["tmp807"] = pulse.runtime.buildValidArray(pulse.placeholder.tahoe, pulse.placeholder.checkoutText, pulse.placeholder.pyText, pulse.placeholder.erText);
            pulse.placeholder["pageName_ph"] = pulse.runtime.join(pulse.placeholder.tmp807, ":");
            pulse.placeholder["tmp809"] = pulse.runtime.buildValidArray(pulse.placeholder.pageName_ph, pulse.placeholder.userText);
            pulse.placeholder["prop2_ph"] = pulse.runtime.join(pulse.placeholder.tmp809, ":");
        },

        common_checkout_pay_uc: function(pulsePayload) {
            pulse.runtime.common_checkout_tahoe(pulsePayload);
            pulse.runtime.common_checkout_er_groups(pulsePayload);
            pulse.runtime.common_er_uc(pulsePayload);
            pulse.placeholder["tmp795"] = pulse.runtime.hasValue(pulse.runtime.getProperty(pulse.placeholder.yl, "sp"));
            pulse.placeholder["uc_pyCcSaved"] = pulse.runtime.equals(pulse.placeholder.tmp795, true, true, false);
            pulse.placeholder["tmp797"] = pulse.runtime.buildValidArray(pulse.placeholder.tahoe, pulse.placeholder.checkoutText, pulse.placeholder.pyText, pulse.placeholder.error);
            pulse.placeholder["tmp798"] = pulse.runtime.join(pulse.placeholder.tmp797, ":");
            pulse.placeholder["tmp799"] = pulse.runtime.buildValidArray(pulse.placeholder.tahoe, pulse.placeholder.checkoutText, pulse.placeholder.pySavedText, pulse.placeholder.error);
            pulse.placeholder["tmp800"] = pulse.runtime.join(pulse.placeholder.tmp799, ":");
            pulse.placeholder["pageName_ph"] = pulse.runtime.equals(true, pulse.placeholder.uc_pyCcSaved, pulse.placeholder.tmp800, pulse.placeholder.tmp798);
            pulse.placeholder["tmp802"] = pulse.runtime.buildValidArray(pulse.placeholder.pageName_ph, pulse.placeholder.userText);
            pulse.placeholder["prop2_ph"] = pulse.runtime.join(pulse.placeholder.tmp802, ":");
        },

        common_checkout_pkp_err_uc: function(pulsePayload) {
            pulse.runtime.common_checkout_ffmethods(pulsePayload);
            pulse.placeholder["tmp781"] = pulse.runtime.buildValidArray(pulse.placeholder.checkoutText, pulse.placeholder.ffDetailsText, pulse.placeholder.pkpText, pulse.placeholder.erText);
            pulse.placeholder["pageName_ph"] = pulse.runtime.join(pulse.placeholder.tmp781, ":");
            pulse.placeholder["tmp783"] = pulse.runtime.buildValidArray(pulse.placeholder.pageName_ph, pulse.placeholder.userText);
            pulse.placeholder["tmp784"] = pulse.runtime.join(pulse.placeholder.tmp783, ":");
            pulse.placeholder["tmp785"] = pulse.runtime.buildValidArray(pulse.placeholder.checkoutText, pulse.placeholder.ffDetailsText, pulse.placeholder.pkpText, pulse.placeholder.mixedText, pulse.placeholder.erText, pulse.placeholder.userText);
            pulse.placeholder["tmp786"] = pulse.runtime.join(pulse.placeholder.tmp785, ":");
            pulse.placeholder["prop2_ph"] = pulse.runtime.equals(true, pulse.placeholder.uc_mixed, pulse.placeholder.tmp786, pulse.placeholder.tmp784);
        },

        common_checkout_pkp_uc: function(pulsePayload) {
            pulse.runtime.common_checkout_ffmethods(pulsePayload);
            pulse.placeholder["tmp773"] = pulse.runtime.buildValidArray(pulse.placeholder.checkoutText, pulse.placeholder.ffDetailsText, pulse.placeholder.pkpText);
            pulse.placeholder["pageName_ph"] = pulse.runtime.join(pulse.placeholder.tmp773, ":");
            pulse.placeholder["tmp775"] = pulse.runtime.buildValidArray(pulse.placeholder.pageName_ph, pulse.placeholder.userText);
            pulse.placeholder["tmp776"] = pulse.runtime.join(pulse.placeholder.tmp775, ":");
            pulse.placeholder["tmp777"] = pulse.runtime.buildValidArray(pulse.placeholder.pageName_ph, pulse.placeholder.mixedText, pulse.placeholder.userText);
            pulse.placeholder["tmp778"] = pulse.runtime.join(pulse.placeholder.tmp777, ":");
            pulse.placeholder["prop2_ph"] = pulse.runtime.equals(true, pulse.placeholder.uc_mixed, pulse.placeholder.tmp778, pulse.placeholder.tmp776);
        },

        common_checkout_place_order_err_uc: function(pulsePayload) {
            pulse.runtime.common_checkout_tahoe(pulsePayload);
            pulse.placeholder["tmp824"] = pulse.runtime.buildValidArray(pulse.placeholder.tahoe, pulse.placeholder.checkoutText, pulse.placeholder.revOrderText, pulse.placeholder.erText);
            pulse.placeholder["pageName_ph"] = pulse.runtime.join(pulse.placeholder.tmp824, ":");
            pulse.placeholder["tmp826"] = pulse.runtime.buildValidArray(pulse.placeholder.pageName_ph, pulse.placeholder.userText);
            pulse.placeholder["prop2_ph"] = pulse.runtime.join(pulse.placeholder.tmp826, ":");
        },

        common_checkout_rev_uc: function(pulsePayload) {
            pulse.runtime.common_checkout_tahoe(pulsePayload);
            pulse.placeholder["tmp819"] = pulse.runtime.buildValidArray(pulse.placeholder.tahoe, pulse.placeholder.checkoutText, pulse.placeholder.revOrderText);
            pulse.placeholder["pageName_ph"] = pulse.runtime.join(pulse.placeholder.tmp819, ":");
            pulse.placeholder["tmp821"] = pulse.runtime.buildValidArray(pulse.placeholder.pageName_ph, pulse.placeholder.userText);
            pulse.placeholder["prop2_ph"] = pulse.runtime.join(pulse.placeholder.tmp821, ":");
        },

        common_checkout_shp_err_uc: function(pulsePayload) {
            pulse.runtime.common_checkout_ffmethods(pulsePayload);
            pulse.runtime.common_checkout_shpaddr(pulsePayload);
            pulse.runtime.common_checkout_tahoe(pulsePayload);
            pulse.placeholder["tmp720"] = pulse.runtime.buildValidArray(pulse.placeholder.checkoutText, pulse.placeholder.ffDetailsText);
            pulse.placeholder["tmp721"] = pulse.runtime.join(pulse.placeholder.tmp720, ":");
            pulse.placeholder["tmp722"] = pulse.runtime.buildValidArray(pulse.placeholder.tahoe, pulse.placeholder.checkoutText, pulse.placeholder.prfAddrText);
            pulse.placeholder["tmp723"] = pulse.runtime.join(pulse.placeholder.tmp722, ":");
            pulse.placeholder["pageNamePrefix"] = pulse.runtime.equals(true, pulse.placeholder.uc_tahoe, pulse.placeholder.tmp723, pulse.placeholder.tmp721);
            pulse.placeholder["tmp725"] = pulse.runtime.buildValidArray(pulse.placeholder.pageNamePrefix, pulse.placeholder.shpText, pulse.placeholder.erText);
            pulse.placeholder["pageName_ph"] = pulse.runtime.join(pulse.placeholder.tmp725, ":");
            pulse.placeholder["tmp727"] = pulse.runtime.buildValidArray(pulse.placeholder.pageName_ph, pulse.placeholder.userText);
            pulse.placeholder["tmp728"] = pulse.runtime.join(pulse.placeholder.tmp727, ":");
            pulse.placeholder["tmp729"] = pulse.runtime.buildValidArray(pulse.placeholder.checkoutText, pulse.placeholder.ffDetailsText, pulse.placeholder.shpText, pulse.placeholder.mixedText, pulse.placeholder.erText, pulse.placeholder.userText);
            pulse.placeholder["tmp730"] = pulse.runtime.join(pulse.placeholder.tmp729, ":");
            pulse.placeholder["prop2_ph"] = pulse.runtime.equals(true, pulse.placeholder.uc_mixed, pulse.placeholder.tmp730, pulse.placeholder.tmp728);
        },

        common_checkout_shp_uc: function(pulsePayload) {
            pulse.runtime.common_checkout_ffmethods(pulsePayload);
            pulse.runtime.common_checkout_shpaddr(pulsePayload);
            pulse.runtime.common_checkout_tahoe(pulsePayload);
            pulse.placeholder["tmp705"] = pulse.runtime.buildValidArray(pulse.placeholder.checkoutText, pulse.placeholder.ffDetailsText);
            pulse.placeholder["tmp706"] = pulse.runtime.join(pulse.placeholder.tmp705, ":");
            pulse.placeholder["tmp707"] = pulse.runtime.buildValidArray(pulse.placeholder.tahoe, pulse.placeholder.checkoutText, pulse.placeholder.prfAddrText);
            pulse.placeholder["tmp708"] = pulse.runtime.join(pulse.placeholder.tmp707, ":");
            pulse.placeholder["pageNamePrefix"] = pulse.runtime.equals(true, pulse.placeholder.uc_tahoe, pulse.placeholder.tmp708, pulse.placeholder.tmp706);
            pulse.placeholder["tmp710"] = pulse.runtime.buildValidArray(pulse.placeholder.pageNamePrefix, pulse.placeholder.shpText);
            pulse.placeholder["pageName_ph"] = pulse.runtime.join(pulse.placeholder.tmp710, ":");
            pulse.placeholder["tmp712"] = pulse.runtime.buildValidArray(pulse.placeholder.pageName_ph, pulse.placeholder.userText);
            pulse.placeholder["tmp713"] = pulse.runtime.join(pulse.placeholder.tmp712, ":");
            pulse.placeholder["tmp714"] = pulse.runtime.buildValidArray(pulse.placeholder.checkoutText, pulse.placeholder.ffDetailsText, pulse.placeholder.shpText, pulse.placeholder.mixedText, pulse.placeholder.userText);
            pulse.placeholder["tmp715"] = pulse.runtime.join(pulse.placeholder.tmp714, ":");
            pulse.placeholder["prop2_ph"] = pulse.runtime.equals(true, pulse.placeholder.uc_mixed, pulse.placeholder.tmp715, pulse.placeholder.tmp713);
        },

        common_checkout_shpaddr: function(pulsePayload) {
            pulse.placeholder["uc_updateShpAddr"] = pulse.runtime.equals(pulse.runtime.getProperty(pulse.placeholder.ad, "ty"), "edit", true, false);
            pulse.placeholder["uc_addShpAddr"] = pulse.runtime.equals(pulse.runtime.getProperty(pulse.placeholder.ad, "ty"), "new", true, false);
        },

        common_checkout_tahoe: function(pulsePayload) {
            pulse.placeholder["tmp643"] = pulse.runtime.match(pulsePayload.u, "\\w*/shipping-pass\\w*");
            pulse.placeholder["uc_tahoe"] = pulse.runtime.hasValue(pulse.placeholder.tmp643);
            pulse.placeholder["tahoe"] = pulse.runtime.equals(pulse.placeholder.uc_tahoe, true, pulse.placeholder.tahoeText, null);
        },

        common_checkout_texts: function(pulsePayload) {
            pulse.placeholder["checkoutText"] = "Checkout";
            pulse.placeholder["loginText"] = "Login";
            pulse.placeholder["createAcctText"] = "Create Account";
            pulse.placeholder["forgotPasswordText"] = "Forgot Password";
            pulse.placeholder["passwordResetText"] = "Password Reset";
            pulse.placeholder["ffText"] = "Fulfillment";
            pulse.placeholder["noZipText"] = "No Zip";
            pulse.placeholder["ffMthdText"] = "Fulfillment Method";
            pulse.placeholder["ffDetailsText"] = "Fulfillment Details";
            pulse.placeholder["pkpText"] = "Pick Up";
            pulse.placeholder["pkpLocText"] = "Pick Up Location";
            pulse.placeholder["shpText"] = "Shipping";
            pulse.placeholder["upShpText"] = "Update Shipping Address";
            pulse.placeholder["addShpText"] = "Add New Shipping Address";
            pulse.placeholder["addValidText"] = "Shipping Address Validation";
            pulse.placeholder["mixedText"] = "Mixed";
            pulse.placeholder["pyText"] = "Payment";
            pulse.placeholder["pySavedText"] = "Payment with Saved";
            pulse.placeholder["pyAddText"] = "Add New Payment Method";
            pulse.placeholder["pyEditSavedText"] = "Edit Saved Payment Method";
            pulse.placeholder["addText"] = "Add New";
            pulse.placeholder["editText"] = "Edit";
            pulse.placeholder["giftcardText"] = "GiftCard";
            pulse.placeholder["creditcardText"] = "CC";
            pulse.placeholder["addCCText"] = "Add New Card";
            pulse.placeholder["revOrderText"] = "Review Order";
            pulse.placeholder["erText"] = "Error";



            pulse.placeholder["tmp638"] = pulse.runtime.equals(pulse.runtime.getProperty(pulse.placeholder.cu, "cf"), "New Account Email", "New Account", pulse.runtime.equals(pulse.runtime.getProperty(pulse.placeholder.cu, "cf"), "Guest", "Non-Guest", pulse.runtime.getProperty(pulse.placeholder.cu, "cf")));
            pulse.placeholder["userText"] = pulse.runtime.equals(pulse.runtime.getProperty(pulse.placeholder.cu, "gs"), 1, "Guest", pulse.runtime.equals(pulse.runtime.getProperty(pulse.placeholder.cu, "cf"), "New", "New Account", pulse.placeholder.tmp638));
            pulse.placeholder["pswdResetText"] = "Password Reset";
            pulse.placeholder["prfAddrText"] = "Preferred Address";
            pulse.placeholder["tahoeText"] = "ShippingPass";
        },

        common_checkout_zip_uc: function(pulsePayload) {
            pulse.placeholder["tmp690"] = pulse.runtime.buildValidArray(pulse.placeholder.checkoutText, pulse.placeholder.ffText, pulse.placeholder.noZipText);
            pulse.placeholder["pageName_ph"] = pulse.runtime.join(pulse.placeholder.tmp690, ":");
            pulse.placeholder["tmp692"] = pulse.runtime.buildValidArray(pulse.placeholder.pageName_ph, pulse.placeholder.userText);
            pulse.placeholder["prop2_ph"] = pulse.runtime.join(pulse.placeholder.tmp692, ":");
        },

        common_collection_groups: function(pulsePayload) {
            pulse.placeholder["ta"] = pulse.runtime.getObjFirstData("ta");
        },

        common_er_texts: function(pulsePayload) {
            pulse.placeholder["erText"] = "Error";
        },

        common_er_uc: function(pulsePayload) {
            pulse.placeholder["tmp188"] = pulse.runtime.notEquals(pulse.runtime.getProperty(pulse.placeholder.er, "ms"), null, true, false);
            pulse.placeholder["tmp189"] = pulse.runtime.hasValue(pulse.runtime.getProperty(pulse.placeholder.er, "ms"));
            pulse.placeholder["tmp190"] = pulse.runtime.logicalAND(pulse.placeholder.tmp189, pulse.placeholder.tmp188, true, false);
            pulse.placeholder["tmp191"] = pulse.runtime.notEquals(pulse.runtime.getProperty(pulse.placeholder.er, "id"), null, true, false);
            pulse.placeholder["tmp192"] = pulse.runtime.hasValue(pulse.runtime.getProperty(pulse.placeholder.er, "id"));
            pulse.placeholder["tmp193"] = pulse.runtime.logicalAND(pulse.placeholder.tmp192, pulse.placeholder.tmp191, true, false);
            pulse.placeholder["tmp194"] = pulse.runtime.logicalOR(pulse.placeholder.tmp193, pulse.placeholder.tmp190, true, false);
            pulse.placeholder["tmp195"] = pulse.runtime.hasValue(pulse.placeholder.er);
            pulse.placeholder["uc_er"] = pulse.runtime.logicalAND(pulse.placeholder.tmp195, pulse.placeholder.tmp194, true, false);
            pulse.placeholder["error"] = pulse.runtime.equals(pulse.placeholder.uc_er, true, pulse.placeholder.erText, null);
        },

        common_master_groups: function(pulsePayload) {
            pulse.placeholder["st"] = pulse.runtime.getObjFirstData("st");
        },

        common_onehg_base_groups: function(pulsePayload) {
            pulse.placeholder["co"] = pulse.runtime.getObjFirstData("co");
            pulse.placeholder["od"] = pulse.runtime.getObjFirstData("od");
        },

        common_onehg_groups: function(pulsePayload) {
            pulse.runtime.common_onehg_base_groups(pulsePayload);
            pulse.placeholder["primaryPr"] = pulse.runtime.execJsonPath(pulsePayload.pr, "$..[?(@.wf<1)]");
            pulse.placeholder["firstPr"] = pulse.runtime.getObjFirstData("pr");
            pulse.placeholder["tmp487"] = pulse.runtime.firstArrayElm(pulse.placeholder.primaryPr);
            pulse.placeholder["pr"] = pulse.runtime.equals(pulse.runtime.getProperty(pulse.placeholder.primaryPr, "length"), 0, pulse.placeholder.firstPr, pulse.placeholder.tmp487);
        },

        common_onehg_texts: function(pulsePayload) {
            pulse.placeholder["oneHGText"] = "1HG";
            pulse.placeholder["oneHGErrorText"] = "Error";
        },

        common_pac_groups: function(pulsePayload) {
            pulse.runtime.common_prod_groups(pulsePayload);
        },

        common_prod_groups: function(pulsePayload) {
            pulse.placeholder["sl"] = pulse.runtime.getObjFirstData("sl");
            pulse.placeholder["ur"] = pulse.runtime.getObjFirstData("ur");
            pulse.placeholder["uq"] = pulse.runtime.getObjFirstData("uq");
            pulse.placeholder["co"] = pulse.runtime.getObjFirstData("co");
            pulse.placeholder["pr__se__st"] = pulsePayload["pr__se__st"];
            pulse.placeholder["primaryPr"] = pulse.runtime.execJsonPath(pulsePayload.pr, "$..[?(@.wf<1)]");
            pulse.placeholder["firstPr"] = pulse.runtime.getObjFirstData("pr");
            pulse.placeholder["tmp266"] = pulse.runtime.firstArrayElm(pulse.placeholder.primaryPr);
            pulse.placeholder["pr"] = pulse.runtime.equals(pulse.runtime.getProperty(pulse.placeholder.primaryPr, "length"), 0, pulse.placeholder.firstPr, pulse.placeholder.tmp266);
            pulse.placeholder["prKey"] = pulse.runtime.template("$..[key('{{s1}}')]", pulse.runtime.getProperty(pulse.placeholder.pr, "id"));
            pulse.placeholder["tmp269"] = pulse.runtime.execJsonPath(pulsePayload.pr__se, pulse.placeholder.prKey);
            pulse.placeholder["pr__se"] = pulse.runtime.firstArrayElm(pulse.placeholder.tmp269);
            pulse.placeholder["taxoPathPr"] = pulse.placeholder.pr;
        },

        common_prod_taxonomy: function(pulsePayload) {
            pulse.placeholder["taxoPath"] = pulse.runtime.split(pulse.runtime.getProperty(pulse.placeholder.taxoPathPr, "pc"), "/");
            pulse.placeholder["tmp295"] = pulse.runtime.execJsonPath(pulse.placeholder.taxoPath, "$..[0]");
            pulse.placeholder["deptName"] = pulse.runtime.firstArrayElm(pulse.placeholder.tmp295);
            pulse.placeholder["tmp297"] = pulse.runtime.execJsonPath(pulse.placeholder.taxoPath, "$..[1]");
            pulse.placeholder["catName"] = pulse.runtime.firstArrayElm(pulse.placeholder.tmp297);
            pulse.placeholder["tmp299"] = pulse.runtime.execJsonPath(pulse.placeholder.taxoPath, "$..[2]");
            pulse.placeholder["subCatName"] = pulse.runtime.firstArrayElm(pulse.placeholder.tmp299);
            pulse.placeholder["tmp301"] = pulse.runtime.buildValidArray(pulse.placeholder.deptName, pulse.placeholder.catName, pulse.placeholder.subCatName);
            pulse.placeholder["prop4_ph"] = pulse.runtime.join(pulse.placeholder.tmp301, ":");
            pulse.placeholder["prop5_ph"] = pulse.runtime.join(pulse.placeholder.taxoPath, ":");
        },

        common_prod_uc: function(pulsePayload) {
            pulse.runtime.common_prod_taxonomy(pulsePayload);
            pulse.placeholder["prop2_ph"] = pulse.runtime.template("{{s1}} Product {{s2}}", pulse.runtime.getProperty(pulse.placeholder.pr, "nm"), pulse.runtime.getProperty(pulse.placeholder.pr, "us"));
        },

        common_ql_groups: function(pulsePayload) {
            pulse.runtime.common_prod_groups(pulsePayload);
        },

        common_ql_uc: function(pulsePayload) {
            pulse.runtime.common_prod_uc(pulsePayload);
        },

        common_refine_res_uc: function(pulsePayload) {
            pulse.placeholder["uc_noRes"] = pulse.runtime.equals(pulse.runtime.getProperty(pulse.placeholder.pl, "tr"), 0, true, false);
            pulse.placeholder["tmp56"] = pulse.runtime.arrayLength(pulse.runtime.getProperty(pulse.placeholder.pl, "st"));
            pulse.placeholder["storeEntries"] = pulse.runtime.greaterThan(pulse.placeholder.tmp56, 0, true, false);
            pulse.placeholder["uc_storeAvailSel"] = pulse.runtime.equals(pulse.placeholder.storeEntries, true, true, false);
            pulse.placeholder["storesLength"] = pulse.runtime.arrayLength(pulse.runtime.getProperty(pulse.placeholder.pl, "st"));
            pulse.placeholder["isSingleStore"] = pulse.runtime.equals(pulse.placeholder.storesLength, 1, true, false);
            pulse.placeholder["isOnlineOnly"] = pulse.runtime.logicalAND(pulse.placeholder.isSingleStore, pulse.placeholder.onlineSel, true, false);
            pulse.placeholder["uc_onlineSel"] = pulse.runtime.switchCase(pulse.placeholder.isOnlineOnly, true, true, false);
            pulse.placeholder["newRefSrch"] = pulse.runtime.equals(pulse.runtime.getProperty(pulse.placeholder.pl, "rr"), "2", true, false);
            pulse.placeholder["tmp65"] = pulse.runtime.arrayLength(pulse.runtime.getProperty(pulse.placeholder.nf, "sn"));
            pulse.placeholder["uc_navFacetSel"] = pulse.runtime.greaterThan(pulse.placeholder.tmp65, 0, true, false);
        },

        common_search_groups: function(pulsePayload) {
            pulse.placeholder["pl"] = pulse.runtime.getObjFirstData("pl");
            pulse.placeholder["sr"] = pulse.runtime.getObjFirstData("sr");
            pulse.placeholder["pr__se"] = pulsePayload["pr__se"];
            pulse.placeholder["ta"] = pulse.runtime.getObjFirstData("ta");
            pulse.placeholder["fa"] = pulsePayload["fa"];
            pulse.placeholder["or"] = pulse.runtime.getObjFirstData("or");
            pulse.placeholder["nf"] = pulse.runtime.getObjFirstData("nf");
            pulse.placeholder["sc"] = pulse.runtime.getObjFirstData("sc");
        },

        common_search_uc: function(pulsePayload) {
            pulse.runtime.common_refine_res_uc(pulsePayload);
            pulse.placeholder["uc_autoCorrect"] = pulse.runtime.equals(pulse.runtime.getProperty(pulse.placeholder.sr, "me"), "auto_corrected", true, false);
            pulse.placeholder["uc_typeAhead"] = pulse.runtime.equals(pulse.runtime.getProperty(pulse.placeholder.sr, "me"), "type_ahead", true, false);
            pulse.placeholder["uc_relaSrch"] = pulse.runtime.equals(pulse.runtime.getProperty(pulse.placeholder.sr, "me"), "related", true, false);
            pulse.placeholder["uc_crossCat"] = pulse.runtime.equals(pulse.runtime.getProperty(pulse.placeholder.sr, "me"), "cross_category", true, false);
        },

        common_taxonomy_uc: function(pulsePayload) {
            pulse.placeholder["deptExists"] = pulse.runtime.hasValue(pulse.runtime.getProperty(pulse.placeholder.ta, "dn"));
            pulse.placeholder["catExists"] = pulse.runtime.hasValue(pulse.runtime.getProperty(pulse.placeholder.ta, "cn"));
            pulse.placeholder["tmp47"] = pulse.runtime.hasValue(pulse.runtime.getProperty(pulse.placeholder.ta, "cn"));
            pulse.placeholder["noCatExists"] = pulse.runtime.equals(pulse.placeholder.tmp47, true, false, true);
            pulse.placeholder["subcatExists"] = pulse.runtime.hasValue(pulse.runtime.getProperty(pulse.placeholder.ta, "sn"));
            pulse.placeholder["tmp50"] = pulse.runtime.hasValue(pulse.runtime.getProperty(pulse.placeholder.ta, "sn"));
            pulse.placeholder["noSubcatExists"] = pulse.runtime.equals(pulse.placeholder.tmp50, true, false, true);
            pulse.placeholder["uc_dept"] = pulse.runtime.logicalAND(pulse.placeholder.deptExists, pulse.placeholder.noCatExists, true, false);
            pulse.placeholder["uc_cat"] = pulse.runtime.logicalAND(pulse.placeholder.catExists, pulse.placeholder.noSubcatExists, true, false);
            pulse.placeholder["uc_subcat"] = pulse.placeholder.subcatExists;
        },

        common_thankyou_groups: function(pulsePayload) {
            pulse.placeholder["cu"] = pulse.runtime.getObjFirstData("cu");
            pulse.placeholder["ad"] = pulse.runtime.getObjFirstData("ad");
            pulse.placeholder["yl"] = pulse.runtime.getObjFirstData("yl");
            pulse.placeholder["pr"] = pulse.runtime.getObjFirstData("pr");
            pulse.placeholder["tmp597"] = pulse.runtime.execJsonPath(pulsePayload.od, "$..[?(@.cf<1)]");
            pulse.placeholder["od"] = pulse.runtime.firstArrayElm(pulse.placeholder.tmp597);
            pulse.placeholder["py"] = pulse.runtime.getObjFirstData("py");
        },

        common_thankyou_texts: function(pulsePayload) {
            pulse.placeholder["odText"] = "Order Confirmation";
            pulse.placeholder["pipText"] = "Pay In Person Reservation Confirmation";



            pulse.placeholder["tmp859"] = pulse.runtime.equals(pulse.runtime.getProperty(pulse.placeholder.cu, "cf"), "New Account Email", "New Account", pulse.runtime.equals(pulse.runtime.getProperty(pulse.placeholder.cu, "cf"), "Guest", "Non-Guest", pulse.runtime.getProperty(pulse.placeholder.cu, "cf")));
            pulse.placeholder["userText"] = pulse.runtime.equals(pulse.runtime.getProperty(pulse.placeholder.cu, "gs"), 1, "Guest", pulse.runtime.equals(pulse.runtime.getProperty(pulse.placeholder.cu, "cf"), "New", "New Account", pulse.placeholder.tmp859));

            pulse.placeholder["tahoeText"] = "ShippingPass";
            pulse.placeholder["checkoutText"] = "Checkout";
        },

        common_thankyou_uc: function(pulsePayload) {
            pulse.placeholder["uc_cash"] = pulse.runtime.equals(pulse.runtime.getProperty(pulse.placeholder.py, "ty"), "PIP", true, false);
            pulse.placeholder["tmp870"] = pulse.runtime.match(pulsePayload.r, "\\w*/shipping-pass\\w*");
            pulse.placeholder["uc_tahoe"] = pulse.runtime.hasValue(pulse.placeholder.tmp870);
            pulse.placeholder["tahoe"] = pulse.runtime.equals(pulse.placeholder.uc_tahoe, true, pulse.placeholder.tahoeText, null);
            pulse.placeholder["tmp874"] = pulse.runtime.buildValidArray(pulse.placeholder.tahoe, pulse.placeholder.checkoutText, pulse.placeholder.odText);
            pulse.placeholder["tmp875"] = pulse.runtime.join(pulse.placeholder.tmp874, ":");
            pulse.placeholder["tmp876"] = pulse.runtime.buildValidArray(pulse.placeholder.tahoe, pulse.placeholder.checkoutText, pulse.placeholder.pipText);
            pulse.placeholder["tmp877"] = pulse.runtime.join(pulse.placeholder.tmp876, ":");
            pulse.placeholder["pageName_ph"] = pulse.runtime.equals(pulse.placeholder.uc_cash, true, pulse.placeholder.tmp877, pulse.placeholder.tmp875);
            pulse.placeholder["tmp879"] = pulse.runtime.buildValidArray(pulse.placeholder.pageName_ph, pulse.placeholder.userText);
            pulse.placeholder["prop2_ph"] = pulse.runtime.join(pulse.placeholder.tmp879, ":");
        },

        common_xpr_groups: function(pulsePayload) {
            pulse.placeholder["ee"] = pulse.runtime.getObjFirstData("ee", "XPR");
            pulse.placeholder["ee__ex"] = pulse.runtime.getObjFirstData("ee__ex", "XPR");
            pulse.placeholder["local_ee__ex"] = pulse.runtime.readLocalStorage("ee__ex");
            pulse.placeholder["local_ee"] = pulse.runtime.readLocalStorage("ee");
        },

        common_xpr_pv: function(pulsePayload) {
            pulse.placeholder["tmp6"] = pulse.runtime.prop13fn(pulse.placeholder.ee__ex);
            pulse.placeholder["tmp7"] = pulse.runtime.prop13fn(pulse.placeholder.local_ee__ex);
            pulse.placeholder["tmp8"] = pulse.runtime.hasValue(pulse.placeholder.local_ee__ex);
            pulse.placeholder["prop13ph"] = pulse.runtime.switchCase(true, pulse.placeholder.tmp8, pulse.placeholder.tmp7, pulse.placeholder.tmp6);
        }
    };

    bc.utils.merge(mp, mappingsInterpreter);

})(_bcq, pulse.runtime);
(function(bc, mp) {
    'use strict';

    mp["wmbeacon"] = mp["wmbeacon"] || {};
    mp["wmbeacon"]["enums"] = {
        "rqTp": "post_limit"
    };

})(_bcq, pulse.runtime);
(function(bc, mp) {
    'use strict';

    var mappingsInterpreter = {

        wmbeacon_Account_ACCT_VIEW: function(pulsePayload) {
            pulse.runtime.common_xpr_groups(pulsePayload);
            pulse.runtime.wmbeacon_xpr_pv(pulsePayload);
        },

        wmbeacon_Account_LANDING_VIEW: function(pulsePayload) {
            pulse.runtime.common_xpr_groups(pulsePayload);
            pulse.runtime.wmbeacon_xpr_pv(pulsePayload);
        },
        wmbeacon_AccountManage_ACCT_MANAGE_VIEW: function(pulsePayload) {
            pulse.runtime.common_xpr_groups(pulsePayload);
            pulse.runtime.wmbeacon_xpr_pv(pulsePayload);
        },

        wmbeacon_AccountManage_SETTINGS_VIEW: function(pulsePayload) {
            pulse.runtime.common_xpr_groups(pulsePayload);
            pulse.runtime.wmbeacon_xpr_pv(pulsePayload);
        },
        wmbeacon_AccountManage__SETTINGS_VIEW: function(pulsePayload) {
            pulse.runtime.common_xpr_groups(pulsePayload);
            pulse.runtime.wmbeacon_xpr_pv(pulsePayload);
        },
        wmbeacon_AccountOrder__ORDER_LIST_VIEW: function(pulsePayload) {
            pulse.runtime.common_xpr_groups(pulsePayload);
            pulse.runtime.wmbeacon_xpr_pv(pulsePayload);
        },

        wmbeacon_AccountOrder__ORDER_VIEW: function(pulsePayload) {
            pulse.runtime.common_xpr_groups(pulsePayload);
            pulse.runtime.wmbeacon_xpr_pv(pulsePayload);
        },
        wmbeacon_AccountReturns__RETURNS_LIST_VIEW: function(pulsePayload) {
            pulse.runtime.common_xpr_groups(pulsePayload);
            pulse.runtime.wmbeacon_xpr_pv(pulsePayload);
        },

        wmbeacon_AccountReturns__RETURNS_VIEW: function(pulsePayload) {
            pulse.runtime.common_xpr_groups(pulsePayload);
            pulse.runtime.wmbeacon_xpr_pv(pulsePayload);
        },
        wmbeacon_AccountSigin_SIGN_IN_ERR: function(pulsePayload) {
            pulse.runtime.common_xpr_groups(pulsePayload);
            pulse.runtime.wmbeacon_xpr_pv(pulsePayload);
        },

        wmbeacon_AccountSigin_SIGN_IN_VIEW: function(pulsePayload) {
            pulse.runtime.common_xpr_groups(pulsePayload);
            pulse.runtime.wmbeacon_xpr_pv(pulsePayload);
        },
        wmbeacon_Account__NEW_ACCT_VIEW: function(pulsePayload) {
            pulse.runtime.common_xpr_groups(pulsePayload);
            pulse.runtime.wmbeacon_xpr_pv(pulsePayload);
        },

        wmbeacon_Account__PSWD_FRGT_VIEW: function(pulsePayload) {
            pulse.runtime.common_xpr_groups(pulsePayload);
            pulse.runtime.wmbeacon_xpr_pv(pulsePayload);
        },

        wmbeacon_Account__PSWD_RESET_VIEW: function(pulsePayload) {
            pulse.runtime.common_xpr_groups(pulsePayload);
            pulse.runtime.wmbeacon_xpr_pv(pulsePayload);
        },

        wmbeacon_Account__SIGN_IN_VIEW: function(pulsePayload) {
            pulse.runtime.common_xpr_groups(pulsePayload);
            pulse.runtime.wmbeacon_xpr_pv(pulsePayload);
        },

        wmbeacon_Account__SIGN_OUT_VIEW: function(pulsePayload) {
            pulse.runtime.common_xpr_groups(pulsePayload);
            pulse.runtime.wmbeacon_xpr_pv(pulsePayload);
        },
        wmbeacon_AdsBanner_ADS_CLICK: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },

        wmbeacon_AdsBanner_ADS_CSA_ERR: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },

        wmbeacon_AdsBanner_ADS_HL_ERR: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },

        wmbeacon_AdsBanner_ADS_IN_VIEW: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },

        wmbeacon_AdsBanner_ADS_MIDAS_ERR: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },

        wmbeacon_AdsBanner_ADS_NOT_AVAILABLE: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },

        wmbeacon_AdsBanner_ADS_PAGINATION: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },

        wmbeacon_AdsBanner_ADS_SHOWN: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },
        wmbeacon_AdsCntxtsrchGgl_ADS_CLICK: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },

        wmbeacon_AdsCntxtsrchGgl_ADS_CSA_ERR: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },

        wmbeacon_AdsCntxtsrchGgl_ADS_HL_ERR: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },

        wmbeacon_AdsCntxtsrchGgl_ADS_IN_VIEW: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },

        wmbeacon_AdsCntxtsrchGgl_ADS_MIDAS_ERR: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },

        wmbeacon_AdsCntxtsrchGgl_ADS_NOT_AVAILABLE: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },

        wmbeacon_AdsCntxtsrchGgl_ADS_PAGINATION: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },

        wmbeacon_AdsCntxtsrchGgl_ADS_SHOWN: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },
        wmbeacon_AdsCntxtsrchYahoo_ADS_CLICK: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },

        wmbeacon_AdsCntxtsrchYahoo_ADS_CSA_ERR: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },

        wmbeacon_AdsCntxtsrchYahoo_ADS_HL_ERR: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },

        wmbeacon_AdsCntxtsrchYahoo_ADS_IN_VIEW: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },

        wmbeacon_AdsCntxtsrchYahoo_ADS_MIDAS_ERR: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },

        wmbeacon_AdsCntxtsrchYahoo_ADS_NOT_AVAILABLE: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },

        wmbeacon_AdsCntxtsrchYahoo_ADS_PAGINATION: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },

        wmbeacon_AdsCntxtsrchYahoo_ADS_SHOWN: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },
        wmbeacon_AdsHklgWlmrt_ADS_CLICK: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },

        wmbeacon_AdsHklgWlmrt_ADS_CSA_ERR: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },

        wmbeacon_AdsHklgWlmrt_ADS_HL_ERR: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },

        wmbeacon_AdsHklgWlmrt_ADS_IN_VIEW: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },

        wmbeacon_AdsHklgWlmrt_ADS_MIDAS_ERR: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },

        wmbeacon_AdsHklgWlmrt_ADS_NOT_AVAILABLE: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },

        wmbeacon_AdsHklgWlmrt_ADS_PAGINATION: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },

        wmbeacon_AdsHklgWlmrt_ADS_SHOWN: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },
        wmbeacon_AdsMultiWlmrt_ADS_CLICK: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },

        wmbeacon_AdsMultiWlmrt_ADS_CSA_ERR: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },

        wmbeacon_AdsMultiWlmrt_ADS_HL_ERR: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },

        wmbeacon_AdsMultiWlmrt_ADS_IN_VIEW: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },

        wmbeacon_AdsMultiWlmrt_ADS_MIDAS_ERR: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },

        wmbeacon_AdsMultiWlmrt_ADS_NOT_AVAILABLE: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },

        wmbeacon_AdsMultiWlmrt_ADS_PAGINATION: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },

        wmbeacon_AdsMultiWlmrt_ADS_SHOWN: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },
        wmbeacon_AdsProdlistGgl_ADS_CLICK: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },

        wmbeacon_AdsProdlistGgl_ADS_CSA_ERR: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },

        wmbeacon_AdsProdlistGgl_ADS_HL_ERR: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },

        wmbeacon_AdsProdlistGgl_ADS_IN_VIEW: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },

        wmbeacon_AdsProdlistGgl_ADS_MIDAS_ERR: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },

        wmbeacon_AdsProdlistGgl_ADS_NOT_AVAILABLE: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },

        wmbeacon_AdsProdlistGgl_ADS_PAGINATION: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },

        wmbeacon_AdsProdlistGgl_ADS_SHOWN: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },
        wmbeacon_AdsShopGgl_ADS_CLICK: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },

        wmbeacon_AdsShopGgl_ADS_CSA_ERR: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },

        wmbeacon_AdsShopGgl_ADS_HL_ERR: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },

        wmbeacon_AdsShopGgl_ADS_IN_VIEW: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },

        wmbeacon_AdsShopGgl_ADS_MIDAS_ERR: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },

        wmbeacon_AdsShopGgl_ADS_NOT_AVAILABLE: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },

        wmbeacon_AdsShopGgl_ADS_PAGINATION: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },

        wmbeacon_AdsShopGgl_ADS_SHOWN: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },
        wmbeacon_AdsWlmrtWlmrt_ADS_CLICK: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },

        wmbeacon_AdsWlmrtWlmrt_ADS_CSA_ERR: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },

        wmbeacon_AdsWlmrtWlmrt_ADS_HL_ERR: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },

        wmbeacon_AdsWlmrtWlmrt_ADS_IN_VIEW: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },

        wmbeacon_AdsWlmrtWlmrt_ADS_MIDAS_ERR: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },

        wmbeacon_AdsWlmrtWlmrt_ADS_NOT_AVAILABLE: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },

        wmbeacon_AdsWlmrtWlmrt_ADS_PAGINATION: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },

        wmbeacon_AdsWlmrtWlmrt_ADS_SHOWN: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },
        wmbeacon_Browse_BROWSE_VIEW: function(pulsePayload) {
            pulse.runtime.common_xpr_groups(pulsePayload);
            pulse.runtime.wmbeacon_xpr_pv(pulsePayload);
        },

        wmbeacon_Browse_ON_IMAGE_SELECT: function(pulsePayload) {
            pulse.runtime.wmbeacon_item_positioning(pulsePayload);
        },

        wmbeacon_Browse_ON_TITLE_SELECT: function(pulsePayload) {
            pulse.runtime.wmbeacon_item_positioning(pulsePayload);
        },

        wmbeacon_Browse_PERFORMANCE_METRICS: function(pulsePayload) {
            pulse.runtime.wmbeacon_pctx_pv(pulsePayload);
        },
        wmbeacon_BuyTogether_BUYTOGETHER_VIEW: function(pulsePayload) {
            pulse.runtime.common_xpr_groups(pulsePayload);
            pulse.runtime.wmbeacon_xpr_pv(pulsePayload);
        },
        wmbeacon_CartHelper_ON_ATC: function(pulsePayload) {
            pulse.placeholder["tmp0"] = pulse.runtime.getObj("ca", "ShoppingCart");
            pulse.placeholder["tmp1"] = pulse.runtime.hasValue(pulse.placeholder.tmp0);
            pulse.output["is_not_shopping_cart"] = pulse.runtime.equals(true, pulse.placeholder.tmp1, false, true);
            pulse.output["pr"] = pulse.runtime.getObj("pr", "CartHelper");
        },
        wmbeacon_CategoryListings_CATEGORY_VIEW: function(pulsePayload) {
            pulse.runtime.common_xpr_groups(pulsePayload);
            pulse.runtime.wmbeacon_xpr_pv(pulsePayload);
            pulse.placeholder["ta"] = pulse.runtime.getObjFirstData("ta");
            pulse.placeholder["tmp_ta"] = pulse.runtime.writeLocalStorage("tmp_ta", pulse.placeholder.ta);
        },

        wmbeacon_CategoryListings_ON_UNIV_LINK: function(pulsePayload) {
            pulse.placeholder["ta"] = pulse.runtime.readLocalStorage("tmp_ta");
            pulse.placeholder["uc_si"] = pulse.runtime.hasValue(pulse.runtime.getProperty(pulse.placeholder.ta, "si"));
            pulse.placeholder["uc_ci"] = pulse.runtime.hasValue(pulse.runtime.getProperty(pulse.placeholder.ta, "ci"));
            pulse.placeholder["uc_di"] = pulse.runtime.hasValue(pulse.runtime.getProperty(pulse.placeholder.ta, "di"));
            pulse.placeholder["pageId_evar22"] = pulse.runtime.switchCase(true, pulse.placeholder.uc_si, pulse.runtime.getProperty(pulse.placeholder.ta, "si"), pulse.placeholder.uc_ci, pulse.runtime.getProperty(pulse.placeholder.ta, "ci"), pulse.placeholder.uc_di, pulse.runtime.getProperty(pulse.placeholder.ta, "di"), "1");
            pulse.runtime.wmbeacon_univ_click(pulsePayload);
            pulse.placeholder["tmp_ta_remove"] = pulse.runtime.writeLocalStorage("tmp_ta", null);
        },

        wmbeacon_CategoryListings_PERFORMANCE_METRICS: function(pulsePayload) {
            pulse.runtime.wmbeacon_pctx_pv(pulsePayload);
        },
        wmbeacon_Checkout_CHCKOUT_SUM: function(pulsePayload) {
            pulse.runtime.common_xpr_groups(pulsePayload);
            pulse.runtime.wmbeacon_xpr_pv(pulsePayload);
            pulse.output["ca"] = pulse.runtime.getObj("ca", "Checkout");
            pulse.output["cu"] = pulse.runtime.getObj("cu", "Checkout");
            pulse.output["pr"] = pulse.runtime.getObj("pr", "Checkout");
            pulse.output["se"] = pulse.runtime.getObj("se", "Checkout");
            pulse.output["st"] = pulse.runtime.getObj("st", "Checkout");
            pulse.output["fl"] = pulse.runtime.getObj("fl", "Checkout");
            pulse.output["pr__se"] = pulse.runtime.getObj("pr__se", "Checkout");
            pulse.output["pr__se__st__fl"] = pulse.runtime.getObj("pr__se__st__fl", "Checkout");
            pulse.output["fg"] = pulse.runtime.getObj("fg", "Checkout");
            pulse.output["fg__st__fl"] = pulse.runtime.getObj("fg__st__fl", "Checkout");
            pulse.runtime.wmbeacon_omni_track_val(pulsePayload);
        },

        wmbeacon_Checkout_CHCKOUT_WELCOME_VIEW: function(pulsePayload) {
            pulse.runtime.common_xpr_groups(pulsePayload);
            pulse.runtime.wmbeacon_xpr_pv(pulsePayload);
            pulse.output["co"] = pulse.runtime.getObj("co", "Checkout");
            pulse.output["cu"] = pulse.runtime.getObj("cu", "Checkout");
        },

        wmbeacon_Checkout_ON_ADDR_CHANGE: function(pulsePayload) {
            pulse.output["ad"] = pulse.runtime.getObj("ad", "Checkout");
            pulse.output["al"] = pulse.runtime.getObj("al", "Checkout");
        },

        wmbeacon_Checkout_ON_ALL_PKP: function(pulsePayload) {
            pulse.output["fl"] = pulse.runtime.getObj("fl", "Checkout");
            pulse.output["fg"] = pulse.runtime.getObj("fg", "Checkout");
            pulse.output["fg__st__fl"] = pulse.runtime.getObj("fg__st__fl", "Checkout");
        },

        wmbeacon_Checkout_ON_ALL_SHP: function(pulsePayload) {
            pulse.output["fl"] = pulse.runtime.getObj("fl", "Checkout");
            pulse.output["fg"] = pulse.runtime.getObj("fg", "Checkout");
            pulse.output["fg__st__fl"] = pulse.runtime.getObj("fg__st__fl", "Checkout");
        },

        wmbeacon_Checkout_ON_ASSOC_OVERLAY_VIEW: function(pulsePayload) {
            pulse.runtime.common_xpr_groups(pulsePayload);
            pulse.runtime.wmbeacon_xpr_pv(pulsePayload);
            pulse.output["dc"] = pulse.runtime.getObj("dc", "Checkout");
        },

        wmbeacon_Checkout_ON_CHCKOUT_GUEST: function(pulsePayload) {
            pulse.output["cu"] = pulse.runtime.getObj("cu", "Checkout");
        },

        wmbeacon_Checkout_ON_CHCKOUT_SIGN_IN: function(pulsePayload) {
            pulse.output["cu"] = pulse.runtime.getObj("cu", "Checkout");
        },

        wmbeacon_Checkout_ON_CHG_PKP_LOC: function(pulsePayload) {
            pulse.output["pr"] = pulse.runtime.getObj("pr", "Checkout");
            pulse.output["se"] = pulse.runtime.getObj("se", "Checkout");
            pulse.output["st"] = pulse.runtime.getObj("st", "Checkout");
            pulse.output["fl"] = pulse.runtime.getObj("fl", "Checkout");
            pulse.output["pr__se"] = pulse.runtime.getObj("pr__se", "Checkout");
            pulse.output["fg"] = pulse.runtime.getObj("fg", "Checkout");
            pulse.output["fg__st__fl"] = pulse.runtime.getObj("fg__st__fl", "Checkout");
        },

        wmbeacon_Checkout_ON_CHG_SHP: function(pulsePayload) {
            pulse.output["pr"] = pulse.runtime.getObj("pr", "Checkout");
            pulse.output["se"] = pulse.runtime.getObj("se", "Checkout");
            pulse.output["st"] = pulse.runtime.getObj("st", "Checkout");
            pulse.output["fl"] = pulse.runtime.getObj("fl", "Checkout");
            pulse.output["pr__se"] = pulse.runtime.getObj("pr__se", "Checkout");
            pulse.output["fg"] = pulse.runtime.getObj("fg", "Checkout");
            pulse.output["fg__st__fl"] = pulse.runtime.getObj("fg__st__fl", "Checkout");
        },

        wmbeacon_Checkout_ON_FF_CONT: function(pulsePayload) {
            pulse.output["pr"] = pulse.runtime.getObj("pr", "Checkout");
            pulse.output["se"] = pulse.runtime.getObj("se", "Checkout");
            pulse.output["st"] = pulse.runtime.getObj("st", "Checkout");
            pulse.output["fl"] = pulse.runtime.getObj("fl", "Checkout");
            pulse.output["pr__se"] = pulse.runtime.getObj("pr__se", "Checkout");
            pulse.output["pr__se__st__fl"] = pulse.runtime.getObj("pr__se__st__fl", "Checkout");
            pulse.output["fg"] = pulse.runtime.getObj("fg", "Checkout");
            pulse.output["fg__st__fl"] = pulse.runtime.getObj("fg__st__fl", "Checkout");
        },

        wmbeacon_Checkout_ON_FF_VIEW: function(pulsePayload) {
            pulse.runtime.common_xpr_groups(pulsePayload);
            pulse.runtime.wmbeacon_xpr_pv(pulsePayload);
            pulse.output["cu"] = pulse.runtime.getObj("cu", "Checkout");
            pulse.output["pr"] = pulse.runtime.getObj("pr", "Checkout");
            pulse.output["se"] = pulse.runtime.getObj("se", "Checkout");
            pulse.output["st"] = pulse.runtime.getObj("st", "Checkout");
            pulse.output["fl"] = pulse.runtime.getObj("fl", "Checkout");
            pulse.output["pr__se"] = pulse.runtime.getObj("pr__se", "Checkout");
            pulse.output["pr__se__st__fl"] = pulse.runtime.getObj("pr__se__st__fl", "Checkout");
            pulse.output["fg"] = pulse.runtime.getObj("fg", "Checkout");
            pulse.output["fg__st__fl"] = pulse.runtime.getObj("fg__st__fl", "Checkout");
        },

        wmbeacon_Checkout_ON_NEW_ACCT: function(pulsePayload) {
            pulse.output["cu"] = pulse.runtime.getObj("cu", "Checkout");
        },

        wmbeacon_Checkout_ON_NEW_ACCT_COMPLETE: function(pulsePayload) {
            pulse.output["cu"] = pulse.runtime.getObj("cu", "Checkout");
        },

        wmbeacon_Checkout_ON_NEW_ACCT_INIT: function(pulsePayload) {
            pulse.output["cu"] = pulse.runtime.getObj("cu", "Checkout");
        },

        wmbeacon_Checkout_ON_PAYMENT_CHANGE: function(pulsePayload) {
            pulse.output["py"] = pulse.runtime.getObj("py", "Checkout");
            pulse.output["yl"] = pulse.runtime.getObj("yl", "Checkout");
        },

        wmbeacon_Checkout_ON_PAYMENT_CHANGE_INIT: function(pulsePayload) {
            pulse.output["ad"] = pulse.runtime.getObj("ad", "Checkout");
            pulse.output["py"] = pulse.runtime.getObj("py", "Checkout");
            pulse.output["yl"] = pulse.runtime.getObj("yl", "Checkout");
        },

        wmbeacon_Checkout_ON_PAYMENT_CHANGE_TGL: function(pulsePayload) {
            pulse.output["py"] = pulse.runtime.getObj("py", "Checkout");
        },

        wmbeacon_Checkout_ON_PAYMENT_CONT: function(pulsePayload) {
            pulse.output["py"] = pulse.runtime.getObj("py", "Checkout");
            pulse.output["yl"] = pulse.runtime.getObj("yl", "Checkout");
        },

        wmbeacon_Checkout_ON_PAYMENT_VIEW: function(pulsePayload) {
            pulse.runtime.common_xpr_groups(pulsePayload);
            pulse.runtime.wmbeacon_xpr_pv(pulsePayload);
            pulse.output["ca"] = pulse.runtime.getObj("ca", "Checkout");
            pulse.output["cu"] = pulse.runtime.getObj("cu", "Checkout");
            pulse.output["ad"] = pulse.runtime.getObj("ad", "Checkout");
            pulse.output["yl"] = pulse.runtime.getObj("yl", "Checkout");
            pulse.output["py"] = pulse.runtime.getObj("py", "Checkout");
            pulse.output["fl"] = pulse.runtime.getObj("fl", "Checkout");
            pulse.output["er"] = pulse.runtime.getObj("er", "Checkout");
        },

        wmbeacon_Checkout_ON_PICKUP_CONT: function(pulsePayload) {
            pulse.output["pc"] = pulse.runtime.getObj("pc", "Checkout");
            pulse.output["ul"] = pulse.runtime.getObj("ul", "Checkout");
        },

        wmbeacon_Checkout_ON_PICKUP_VIEW: function(pulsePayload) {
            pulse.runtime.common_xpr_groups(pulsePayload);
            pulse.runtime.wmbeacon_xpr_pv(pulsePayload);
            pulse.output["pc"] = pulse.runtime.getObj("pc", "Checkout");
            pulse.output["ul"] = pulse.runtime.getObj("ul", "Checkout");
            pulse.output["ca"] = pulse.runtime.getObj("ca", "Checkout");
            pulse.output["cu"] = pulse.runtime.getObj("cu", "Checkout");
            pulse.output["ad"] = pulse.runtime.getObj("ad", "Checkout");
            pulse.output["yl"] = pulse.runtime.getObj("yl", "Checkout");
            pulse.output["py"] = pulse.runtime.getObj("py", "Checkout");
            pulse.output["fl"] = pulse.runtime.getObj("fl", "Checkout");
            pulse.output["er"] = pulse.runtime.getObj("er", "Checkout");
        },

        wmbeacon_Checkout_ON_REV_ORDER_VIEW: function(pulsePayload) {
            pulse.runtime.common_xpr_groups(pulsePayload);
            pulse.runtime.wmbeacon_xpr_pv(pulsePayload);
            pulse.output["pr"] = pulse.runtime.getObj("pr", "Checkout");
            pulse.output["pr__se"] = pulse.runtime.getObj("pr__se", "Checkout");
            pulse.output["pr__se__st__fl"] = pulse.runtime.getObj("pr__se__st__fl", "Checkout");
            pulse.output["fg__st__fl"] = pulse.runtime.getObj("fg__st__fl", "Checkout");
            pulse.output["ca"] = pulse.runtime.getObj("ca", "Checkout");
            pulse.output["cu"] = pulse.runtime.getObj("cu", "Checkout");
            pulse.output["ad"] = pulse.runtime.getObj("ad", "Checkout");
            pulse.output["yl"] = pulse.runtime.getObj("yl", "Checkout");
            pulse.output["py"] = pulse.runtime.getObj("py", "Checkout");
            pulse.output["fl"] = pulse.runtime.getObj("fl", "Checkout");
            pulse.output["er"] = pulse.runtime.getObj("er", "Checkout");
        },

        wmbeacon_Checkout_ON_SHP_CONT: function(pulsePayload) {
            pulse.output["ad"] = pulse.runtime.getObj("ad", "Checkout");
            pulse.output["al"] = pulse.runtime.getObj("al", "Checkout");
        },

        wmbeacon_Checkout_ON_SHP_VIEW: function(pulsePayload) {
            pulse.runtime.common_xpr_groups(pulsePayload);
            pulse.runtime.wmbeacon_xpr_pv(pulsePayload);
            pulse.output["ca"] = pulse.runtime.getObj("ca", "Checkout");
            pulse.output["cu"] = pulse.runtime.getObj("cu", "Checkout");
            pulse.output["ad"] = pulse.runtime.getObj("ad", "Checkout");
            pulse.output["yl"] = pulse.runtime.getObj("yl", "Checkout");
            pulse.output["py"] = pulse.runtime.getObj("py", "Checkout");
            pulse.output["fl"] = pulse.runtime.getObj("fl", "Checkout");
            pulse.output["er"] = pulse.runtime.getObj("er", "Checkout");
            pulse.output["al"] = pulse.runtime.getObj("al", "Checkout");
            pulse.output["pr"] = pulse.runtime.getObj("pr", "Checkout");
            pulse.output["pr__se"] = pulse.runtime.getObj("pr__se", "Checkout");
            pulse.output["pr__se__st__fl"] = pulse.runtime.getObj("pr__se__st__fl", "Checkout");
            pulse.output["fg__st__fl"] = pulse.runtime.getObj("fg__st__fl", "Checkout");
        },

        wmbeacon_Checkout_PERFORMANCE_METRICS: function(pulsePayload) {
            pulse.runtime.wmbeacon_pctx_pv(pulsePayload);
        },
        wmbeacon_Collection_COLLECTION_VIEW: function(pulsePayload) {
            pulse.runtime.common_xpr_groups(pulsePayload);
            pulse.runtime.wmbeacon_xpr_pv(pulsePayload);
        },

        wmbeacon_Collection_PERFORMANCE_METRICS: function(pulsePayload) {
            pulse.runtime.wmbeacon_pctx_pv(pulsePayload);
        },
        wmbeacon_CreateBabyRegistry_CREATE_BB_REG_ERR: function(pulsePayload) {
            pulse.runtime.common_xpr_groups(pulsePayload);
            pulse.runtime.wmbeacon_xpr_pv(pulsePayload);
        },

        wmbeacon_CreateBabyRegistry_CREATE_BB_REG_VIEW: function(pulsePayload) {
            pulse.runtime.common_xpr_groups(pulsePayload);
            pulse.runtime.wmbeacon_xpr_pv(pulsePayload);
        },
        wmbeacon_CreateWeddingRegistry_CREATE_W_REG_ERR: function(pulsePayload) {
            pulse.runtime.common_xpr_groups(pulsePayload);
            pulse.runtime.wmbeacon_xpr_pv(pulsePayload);
        },

        wmbeacon_CreateWeddingRegistry_CREATE_W_REG_VIEW: function(pulsePayload) {
            pulse.runtime.common_xpr_groups(pulsePayload);
            pulse.runtime.wmbeacon_xpr_pv(pulsePayload);
        },
        wmbeacon_DisplayBabyRegistry_DISPLAY_BB_REG_VIEW: function(pulsePayload) {
            pulse.runtime.common_xpr_groups(pulsePayload);
            pulse.runtime.wmbeacon_xpr_pv(pulsePayload);
        },
        wmbeacon_DisplayWeddingRegistry_DISPLAY_W_REG_VIEW: function(pulsePayload) {
            pulse.runtime.common_xpr_groups(pulsePayload);
            pulse.runtime.wmbeacon_xpr_pv(pulsePayload);
        },
        wmbeacon_ErrorPage_ERRORPAGE_VIEW: function(pulsePayload) {
            pulse.runtime.common_xpr_groups(pulsePayload);
            pulse.runtime.wmbeacon_xpr_pv(pulsePayload);
        },
        wmbeacon_Expo__EXPO_VIEW: function(pulsePayload) {
            pulse.runtime.common_xpr_groups(pulsePayload);
            pulse.runtime.wmbeacon_xpr_pv(pulsePayload);
        },

        wmbeacon_Expo__ON_EXPO: function(pulsePayload) {
            pulse.runtime.common_xpr_groups(pulsePayload);
            pulse.runtime.wmbeacon_xpr_pv(pulsePayload);
        },
        wmbeacon_GrpChoicePage_GRPNG_VIEW: function(pulsePayload) {
            pulse.runtime.common_xpr_groups(pulsePayload);
            pulse.runtime.wmbeacon_xpr_pv(pulsePayload);
        },
        wmbeacon_GrpNonChoicePage_GRPNG_VIEW: function(pulsePayload) {
            pulse.runtime.common_xpr_groups(pulsePayload);
            pulse.runtime.wmbeacon_xpr_pv(pulsePayload);
        },
        wmbeacon_Header_ON_UNIV_LINK: function(pulsePayload) {
            pulse.placeholder["co"] = pulse.runtime.getObjFirstData("co");
            pulse.placeholder["pageId_evar22"] = pulse.runtime.getProperty(pulse.placeholder.co, "ty");
            pulse.placeholder["catNavBar_prop29"] = pulse.runtime.getKeys(pulse.runtime.getObj("li"))[0];
            pulse.runtime.wmbeacon_univ_click(pulsePayload);
        },
        wmbeacon_HomePage_FIRST_VIEW: function(pulsePayload) {
            pulse.runtime.common_xpr_groups(pulsePayload);
            pulse.runtime.wmbeacon_xpr_pv(pulsePayload);
        },

        wmbeacon_HomePage_HOMEPAGE_VIEW: function(pulsePayload) {
            pulse.runtime.common_xpr_groups(pulsePayload);
            pulse.runtime.wmbeacon_xpr_pv(pulsePayload);
        },

        wmbeacon_HomePage_ON_UNIV_LINK: function(pulsePayload) {
            pulse.placeholder["pageId_evar22"] = "0";
            pulse.runtime.wmbeacon_univ_click(pulsePayload);
        },

        wmbeacon_HomePage_PERFORMANCE_METRICS: function(pulsePayload) {
            pulse.runtime.wmbeacon_pctx_pv(pulsePayload);
        },
        wmbeacon_Irs__ADD_TO_CART: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },

        wmbeacon_Irs__BOOTSTRAP: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },

        wmbeacon_Irs__INIT: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },

        wmbeacon_Irs__PAGINATION: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },

        wmbeacon_Irs__PLACEMENT: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },

        wmbeacon_Irs__PRODUCT_INTEREST: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },

        wmbeacon_Irs__QUICKLOOK: function(pulsePayload) {
            pulse.placeholder["test"] = "test";
        },
        wmbeacon_LocalStore_PERFORMANCE_METRICS: function(pulsePayload) {
            pulse.runtime.wmbeacon_pctx_pv(pulsePayload);
        },

        wmbeacon_LocalStore_STORE_DETAIL_ERR: function(pulsePayload) {
            pulse.runtime.common_xpr_groups(pulsePayload);
            pulse.runtime.wmbeacon_xpr_pv(pulsePayload);
        },

        wmbeacon_LocalStore_STORE_DETAIL_VIEW: function(pulsePayload) {
            pulse.runtime.common_xpr_groups(pulsePayload);
            pulse.runtime.wmbeacon_xpr_pv(pulsePayload);
        },
        wmbeacon_ManageBabyRegistry_MANAGE_BB_REG_ERR: function(pulsePayload) {
            pulse.runtime.common_xpr_groups(pulsePayload);
            pulse.runtime.wmbeacon_xpr_pv(pulsePayload);
        },

        wmbeacon_ManageBabyRegistry_MANAGE_BB_REG_VIEW: function(pulsePayload) {
            pulse.runtime.common_xpr_groups(pulsePayload);
            pulse.runtime.wmbeacon_xpr_pv(pulsePayload);
        },
        wmbeacon_ManageWeddingRegistry_MANAGE_W_REG_ERR: function(pulsePayload) {
            pulse.runtime.common_xpr_groups(pulsePayload);
            pulse.runtime.wmbeacon_xpr_pv(pulsePayload);
        },

        wmbeacon_ManageWeddingRegistry_MANAGE_W_REG_VIEW: function(pulsePayload) {
            pulse.runtime.common_xpr_groups(pulsePayload);
            pulse.runtime.wmbeacon_xpr_pv(pulsePayload);
        },
        wmbeacon_MerchModule__ON_UNIV_LINK: function(pulsePayload) {
            pulse.placeholder["pageId_evar22"] = "";
            pulse.runtime.wmbeacon_univ_click(pulsePayload);
        },
        wmbeacon_OneHG_CONFIRM_VIEW: function(pulsePayload) {
            pulse.runtime.common_xpr_groups(pulsePayload);
            pulse.runtime.wmbeacon_xpr_pv(pulsePayload);
        },

        wmbeacon_OneHG_LANDING_VIEW: function(pulsePayload) {
            pulse.runtime.common_xpr_groups(pulsePayload);
            pulse.runtime.wmbeacon_xpr_pv(pulsePayload);
        },

        wmbeacon_OneHG_LANDING_VIEW_ERR: function(pulsePayload) {
            pulse.runtime.common_xpr_groups(pulsePayload);
            pulse.runtime.wmbeacon_xpr_pv(pulsePayload);
        },

        wmbeacon_OneHG_PERFORMANCE_METRICS: function(pulsePayload) {
            pulse.runtime.wmbeacon_pctx_pv(pulsePayload);
        },

        wmbeacon_OneHG_REVIEW_VIEW: function(pulsePayload) {
            pulse.runtime.common_xpr_groups(pulsePayload);
            pulse.runtime.wmbeacon_xpr_pv(pulsePayload);
        },
        wmbeacon_PAC_ON_CHCKOUT: function(pulsePayload) {
            pulse.placeholder["checkoutInitiationPage"] = pulse.runtime.writeLocalStorage("checkoutInitiationPage", "PAC");
        },
        wmbeacon_Page__PAGE_VIEW: function(pulsePayload) {
            pulse.runtime.common_xpr_groups(pulsePayload);
            pulse.runtime.wmbeacon_xpr_pv(pulsePayload);
        },
        wmbeacon_PrintBabyRegistry_PRINT_BB_REG_VIEW: function(pulsePayload) {
            pulse.runtime.common_xpr_groups(pulsePayload);
            pulse.runtime.wmbeacon_xpr_pv(pulsePayload);
        },
        wmbeacon_PrintList_PRINT_LIST_VIEW: function(pulsePayload) {
            pulse.runtime.common_xpr_groups(pulsePayload);
            pulse.runtime.wmbeacon_xpr_pv(pulsePayload);
        },
        wmbeacon_PrintWeddingRegistry_PRINT_W_REG_VIEW: function(pulsePayload) {
            pulse.runtime.common_xpr_groups(pulsePayload);
            pulse.runtime.wmbeacon_xpr_pv(pulsePayload);
        },
        wmbeacon_ProductPage_ON_UNIV_LINK: function(pulsePayload) {
            pulse.placeholder["primaryPr"] = pulse.runtime.execJsonPath(pulsePayload.pr, "$..[?(@.wf<1)]");
            pulse.placeholder["firstPr"] = pulse.runtime.getObjFirstData("pr");
            pulse.placeholder["tmp4"] = pulse.runtime.firstArrayElm(pulse.placeholder.primaryPr);
            pulse.placeholder["pr"] = pulse.runtime.equals(pulse.runtime.getProperty(pulse.placeholder.primaryPr, "length"), 0, pulse.placeholder.firstPr, pulse.placeholder.tmp4);
            pulse.placeholder["pageId_evar22"] = pulse.runtime.template("ID-{{s1}}", pulse.runtime.getProperty(pulse.placeholder.pr, "us"));
            pulse.runtime.wmbeacon_univ_click(pulsePayload);
        },

        wmbeacon_ProductPage_PRODUCT_VIEW: function(pulsePayload) {
            pulse.runtime.common_xpr_groups(pulsePayload);
            pulse.runtime.wmbeacon_xpr_pv(pulsePayload);
        },
        wmbeacon_SchoolLists_ON_UNIV_LINK: function(pulsePayload) {
            pulse.placeholder["pageId_evar22"] = "0";
            pulse.runtime.wmbeacon_univ_click(pulsePayload);
        },
        wmbeacon_SearchResults_PERFORMANCE_METRICS: function(pulsePayload) {
            pulse.runtime.wmbeacon_pctx_pv(pulsePayload);
        },

        wmbeacon_SearchResults_SEARCH_VIEW: function(pulsePayload) {
            pulse.runtime.common_xpr_groups(pulsePayload);
            pulse.runtime.wmbeacon_xpr_pv(pulsePayload);
        },
        wmbeacon_ShoppingCart_PERFORMANCE_METRICS: function(pulsePayload) {
            pulse.runtime.wmbeacon_pctx_pv(pulsePayload);
        },

        wmbeacon_ShoppingCart_SHOPCART_VIEW: function(pulsePayload) {
            pulse.runtime.common_xpr_groups(pulsePayload);
            pulse.runtime.wmbeacon_xpr_pv(pulsePayload);
        },

        wmbeacon_ShoppingCart_ON_CHCKOUT: function(pulsePayload) {
            pulse.placeholder["checkoutInitiationPage"] = pulse.runtime.writeLocalStorage("checkoutInitiationPage", "Shopping Cart");
        },
        wmbeacon_SpotLight__SPOTLIGHT_VIEW: function(pulsePayload) {
            pulse.runtime.common_xpr_groups(pulsePayload);
            pulse.runtime.wmbeacon_xpr_pv(pulsePayload);
        },
        wmbeacon_StoreFinder_PERFORMANCE_METRICS: function(pulsePayload) {
            pulse.runtime.wmbeacon_pctx_pv(pulsePayload);
        },

        wmbeacon_StoreFinder_STORE_FINDER_ERR: function(pulsePayload) {
            pulse.runtime.common_xpr_groups(pulsePayload);
            pulse.runtime.wmbeacon_xpr_pv(pulsePayload);
        },

        wmbeacon_StoreFinder_STORE_FINDER_VIEW: function(pulsePayload) {
            pulse.runtime.common_xpr_groups(pulsePayload);
            pulse.runtime.wmbeacon_xpr_pv(pulsePayload);
        },
        wmbeacon_Thankyou_PERFORMANCE_METRICS: function(pulsePayload) {
            pulse.runtime.wmbeacon_pctx_pv(pulsePayload);
        },

        wmbeacon_Thankyou_THANK_YOU_VIEW: function(pulsePayload) {
            pulse.runtime.common_xpr_groups(pulsePayload);
            pulse.runtime.wmbeacon_xpr_pv(pulsePayload);
        },
        wmbeacon_Topic_TOPIC_VIEW: function(pulsePayload) {
            pulse.runtime.common_xpr_groups(pulsePayload);
            pulse.runtime.wmbeacon_xpr_pv(pulsePayload);
        },
        wmbeacon_ValueOfTheDay_PERFORMANCE_METRICS: function(pulsePayload) {
            pulse.runtime.wmbeacon_pctx_pv(pulsePayload);
        },

        wmbeacon_ValueOfTheDay_VOD_VIEW: function(pulsePayload) {
            pulse.runtime.common_xpr_groups(pulsePayload);
            pulse.runtime.wmbeacon_xpr_pv(pulsePayload);
        },
        wmbeacon_item_positioning: function(pulsePayload) {
            pulse.placeholder["ta"] = pulse.runtime.getObjFirstData("ta");
            pulse.placeholder["pl"] = pulse.runtime.getObjFirstData("pl");
            pulse.placeholder["li"] = pulse.runtime.getObjFirstData("li");
            pulse.placeholder["tmp968"] = pulse.runtime.template("Manual Shelf | {{s1}} | {{s2}} | {{s3}}", pulse.runtime.getProperty(pulse.placeholder.ta, "hi"), pulse.runtime.getProperty(pulse.placeholder.pl, "pn"), pulse.runtime.getProperty(pulse.placeholder.li, "lc"));
            pulse.placeholder["tmp969"] = pulse.runtime.hasValue(pulse.runtime.getProperty(pulse.placeholder.ta, "hi"));
            pulse.placeholder["temp_itemPos"] = pulse.runtime.switchCase(true, pulse.placeholder.tmp969, pulse.placeholder.tmp968, null);
            pulse.placeholder["itemPos"] = pulse.runtime.writeLocalStorage("itemPos", pulse.placeholder.temp_itemPos);
        },

        wmbeacon_omni_track_val: function(pulsePayload) {
            pulse.placeholder["local_ee"] = pulse.runtime.writeLocalStorage("ee", pulse.placeholder.ee);
            pulse.placeholder["local_ee__ex"] = pulse.runtime.writeLocalStorage("ee__ex", pulse.placeholder.ee__ex);
        },

        wmbeacon_pctx_pv: function(pulsePayload) {
            pulse.runtime.getObj("cm", "PCTX");
            pulse.output["cm"] = pulse.runtime.getObj("cm", "PCTX");
            pulse.output["dd"] = pulse.runtime.getObj("dd", "PCTX");
            pulse.output["cu"] = pulse.runtime.getObj("cu", "PCTX");
            pulse.output["resp"] = pulse.runtime.responsive();
        },

        wmbeacon_univ_click: function(pulsePayload) {
            pulse.placeholder["co"] = pulse.runtime.getObjFirstData("co");
            pulse.placeholder["li"] = pulse.runtime.getObjFirstData("li");
            pulse.placeholder["formatedSt"] = pulse.runtime.formatDate(pulse.runtime.getProperty(pulse.placeholder.co, "st"));
            pulse.placeholder["tmp246"] = pulse.runtime.equals(pulse.runtime.getProperty(pulse.placeholder.li, "pi"), 0, false, true);
            pulse.placeholder["tmp247"] = pulse.runtime.hasValue(pulse.runtime.getProperty(pulse.placeholder.li, "pi"));
            pulse.placeholder["tmp248"] = pulse.runtime.logicalAND(pulse.placeholder.tmp247, pulse.placeholder.tmp246);
            pulse.placeholder["formatedPi"] = pulse.runtime.switchCase(true, pulse.placeholder.tmp248, pulse.runtime.getProperty(pulse.placeholder.li, "pi"), "LPO-NoFrame");
            pulse.placeholder["tmp250"] = pulse.runtime.subString(pulse.runtime.getProperty(pulse.placeholder.co, "ty"), 20);
            pulse.placeholder["tmp251"] = pulse.runtime.hasValue(pulse.runtime.getProperty(pulse.placeholder.li, "nm"));
            pulse.placeholder["formatedNm"] = pulse.runtime.switchCase(true, pulse.placeholder.tmp251, pulse.runtime.getProperty(pulse.placeholder.li, "nm"), pulse.placeholder.tmp250);
            pulse.placeholder["tmp253"] = pulse.runtime.hasValue(pulse.runtime.getProperty(pulse.placeholder.li, "ai"));
            pulse.placeholder["formatedAi"] = pulse.runtime.switchCase(true, pulse.placeholder.tmp253, pulse.runtime.getProperty(pulse.placeholder.li, "ai"), pulse.runtime.getProperty(pulse.placeholder.co, "id"));
            pulse.placeholder["modName"] = pulse.runtime.subString(pulse.runtime.getProperty(pulse.placeholder.co, "nm"), 15);
            pulse.placeholder["temp_povId"] = pulse.runtime.template("{{s1}} | {{s2}} | {{s3}} | {{s4}} |LN-{{s5}} | {{s6}} | {{s7}}", pulse.placeholder.pageId_evar22, pulse.runtime.getProperty(pulse.placeholder.co, "zn"), pulse.placeholder.modName, pulse.placeholder.formatedPi, pulse.placeholder.formatedNm, pulse.placeholder.formatedAi, pulse.placeholder.formatedSt);
            pulse.placeholder["povId"] = pulse.runtime.writeLocalStorage("povId", pulse.placeholder.temp_povId);
            pulse.placeholder["catNavBarId"] = pulse.runtime.writeLocalStorage("catNavBarId", pulse.placeholder.catNavBar_prop29);
        },

        wmbeacon_xpr_pv: function(pulsePayload) {
            pulse.output["ee"] = pulse.runtime.getObj("ee", "XPR");
            pulse.output["ee__ex"] = pulse.placeholder.ee__ex;
        }
    };

    bc.utils.merge(mp, mappingsInterpreter);

})(_bcq, pulse.runtime);
(function (bc) {
	'use strict';
	
	bc.classes.AbstractHandler = {
		/**
		 * Initialize function for the Partner Handlers
		 * @author Carlos Soto <csoto@walmartlabs.com>
		 * @param {Object} Info Object about the configuration object for the Partner's Library and the Partner Mappings at the Partner Level
		 * @return {void}
		 */
		initialize : function (info) {
			this.options = this.parseOptions(info.opts);
			this.rqTp = info.rqTp;
			this.rqTpLimit = info.rqTpLimit;
			if(bc.Interpreter){
				this.interpreter = this.interpreters(info.tmpls);
			}
		},
		
		/**
		 * @desc Specify if tagAction to be invoked even if there is no context-action-partner-config (capc) entry specified for this partner, 
		 * @desc If there is a capc entry and its disabled, tagAction will not be invoked
		 * @author Laxmikant Kurhe <lkurhe@walmartlabs.com>
		 * @return {boolean} 
		 */
		forceTagAction: function(){
			return false;
		},
		
		/**
		 * Transforms the key value pair array of arrays into an options object: [['key1, 'value1'], ['key2, 'value2']] to {key1: 'value1', key2: 'value2'}
		 * @author Carlos Soto <csoto@walmartlabs.com>
		 * @param {Object} Options data for the Library of that Partner
		 * @return {void}
		 */
		parseOptions : function (options) {
			var opts = {}, i;
			
			if (Array.isArray(options)) {
				for (i in options) {
					if (Array.isArray(options[i]) && options[i].length > 1) {
						opts[options[i][0]] = options[i][1];
					}
				}
			} 
			return opts;
		},
		
		/**
		 * Merges the attributes sent by the consumer and the templates defined for the action into the parameters for the tag action
		 * @author Carlos Soto <csoto@walmartlabs.com>
		 * @param {Object} attrs Beacon Attributes to be sent to Beacon and transformed into Partner Variables
		 * @param {Object} result with mappings executed and stored under result.vars and results.phs
		 * @param {boolean} append_attributes Boolean value whether to append attributes in case there is no mapping
		 * @return {Object} set of params to send for the action
		 */
		getParams : function (attrs, result, append_attributes) {
			var result = result || {},
				variables = result.vars || result.output;
			
			// ------------------------------
			// If the append_attributes flag is true, then include all of the attributes to be sent to partner
			if (append_attributes) {
				variables = bc.utils.merge(variables, attrs);
			}
			
			// ------------------------------
			// TODO: check for Tenant Level rules?
			// TODO: check for Context Level rules? If so, we need the context as a parameter. When are these rules executed
			
			// ------------------------------
			// Merge the variables and the jsoned attributes in the response
			return variables;
		},
		
		/**
		 * Merges the attributes sent by the consumer and the templates defined for the action into the parameters for the tag action
		 * @author Laxmikant Kurhe <lkurhe@walmartlabs.com>
		 * @param {Object} attrs Beacon Attributes to be sent to Beacon and transformed into Partner Variables
		 * @param {Object} mapping Variable Mapping to be executed
		 * @param {Object} result object to store mapped values
		 * @return {Object} result with mapped values
		 */
		execMapping : function (attrs, mapping, result) {
			if(Array.isArray(mapping) && mapping.length === 1 && mapping[0].rn === 'jsmp'){
				return this.execMappingNew(attrs, mapping, result);
			}else{
				var result = result || {},
					i, len,
					mapp, val, tmplMapping,
					rn;
				
				result.vars = result.vars || {};
				result.phs = result.phs || {}; 
				
				// ------------------------------
				// TODO: run the Partner Level Mappings here!
				if (Array.isArray(mapping)) {
					len = mapping.length;
					for(i = 0; i < len; i++){
						mapp = mapping[i] || {};
						mapp.rr = mapp.rr || {};
						try
						{
							if(mapp.rr.fn === 'mappingTemplate'){
								if(this.interpreter){
									tmplMapping = this.interpreter.interpret(mapp.rr.fn, mapp.rr.args, attrs, result.phs);
								}
								result = this.execMapping(attrs, tmplMapping, result);
							}
							if(this.interpreter){
								val = this.interpreter.interpret(mapp.rr.fn, mapp.rr.args, attrs, result.phs);
							}
							if(mapp.rt === 'ph'){
								if(typeof mapp.rn === 'string'){	//walmart.prop29AlreadyFired
									rn = mapp.rn.split('.')[0];
									result.phs[rn] = this.buildProperty(result.phs[rn], mapp.rn, val);
								}
							}
							if(mapp.rt === 'pv'){
								if(mapp.rt === 'pv' && mapp.rn === 'mappings' && val && typeof val === 'object'){
								if(val.phs && typeof val.phs === 'object' )
									{
										bc.utils.merge(result.phs,val.phs);
									}
								if(val.vars && typeof val.vars === 'object' )
									{
										bc.utils.merge(result.vars,val.vars);
									}	
								} else if(typeof mapp.rn === 'string'){	//walmart.prop29AlreadyFired
									rn = mapp.rn.split('.')[0];
									result.vars[rn] = this.buildProperty(result.vars[rn], mapp.rn, val);
								}
							}

							
						}
						catch(err)
						{
							//TODO:Add service call to log error trigger in mappping in release mode
					  		if(_bcq&&_bcq.options&&_bcq.options.mode==="debug")
					  		{
						  		bc.utils.log("Error occurred in mapping");
						  		bc.utils.log("----Mapping Object----");
						  		bc.utils.log(mapp);
						  		bc.utils.log("----Error Detail----");
						  		bc.utils.log(err);
					  	    }
						}
					}
				}
				return result;
			}
		},

		execMappingNew : function (attrs, mapping, result) {
			var result = result || {},
				i, len;
			
			// ------------------------------
			// TODO: run the Partner Level Mappings here!
			if (Array.isArray(mapping)) {
				len = mapping.length;
				for(i = 0; i < len; i++){
					try{
							pulse["output"]={};
							pulse["placeholder"]={};
							pulse["runtime"]["pulsePayload"]= attrs;				
							pulse.runtime[mapping[i].rr.fn].apply({}, [attrs]);
							result["output"]=pulse.output;
							result["placeholder"]=pulse.placeholder;
						
					}catch(err){
						//TODO:Add service call to log error trigger in mappping in release mode
				  		if(_bcq&&_bcq.options&&_bcq.options.mode==="debug"){
					  		bc.utils.log("Error occurred in mapping");
					  		bc.utils.log("----Mapping Object----");
					  		bc.utils.log(mapping[i].rr.fn);
					  		bc.utils.log("----Error Detail----");
					  		bc.utils.log(err);
				  	    }
					}
				}
			}
			
			return result;
		},
		
		/**
		 * Merges the attributes sent by the consumer and the templates defined for the action into the parameters for the tag action
		 * @author Pankaj Manghnani <pmanghn@walmartlabs.com>
		 * @param {Object} attrs Beacon Attributes to be sent to Beacon and transformed into Partner Variables
		 * @param {Object} mapping Variable Mapping to be executed
		 */
		execNewMapping : function (attrs, mapping) {
			var result = result || {},
				i, len,
				mapp, val, tmplMapping,
				rn;
			
			result.vars = result.vars || {};
			result.phs = result.phs || {}; 
			
			// ------------------------------
			// TODO: run the Partner Level Mappings here!
			if (Array.isArray(mapping)) {
				len = mapping.length;
				for(i = 0; i < len; i++){
					mapp = mapping[i] || {};
					mapp.rr = mapp.rr || {};
					try
					{
						
						this.interpreter.interpret(mapp.rr.fn,attrs);		
					}
					catch(err)
					{
						//TODO:Add service call to log error trigger in mappping in release mode
				  		if(_bcq&&_bcq.options&&_bcq.options.mode==="debug")
				  		{
					  		bc.utils.log("Error occurred in mapping");
					  		bc.utils.log("----Mapping Object----");
					  		bc.utils.log(mapp);
					  		bc.utils.log("----Error Detail----");
					  		bc.utils.log(err);
				  	    }
					}
				}
			}
			
			return result;
		},

		formatParams: function(params, format){
			var val, k;
			if(typeof params !== 'object' || !params){
				return params;
			}
			val = {};
			function replacer(name, val) {
    			
    			if ( val === undefined ) { 
        				return ''; 
    			}
    			else
				{
    				return val;
    			}
    		} 

			if(format === 'NV'){
				//Format as name value pair, how TBD
				for(k in params){
					if (typeof params[k] === 'object' && params[k]) {
						val = bc.utils.merge(val, params[k]);
					} else {
						val[k] = params[k];
					}
				}
			}else{
				for(k in params){
					if (typeof params[k] === 'object' && params[k]) {
						val[k] = JSON.stringify(params[k],replacer);
					} else {
						val[k] = params[k];
					}
				}
			}
			return val;	
		},
		
		buildProperty: function(targetObj, propNm, val){
			var i, len, rVal;
			if(typeof propNm === 'string'){	//walmart.prop29AlreadyFired
				propNm = propNm.split('.') || [];
				len = propNm.length;
				if(len === 1){
					return val;
				}
				rVal = targetObj || {};
				for(i = 1; i < len; i++){
					if(i === (len - 1)){
						rVal[propNm[i]] = val;
					}else{
						rVal[propNm[i]] = (rVal[propNm[i]] && typeof rVal[propNm[i]] === 'object') ? rVal[propNm[i]] : {};
					}
				}
			}
			return rVal;
		},
		
		/**
		 * @desc Placeholder for the "load" function of the Partner Handlers
		 * @author Carlos Soto <csoto@walmartlabs.com>
		 * @param {Function} callback Function to be called after the library has been loaded
		 * @return {void}
		 */	
		load : function (callback) {
			callback();
		},
		
		/**
		 * @desc Placeholder for the "tagAction" function of the Partner Handlers
		 * @author Laxmikant Kurhe <lkurhe@walmartlabs.com>
		 * @param {String} context the identifier of the context for the action (where the action took place)	 
		 * @param {String} action Name of the Action to be tagged.
		 * @param {Object} attributes Beacon Attributes to be sent to Beacon and transformed into Partner Variables
		 * @param {Object} capc "Context-Action-Partner-Configuration" (capc) Variable Mapping and other configuration for that specific combination
		 * @return {void}
		 */
		beforeTag : function (context, action, attributes, capc) {
			return;
		},
		
		/**
		 * @desc Placeholder for the "validate" function of the Partner Handlers
		 * @author Laxmikant Kurhe <lkurhe@walmartlabs.com> 
		 * @param {String} ctx the identifier of the context for the action (where the action took place)	 
		 * @param {String} act Name of the Action to be tagged.
		 * @param {Object} attrs Beacon Attributes to be sent to Beacon and transformed into Partner Variables
		 * @param {Object} capc "Context-Action-Partner-Configuration" (capc) Variable Mapping and other configuration for that specific combination
		 * @return {void}
		 */
		validate : function (ctx, act, attrs, capc) {
			var capc = capc || {}, result, params;
			if(!capc.vldt){
				return true;
			}
			result = this.execMapping(attrs, capc.vldt.mp) || {};
			params = this.getParams(attrs, result) || {};
			return (params.validate === false) ? params.validate : true;
		},
		
		/**
		 * @desc Placeholder for the "tagAction" function of the Partner Handlers
		 * @author Carlos Soto <csoto@walmartlabs.com>
		 * @param {String} context the identifier of the context for the action (where the action took place)	 
		 * @param {String} action Name of the Action to be tagged.
		 * @param {String} report Name of the RerportID for filtering.
		 * @param {Object} attributes Beacon Attributes to be sent to Beacon and transformed into Partner Variables
		 * @param {Object} capc "Context-Action-Partner-Configuration" (capc) Variable Mapping and other configuration for that specific combination
		 * @return {Int} whether the action was tagged or not (0||1)
		 */
		tagAction : function (context, action, report, attributes, capc) {
			// ------------------------------
			//Validation must return true before triggering call
			if(this.validate(context, action, attributes, capc)){
				
				this.beforeTag(context, action, attributes, capc);
				
				// ------------------------------
				//Logic for tagAction Mapping and triggering call goes here
				// ------------------------------
				
				this.afterTag(context, action, attributes, capc);
			}
			return 0;
		},

		/**
		 * @desc Placeholder for the "tagAction" function of the Partner Handlers
		 * @author Laxmikant Kurhe <lkurhe@walmartlabs.com>
		 * @param {String} context the identifier of the context for the action (where the action took place)	 
		 * @param {String} action Name of the Action to be tagged.
		 * @param {Object} attributes Beacon Attributes to be sent to Beacon and transformed into Partner Variables
		 * @param {Object} capc "Context-Action-Partner-Configuration" (capc) Variable Mapping and other configuration for that specific combination
		 * @return {void}
		 */
		afterTag : function (context, action, attributes, capc) {
			return;
		},
		
		interpreters : function(templates){
			var Interpreter = new bc.utils.extend({}, bc.Interpreter, {
							initialize : function(templates){
								this.tmpls = templates;
							}
						});
			return new Interpreter(templates);
		}
		
	};
})(_bcq);

(function (bc) {

	'use strict';

	bc.classes.AbstractHandler.formatUrl = function(baseURL, params, ieLimit){
		var len, key, 
			keyVal,
			url, urlReqs = [],
			partId;
		
		ieLimit = ieLimit ? ieLimit - 53 : ieLimit;	// deducting length for partId and part parameter 
															// these will be added if data is broken into multiple url's
		
		url = baseURL;
		for (key in params) {
			if(params.hasOwnProperty(key)){
				keyVal = encodeURIComponent(key) + "=" + (typeof params[key] === 'undefined' ? '' : encodeURIComponent(params[key]));
			
				if(ieLimit && ((url.length + keyVal.length) > ieLimit)){	// IE specific logic
					url = (url !== baseURL) ? url.substr(0, url.length-1) : url;
					urlReqs.push(url);
					url = baseURL;
				}
				url += keyVal + '&';
			}
		}
		url = (url !== baseURL) ? url.substr(0, url.length-1) : url;
		urlReqs.push(url);
		len = urlReqs.length;
		if(len > 1){
			partId = bc.utils.getPageViewId();
			for(key = 0; key < len; key++){
				//urlReqs[key] += (urlReqs[key] === baseURL ? '' : '&') + 'partId=' + partId + '&part=' + (key+1) + '.' + len;
				urlReqs[key] = urlReqs[key].replace(baseURL, baseURL + 'partId=' + partId + '&part=' + (key+1) + '.' + len + '&');
			}
		}
		return urlReqs;
	};

	bc.classes.AbstractHandler.triggerUrl = function (baseURL, params){
		var rqTp = typeof this.rqTp === 'string' ? this.rqTp.toLowerCase() : '',
			rqTpLimit = typeof this.rqTpLimit === 'number' ? this.rqTpLimit : undefined, 
			isCors = bc.utils.isIE() && bc.utils.isIE() > 7,	 
			ieLimit = bc.utils.ieUrlLimit(), url, urlQS,
			xhr, urlReqs,
			i, len, 
			postReqURL = baseURL,
			img;
		
		baseURL += ((baseURL.indexOf('?') > -1)?'&':'?');
		urlQS = bc.utils.urlSerialize(params);
		url = baseURL + urlQS;
		
		if(rqTp === 'post' && isCors){
			xhr = bc.utils.corsReq(rqTp, postReqURL);
		}else if(rqTp === 'post_limit' && isCors){
			if(ieLimit){
				rqTpLimit = (rqTpLimit && rqTpLimit < ieLimit) ? rqTpLimit : ieLimit;
			}
			if(url.length > rqTpLimit){
				xhr = bc.utils.corsReq('post', postReqURL);
			}
		}
		
		if(xhr && xhr.send){	// Trigger cors post request if supported
			setTimeout(function(){
				try{
					if(typeof xhr.setRequestHeader === 'function'){
						xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
					}
					// TODO: Remove this hardcoding.. Added for temporary EXPO requirement
					// Specific requirement for IE8/9 POST request
					if(bc.utils.isIE() && bc.utils.isIE() <= 9){
						var expVal = bc.store.getCookie('exp');
						expVal = (typeof expVal !== 'undefined' && expVal !== null) ? decodeURIComponent(expVal) : expVal;
					  params.ck = JSON.stringify({
					    '_def': {
					      SSLB: bc.store.getCookie('SSLB'),
					      exp: expVal,
					      bstc: bc.store.getCookie('bstc'),
					      vtc: bc.store.getCookie('vtc') 
					    }
					  });
					}
					xhr.send(bc.utils.urlSerialize(params));
				}catch(err){}
			}, 0);
		}else if(ieLimit && url.length > ieLimit){	// IE specific logic, send multiple get requests if url length exceeds maxLimit for IE
			urlReqs = this.formatUrl(baseURL, params, ieLimit) || [];
			len = urlReqs.length;
			for(i = 0; i < len; i++){
				img = new Image();
				img.src = urlReqs[i];
			}
		}else{
			img = new Image();
			img.src = url;
		}
	};

	bc.classes.AbstractHandler.metadata = function(params, ctx, act, rpt, skipParams){
		var params = params || {},
			si = this.options.site_id,
			sv = this.options.site_version,
			tv = this.options.tm_version,
			fmt = this.options.beacon_format,
			bh = this.options.bh,
			pctx = bc.utils.getData(bc.utils.pctx, 'cm._def.ctx');		// To get parent-ctx value, which has to be specified by FE in given path.
																		// 'cm' is context metadata group for parent-ctx, if later required to store more info
		params.ts = params.ts || new Date().getTime(); 					// Timestamp that's needed to add as a "random" parameter to avoid url caching
		params.pv_id = bc.page_view_id; 								// Add the Page View ID to the call
		params.x = bc.utils.rumSeq;										// TODO: to be removed soon, added only to ease testing of server side mappings
		if(!skipParams){												// Skip these params may be required for boomerang call
			params.a = act;
			params.ctx = ctx;
			params.rp = rpt;
			params.u = params.u || window.document.URL;				 	// use URL instead of location.href because of a Safari bug
			params.r = params.r || bc.utils.referrer || document.referrer;
			params.lang = window.document && window.document.documentElement && window.document.documentElement.lang ? window.document.documentElement.lang : "";
			
			if(pctx){
				params.pctx = pctx;
			}
		}
		if(bc.utils.hasVal(si)){
			params.si = si;
		}
		if(bc.utils.hasVal(sv)){
			params.sv = sv; 
		}
		if(bc.utils.hasVal(tv)){
			params.tv = tv;
		}
		if(bc.utils.hasVal(fmt)){
			params.fmt = fmt;
		}
		if(bc.utils.hasVal(bh)){
			params.bh = bh;
		}

		if(typeof _isWalmartPhoto !== 'undefined' && _isWalmartPhoto){
			params.si = "usph";
		}
		return params;
	};

	/**
	 * @desc triggerTag can trigger an img or script tag based on tag parameter
	 * @desc triggerTag function will not make any checks for url size
	 * @author 
	 * @param {String} url to be specified for a given tag	 
	 * @param {Object} params name-value pairs of parameter to be assigned to given url
	 * @param {Object} tag type of tag to be triggered
	 * @param {Object} callback function to be executed after resource load
	 * @return {void}
	 */
	bc.classes.AbstractHandler.triggerTag = function(url, params, tag, callback){
		var tag, 
			img,
			iframe,
			urlQS,
			isNotJsFunctionTag=(tag!=='jsFunction');
		if(!url && isNotJsFunctionTag){
			return;
		}
		if(isNotJsFunctionTag){
			urlQS = bc.utils.urlSerialize(params);
			if(urlQS){
				url += (url.indexOf('?') === -1) ? '?' : (url.indexOf('?') === (url.length -1) ? '' : '&');
				url += urlQS;
			}	
		}
		
		if(tag === 'image'){
			img = new Image();
			img.src = url;
		}else if(tag === 'script'){
			bc.utils.loadScript(url, callback);
		}else if(tag === 'iframe'){
			var where, 
			iframe = document.createElement('iframe');
			iframe.src = url;
			iframe.title = '';
			(iframe.frameElement || iframe).style.cssText = "width: 0; height: 0; border: 0; display: inherit";
			where = document.getElementsByTagName('script');
			where = where[where.length - 1];
			where.parentNode.insertBefore(iframe, where);
		}else if(tag === 'jsFunction'){
			if(window[params.fn]){
				window[params.fn].apply(window, params.args);
			}
		}
	};

})(_bcq);

(function (bc) {
	'use strict';

	/**
	 * @desc Bomerang Handler
	 * @author Laxmikant Kurhe <lkurhe@walmartlabs.com> 
	 */
	bc.classes.Wmbeacon = bc.utils.extend({}, bc.classes.AbstractHandler, {
		/**
		 * Initialize function for the WMBeacon Handler
		 * @author Carlos Soto <csoto@walmartlabs.com>
		 * @param {Object} Info Object about the configuration object for the Partner's Library and the Partner Mappings at the Partner Level
		 * @return {void}
		 */
		initialize : function (info, config) {
			this.options = this.parseOptions(info.opts);
			this.rqTp = info.rqTp;
			this.rqTpLimit = info.rqTpLimit;
			this.options.beacon_url = this.beaconURL(this.options, true);
			this.beacon_url = this.beaconURL(this.options);
			
			// ------------------------------
			// Set the autorun value for Boomerang explicitly to false
			this.options.autorun = false;

			// ------------------------------
			// Set the log for debug mode
			if (bc.options.mode === 'debug') {
				this.options.log = bc.utils.log;
			} else {
				this.options.log = false;
			}

			// ------------------------------
			// Set the options for the RoundTrip Plugin.
			// TODO: Not sure if we need this value for Boomerang. Please review the documentation.
			this.options.RT = {cookie: null};
			
			// Build the beacon url if not set
			if (typeof this.options.site_domain === 'undefined' || this.options.site_domain === '') {
				this.options.site_domain = document.domain;
			}
			
			// ------------------------------
			// Log the Configuration Options
			//bc.utils.log('WMBeacon Configuration Options:', this.options);
			
			// ------------------------------
			// Initialize Boomerang Here
			BOOMR.init(this.options);
			BOOMR.plugins.RT.startTimer('t_page', bc.options.start_time);
			BOOMR.plugins.RT.startTimer('t_window', bc.options.start_time);
			if(bc.Interpreter){
				this.interpreter = this.interpreters(info.tmpls, config);
			}
		},
		
		/**
		 * @desc Specify if tagAction to be invoked even if there is no context-action-partner-config (capc) entry specified for this partner, 
		 * @desc If there is a capc entry and its disabled, tagAction will not be invoked
		 * @author Laxmikant Kurhe <lkurhe@walmartlabs.com>
		 * @return {boolean} 
		 */
		forceTagAction: function(){
			return true;
		},
		
		/**
		 * @desc Placeholder for the "beaconURL" function of the Partner Handlers
		 * @author Laxmikant Kurhe <lkurhe@walmartlabs.com>
		 * @param {options} options Options set for generating beacon_url
		 * @param {boolean} isPerf if its a performance
		 * @return {String} beacon_url generated using options
		 */
		beaconURL : function(options, isPerf){
			var options = options || {},
				beacon_url;
			
			// ------------------------------
			// Build the beacon url
			if (typeof options.beacon_url_domain !== 'undefined' && options.beacon_url_domain) {
				beacon_url = options.beacon_url_domain;
			} else {
				beacon_url = bc.domain;
			}
			
			if(isPerf && typeof options.perf_beacon_url_path !== 'undefined' && options.perf_beacon_url_path){
				//isPerf-true i.e. Page Performance data should always go to beacon.gif, this is a requirement.
				beacon_url += options.perf_beacon_url_path;
			}else if(!isPerf && typeof options.beacon_url_path !== 'undefined' && options.beacon_url_path){
				beacon_url += options.beacon_url_path;
			}else{
				// ------------------------------		
				// Add a slash (/) to the end if the beacon_url doesn't have it
				if (beacon_url.charAt(beacon_url.length - 1) !== '/') {
					beacon_url += '/';
				}
				
				// ------------------------------
				// Append the usual gif name "rum.gif"
				beacon_url += 'rum.gif';
			}
			
			// ------------------------------		
			// Take the beacon url and remove the protocol whatever that was it and add the right protocol of the page
			beacon_url = 'https://' + beacon_url.replace(/.*:\/\//g, "");
			return beacon_url;
		},
		
		/**
		 * @desc Placeholder for the "tagAction" function of the Partner Handlers
		 * @author Carlos Soto <csoto@walmartlabs.com>
		 * @param {String} ctx the identifier of the context for the action (where the action took place)	 
		 * @param {String} act Name of the Action to be tagged.
		 * @param {String} rpt Name of the ReportID for filtering.
		 * @param {Object} attrs Beacon Attributes to be sent to Beacon and transformed into Partner Variables
		 * @param {Object} capc "Context-Action-Partner-Configuration" (capc) Variable Mapping and other configuration for that specific combination
		 * @return {Int} whether the action was tagged or not (0||1)
		 */
		tagAction : function (ctx, act, rpt, attrs, capc) {
			var tag = 0, 
				capc = capc || {},
				result,
				params, 
				url = this.beacon_url,
				actOptions = this.parseOptions(capc.opts) || {},
				validation,
				isResponsive,
				aniviaMetadata;
			
			validation = this.validate(ctx, act, attrs, capc);
			
			if(!validation){
				bc.utils.log('Validation failed for action [' + act + '] under context [' + ctx + '], partner [wmbeacon]');
				return tag;
			}
			
			this.beforeTag(ctx, act, attrs, capc);
			
			result = this.execMapping(attrs, capc.mp) || {};
			params = this.getParams(attrs, result, (capc.apnd !== false)) || {};
			
			params = this.allowedGroups(params, capc);
			
			params = this.metadata(params, ctx, act, rpt);
			if (act === 'PERFORMANCE_METRICS') {
				var sp_cookie = bc.store.getCookie('SP');
				if(sp_cookie){
					params.cu = params.cu || {};
					params.cu[bc.utils.defKey] = params.cu[bc.utils.defKey] || {};
					params.cu[bc.utils.defKey]['SP'] = sp_cookie;
				}
			}
			params = this.formatParams(params, capc.formatParams);

			aniviaMetadata = bc.utils.aniviaMetadata();

			if(aniviaMetadata){
				params.dv = JSON.stringify({anivia:aniviaMetadata});
			}
			if(params.cd){
				try{
					params.cd = JSON.parse(params.cd)._def;
				}
				catch(e){
					params.cd = {};
				}
				
			}
			else
			{
				params.cd = {};
			}
			params.cd.dim = bc.utils.clientDim();	//include client Details
			params.cd = JSON.stringify(params.cd);
			isResponsive = bc.utils.isResponsive();

			if(isResponsive !== undefined){
				params.resp = isResponsive;
			}

			// ------------------------------
			// This is a very special case for the entire library.
			// Since the BE is expecting the performance data from 
			// WMBeacon, we're sending it for the action called "PERFORMANCE_METRICS"	
			if (act === 'PERFORMANCE_METRICS') {
				//TODO: for single page applications hash tag should not be removed from "u" params
				//which boomerang removes
				delete params.u; 					// remove the u param as it's going to be added by boomerang anyways
				delete params.r; 					// remove the u param as it's going to be added by boomerang anyways
				if(params.err){
					params.err = JSON.stringify(params.err);
				}
				
				if(!capc.dsGAUserPrefs){
					params['_bsc-gopt'] = this.gaUserPrefs();		// '_bsc-gopt' is to capture Google analytics tracking disable cookie value
				}
				if(bc.options.above_the_fold_end > 0){		// To capture above the fold timing if specified under setOptions
					BOOMR.plugins.RT.startTimer('t_atf', bc.options.start_time);
					BOOMR.plugins.RT.endTimer('t_atf', bc.options.above_the_fold_end);
				}
				BOOMR.plugins.RT.endTimer("t_page");
				// code-tempSolution specific to USGrocery, which is required to identify perf data without changes on grocery code
				if(!params.ctx && (bc.options.bh === 'beacon.delivery.walmart.com' || bc.options.bh === 'beacon.qa.delivery.walmart.com')){
					try{
						var w2gGlobal = angular.element('html').injector().get('w2gGlobal');
						params.ctx = w2gGlobal.routes.byPath(window.location.pathname).name;
					}catch(e){}
				}else if(!params.ctx && (bc.options.bh === 'beacon.pangaea.walmart.ca' || bc.options.bh === 'beacon.qa.pangaea.walmart.ca')){
					if(typeof walmart !== 'undefined' && walmart && walmart.context && typeof walmart.context.pageType === 'string'){
						params.ctx = walmart.context.pageType;
					}
				}
				BOOMR.addVar(params);
				BOOMR.page_ready();
				tag = 1;
			} else {
				// If there is a different beacon domain or path then reconstruct the beacon URL 
				if(actOptions.beacon_url_domain || actOptions.beacon_url_path){
					url = this.beaconURL(actOptions);
				}
				// ------------------------------
				// Trigger beacon url's unless configuration specifically says to return back generated url without triggering
				if(capc.returnUrl === true){
					// Just get url's generated
					url += ((url.indexOf('?') > -1)?'&':'?');
					tag = this.formatUrl(url, params, bc.utils.ieUrlLimit());
					tag = (tag.length === 1) ? tag[0]: tag;
				}else{
					// ------------------------------
					// Create url for the Beacon Call
					this.triggerUrl(url, params);
					tag = 1;
				}
			}
			return tag;
		},
		
		allowedGroups: function(params, capc){
			var capc = capc || {},
				params,
				i, len, k,
				grps = capc.lmt_grps;	// Allowed groups for wmbeacon call
			
			if(Array.isArray(grps)){
				len = grps.length;
				for(i = 0; i< len; i++){
					grps[i] = Array.isArray(grps[i]) ? grps[i].join(bc.utils.separator) : grps[i];
				}
				for(k in params){
					if(k !== 'err' && grps.indexOf(k) === -1){
						delete params[k];		// Remove groups which are not part of Allowed groups for wmbeacon call
					}
				}
			}
			return params;
		},
		
		gaUserPrefs: function(){
			var O = window, 
				v,
		      	xa = function (a) {
				    var b = O._gaUserPrefs;
			        if (b && b.ioo && b.ioo() || a && true === O["gadisable" + a]) return !0;
			        try {
			           var c = O.external;
			           if (c && c._gaUserPrefs && "oo" === c._gaUserPrefs) return !0;
			        } catch (d) {}
			        return !1;
			     };
		    v = (typeof xa === 'function' && xa()) ? 1 : 0; 
		    return v;
		},
		
		interpreters : function(templates, config){

			var WMBInterpreter = bc.utils.extend({}, bc.Interpreter, {

				initialize : function(templates,filter){
					this.tmpls = templates;

					if(filter!==undefined){
						this.filter=filter;
					}

					this.genTmpls = config.tmpls;
				}
				
			});
			return new WMBInterpreter(templates);
		}
		
	});
})(_bcq);

/**
 * @desc Loads and initialize the Partner's libraries we need to deploy
 * @author Carlos Soto <csoto@walmartlabs.com>
 * @param {Object} Configuration data about the Partners
 * @return void
 */
(function (bc, config) {
	'use strict';
	//bc.options.page_specfic_mappings_enable = false; // Need to remove in phase 2 only for experiment folder.
	var i, partner, // iterator(s)
		class_name = '',
		len,
		wait_q, data,
		store,
        queue,
       	rum_mapping_url= bc.options.page_specfic_mappings_enable && bc.options.mapping_identifier? "rum-mappings-" + bc.options.mapping_identifier : "rum-mappings",
        autorun = function () {
            // ------------------------------
            // Ask for the autorun once more, just in case they turned it off after the window.load event.
            if (bc.options.autorun) {
				bc.push(['_tagAction', '', 'PERFORMANCE_METRICS', 'prf.pgl.vww.pgl']);
            }else{
            	BOOMR.plugins.RT.endTimer('t_window', (new Date()).getTime());
            }
        }; 
    class_name = bc.utils.toCamelCase('wmbeacon', true);
    bc.handlers['wmbeacon'] = new bc.classes[class_name](config.ptns['wmbeacon'], config);
    	
	try{
		store = config.store.wait_q;
		wait_q = bc.store.read(store.n, {storage: store.t});
	
		if(Array.isArray(wait_q)){
			while(wait_q.length){
				i = wait_q.pop();
				if(bc.utils.hasVal(i)){
					bc.push(['_tagAction', i.ctx, i.act, i.rpt, i.attrs]);
				}
			}
			// Fetch all the pending requests into Analytics queue, remove them from storage and execute with _bcq commands execution
			// Removing all pending requests at once
			bc.store.write(store.n, wait_q, {storage: store.t});
		}
	}catch(e){
		
	}
	
	if(bc.pubsub){
		bc.pubsub.subscribe(bc.topics.NEW_INTERNAL_VIEW, {callback: bc.utils.newInternalView});
	}

    if (bc.options.mode === 'debug') {
      rum_mapping_url = rum_mapping_url + ".debug.js";	
    }
    else{
    	rum_mapping_url = rum_mapping_url + ".js";
    }
    
	// Call the script that all of the required files, plugins, configurations and libraries (rum.js)
	rum_mapping_url += '?' + bc.utils.urlSerialize({
        mode : bc.options.mode,
        bh : bc.options.bh,	// Sending beacon host folder under 'bh' param, if CDN URL is getting used then _setOptions MUST have correct bh specified
        bd : bc.options.bd, // Sending domain name under 'bd' param, if CDN URL is getting used and same domain is used for multiple sites, _setOptions MUST have correct bd specified
        pv_id : bc.page_view_id
    });

	bc.utils.loadScript(bc.domain + rum_mapping_url);
    // ------------------------------
	// Run all of the commands in the queue
    bc.push.apply(bc, bc.queue);


    
	 
	
	// ------------------------------
	// "_tagAction" command for PERFORMANCE_METRICS when the window loads if autorun is true
    //if (bc.options.autorun) {
    	bc.utils.bind(window, 'load', autorun);
	//}
})(_bcq, _bcc);

