vtex-utils
Version:
A collection of utilities methods for Vtex stores
1,414 lines (1,250 loc) • 162 kB
JavaScript
/*!!
* VtexUtils.js v1.18.1
* https://github.com/zeindelf/vtex-utils
*
* Copyright (c) 2017-2018 Zeindelf
* Released under the MIT license
*
* Date: 2018-09-17T18:32:03.664Z
*/
var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
function createCommonjsModule(fn, module) {
return module = { exports: {} }, fn(module, module.exports), module.exports;
}
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
return typeof obj;
} : function (obj) {
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
};
var classCallCheck = function (instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
};
var createClass = function () {
function defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
return function (Constructor, protoProps, staticProps) {
if (protoProps) defineProperties(Constructor.prototype, protoProps);
if (staticProps) defineProperties(Constructor, staticProps);
return Constructor;
};
}();
var defineProperty = function (obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
};
/* eslint-disable */
if ((typeof window === 'undefined' ? 'undefined' : _typeof(window)) !== 'object') {
commonjsGlobal.window = commonjsGlobal;
commonjsGlobal.window.navigator = {};
}
if ('jQuery' in window || '$' in window) {
/*
* jquery.ajax-retry
* https://github.com/johnkpaul/jquery-ajax-retry
*
* Copyright (c) 2012 John Paul
* Licensed under the MIT license.
*/
(function ($) {
// enhance all ajax requests with our retry API
$.ajaxPrefilter(function (options, originalOptions, jqXHR) {
jqXHR.retry = function (opts) {
if (opts.timeout) {
this.timeout = opts.timeout;
}
if (opts.statusCodes) {
this.statusCodes = opts.statusCodes;
}
return this.pipe(null, pipeFailRetry(this, opts));
};
});
// generates a fail pipe function that will retry `jqXHR` `times` more times
function pipeFailRetry(jqXHR, opts) {
var times = opts.times;
var timeout = jqXHR.timeout;
// takes failure data as input, returns a new deferred
return function (input, status, msg) {
var ajaxOptions = this;
var output = new $.Deferred();
var retryAfter = jqXHR.getResponseHeader('Retry-After');
// whenever we do make this request, pipe its output to our deferred
function nextRequest() {
$.ajax(ajaxOptions).retry({ times: times - 1, timeout: opts.timeout, statusCodes: opts.statusCodes }).pipe(output.resolve, output.reject);
}
if (times > 1 && (!jqXHR.statusCodes || $.inArray(input.status, jqXHR.statusCodes) > -1)) {
// implement Retry-After rfc
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.37
if (retryAfter) {
// it must be a date
if (isNaN(retryAfter)) {
timeout = new Date(retryAfter).getTime() - $.now();
// its a number in seconds
} else {
timeout = parseInt(retryAfter, 10) * 1000;
}
// ensure timeout is a positive number
if (isNaN(timeout) || timeout < 0) {
timeout = jqXHR.timeout;
}
}
if (timeout !== undefined) {
setTimeout(nextRequest, timeout);
} else {
nextRequest();
}
} else {
// no times left, reject our deferred with the current arguments
output.rejectWith(this, arguments);
}
return output;
};
}
})(jQuery);
/*!
* jquery.requestanimationframe - 0.2.3-pre
* https://github.com/gnarf37/jquery-requestAnimationFrame
* Requires jQuery 1.8+
*
* Copyright (c) 2016 Corey Frang
* Licensed under the MIT license.
*/
// UMD factory https://github.com/umdjs/umd/blob/master/jqueryPlugin.js
(function ($) {
if (Number(jQuery.fn.jquery.split('.')[0]) >= 3) {
if (window.console && window.console.warn) {
window.console.warn('The jquery.requestanimationframe plugin is not needed ' + 'in jQuery 3.0 or newer as they handle it natively.');
}
return false;
}
var animating;
function raf() {
if (animating) {
window.requestAnimationFrame(raf);
jQuery.fx.tick();
}
}
if (window.requestAnimationFrame) {
jQuery.fx.timer = function (timer) {
if (timer() && jQuery.timers.push(timer) && !animating) {
animating = true;
raf();
}
};
jQuery.fx.stop = function () {
animating = false;
};
}
})(jQuery);
}
var utilify = createCommonjsModule(function (module, exports) {
/*@preserve
* Utilify.js v0.10.1
* https://github.com/zeindelf/utilify-js
*
* Copyright (c) 2017-2018 Zeindelf
* Released under the MIT license
*
* Date: 2018-09-17T18:11:50.467Z
*/
(function (global, factory) {
module.exports = factory();
}(commonjsGlobal, (function () {
/**
* JavaScript Cookie v2.2.0
* https://github.com/js-cookie/js-cookie
*
* Copyright 2006, 2015 Klaus Hartl & Fagner Brack
* Released under the MIT license
*/
/* eslint-disable */
function extend() {
var i = 0;
var result = {};
for (; i < arguments.length; i++) {
var attributes = arguments[i];
for (var key in attributes) {
result[key] = attributes[key];
}
}
return result;
}
function decode(s) {
return s.replace(/(%[0-9A-Z]{2})+/g, decodeURIComponent);
}
var initCookies = function initCookies(converter) {
function api() {}
function set(key, value, attributes) {
if (typeof document === 'undefined') {
return;
}
attributes = extend({
path: '/'
}, api.defaults, attributes);
if (typeof attributes.expires === 'number') {
attributes.expires = new Date(new Date() * 1 + attributes.expires * 864e+5);
}
// We're using "expires" because "max-age" is not supported by IE
attributes.expires = attributes.expires ? attributes.expires.toUTCString() : '';
try {
var result = JSON.stringify(value);
if (/^[\{\[]/.test(result)) {
value = result;
}
} catch (e) {}
value = converter.write ? converter.write(value, key) : encodeURIComponent(String(value)).replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g, decodeURIComponent);
key = encodeURIComponent(String(key)).replace(/%(23|24|26|2B|5E|60|7C)/g, decodeURIComponent).replace(/[\(\)]/g, escape);
var stringifiedAttributes = '';
for (var attributeName in attributes) {
if (!attributes[attributeName]) {
continue;
}
stringifiedAttributes += '; ' + attributeName;
if (attributes[attributeName] === true) {
continue;
}
// Considers RFC 6265 section 5.2:
// ...
// 3. If the remaining unparsed-attributes contains a %x3B (";")
// character:
// Consume the characters of the unparsed-attributes up to,
// not including, the first %x3B (";") character.
// ...
stringifiedAttributes += '=' + attributes[attributeName].split(';')[0];
}
return document.cookie = key + '=' + value + stringifiedAttributes;
}
function get(key, json) {
if (typeof document === 'undefined') {
return;
}
var jar = {};
// To prevent the for loop in the first place assign an empty array
// in case there are no cookies at all.
var cookies = document.cookie ? document.cookie.split('; ') : [];
var i = 0;
for (; i < cookies.length; i++) {
var parts = cookies[i].split('=');
var cookie = parts.slice(1).join('=');
if (!json && cookie.charAt(0) === '"') {
cookie = cookie.slice(1, -1);
}
try {
var name = decode(parts[0]);
cookie = (converter.read || converter)(cookie, name) || decode(cookie);
if (json) {
try {
cookie = JSON.parse(cookie);
} catch (e) {}
}
jar[name] = cookie;
if (key === name) {
break;
}
} catch (e) {}
}
return key ? jar[key] : jar;
}
api.set = set;
api.get = function (key) {
return get(key, false /* read as raw */);
};
api.getJSON = function (key) {
return get(key, true /* read as json */);
};
api.remove = function (key, attributes) {
set(key, '', extend(attributes, {
expires: -1
}));
};
api.defaults = {};
api.withConverter = initCookies;
return api;
};
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
return typeof obj;
} : function (obj) {
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
};
var classCallCheck = function (instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
};
var createClass = function () {
function defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
return function (Constructor, protoProps, staticProps) {
if (protoProps) defineProperties(Constructor.prototype, protoProps);
if (staticProps) defineProperties(Constructor, staticProps);
return Constructor;
};
}();
var defineProperty = function (obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
};
var _extends = Object.assign || function (target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
return target;
};
var toConsumableArray = function (arr) {
if (Array.isArray(arr)) {
for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i];
return arr2;
} else {
return Array.from(arr);
}
};
/* ! store2 - v2.7.0 - 2018-02-08
* Copyright (c) 2018 Nathan Bubna; Licensed (MIT OR GPL-3.0) */
/* eslint-disable */
var _ = {
version: "2.7.0",
areas: {},
apis: {},
// utilities
inherit: function inherit(api, o) {
for (var p in api) {
if (!o.hasOwnProperty(p)) {
o[p] = api[p];
}
}
return o;
},
stringify: function stringify(d) {
return d === undefined || typeof d === "function" ? d + '' : JSON.stringify(d);
},
parse: function parse(s) {
// if it doesn't parse, return as is
try {
return JSON.parse(s);
} catch (e) {
return s;
}
},
// extension hooks
fn: function fn(name, _fn) {
_.storeAPI[name] = _fn;
for (var api in _.apis) {
_.apis[api][name] = _fn;
}
},
get: function get$$1(area, key) {
return area.getItem(key);
},
set: function set$$1(area, key, string) {
area.setItem(key, string);
},
remove: function remove(area, key) {
area.removeItem(key);
},
key: function key(area, i) {
return area.key(i);
},
length: function length(area) {
return area.length;
},
clear: function clear(area) {
area.clear();
},
// core functions
Store: function Store(id, area, namespace) {
var store = _.inherit(_.storeAPI, function (key, data, overwrite) {
if (arguments.length === 0) {
return store.getAll();
}
if (typeof data === "function") {
return store.transact(key, data, overwrite);
} // fn=data, alt=overwrite
if (data !== undefined) {
return store.set(key, data, overwrite);
}
if (typeof key === "string" || typeof key === "number") {
return store.get(key);
}
if (!key) {
return store.clear();
}
return store.setAll(key, data); // overwrite=data, data=key
});
store._id = id;
try {
var testKey = '_safariPrivate_';
area.setItem(testKey, 'sucks');
store._area = area;
area.removeItem(testKey);
} catch (e) {}
if (!store._area) {
store._area = _.inherit(_.storageAPI, { items: {}, name: 'fake' });
}
store._ns = namespace || '';
if (!_.areas[id]) {
_.areas[id] = store._area;
}
if (!_.apis[store._ns + store._id]) {
_.apis[store._ns + store._id] = store;
}
return store;
},
storeAPI: {
// admin functions
area: function area(id, _area) {
var store = this[id];
if (!store || !store.area) {
store = _.Store(id, _area, this._ns); //new area-specific api in this namespace
if (!this[id]) {
this[id] = store;
}
}
return store;
},
namespace: function namespace(_namespace, noSession) {
if (!_namespace) {
return this._ns ? this._ns.substring(0, this._ns.length - 1) : '';
}
var ns = _namespace,
store = this[ns];
if (!store || !store.namespace) {
store = _.Store(this._id, this._area, this._ns + ns + '.'); //new namespaced api
if (!this[ns]) {
this[ns] = store;
}
if (!noSession) {
store.area('session', _.areas.session);
}
}
return store;
},
isFake: function isFake() {
return this._area.name === 'fake';
},
toString: function toString() {
return 'store' + (this._ns ? '.' + this.namespace() : '') + '[' + this._id + ']';
},
// storage functions
has: function has(key) {
if (this._area.has) {
return this._area.has(this._in(key)); //extension hook
}
return !!(this._in(key) in this._area);
},
size: function size() {
return this.keys().length;
},
each: function each(fn, value) {
// value is used by keys(fillList) and getAll(fillList))
for (var i = 0, m = _.length(this._area); i < m; i++) {
var key = this._out(_.key(this._area, i));
if (key !== undefined) {
if (fn.call(this, key, value || this.get(key)) === false) {
break;
}
}
if (m > _.length(this._area)) {
m--;i--;
} // in case of removeItem
}
return value || this;
},
keys: function keys(fillList) {
return this.each(function (k, list) {
list.push(k);
}, fillList || []);
},
get: function get$$1(key, alt) {
var s = _.get(this._area, this._in(key));
return s !== null ? _.parse(s) : alt || s; // support alt for easy default mgmt
},
getAll: function getAll(fillObj) {
return this.each(function (k, all) {
all[k] = this.get(k);
}, fillObj || {});
},
transact: function transact(key, fn, alt) {
var val = this.get(key, alt),
ret = fn(val);
this.set(key, ret === undefined ? val : ret);
return this;
},
set: function set$$1(key, data, overwrite) {
var d = this.get(key);
if (d != null && overwrite === false) {
return data;
}
return _.set(this._area, this._in(key), _.stringify(data), overwrite) || d;
},
setAll: function setAll(data, overwrite) {
var changed, val;
for (var key in data) {
val = data[key];
if (this.set(key, val, overwrite) !== val) {
changed = true;
}
}
return changed;
},
add: function add(key, data) {
var d = this.get(key);
if (d instanceof Array) {
data = d.concat(data);
} else if (d !== null) {
var type = typeof d === "undefined" ? "undefined" : _typeof(d);
if (type === (typeof data === "undefined" ? "undefined" : _typeof(data)) && type === 'object') {
for (var k in data) {
d[k] = data[k];
}
data = d;
} else {
data = d + data;
}
}
_.set(this._area, this._in(key), _.stringify(data));
return data;
},
remove: function remove(key) {
var d = this.get(key);
_.remove(this._area, this._in(key));
return d;
},
clear: function clear() {
if (!this._ns) {
_.clear(this._area);
} else {
this.each(function (k) {
_.remove(this._area, this._in(k));
}, 1);
}
return this;
},
clearAll: function clearAll() {
var area = this._area;
for (var id in _.areas) {
if (_.areas.hasOwnProperty(id)) {
this._area = _.areas[id];
this.clear();
}
}
this._area = area;
return this;
},
// internal use functions
_in: function _in(k) {
if (typeof k !== "string") {
k = _.stringify(k);
}
return this._ns ? this._ns + k : k;
},
_out: function _out(k) {
return this._ns ? k && k.indexOf(this._ns) === 0 ? k.substring(this._ns.length) : undefined : // so each() knows to skip it
k;
}
}, // end _.storeAPI
storageAPI: {
length: 0,
has: function has(k) {
return this.items.hasOwnProperty(k);
},
key: function key(i) {
var c = 0;
for (var k in this.items) {
if (this.has(k) && i === c++) {
return k;
}
}
},
setItem: function setItem(k, v) {
if (!this.has(k)) {
this.length++;
}
this.items[k] = v;
},
removeItem: function removeItem(k) {
if (this.has(k)) {
delete this.items[k];
this.length--;
}
},
getItem: function getItem(k) {
return this.has(k) ? this.items[k] : null;
},
clear: function clear() {
for (var k in this.items) {
this.removeItem(k);
}
},
toString: function toString() {
return this.length + ' items in ' + this.name + 'Storage';
} // end _.storageAPI
} };
// safely set this up (throws error in IE10/32bit mode for local files)
var store = _.Store("local", function () {
try {
return localStorage;
} catch (e) {}
}());
store.local = store; // for completeness
store._ = _; // for extenders and debuggers...
// safely setup store.session (throws exception in FF for file:/// urls)
store.area("session", function () {
try {
return sessionStorage;
} catch (e) {}
}());
(function (store, _) {
var _set = _.set,
_get = _.get,
_remove = _.remove,
_key = _.key,
_length = _.length,
_clear = _.clear;
_.overflow = function (area, create) {
var name = area === _.areas.local ? '+local+' : area === _.areas.session ? '+session+' : false;
if (name) {
var overflow = _.areas[name];
if (create && !overflow) {
overflow = store.area(name)._area; // area() copies to _.areas
} else if (create === false) {
delete _.areas[name];
delete store[name];
}
return overflow;
}
};
_.set = function (area, key, string) {
try {
_set.apply(this, arguments);
} catch (e) {
if (e.name === 'QUOTA_EXCEEDED_ERR' || e.name === 'NS_ERROR_DOM_QUOTA_REACHED' || e.toString().indexOf("QUOTA_EXCEEDED_ERR") !== -1 || e.toString().indexOf("QuotaExceededError") !== -1) {
// the e.toString is needed for IE9 / IE10, cos name is empty there
return _.set(_.overflow(area, true), key, string);
}
throw e;
}
};
_.get = function (area, key) {
var overflow = _.overflow(area);
return overflow && _get.call(this, overflow, key) || _get.apply(this, arguments);
};
_.remove = function (area, key) {
var overflow = _.overflow(area);
if (overflow) {
_remove.call(this, overflow, key);
}
_remove.apply(this, arguments);
};
_.key = function (area, i) {
var overflow = _.overflow(area);
if (overflow) {
var l = _length.call(this, area);
if (i >= l) {
i = i - l; // make i overflow-relative
for (var j = 0, m = _length.call(this, overflow); j < m; j++) {
if (j === i) {
// j is overflow index
return _key.call(this, overflow, j);
}
}
}
}
return _key.apply(this, arguments);
};
_.length = function (area) {
var length = _length(area),
overflow = _.overflow(area);
return overflow ? length + _length(overflow) : length;
};
_.clear = function (area) {
_.overflow(area, false);
_clear.apply(this, arguments);
};
})(store, store._, undefined);
(function (store, _) {
var prefix = 'exp@',
suffix = ';',
parse = _.parse,
_get = _.get,
_set = _.set;
_.parse = function (s) {
if (s && s.indexOf(prefix) === 0) {
s = s.substring(s.indexOf(suffix) + 1);
}
return parse(s);
};
_.expires = function (s) {
if (s && s.indexOf(prefix) === 0) {
return parseInt(s.substring(prefix.length, s.indexOf(suffix)), 10);
}
return false;
};
_.when = function (min) {
// if min, return min->date, else date->min
var now = Math.floor(new Date().getTime() / 1000);
return min ? new Date((now + min) * 1000) : now;
};
_.cache = function (area, key) {
var s = _get(area, key),
min = _.expires(s);
if (min && _.when() >= min) {
return area.removeItem(key);
}
return s;
};
_.get = function (area, key) {
var s = _.cache(area, key);
return s === undefined ? null : s;
};
_.set = function (area, key, string, min) {
try {
if (min) {
string = prefix + (_.when() + min) + suffix + string;
}
_set(area, key, string);
} catch (e) {
if (e.name === 'QUOTA_EXCEEDED_ERR' || e.name === 'NS_ERROR_DOM_QUOTA_REACHED') {
var changed = false;
for (var i = 0, m = area.length; i < m; i++) {
if (_.cache(area, key) === undefined) {
changed = true;
}
}
if (changed) {
return _.set.apply(this, arguments);
}
}
throw e;
}
};
})(store, store._, undefined);
var stringHelpers = {
/**
* Capitalize a string
*
* @param {string} str - The String
* @return {string} The modified string
* @example
* capitalize('foo bar'); // 'Foo Bar'
*/
capitalize: function capitalize(str) {
return str.replace(/(?:^|\s)\S/g, function (match) {
return match.toUpperCase();
});
},
/**
* Replace <, >, &, ', " and / with HTML entities.
* @param {string} str - The string to check
* @return {boolean}
*/
escape: function escape(str) {
return str.replace(/&/g, '&').replace(/"/g, '"').replace(/'/g, ''').replace(/</g, '<').replace(/>/g, '>').replace(/\//g, '/').replace(/\\/g, '\').replace(/`/g, '`');
},
/**
* Normalize text adding first character to upper after punctuations (. ? !)
*
* @param {String} [str] Text to convert
* @return {String}
*/
normalizeText: function normalizeText(str) {
var _this = this;
var re = /(^|[.!?]\s+)([a-z])/g;
var normalize = function normalize(str) {
return str.toLowerCase().replace(re, function (m, $1, $2) {
return $1 + $2.toUpperCase();
});
};
var addSpace = function addSpace(str) {
return _this.strCompact(str.replace(/[,.!?:;]+(?=\S)/g, '$& '));
};
return normalize(addSpace(str));
},
/**
* Zero padding number
*
* @param {integer} number Number to format
* @param {integer} [size=2] Digits limit
* @return {string} Formatted num with zero padding
*/
pad: function pad(number, size) {
var stringNum = String(number);
while (stringNum.length < (size || 2)) {
stringNum = '0' + stringNum;
}
return stringNum;
},
/**
* Remove accents from a string
* @param {string} str - The string to remove accents
* @return {string} The modified string
* @example
* removeAccent('Olá Mündô!'); // 'Ola Mundo!'
*/
removeAccent: function removeAccent(str) {
var reAccents = /[àáâãäçèéêëìíîïñòóôõöùúûüýÿÀÁÂÃÄÇÈÉÊËÌÍÎÏÑÒÓÔÕÖÙÚÛÜÝ]/g;
// Prefixed with some char to avoid off-by-one:
var replacements = '_aaaaaceeeeiiiinooooouuuuyyAAAAACEEEEIIIINOOOOOUUUUY';
return str.replace(reAccents, function (match) {
return replacements[reAccents.source.indexOf(match)];
});
},
/**
* Slugify a text, removing/replacing all special characters and spaces with dashes '-'
* @param {string} str - The string to sanitize
* @return {string} The modified string
* @example
* slugifyText('Olá Mundo!'); // 'ola-mundo'
*/
slugifyText: function slugifyText(str) {
str = str.replace(/^\s+|\s+$/g, '') // trim
.toLowerCase().replace(/\./g, '-') // Replace a dot for a -
.replace(/\*/g, '-') // Replace a * for a -
.replace(/\+/g, '-'); // Replace a + for a -
// Remove accents, swap ñ for n, etc
var from = 'àáäâãèéëêìíïîòóöôõùúüûýÿñç·/_,:;';
var to = 'aaaaaeeeeiiiiooooouuuuyync------';
for (var i = 0, len = from.length; i < len; i += 1) {
str = str.replace(new RegExp(from.charAt(i), 'g'), to.charAt(i));
}
str = str.replace(/[^a-z0-9 -]/g, '') // Remove invalid chars
.replace(/\s+/g, '-') // Collapse whitespace and replace by -
.replace(/-+/g, '-'); // Collapse dashes
if (str.charAt(0) === '-') str = str.substr(1);
if (str.charAt(str.length - 1) === '-') str = str.substr(0, str.length - 1);
return str;
},
/**
* Compacts whitespace in the string to a single space and trims the ends.
*
* @param {String} [str] String to remove spaces
* @return {String}
* @example
* strCompact(' Foo Bar Baz ') // 'Foo Bar Baz'
*/
strCompact: function strCompact(str) {
return this.trim(str).replace(/([\r\n\s])+/g, function (match, whitespace) {
return whitespace === ' ' ? whitespace : ' ';
});
},
/**
* Multiple string replace, PHP str_replace clone
* @param {string|Array} search - The value being searched for, otherwise known as the needle.
* An array may be used to designate multiple needles.
* @param {string|Array} replace - The replacement value that replaces found search values.
* An array may be used to designate multiple replacements.
* @param {string} subject - The subject of the replacement
* @return {string} The modified string
* @example
* strReplace(['olá', 'mundo'], ['hello', 'world'], 'olá mundo'); // 'hello world'
* strReplace(['um', 'dois'], 'olá', 'um dois três'); // Output 'olá olá três'
*/
strReplace: function strReplace(search, replace, subject) {
var regex = void 0;
if (validateHelpers.isArray(search)) {
for (var i = 0; i < search.length; i++) {
search[i] = search[i].replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&');
regex = new RegExp(search[i], 'g');
subject = subject.replace(regex, validateHelpers.isArray(replace) ? replace[i] : replace);
}
} else {
search = search.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&');
regex = new RegExp(search, 'g');
subject = subject.replace(regex, validateHelpers.isArray(replace) ? replace[0] : replace);
}
return subject;
},
/**
* Remove leading and trailing empty spaces.
*
* @param {String} str - The string.
* @returns {String} The new string.
* @example
* trim(' Foo ') // 'Foo'
*/
trim: function trim(str) {
if (validateHelpers.isString(str)) {
return str.replace(/^\s+|\s+$/gm, '');
}
return '';
},
/**
* Make a string's first character uppercase
* PHP ucfirst clone
*
* @param {String} str - The string.
* @returns {String} The new string.
* @example
* ucfirst('foo bar foz') // 'Foo bar foz'
*/
ucfirst: function ucfirst(str) {
str += '';
var f = str.charAt(0).toUpperCase();
return f + str.substr(1);
},
/**
* Converts hyphens and camel casing to underscores.
*
* @param {String} str String to convert
* @return {String}
*/
underscore: function underscore(str) {
return str.replace(/[-\s]+/g, '_').replace(/([A-Z\d]+)([A-Z][a-z])/g, '$1_$2').replace(/([a-z\d])([A-Z])/g, '$1_$2').toLowerCase();
},
/**
* Replaces HTML encoded entities with <, >, &, ', " and /.
* @param {string} str - The string to check
* @return {boolean}
*/
unescape: function unescape(str) {
return str.replace(/&/g, '&').replace(/"/g, '"').replace(/'/g, '\'').replace(/</g, '<').replace(/>/g, '>').replace(///g, '/').replace(/\/g, '\\').replace(/`/g, '`');
}
};
var globalHelpers = {
/**
* Recursively transform key strings to camelCase if param is an Object.
* If param is string, return an camel cased string.
*
* @param {Object|String} obj Object or string to transform
* @returns {Object|String}
*/
camelize: function camelize(obj) {
var _this = this;
var _camelize = function _camelize(str) {
str = stringHelpers.underscore(str);
str = stringHelpers.slugifyText(str);
return str.replace(/[_.-\s](\w|$)/g, function (_, x) {
return x.toUpperCase();
});
};
if (validateHelpers.isDate(obj) || validateHelpers.isRegExp(obj)) {
return obj;
}
if (validateHelpers.isArray(obj)) {
return obj.map(function (item, index) {
if (validateHelpers.isObject(item)) {
return _this.camelize(item);
}
return item;
});
}
if (validateHelpers.isString(obj)) {
return _camelize(obj);
}
return Object.keys(obj).reduce(function (acc, key) {
var camel = _camelize(key);
acc[camel] = obj[key];
if (validateHelpers.isObject(obj[key])) {
acc[camel] = _this.camelize(obj[key]);
}
return acc;
}, {});
},
/**
* Check if value contains in an element
*
* @category Global
* @param {String} value - Value to check
* @param {String|Array} elem - String or array
* @return {Boolean} - Return true if element contains a value
*/
contains: function contains(value, elem) {
if (validateHelpers.isArray(elem)) {
for (var i = 0, len = elem.length; i < len; i += 1) {
if (elem[i] === value) {
return true;
}
}
}
if (validateHelpers.isString(elem)) {
return elem.indexOf(value) >= 0;
}
return false;
},
/**
* Creates a debounced function that delays invoking `func` until after `wait`
* milliseconds have elapsed since the last time the debounced function was
* invoked, or until the next browser frame is drawn. The debounced function
* comes with a `cancel` method to cancel delayed `func` invocations and a
* `flush` method to immediately invoke them. Provide `options` to indicate
* whether `func` should be invoked on the leading and/or trailing edge of the
* `wait` timeout. The `func` is invoked with the last arguments provided to the
* debounced function. Subsequent calls to the debounced function return the
* result of the last `func` invocation.
*
* **Note:** If `leading` and `trailing` options are `true`, `func` is
* invoked on the trailing edge of the timeout only if the debounced function
* is invoked more than once during the `wait` timeout.
*
* If `wait` is `0` and `leading` is `false`, `func` invocation is deferred
* until the next tick, similar to `setTimeout` with a timeout of `0`.
*
* If `wait` is omitted in an environment with `requestAnimationFrame`, `func`
* invocation will be deferred until the next frame is drawn (typically about
* 16ms).
*
* See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)
* for details over the differences between `debounce` and `throttle`.
*
* @from Lodash
*
* @category Global
* @param {Function} func The function to debounce.
* @param {number} [wait=0] The number of milliseconds to delay; if omitted, `requestAnimationFrame` is used (if available).
* @param {Object} [options={}] The options object.
* @param {boolean} [options.leading=false] Specify invoking on the leading edge of the timeout.
* @param {number} [options.maxWait] The maximum time `func` is allowed to be delayed before it's invoked.
* @param {boolean} [options.trailing=true] Specify invoking on the trailing edge of the timeout.
* @return {Function} Returns the new debounced function.
* @example
* // Avoid costly calculations while the window size is in flux.
* $(window).on('resize', debounce(calculateLayout, 150));
*
* // Invoke `sendMail` when clicked, debouncing subsequent calls.
* $(element).on('click', debounce(sendMail, 300, {
* 'leading': true,
* 'trailing': false,
* }));
*
* // Ensure `batchLog` is invoked once after 1 second of debounced calls.
* const debounced = debounce(batchLog, 250, { 'maxWait': 1000 })
* const source = new EventSource('/stream')
* $(source).on('message', debounced)
*
* // Cancel the trailing debounced invocation.
* $(window).on('popstate', debounced.cancel)
*
* // Check for pending invocations.
* const status = debounced.pending() ? "Pending..." : "Ready"
*/
debounce: function debounce(func, wait, options) {
var lastArgs = void 0;
var lastThis = void 0;
var maxWait = void 0;
var result = void 0;
var timerId = void 0;
var lastCallTime = void 0;
var lastInvokeTime = 0;
var leading = false;
var maxing = false;
var trailing = true;
// Bypass `requestAnimationFrame` by explicitly setting `wait=0`.
var useRAF = !wait && wait !== 0 && typeof window.requestAnimationFrame === 'function';
if (typeof func != 'function') {
throw new TypeError('Expected a function');
}
wait = +wait || 0;
if (validateHelpers.isObject(options)) {
leading = !!options.leading;
maxing = 'maxWait' in options;
maxWait = maxing ? Math.max(+options.maxWait || 0, wait) : maxWait;
trailing = 'trailing' in options ? !!options.trailing : trailing;
}
function invokeFunc(time) {
var args = lastArgs;
var thisArg = lastThis;
lastArgs = lastThis = undefined;
lastInvokeTime = time;
result = func.apply(thisArg, args);
return result;
}
function startTimer(pendingFunc, wait) {
if (useRAF) {
return window.requestAnimationFrame(pendingFunc);
}
return setTimeout(pendingFunc, wait);
}
function cancelTimer(id) {
if (useRAF) {
return window.cancelAnimationFrame(id);
}
clearTimeout(id);
}
function leadingEdge(time) {
// Reset any `maxWait` timer.
lastInvokeTime = time;
// Start the timer for the trailing edge.
timerId = startTimer(timerExpired, wait);
// Invoke the leading edge.
return leading ? invokeFunc(time) : result;
}
function remainingWait(time) {
var timeSinceLastCall = time - lastCallTime;
var timeSinceLastInvoke = time - lastInvokeTime;
var timeWaiting = wait - timeSinceLastCall;
return maxing ? Math.min(timeWaiting, maxWait - timeSinceLastInvoke) : timeWaiting;
}
function shouldInvoke(time) {
var timeSinceLastCall = time - lastCallTime;
var timeSinceLastInvoke = time - lastInvokeTime;
// Either this is the first call, activity has stopped and we're at the
// trailing edge, the system time has gone backwards and we're treating
// it as the trailing edge, or we've hit the `maxWait` limit.
return lastCallTime === undefined || timeSinceLastCall >= wait || timeSinceLastCall < 0 || maxing && timeSinceLastInvoke >= maxWait;
}
function timerExpired() {
var time = Date.now();
if (shouldInvoke(time)) {
return trailingEdge(time);
}
// Restart the timer.
timerId = startTimer(timerExpired, remainingWait(time));
}
function trailingEdge(time) {
timerId = undefined;
// Only invoke if we have `lastArgs` which means `func` has been
// debounced at least once.
if (trailing && lastArgs) {
return invokeFunc(time);
}
lastArgs = lastThis = undefined;
return result;
}
function cancel() {
if (timerId !== undefined) {
cancelTimer(timerId);
}
lastInvokeTime = 0;
lastArgs = lastCallTime = lastThis = timerId = undefined;
}
function flush() {
return timerId === undefined ? result : trailingEdge(Date.now());
}
function pending() {
return timerId !== undefined;
}
function debounced() {
var time = Date.now();
var isInvoking = shouldInvoke(time);
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
lastArgs = args;
/* eslint-disable */
lastThis = this;
/* eslint-enable */
lastCallTime = time;
if (isInvoking) {
if (timerId === undefined) {
return leadingEdge(lastCallTime);
}
if (maxing) {
// Handle invocations in a tight loop.
timerId = startTimer(timerExpired, wait);
return invokeFunc(lastCallTime);
}
}
if (timerId === undefined) {
timerId = startTimer(timerExpired, wait);
}
return result;
}
debounced.cancel = cancel;
debounced.flush = flush;
debounced.pending = pending;
return debounced;
},
/**
* Get variable type
*
* @category Global
* @param {Mix} variable - Variable to check type
* @return {string} Name of variable type
* @example
* getType(123); // 'number'
* getType([]); // 'array'
* getType({}); // 'object'
* // and so on...
*/
getType: function getType(variable) {
var types = {
'undefined': 'undefined',
'number': 'number',
'boolean': 'boolean',
'string': 'string',
'[object Function]': 'function',
'[object RegExp]': 'regexp',
'[object Array]': 'array',
'[object Date]': 'date',
'[object Error]': 'error'
};
return types[typeof variable === 'undefined' ? 'undefined' : _typeof(variable)] || types[{}.toString.call(variable)] || (variable ? 'object' : 'null');
},
/**
* Get url params from a query string
*
* @category Global
* @param {string} name - Param name
* @param {string} entryPoint - Full url or query string
* @return {string} Value query string param
* @example
* // URL: https://site.com?param1=foo¶m2=bar
* getUrlParameter('param1'); // foo
* getUrlParameter('param2'); // bar
*
* // Given entry point
* var url = 'http://www.site.com?param1=foo¶m2=bar¶m3=baz';
* getUrlParameter('param3', url); // baz
*/
getUrlParameter: function getUrlParameter(name, entryPoint) {
entryPoint = !validateHelpers.isString(entryPoint) ? window.location.href : entryPoint.substring(0, 1) === '?' ? entryPoint : '?' + entryPoint;
name = name.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]');
var regex = new RegExp('[\\?&]' + name + '=([^&#]*)');
var results = regex.exec(entryPoint);
return results === null ? '' : decodeURIComponent(results[1].replace(/\+/g, ' '));
},
parseJwt: function parseJwt(token) {
var b64DecodeUnicode = function b64DecodeUnicode(str) {
return decodeURIComponent(Array.prototype.map.call(atob(str), function (c) {
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
}).join(''));
};
return JSON.parse(b64DecodeUnicode(token.split('.')[1].replace(/-/g, '+').replace(/_/g, '/')));
},
/**
* Resize image by aspect ratio
*
* @category Global
* @param {String} type Resize by 'width' or 'height'
* @param {Number} newSize New value to resize
* @param {Number} aspectRatio Image aspect ratio (calculate by (width / height))
* @return {Object} Object with new 'width' and 'height'
*/
resizeImageByRatio: function resizeImageByRatio(type, newSiz