const camelCaseDefautl = {firstUpper: false, locale: false}
/**
* CamelCase
* @memberOf module:Utils
* @type {Function}
*/
export const camelCase = function(src, options = camelCaseDefautl) {
const SEPARATOR = /[_.\- ]+/;
if (not(src)) {
return src;
}
if (isArrayish(src)) {
src = src.map(x => x.trim())
.filter(x => x.length)
.join('-')
} else {
src = src.trim()
}
if (src.length === 0) {
return ''
}
var o = extend({}, camelCaseDefautl, options),
tLC = (not(o.locale) || o.locale == false)
? string => string.toLowerCase()
: string => string.toLocaleLowerCase(o.locale),
tUC = (not(o.locale) || o.locale == false)
? string => string.toUpperCase()
: string => string.toLocaleUpperCase(o.locale)
if (src.length === 1) {
if (SEPARATOR.test(src)) {
return "";
}
return o.firstUpper ? tUC(src) : tLC(src)
}
var wordArr = src.split(SEPARATOR),
newSrc = "";
each(wordArr, (chart, ix) => {
if (ix == 0) {
newSrc += (o.firstUpper ? tUC(chart.charAt(0)) : tLC(chart.charAt(0))) + chart.slice(1);
} else if (ix > 0) {
newSrc += tUC(chart.charAt(0)) + chart.slice(1)
} else{
newSrc += chart;
}
})
return newSrc;
};
/**
* Alias String.prototype.valueOf
* @memberOf module:Utils
* @type {Function}
*/
export const strValue = String.prototype.valueOf
/**
* Alias Object.prototype.toString
* @memberOf module:Utils
* @type {Function}
*/
export const toStr = Object.prototype.toString
/**
* Valida String u Object
* @memberOf module:Utils
* @param {(String|Object)} value la cadena a evaluar
*
* @return {Boolean}
*/
export const tryStringObject = function tryStringObject(value) {
try {
strValue.call(value)
return true
} catch (e) {
return false
}
}
/**
* Alias Object.defineProperty
* @memberOf module:Utils
* @type {Function}
*/
export const defineProperty = Object.defineProperty
/**
* Alias Object.getOwnPropertyDescriptor
* @memberOf module:Utils
* @type {Function}
*/
export const gOPD = Object.getOwnPropertyDescriptor
/**
* Verifica si es una Array
* @memberOf module:Utils
* @function isArray
* @return {Boolean}
*/
export const isArray = Array.isArray
/**
* Funtions
*/
/**
* Establece Propiedades de los Objetos
* @memberOf module:Utils
* @private
* @param {Object} target el Objecto
* @param {Object} opt opciones del objecto
*/
export function setPropertyObj(target, opt) {
if (defineProperty && opt.name === "__proto__") {
defineProperty(target, opt.name, {
enumerable: true,
configurable: true,
value: opt.newValue,
writable: true,
})
} else {
target[opt.name] = opt.newValue
}
}
/**
* Obtiene una propiedad de un objecto
* @memberOf module:Utils
* @private
* @param {Object} obj El Objecto
* @param {String} name Nombre de la propiedad
*
* @return {(Void|*)}
*/
export function getProperty(obj, name) {
if (name === "__proto__") {
if (!hasProp(obj, name)) {
return void 0
} else if (gOPD) {
return gOPD(obj, name).value
}
}
return obj[name]
}
/**
* Extiende un objeto o matriz y combinar sus elementos
* @memberOf module:Utils
* @function extend
* @param {...*} Argumentos Lista de Objetos a iterar
* @return {(String|Object|Array)} retorna el elemento, o la unión de ellos
*/
export function extend(...args) {
let options,
name,
src,
copy,
copyIsArray,
clone,
target,
deep,
i,
length = 0
if (args.length === 0) {
return void 0
}
target = args[0]
length = args.length
i = 1
deep = false
if (typeof target === "boolean") {
deep = target
target = args[1] || {}
i = 2
}
if (empty(target) || (typeof target !== "object" && typeof target !== "function")) {
target = {}
}
for (; i < length; ++i) {
if (args[i] !== null) {
options = args[i]
for (name in options) {
if (hasProp(options, name)) {
src = getProperty(target, name)
copy = getProperty(options, name)
if (target !== copy) {
copyIsArray = isArrayish(copy)
if (deep && copy && (isObject(copy) || copyIsArray)) {
if (copyIsArray) {
copyIsArray = false
clone = src && isArrayish(src) ? src : []
} else {
clone = src && isObject(src) ? src : {}
}
setPropertyObj(target, {
name: name,
newValue: extend(deep, clone, copy),
})
} else if (!not(copy)) {
setPropertyObj(target, { name: name, newValue: copy })
}
}
}
}
}
}
return target
}
/**
* Verifica si es un texto valido
* @memberOf module:Utils
* @function isString
* @param {*} value
* @return {Boolean} verdadero si es un string
*/
export function isString(value) {
const strClass = "[object String]",
hasToStringTag = typeof Symbol === "function" && typeof Symbol.toStringTag === "symbol"
if (typeof value === "string") {
return true
}
if (typeof value !== "object") {
return false
}
return hasToStringTag ? tryStringObject(value) : toStr.call(value) === strClass
}
/**
* Verifica si es un objecto
* @memberOf module:Utils
* @function isObject
* @param {*} obj
* @return {Boolean} verdadero si es un objecto
*/
export function isObject(obj) {
let proto
if ( !obj || toStr.call( obj ) !== "[object Object]" ) {
return false
}
proto = obj.prototype !== undefined
if ( !proto ) {
return true
}
return proto.constructor && typeof proto.constructor === "function"
}
/**
* Verifica si es una Matriz
* @memberOf module:Utils
* @function isArrayish
* @param {*} obj
* @return {Boolean} Verdadero si es un array
*/
export function isArrayish(obj) {
if (!obj) {
return false
}
return obj instanceof Array || isArray(obj) ||
(obj.length >= 0 && obj.splice instanceof Function)
}
/**
* Verifica si es un número
* @function isNumber
* @memberOf module:Utils
* @param {*} num
* @return {Boolean} verdadero si es un tipo numérico
*/
export function isNumber(num) {
if (typeof num === "number") {
return num - num === 0
}
if (typeof num === "string" && num.trim() !== "") {
return Number.isFinite ? Number.isFinite(+num) : isFinite(+num)
}
return false
}
/**
* Verifica si es una función
* @memberOf module:Utils
* @function isFunction
* @param {*} fn
* @return {Boolean} verdadero si es una función
*/
export function isFunction(fn) {
if (!fn) {
return false
}
const string = toStr.call(fn)
return string === "[object Function]" ||
(typeof fn === "function" && string !== "[object RegExp]") ||
(typeof window !== "undefined" &&
// IE8 and below
(fn === window.setTimeout ||
fn === window.alert ||
fn === window.confirm ||
fn === window.prompt))
}
/**
* Busca y valida la propiedad del objeto dato
* @memberOf module:Utils
* @function hasProp
* @param {Object} obj objeto a verificar
* @param {String} prop propiedad a buscar
* @return {Boolean} verdadero si la propiedad existe dentro del objeto
*/
export function hasProp(obj, prop) {
return Object.prototype.hasOwnProperty.call(obj, prop)
}
/**
* Extensión de [object|function|array|string].toString([native])
* @memberOf module:Utils
* @function toString
* @param {string} arg tipo que contiene la función toString
* @return {(Boolean|String)} El resultado del toString o falso
*/
export function toString(arg) {
return !empty(arg) && isFunction(arg.toString) ? arg.toString() : false
}
/**
* Verifica si es un selector valido
* @memberOf module:Utils
* @function isSelector
* @param {String} selector
* @return {Boolean} Verdadero si es un selector
*/
export function isSelector(selector) {
if (!isString(selector)) {
return false
}
try {
document.querySelector(selector)
} catch (error) {
return false
}
return true
}
/**
* Verifica si la variable dada esta vaciá
* @memberOf module:Utils
* @function empty
* @example
* let a
* empty(a) // true
* empty(0) // true
* empty(0.0) // true
* empty(false) // true
* empty([]) // true
* empty({}) // true
* empty("") // true
* empty() // true
* empty(1) // false
* @param {*} arg Variable, Objecto, matriz etc.. a verificar
* @return {Boolean} Verdadero si esta vació
*/
export function empty(arg) {
let und
const emptyVal = [undefined, null, false, 0, 0.0, "", "0", "0.0", und],
l = emptyVal.length
if (typeof arg === "undefined") {
return true
}
for (let i = 0; i < l; i++) {
if (arg === emptyVal[i]) return true
}
if (isArrayish(arg)) {
return arg.length === 0
}
if (isObject(arg)) {
let o = 0
for (let i in arg) {
if (hasProp(arg, i)) {
o++
}
}
return o === 0
}
return false
}
/**
* Verifica si la variable dada no es nula o indefinida
* @memberOf module:Utils
* @function not
* @param {*} arg Variable
* @return {Boolean} verdadero si esta nula o indefinida
*/
export function not(arg) {
return arg === undefined || arg === null
}
/**
* Obtiene los estilos computados del elemento
* @memberOf module:Utils
* @function getStyleComputed
* @param {Element} el El Elemento
* @param {String} prop La Propiedad
* @param {String} pseudoElt PseudoElt
* @return {Array}
*/
export function getStyleComputed(el, prop, pseudoElt = "") {
if (empty(el) || !isElement(el)) {
return
}
if (!empty(prop) && prop.indexOf(":") === 0) {
pseudoElt = prop
prop = undefined
}
if (empty(prop)) {
return window.getComputedStyle(el, pseudoElt)
}
if ( isArrayish(prop)) {
let ListProperty = {},
propertys = window.getComputedStyle(el, pseudoElt)
prop.forEach( (property) => {
ListProperty[property] = propertys[property]
})
return ListProperty
}
let propertyStyle = window.getComputedStyle(el, pseudoElt)
return propertyStyle[prop]
}
/**
* Verifica si es un elemento
* @memberOf module:Utils
* @function isElement
* @param {*} el
* @return {Boolean} Verdadero si el es un Elemento del DOM
*/
export function isElement(el) {
if (empty(el)) {
return false
}
if (isString(el)) {
return isSelector(el)
}
if (el instanceof HTMLElement) {
return true
}
return typeof el === "object" && el.nodeType === 1 && isString(el.nodeName)
}
/**
* Verifica si es un Elemento Fascino
* @memberOf module:Utils
* @function isFascinoElement
* @param {*} el
* @return {Boolean} Verdadero si es un elemento de Fascino o _$
*/
export function isFascinoElement(el) {
if (empty(el)) {
return false
}
if (el.constructor && el.constructor.name.toUpperCase() === "FASCINO" ) {
return true
}
return hasProp(el, "Elem")
}
/**
* Verifica si el elemento es visible en el DOM
* @memberOf module:Utils
* @function isVisible
* @param {(String|Element)} el
* @return {Boolean} Verdadero si es visible
*/
export function isVisible(el) {
if (empty(el)) {
return false
}
var elem = !isElement(el) ? null : isSelector(el) ? document.querySelector(el) : el
if (empty(elem)) {
return false
}
let Body = document.querySelector("body"),
HTML = document.querySelector("html")
while (elem && elem !== Body && elem !== HTML) {
let property = getStyleComputed(elem, ["display", "opacity", "visibility"])
if (property.display === "none") {
return false
}
if (toString(property.opacity) === "0") {
return false
}
if (property.visibility === "hidden") {
return false
}
elem = elem.parentNode
}
return true
}
/**
* Verifica si el elemento esta oculto
* @memberOf module:Utils
* @function isHiden
* @param {(String|Element)} el
* @return {Boolean} Verdadero si esta oculto
*/
export function isHiden(el) {
return el.hidden || !isVisible(el)
}
/**
* Valida una URL
* @memberOf module:Utils
* @function isURL
* @param {(String|URL)} u URI a validar
* @return {Boolean}
*/
export function isURL(u) {
return u instanceof URL || /(http|https|ftp):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/.test(u)
}
/**
* Combinar 2 array
* @memberOf module:Utils
* @function merge
* @param {Array} n1 Matriz n1
* @param {Array} n2 Matriz n2
* @return {Array} El array resultante
*/
export function merge(n1, n2) {
let l = +n2.length, j = 0, i = n1.length
for ( ; j < l; j++) {
n1[i++] = n2[j]
}
n1.length = i
return n1
}
/**
* ForEach Personalizado.
* <p>Extiende la funcionalidad del forEach por defecto de los Array para todo tipo de elementos.</p>
* <p>Para saber más visite <a href="https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach" target="_blank" alt="Docuementación de ForEach">forEach en Developer Mozilla</a></p>
* @memberOf module:Utils
* @function each
* @param {(Object|Array)} arr El Objecto a iterar
* @param {Function} callback Función a ejecutar
* @param {(Object|Array)} thisArg Valor de la constante this
*/
export function each(arr, callback, thisArg) {
if (empty(arr)) {
return
}
if (typeof arr.forEach === "function") {
return arr.forEach(callback, thisArg)
}
if (!isFunction(callback)) {
return arr
}
let T,
k,
O = Object(arr),
len = O.length >>> 0
if (len === 0 && isObject(O)) {
len = Object.keys(O).length
}
if (!empty(thisArg)) {
T = thisArg
}
for ( k in O) {
if (hasProp(O, k)) {
let KeyValue = O[k]
callback.call(T, KeyValue, k, O)
}
}
}
/**
* <p>Analiza y crea un nuevo elemento script que añada al body</p>
* <p>Util para el uso de {@link Plugins.Ajax.XHR Ajax}, y cargas de html en linea</p>
* @memberOf module:Utils
* @function createScript
* @param {(String|Element|Array)} script
* @return {Element} El nuevo Script
*/
export function createScript(script) {
let s = document.createElement("script"),
_s
s.type = "text/javascript"
if (empty(script)) {
return _$(s)
}
_s = _$(script).Elem[0]
if (!empty(_s.src)) {
s.src = _s.src
} else {
s.textContent = _s.innerText
}
document.body.appendChild(s)
if (_s.parentNode) {
_s.parentNode.removeChild(_s)
}
return s
}
/**
* Normaliza y busca los elementos Script
* @memberOf module:Utils
* @function script
* @param {Element} el El elemento script o padre del Script
* @return {void}
*/
export function script(el) {
if (empty(el)) {
return createScript()
}
const _el = _$(el).Elem[0]
if (_el.tagName && _el.tagName === "SCRIPT") {
createScript(_el)
} else {
_$(_el).find("script").each((s) => {
createScript(s)
})
}
}
/**
* Esta función recibe una etiqueta e intenta crear un Object HTMLElement de la misma
* @memberOf module:Utils
* @function parseHTML
* @param {String} data el texto HTML
* @return {(Element|Array)} El nuevo objeto o una matriz
*/
export function parseHTML(data) {
let base, singleTag, result = [], ctx, _context,
regexpSingleTag = /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i; // eslint-disable-line
if (typeof data !== "string") {
return []
}
data = data.trim()
ctx = document.implementation.createHTMLDocument("")
base = ctx.createElement("base")
base.href = document.location.href
ctx.head.appendChild( base )
_context = ctx.body
singleTag = regexpSingleTag.exec(data)
if (singleTag) {
result.push(document.createElement(singleTag[1]))
} else {
_context.innerHTML = data
for (let i = 0; i < _context.childNodes.length; i++) {
result.push(_context.childNodes[i])
}
}
return result
}
/**
* Regula y normaliza el nombre de un atributo, función, o variable para su uso en Javascript
* @memberOf module:Utils
* @function normName
* @param {String} name variable
* @return {(String|void)} el nombre normalizado o indefinido
*/
export function normName(name) {
return typeof name !== "string" ? undefined : name.replace(/-/g, "").toLowerCase()
}
/**
* Transforma un Byte en su unidad correspondiente
* @memberOf module:Utils
* @function formatBytes
* @param {Number} bytes Bytes a dar formato
* @param {Number} decimals Cantidad de decimales a mostrar
* @return {String}
*/
export function formatBytes(bytes, decimals = 2) {
if (bytes === 0) return "0 Bytes";
const k = 1024;
const dm = decimals < 0 ? 0 : decimals;
const sizes = ["Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + " " + sizes[i];
}
/**
* Establece opciones por defecto a los Simple plugins
* @memberOf module:Utils
* @function SetOptinsOfData
* @param {(Element|Fascino|String)} el Elemento
* @param {Object} defaults Opciones por defecto
* @return {Object} Nuevas Opciones
*/
export function setOptionsOfData(el, defaults) {
let o = {}, data = _$(el).data()
each(data, (d, i) => {
if (hasProp(defaults, i)) {
try{
o[i] = JSON.parse(d)
} catch (e) {
o[i] = d
}
}
})
return extend({}, defaults, o)
}
/**
* Genera un numero aleatorio entre rangos
* @memberOf module:Utils
* @function random
* @param {(Number|Undefined)} min Número minino
* @param {(Number|Undefined)} max Número máximo
* @return {Number} Resultado aleatorio
*/
export function random(min, max) {
if (min == undefined && max == undefined) {
return Math.random()
} else if (min == undefined || max == undefined) {
let base = min || max
return Math.floor(Math.random() * base)
} else {
return Math.floor(Math.random() * (max - min)) + min
}
}
/**
* Obtiene un valor Aleatorio de una Matriz o un Objeto
* @memberOf module:Utils
* @function randomMap
* @param {(Object|String)} arr Matriz u Objecto
* @return {(Number|*)} Valor de la Matriz u Objecto o -1 si no tiene éxito
*/
export function randomMap(arr) {
if (empty(arr)) {
return -1;
}
if ( isArrayish(arr) ) {
return arr[
Math.floor(Math.random() * arr.length)
];
}
if (isObject(arr)) {
let k = Object.keys(arr);
return arr[
k[Math.floor(Math.random() * k.length)]
];
}
return -1;
}
/**
* Convierte los datos tipo texto JSON pasados por atributos a un objecto valido
* @memberOf module:Utils
* @function normalizeData
* @param {String} data
* @return {Object} El objeto JSON
*/
export function normalizeData(data) {
try {
return JSON.parse(data)
} catch (e) {
return data
}
}
/**
* Valida y obtiene un elemento dado
* @memberOf module:Utils
* @function normalizeElements
* @param {(String|Array|Fascino)} s
* @return {(Object|Element|Array|undefined)} El elemento en su expresión para su uso
*/
export function normalizeElements(s) {
let result
if (isString(s)) {
result = isSelector(s) ? _$(s) : parseHTML(s)
} else if (isElement(s)) {
result = [s]
} else if (isFascinoElement(s)) {
result = s
} else if (isArrayish(s)) {
result = s
}
return result
}
/**
* Genera un Identificador único basado en la fecha y hora actual
* @memberOf module:Utils
* @function uniqueId
* @param {String} prefix Prefijo del identificador
* @return {String} Identificador
*/
export function uniqueId(prefix = "fs") {
let d = new Date().getTime()
return (prefix !== "" ? prefix + "-" : "") + "xxxx-xxxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) {
let r = (d + Math.random() * 16) % 16 | 0
d = Math.floor(d / 16)
return (c === "x" ? r : (r & 0x3 | 0x8)).toString(16)
})
}
/**
* Genera una cadena HTML codificada para mostrar en pre o navegador
* @memberOf module:Utils
* @function htmlEntities
* @param {String} str Cadena de código Html
* @example
* <div>
* <pre></pre>
* <script>
* _$("pre").html(_$.htmlEntities("<section><h2>Hola Mundo</h2></section>"))
* </script>
* </div>
* @return {String}
*/
export function htmlEntities(str) {
return String(str).replace(/</g, "<").replace(/>/g, ">").replace('/"/g', """)
}
/**
* Limpia un texto pre-codificado
* @memberOf module:Utils
* @function cleanPreCode
* @param {String} textContent Texto
* @return {String}
*/
export function cleanPreCode(textContent) {
let txt = textContent
.replace(/^[\r\n]+/, "") // strip leading newline
.replace(/\s+$/g, ""),
mat, str, re = /^[\t ]+/gm, len, min = 1e3
if (/^\S/gm.test(txt)) {
return txt
}
/* jshint -W084 */
/* eslint-disable-next-line */
while (mat = re.exec(txt)) {
len = mat[0].length
if (len < min) {
min = len
str = mat[0]
}
}
if (min === 1e3) {
return
}
return txt.replace(new RegExp("^" + str, "gm"), "").trim()
}
/**
* Transforma una cadena de texto en una matriz
* @memberOf module:Utils
* @function strToArr
* @param {String} str La cadena
* @param {String} separator El separador
*
* @return {Array}
*/
export function strToArr(str, separator = ' ') {
if (empty(str) ) {
return []
}
if(str.indexOf(separator) === -1) {
return [str]
}
return isArrayish(str) ? str : str.split(separator)
}
/**
* Crea una uri a partir de un String
* @memberOf module:Utils
* @function createURI
* @example
* _$.createURI('mifile.php')
* // return --> https://domain.ext/path/mifile.php
* @param {String} u Dirección o path a convertir
* @return {String} URI bien formateada
*/
export function createURI(u){
var a = document.createElement('a')
a.href = u
return !not(a.href) && isURL(a.href) ? a.href : u
}
/**
* Construye una URL valida para la API fetch o XMLHttpRequest
* @memberOf module:Utils
* @function url
* @param {String} urlBase URL
* @param {Object} params Conjunto de parametros de URLSearchParams
* @return {URL} API URL
*/
export function url(urlBase, params = {}) {
if (!isURL(urlBase)) {
urlBase = createURI(urlBase)
}
var url = new URL( urlBase );
Object.keys( params ).forEach( key => url.searchParams.append( key, params[ key ] ) );
return url
}
/**
* Convierte un Objecto JSON a u objecto del tipo FromData
* @memberOf module:Utils
* @function jsonToFormdata
* @param {Object} obj El Objecto
* @return {FromData}
*/
export function jsonToFormdata(obj) {
if (!isObject(obj)) {
return null
}
let fromdata = new FormData()
each(obj, (v, k) => {
fromdata.append(camelCase(k), v)
})
return fromdata
}