@fto-consult/common
Version:
Un ensemble de bibliothèques et d'utilistaires communs pour le développement d'applications javascript
1,214 lines (1,088 loc) • 42.9 kB
JavaScript
// Copyright 2022 @fto-consult/Boris Fouomene. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
import isNonNullString from "./isNonNullString";
import _uniqid from "./uniqid";
import _isDomElement from "./dom/isDOMElement";
import { isPlainObject as _isPlainObject} from "./extendObj";
import defStr from "./defaultStr"
import { parseJSON as pJSON, isJSON as isJ } from "./json";
import isDateObj from "./isDateObj";
import sprintf from "./sprintf";
import base64 from "$base64";
import "./object.filter";
export {default as global} from "./global";
export {default as parseCSV} from "./parseCSV";
export * from "./rn-webview";
export {default as classNames} from "./classNames";
export {sprintf,isNonNullString};
export {default as LorenIpsum} from "./loremIpsum";
export {default as loremIpsum } from "./loremIpsum";
export {default as StringBuilder} from "./StringBuilder";
export * from "./isRegex";
export * from "./compare";
export {default as stringify} from "./stringify";
export const uniqid = _uniqid;
export const parseJSON = pJSON;
export const isJSON = isJ;
export const isDOMElement = _isDomElement;
export {default as extendObj } from "./extendObj";
export * from "./extendObj";
export const defaultStr = defStr;
export function isFunction(function_name){
return typeof function_name == 'function' && true || false;
}
export const isWindowClient = x=> typeof window !== "undefined" && typeof (window) =="object" ? true : false;
if(typeof __DEV__ == 'undefined'){
global.__DEV__ = true;
}
export * from "./uri";
export * from "./sanitizeName";
export const arrayValueExists = function(array,value,ignoreCase,compare) {
if(isFunction(ignoreCase)){
compare = ignoreCase;
}
compare = defaultFunc(compare,(a,b)=>a == b);
ignoreCase = defaultBool(ignoreCase,false);
if(typeof array != 'object' && typeof value == 'object'){
var _t = value;
value = array
array = _t;
}
if(typeof array != "object" | array === null) return false;
for (var key in array) {
if(compare(array[key],value)) return true
if(ignoreCase && isNonNullString(value) && isNonNullString(array[key])){
if(array[key].toLowerCase().trim() === value.toLowerCase().trim ()){
return true;
}
}
}
return false;
}
/**helper functions
* détermine si la valeur d'un élement existe dans un tableau
* @param array / value, le tableau où l'élément à vérifier
* @param value / array : la valeur ou le tableau de l'élément à vérifier
* @param ignoreCase : bool default false, si la casse sera ignorée où pas
* @param compare : function de comparaison des éléments du tableau
*
*/
export const arrayKeyExists = function(array, key_to_check) {
if(typeof array != 'object' && typeof key_to_check=='object'){
var t = array;
array = key_to_check;
key_to_check = t;
}
if(typeof array != "object" | array == null) return false;
for (var key in array) {
if(key_to_check == key) return true
}
return false;
}
export const isPlainObject = _isPlainObject;
export const isPlainObj = isPlainObject;
/*** simillaire à Array.map mais sauf que, prend un objet ou un tableau en paramètre
retourne comme résultat, un tableau
*/
export const ObjectMapToArray = Object.mapToArray = function(obj,fn){
if(Array.isArray(obj)){
return obj.map(fn);
}
return Object.toArray(Object.map(obj,fn));
};
export const mapObj = Object.map = function(obj,fn){
if(typeof fn != 'function') {
return {};
}
if(Array.isArray(obj)) return obj.map((item,index)=>{
return fn(item,index,index);
});
if(!(obj) || typeof obj !=='object') {
return {};
}
var oReturn = {};
let mapI=0;
for (let sCurObjectPropertyName in obj) {
if(obj.hasOwnProperty(sCurObjectPropertyName)) {
oReturn[sCurObjectPropertyName] = fn.call(obj,obj[sCurObjectPropertyName], sCurObjectPropertyName,mapI,true);
mapI++;
}
}
return oReturn;
}
export const mapObject = mapObj;
/****
* détermine la taille d'un tableau/object
* @param : l'objet à déterminer la taille
@param : breakonFirstElementFound {boolean}, retourne immédiatement après le premier élément trouvé
*/
export const objectSize = Object.size = function(obj,breakonFirstElementFound) {
if(!obj || typeof obj != "object") return 0;
if(Array.isArray(obj)){
return obj.length;
}
if(typeof breakonFirstElementFound !=='boolean'){
breakonFirstElementFound = false;
}
let size = 0;
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
size++;
if(breakonFirstElementFound === true) return size;
}
}
return size;
}
/******
* converti un objet en tableau
* @param : l'objet à covertir
* @param : la functon de rappel prenant en paramètre l'ensemble des clés de l'objet suivant leur ordre dans le tableau
@param : string le nom du champ à utiliser pour garder les clés des différentes instances d'objet
*/
export const ObjectToArray = Object.toArray = function(obj,cb,keyName){
if(Array.isArray(obj)) return obj;
if(!isPlainObject(obj)) {
if(isNullOrEmpty(obj,true)) return [];
return [obj];
}
var r = [];
var keys = [];
Object.keys(obj).map(function(k){
//la clé est définie comme clée des différents instances de l'objet
if(isNonNullString(keyName) && isObj(obj[k])){
obj[k][keyName] = k;
}
keys.push(k);
r.push(obj[k])
});
if(isFunction(cb)){
cb(keys);
}
return r;
}
export function defaultVal (){
var args = Array.prototype.slice.call(arguments,0);
let nullV = undefined;
for(let i in args){
if(args[i] !== undefined && args[i] !== '') {
if(args[i] === null){
nullV = null;
} else {
return args[i]
}
}
}
return nullV;
}
export function defaultBool(){
var args = Array.prototype.slice.call(arguments,0);
for(var i in args){
if(typeof args[i] === 'boolean') return args[i]
}
return false;
}
export function defaultDecimal (){
var args = Array.prototype.slice.call(arguments,0);
for(var i in args){
if(isDecimal(args[i]) && args[i] !== 0) return args[i]
}
return 0;
}
export const defaultNumber = function(){
var args = Array.prototype.slice.call(arguments,0);
for(var i in args){
if(isNumber(args[i]) && args[i] !== 0) return args[i]
}
return 0;
}
export const isUndefined = (str) =>{return typeof str === 'undefined'};
export const defaultFunc = function(){
var args = Array.prototype.slice.call(arguments,0);
for(var i in args){
if(typeof args[i] === "function") return args[i]
}
return ()=>{};
}
/*** fix bug, defaultObj, où l'on perd la référence lorsque l'orsqu'une seule variable passée en paramètre est de type object */
export const defaultObj = function() {
var args = Array.prototype.slice.call(arguments,0);
if(args.length === 1) return isObj(args[0]) ? args[0] : {};
let prevObj = null;
for(var i in args){
const x = args[i];
if(isObj(x)) {
if(Object.size(x,true)>0) return x;
if(!prevObj){
prevObj = x;
}
}
}
return prevObj || {};
}
export const isObjOrArray = x => x && typeof x =="object" ? true : false;
export const defaultObjOrArray = function(){
var args = Array.prototype.slice.call(arguments,0);
for(var i in args){
let x = args[i];
if(isObjOrArray(x)) return x;
}
return null;
}
export const isObjectOrArray= a => isObj(a) || isArray(a);
export const defaultArray = function(){
var args = Array.prototype.slice.call(arguments,0);
if(args.length === 1 && isArray(args[0])) return args[0];
let prevA = null;
for(var i in args){
let x = args[i];
if(x && Array.isArray(x)){
if(x.length > 0) return x;
}
if(!prevA){
prevA = x;
}
}
return prevA || [];
}
export {default as isPromise} from "./isPromise";
export const isPureFunction = (functionName) =>{
return typeof functionName === 'function';
}
export const isString = function(str){
return typeof str === "string";
}
export const isBool = function(v){
return typeof v === 'boolean';
}
export const isArray = function(array){
if(typeof Array.isArray === 'function'){
return Array.isArray(array);
}
return Object.prototype.toString.call(array) === '[object Array]';
}
export const isNumber = function(n) {
if(typeof n === 'number' && !isNaN(n)) return true;
return n === +n && n === (n|0);
}
export function isInteger(x) { return typeof x === "number" && isFinite(x) && Math.floor(x) === x; }
export const isFloat = function(n) {
if(isNumber(n)) return true;
if(isNaN(n)) return false;
return n === +n && n !== (n|0);
}
export const isDecimal = isFloat;
export function isObj (obj){
if(!obj) return false;
return obj && Object.prototype.toString.call(obj) === '[object Object]' && !(obj instanceof RegExp)? true : false;
}
export const isNullOrEmpty = function (object,checkDomElement,escapeBoolean){
if(isDateObj(object)) return false;
if(typeof object == 'number') return false;
if(typeof object === 'boolean'){
if(checkDomElement === true || escapeBoolean === true){
return false;
}
return (object == false);
}
if(typeof object == 'undefined' || object === null || object === undefined || object === '') return true;
if(typeof object == 'string'){
return (object == null | object == '');
}
if(typeof object == 'object'){
var $return = (Object.size(object,true) > 0)? false : true;
if(Array.isArray(object)) return $return;
if(checkDomElement) {
$return = ($return == false) ? false : isDOMElement(object)? false : true;
}
return $return;
}
return false;
}
export const isValidDataFileName = function(value,escapeDot){
if(!isNonNullString(value)) return false;
if(escapeDot === true) value = value.replaceAll(".","");
return /^[A-Za-z0-9_-]+$/.test(value);
}
export const isConstructor = function isConstructor(obj){
if(isNullOrEmpty(obj)) return false;
return !!obj.prototype && !!obj.prototype.constructor.name;
}
export const isWindow = function(obj) {
var toString = Object.prototype.toString.call(obj);
return toString == '[object global]' || toString == '[object Window]' || toString == '[object DOMWindow]';
};
/*****
* @param {string} le nombre à parser
* @param {boolean} si l'on doit préserver le nombre de décimales
*/
export const parseDecimal = (x,preserveDecimalLength) =>{
if(isDecimal(x)) return x;
if(isNonNullString(x)) {
if(!x.contains(".")){
x = x.replace(",",".");
}
return parseFloat(x.replaceAll(" ",''));
}
return 0;
}
export const getObjectClass = function (obj){
if (obj && obj.constructor && obj.constructor.toString()) {
return obj.constructor;
}
return null;
}
export const isIE = function() {
if(typeof window =="undefined" || !window) return false;
if(!window.navigator || !isNonNullString(window.navigator.userAgent)) return false;
var msie = ua.indexOf('msie ');
if (msie > 0) {
// IE 10 or older => return version number
return parseInt(ua.substring(msie + 5, ua.indexOf('.', msie)), 10);
}
var trident = ua.indexOf('trident/');
if (trident > 0) {
// IE 11 => return version number
var rv = ua.indexOf('rv:');
return parseInt(ua.substring(rv + 3, ua.indexOf('.', rv)), 10);
}
var edge = ua.indexOf('edge/');
if (edge > 0) {
// Edge (IE 12+) => return version number
return parseInt(ua.substring(edge + 5, ua.indexOf('.', edge)), 10);
}
// other browser
return false;
}
export const randomInt = function(min,max) {
if(isObj(min)){
max = isNumber(min.max) ? min.max : 100;
min = isNumber(min.min)? min.max : 0;
}
if(!isNumber(min)){
min = 0;
}
if(!isNumber(max)){
max = 100;
}
return Math.floor(Math.random() * max) + min;
}
export const randomNumber = randomInt;
export const isMobileOrTablet = function(){
var check = false;
if(typeof navigator == undefined || navigator == null) return false;
(function(a){if(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino|android|ipad|playbook|silk/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4))) check = true;})(navigator.userAgent||navigator.vendor||window.opera);
return check;
}
export {default as isTouchDevice} from "./isTouchDevice"
export {isClientSide,isServerSide} from "$cplatform"
export * from "./string";
require("./dom")
require("./polyfill");
/*****
* ucfirstUnderground : change the string from camel case into snake case
* (addElementComponent => ADD_ELEMENT_COMPONENT)
* exemple :
* toSnakeCase('thisISDifficult') -> THIS_IS_DIFFICULT
toSnakeCase('thisISNT') -> THIS_ISNT
*/
export const toSnakeCase = (text)=> {
if(!isNonNullString(text)) return '';
text = text.trim();
return text.replace(/(.)([A-Z][a-z]+)/, '$1_$2').replace(/([a-z0-9])([A-Z])/, '$1_$2').toUpperCase()
}
export const toSnake= toSnakeCase;
String.prototype.toSnakeCase = String.prototype.snakeCase = String.prototype.toSnake = function(){
return toSnakeCase(this.toString());
}
/*****
* undergroundUcFirst : change the string from snake case into camel case (
* ADD_ELEMENT_COMPONENT => addElementComonent)
* exemple :
* camelCase('THIS_IS_DIFFICULT') -> 'ThisISDifficult
camelCase('THIS_ISNT') -> 'THISISNT'
*/
export const toCamelCase = (text) => {
if(!isNonNullString(text)) return '';
text = text.trim();
return text.charAt(0)+text.replace(/(_\w)/g, k => k[1].toUpperCase()).substring(1)
}
export const toCamel = toCamelCase;
String.prototype.toCamelCase = String.prototype.toCamel = String.prototype.camelCase = function(){
return toCamelCase(this.toString());
}
export const ucFirst = function(str) {
if(!str || typeof str !=="string") return "";
str = str.trim();
return str.charAt(0).toUpperCase() + str.slice(1);
};
export const upperFirst = ucFirst;
if(typeof String.prototype.ucFirst !='function'){
String.prototype.ucFirst = function(){
return ucFirst(this.toString());
}
}
export const lowerFirst = function(str) {
if(!str || typeof str !=="string") return "";
str = str.trim();
return str.charAt(0).toLowerCase() + str.slice(1);
};
String.prototype.toUpperFirst = upperFirst;
String.prototype.lowerFirst = String.prototype.toLowerFirst = function(){
return lowerFirst(this.toString());
};
const _isClassExtends = (ChildClass, ParentClass)=> {
if(!ChildClass || !ChildClass.prototype) return false;
let _p = ChildClass.prototype;
while (_p != null) {
if (_p == ParentClass.prototype)
return true;
_p = _p.__proto__;
}
return false;
}
/**** vérifie si la sous classe passé en premier paramètre hérite de la seconde clase
@param, la classe enfant,
@param, la classe parent
*/
export const isClassExtends = (ChildClass,ParentClass)=>{
if(!isObj(ChildClass)) return false;
return _isClassExtends(ChildClass,ParentClass) ||
(ChildClass.constructor && _isClassExtends(ChildClass.constructor,ParentClass))
}
export {default as debounce} from "./debounce";
const isDataURLRegex = /^data:([a-z]+\/[a-z0-9-+.]+(;[a-z0-9-.!#$%*+.{}|~`]+=[a-z0-9-.!#$%*+.{}|~`]+)*)?(;base64)?,([a-z0-9!$&',()*+;=\-._~:@\/?%\s]*?)$/i;
export const isDataURL = function isDataURL(s) {
return isNonNullString(s) && !s.contains("data:image/x-icon") && !!s.match(isDataURLRegex);
}
export const isValidImageSrc = src => {
if(!isNonNullString(src)) return false;
src = src.trim();
if(src.startsWith("blob:http")){
src = src.ltrim("blob:");
}
return isDataURL(src) || isValidUrl(src) || src.startsWith("data:image/");
}
export const isBlob = (blob) =>{
if(!blob) return false;
try {
if(blob instanceof Blob) return true;
} catch{}
return false;
}
export const isBase64 = function isBase64(str, options) {
if(!isNonNullString(str)) return false;
options = defaultObj(options);
options.urlSafe = defaultBool(options.urlSafe,false);
const len = str.length;
if (options.urlSafe) {
return /^[A-Z0-9_\-]*$/i.test(str);
}
if (len % 4 !== 0 || /[^A-Z0-9+\/=]/i.test(str)) {
return false;
}
const firstPaddingChar = str.indexOf('=');
return firstPaddingChar === -1 || firstPaddingChar === len - 1 ||
(firstPaddingChar === len - 2 && str[len - 1] === '=');
}
/**** parser for data url */
let dataURLDecoder = (dataURLStr)=>{
if(!isDataURL(dataURLStr)) return undefined;
let dataURLPattern = /^data:((.*?)(;charset=.*?)?)(;base64)?,/;
// parse the dataURL components as per RFC 2397
let matches = dataURLStr.match(dataURLPattern);
if (!matches) {
return undefined;
}
// default to text/plain;charset=utf-8
var mediaType = matches[2]
? matches[1]
: 'text/plain' + (matches[3] || ';charset=utf-8');
return {
matches,
isBase64 : !!matches[4],
data : dataURLStr.slice(matches[0].length),
mediaType
}
}
export const parseDataURL = (s) => {
if (!isDataURL(s)) {
return undefined;
}
const parts = s.trim().match(isDataURLRegex);
const parsed = {};
if (parts[1]) {
parsed.mediaType = parts[1].toLowerCase();
const mediaTypeParts = parts[1].split(';').map(x => x.toLowerCase());
parsed.contentType = mediaTypeParts[0];
mediaTypeParts.slice(1).forEach((attribute) => {
const p = attribute.split('=');
parsed[p[0]] = p[1];
});
}
parsed.isBase64 = !!parts[parts.length - 2];
parsed.data = parts[parts.length - 1] || '';
parsed.toBuffer = () => {
const encoding = parsed.isBase64 ? 'base64' : 'utf8';
return Buffer.from? Buffer.from(parsed.data, encoding) : new Buffer(parsed.data, encoding);
};
//{mediaType,contentType}
return parsed;
}
/*** retoune le type d'une chaine dataURl */
export const getTypeFromDataURL = (dataURL)=>{
if(!isDataURL(dataURL)) return null;
return dataURL.split(',')[0].split(':')[1].split(';')[0]
}
export const getMimeTypeFromDataURL = getTypeFromDataURL;
/**** convertis une chaine de caractère data-url en objet blob
* @see : https://stackoverflow.com/questions/12168909/blob-from-dataurl
*/
export function dataURLToBlob(dataurl) {
if(!isDataURL(dataurl)) return null;
var parts = dataurl.split(','), mime = parts[0].match(/:(.*?);/)[1]
if(parts[0].indexOf('base64') !== -1) {
var bstr = base64.atob(parts[1]), n = bstr.length, u8arr = new Uint8Array(n)
while(n--){
u8arr[n] = bstr.charCodeAt(n)
}
return new Blob([u8arr], {type:mime})
} else {
var raw = decodeURIComponent(parts[1])
return new Blob([raw], {type: mime})
}
}
/*** converti un contenu base 64 en blob
* @see : https://stackoverflow.com/questions/34993292/how-to-save-xlsx-data-to-file-as-a-blob/35713609#35713609
* @param {string} base64Data la chaine a convertir
* @return {null || Blob} null si le contenu base64Data est invalide
*/
export function base64toBlob(base64Data, contentType) {
if(!isBase64(base64Data)) return null;
contentType = defaultStr(contentType);
let sliceSize = 1024;
let byteCharacters = atob(base64Data);
let bytesLength = byteCharacters.length;
let slicesCount = Math.ceil(bytesLength / sliceSize);
let byteArrays = new Array(slicesCount);
for (let sliceIndex = 0; sliceIndex < slicesCount; ++sliceIndex) {
let begin = sliceIndex * sliceSize;
let end = Math.min(begin + sliceSize, bytesLength);
let bytes = new Array(end - begin);
for (var offset = begin, i = 0; offset < end; ++i, ++offset) {
bytes[i] = byteCharacters[offset].charCodeAt(0);
}
byteArrays[sliceIndex] = new Uint8Array(bytes);
}
return new Blob(byteArrays, { type: contentType });
}
export const base64ToBlob = base64toBlob;
/**** convertis une chaine de caractère data-url en objet blob */
export function dataURLToBase64(dataURLStr){
if(!isDataURL(dataURLStr)) return undefined;
return dataURLStr.replace(/^data:.+;base64,/, '')
}
/*** vérifie si la valeur passée en paramètre est un email valide
* @param {string} email à vérifier
* @param {bool}, si le validateur doit retourner false lorsque l'émail n'est pas une chaine de caractère
*/
export const isValidEmail = (value,required)=>{
if(!isNonNullString(value)){
return required ? false : true;
}
let re = /^(")?(?:[^\."])(?:(?:[\.])?(?:[\w\-!#$%&'*+\/=?\^_`{|}~]))*\1@(\w[\-\w]*\.){1,5}([A-Za-z]){2,6}$/
return value.match(re) ? true : false;
}
/***@function
* @alias isValidEmail
* alias à la fonction isValidEmail
*/
export const isValidMail = isValidEmail;
/**
* Mask email address with asterisks to comply GDPR
* john.doe@example.com => j******e@e****e.com
* @param {string} emailAddress email address
* @returns {string} masked email address
*/
export const hideEmailAddress = function maskEmailAddress (emailAddress) {
if(!isNonNullString(emailAddress)) return "";
function mask(str) {
if(!isNonNullString(str)) return "";
var strLen = str.length;
if (strLen > 4) {
return str.substr(0, 1) + str.substr(1, strLen - 1).replace(/\w/g, '*') + str.substr(-1,1);
}
return str.replace(/\w/g, '*');
}
return emailAddress.replace(/([\w.]+)@([\w.]+)(\.[\w.]+)/g, function (m, p1, p2, p3) {
return mask(p1) + '@' + mask(p2) + p3;
});
}
/*** mask some number in a phone number */
export const maskPhoneNumber = function(number){
number = defaultStr(number).replaceAll(" ","");
if(!number || number.length < 5) return "";
if(number < 8){
return number.substring(0,2) + number.substr(2,number.length).replace(/.(?=.{2})/g, "*");
}
return number.substring(0,4) + number.substr(4,number.length).replace(/.(?=.{2})/g, "*");
}
export const typeOf = function (obj) {
return ({}).toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase();
}
// Escapes the special characters in @text so that it can serve as a literal pattern in a regular expression
export const escapeSpecialChars = (function () {
var _pattern = /([.*+?=!:${}()|\-\^\[\]\/\\])/g;
return function (text) {
if (typeof text !== "string") return null;
return text.replace(_pattern, "\\$1");
}
}())
/**** auto bind, les méthodes sur l'objet context passé en paramètre
@praam methodsName : la ou les function qui seront binding par le context
@param, obj : le context sur lequel appliquer les fonctions
@param fucntion : la fonction de rappel prenant en paramètre le nom de la méthode courante, appelée à chaque boucle sur les différentes fonction de l'objet context
Exemple : f = autobind(f,context);
: autobind.call(this,['m1','m2','m3']);
: autobind.call(this,null,indivualMethodCallback) //bind automatiquement toutes les méthodes de 'lobjet
: autobind.call(this,individualMethodCallback)
*/
export const autobind = function autobind(methodsName,context,individualMethodCallback){
if(isFunction(methodsName)){
individualMethodCallback = methodsName;
methodsName = undefined;
context = context || this;
}
if(!context) context = this;
if(!context) return;
if(isObj(context) || isConstructor(context)) {
let r = [];
if(!methodsName) methodsName= '';
else r = Object.toArray(methodsName);
Object.getAllMethodNames(context,function(m){
if(r.length > 0 && !arrayValueExists(m,r)) return;
if(typeof(context[m]) != 'function') return;
try {
context[m] = context[m].bind(context);
} catch(e){
context[m].bind(context);
}
if(typeof individualMethodCallback == 'function'){
individualMethodCallback.call(context,m);
}
});
}
if(isObjOrArray(methodsName)){
for(let k in methodsName){
if(typeof(methodsName[k]) == 'function'){
methodsName[k] = methodsName[k].bind(context);
}
}
} else if(typeof(methodsName) == 'function'){
methodsName = methodsName.bind(context);
}
return methodsName;
}
/***
* Retourne la liste des méthodes de l'objet passé en paramètre dans un tableau
* @param object obj : l'objet auquel l'on désire retourner les méthodes de l'objet
* @param function individualMethodCallback : la function à appeler sur chaque méthode trouvée lorsque la boucle parcourant les différentes méthodes est effectuée
*/
export const getAllMethodNames = Object.getAllMethodNames = function (obj,individualMethodCallback,level) {
let props = []
if(!obj) return []
let _obj = obj;
level = isNumber(level)?level:1;
let index = 0;
do {
let l = Object.getOwnPropertyNames(obj)
.concat(Object.getOwnPropertySymbols(obj).map(s => s.toString()))
.sort()
.filter((p, i, arr) =>
typeof obj[p] === 'function' && //only the methods
p !== 'constructor' && //not the constructor
(i == 0 || p !== arr[i - 1]) && //not overriding in this prototype
props.indexOf(p) === -1 //not overridden in a child
)
props = props.concat(l)
index++;
}
while (
(obj = Object.getPrototypeOf(obj)) && //walk-up the prototype chain
Object.getPrototypeOf(obj) //not the the Object prototype methods (hasOwnProperty, etc...)
&& index <= level //on parcours toutes les propriétés jusqu'à une certaine hiérarchie
)
if(typeof individualMethodCallback === 'function'){
individualMethodCallback.bind(_obj);
props.map(l =>{
individualMethodCallback.call(_obj,l);
});
}
return props
}
const getItem = (x,prop) => isObj(x) && prop in x ? x[prop] : x;
function mergeSort(array,compare) {
if(!Array.isArray(array)) return [];
var length = array.length,
middle = Math.floor(length / 2);
if (!compare) {
compare = function(left, right) {
if (left < right)
return -1;
if (left == right)
return 0;
else
return 1;
};
}
if (length < 2)
return array;
return merge(
mergeSort(array.slice(0, middle),compare),
mergeSort(array.slice(middle, length),compare),
compare
);
}
function merge(left, right, compare) {
var result = [];
while (left.length > 0 || right.length > 0) {
if (left.length > 0 && right.length > 0) {
if (compare(left[0], right[0]) <= 0) {
result.push(left[0]);
left = left.slice(1);
}
else {
result.push(right[0]);
right = right.slice(1);
}
}
else if (left.length > 0) {
result.push(left[0]);
left = left.slice(1);
}
else if (right.length > 0) {
result.push(right[0]);
right = right.slice(1);
}
}
return result;
}
/**
* Trie un objeet ou un tableau d'elements.
* exemple : sortBy([{test:'b'},{test:'b}],{parser:(a,column)=>a[column],dir:'asc',ignoreCase:fale})
* Exemple de cfg : {dir:'asc',getItem:(item,column)=>{},}
* @param {Array || object} la collection à trier
* @param {Object} cfg: les options de configuration :
* cfg = {
deleteKey : ///si la clé sera supprimée
keyName : le nom de la clé unique à chaque item
returnObject : true // un object sera retourné
returnArray : true //si le resultat retourné sera un tableau où non
* desc : true || dir : 'asc' || dir : 'desc' //la direction du trie
* column || columnName : 'test' //le nom de la colonne à utiliser pour le trie si c'est un tableu
* igonoreCase : true //si la casse sera ignorée lors du trie
* }
*/
export const sortBy = function sortby(array, cfg,itemMutator) {
if (!isObj(cfg)) cfg = {};
if(!isObjOrArray(array)) {
return (cfg.returnArray === false || cfg.returnObject !== false) ? {} : []
}
let result = {};
if(isNonNullString(cfg.dir)){
cfg.dir = cfg.dir.toLowerCase().trim();
cfg.desc = cfg.dir === 'desc';
}
if(!typeof cfg.desc == 'boolean'){
cfg.desc = false;
}
cfg.desc = !!cfg.desc ? -1 : 1;
let keys = []
let keyName = defaultStr(cfg.keyName,uniqid("sort-by-object-keyname"));
let columnName = defaultStr(cfg.column,cfg.columnName);
cfg.getItem = defaultFunc(cfg.getItem,getItem);
//itemMutator = defaultFunc(itemMutator,cfg.mutator,cfg.itemMutator);
const compare = function(a, b){
a = cfg.getItem(a,columnName,{a,b,getItem});
if(a === undefined) a = "";
b = cfg.getItem(b,columnName,{a,b,getItem});
if(b ===undefined) b = "";
switch(typeof(a)) {
case 'string' :
if(cfg.ignoreCase !==false){
a = typeof a =='string' ? a.toLowerCase():'';
b = typeof b ==='string' ? b.toLowerCase() : '';
}
break;
case 'boolean' :
a = a+'';
b = b+'';
break;
default :
break;
}
return cfg.desc * (a < b ? -1 : +(a > b));
};
let r = Object.toArray(array,(_keys)=>{keys = _keys;},keyName);
r = mergeSort(r,compare);
if(isObj(array) && (cfg.returnArray === false || cfg.returnObject !== false)){
for(let i in r){
result[defaultStr(r[i][keyName],keys[i])] = r[i];
if((keyName != cfg.keyName) || cfg.deleteKey) delete r[i][keyName];
}
return result;
}
return r;
};
/*** suites des constantes et fonctions utiles */
/**
retourne l'extension du fichier passé en paramètre
@param string le chemin du fichier
@param bool withoutDash, précise si l'extension sera retourné avec le point ou pas
*/
export const getFileExtension = function(path,withoutDash){
if(!path || typeof path != 'string') return '';
if(path.indexOf(".") ===-1) return '';
var er = path.split(".");
var e = er[er.length-1];
//var e = path.slice(1).split('.').pop();
withoutDash = (withoutDash == undefined) ? true : withoutDash;
e = e.trim().ltrim(".");
if(e.startsWith("/")){
return '';
}
if(!withoutDash){
e = "."+e;
}
return e;
}
/**** retourne le chemin du répertoire parent à un path */
export const getFileDirectory = (filePath) => {
if(!isNonNullString(filePath)) return "";
if (filePath.indexOf("/") == -1) { // windows
return filePath.substring(0, filePath.lastIndexOf('\\'));
}
else { // unix
return filePath.substring(0, filePath.lastIndexOf('/'));
}
}
/*** retourne le nom du fichier à partir de son chemin complet
* @param filePath : le chemin du fichier
* @param withoutExtension : bool pour indiquer si le nom sera retourneé sans extension
* par défaut : faux
*/
export const getFileName = (filePath,withoutExtension)=>{
if(!isNonNullString(filePath)) return "";
const isNotPath = !filePath.contains("/") && !filePath.contains("\\");
if(!isNotPath){
filePath.rtrim("/").rtrim("\\").ltrim("/").ltrim("\\").trim();
if(!filePath) return filePath;
filePath = filePath.replace(/^.*(\\|\/|\:)/, '');
}
if(withoutExtension){
//return filePath.replace(/(\.[^.]*)$/, '');
let er = filePath.split(".");
let e = er[er.length-1];
return filePath.rtrim("."+e).rtrim(".");
}
return filePath;
}
/****
* exécute la fonction dont la chaine de caractèr est passée en paramètre comme nom
*/
export const executeFunctionByName = function(functionName, context /*, args */) {
var args = [].slice.call(arguments).splice(2);
var namespaces = functionName.split(".");
var func = namespaces.pop();
for(var i = 0; i < namespaces.length; i++) {
context = context[namespaces[i]];
}
return context[func].apply(context, args);
}
/****
* retourne la valeur de la propriété passée à un objet au cas où elle existe
* @param object, l'objet en question
* @param string property_name, le nom de la propreté qu'on souhaite récupérer sur l'objet object
* @param default value, la valeur par défaut à retourner au cas où l'objet object n'admet pas de prorieté prop
*/
export const getPropValue = Object.getPropValue = function getPropValue(object, property_name,default_value){
if(typeof property_name == 'object' & typeof object != 'object'){
var t = property_name;
property_name = object;
object = t;
}
if(typeof object != 'object'){
if(typeof default_value != "undefined") return default_value
return '';
}
if(typeof property_name == 'object') return default_value;
if(object && typeof object[property_name] != "undefined"){
if(object[property_name] != null & object[property_name] != 'null') return object[property_name]
}
if(typeof default_value != "undefined") return default_value;
return '';
}
/*** compare deux variable :
* @param a : mixted : object, array, int, ....
* @param b : mixted : object, array, int, ....
* @param boolean : autoriser la prise en compte des valeurs non définies ou nulles
* si les objets sont de type différents alors la fonction retourne false
*/
export const compare = function compare (a,b,avoidUndefinedValue) {
var obj_str = '[object Object]',
arr_str = '[object Array]',
a_type = Object.prototype.toString.apply(a),
b_type = Object.prototype.toString.apply(b);
if(avoidUndefinedValue === true){
if(typeof a ==='undefined' || typeof b ==='undefined') return false;
if(a === null || b === null || (a_type =='string' && a ==='') || (b_type =='string' && b ==='')) return false;
}
if ( a_type !== b_type) { return false; }
if (a_type === obj_str) {
return compareObject(a,b);
}
if (a_type === arr_str) {
return compareArray(a,b);
}
return (a === b);
}
/*** compare two objects */
export const compareObject = function(objA,objB) {
var i,a_type,b_type;
// Compare if they are references to each other
if (objA === objB) { return true;}
if (Object.keys(objA).length !== Object.keys(objB).length) { return false;}
for (i in objA) {
if (objA.hasOwnProperty(i)) {
if (typeof objB[i] === 'undefined') {
return false;
}
else {
a_type = Object.prototype.toString.apply(objA[i]);
b_type = Object.prototype.toString.apply(objB[i]);
if (a_type !== b_type) {
return false;
}
}
}
if (compare(objA[i],objB[i]) === false){
return false;
}
}
return true;
}
/*** compare two arrays */
export const compareArray = function (arrayA, arrayB) {
var a,b,i,l,a_type,b_type;
// References to each other?
if (arrayA === arrayB) { return true;}
if (arrayA.length != arrayB.length) { return false; }
// sort modifies original array
// (which are passed by reference to our method!)
// so clone the arrays before sorting
a = extendObj(true, [], arrayA);
b = extendObj(true, [], arrayB);
a.sort();
b.sort();
for (i = 0, l = a.length; i < l; i+=1) {
a_type = Object.prototype.toString.apply(a[i]);
b_type = Object.prototype.toString.apply(b[i]);
if (a_type !== b_type) {
return false;
}
if (compare(a[i],b[i]) === false) {
return false;
}
}
return true;
}
function increment_string_num(str){
let inc = String(parseInt(str)+1);
return str.slice(0, str.length-inc.length)+inc;
}
// 'item001' => 'item002'
export const incrementAlphanumericStr = function incrementAlphanumericStr (str){
if(typeof str ==='number') str = str+"";
if(typeof str !=='string') return "";
var numeric = str.match(/\d+$/)[0];
var prefix = str.split(numeric)[0];
return prefix+increment_string_num(numeric);
}
export * from "./numberToWords"
export * from "./numberToLocaleString";
/*** randomise l'alphabet */
export function randomAlphabet() {
let text = '';
const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
text += possible.charAt(Math.floor(Math.random() * possible.length));
return text;
}
export const randomText = randomAlphabet;
const _classExtends = (ChildClass, ParentClass)=> {
if(!ChildClass || !ChildClass.prototype) return false;
let _p = ChildClass.prototype;
while (_p != null) {
if (_p == ParentClass.prototype)
return true;
_p = _p.__proto__;
}
return false;
}
export const classExtends = (ChildClass,ParentClass)=>{
if(!ChildClass) return false;
return _classExtends(ChildClass,ParentClass) ||
(ChildClass.constructor && _classExtends(ChildClass.constructor,ParentClass));
}
export const decodeBase64 = function(base64Str){
if(isNonNullString(base64Str)){
if(isBase64(base64Str)){
return base64.decode(base64Str);
}
return base64Str;
}
return "";
}
export const fromBase64ToStr = decodeBase64;
export const fromBase64ToString = decodeBase64;
/*** retourne la valeur de chaine de caractère au format base 64 qu'elle trouve
* si aucune chaine de caractère n'est au format base64, la première chaine de caractère non nulle de la liste
* est encodée au format base64 et retournée
*/
export const defaultBase64 = function(){
const args = Array.prototype.slice.call(arguments,0);
let noBase64 = "";
for(let i in args){
const str = args[i];
if(isNonNullString(str)){
if(isBase64(str)){
return str;
}
if(!noBase64){
noBase64 = str;
}
}
}
if(noBase64){
return base64.encode(noBase64);
}
return "";
}
function buildFormData(formData, data, parentKey) {
if (data && typeof data === 'object' && !(data instanceof Date) && !(data instanceof File)) {
Object.keys(data).forEach(key => {
buildFormData(formData, data[key], parentKey ? `${parentKey}[${key}]` : key);
});
} else {
const value = data == null ? '' : data;
formData.append(parentKey, value);
}
}
/**** convertis un objet javascript en formData
* @param {object} data l'objet à convertir en formData
* @return {FormData}
*/
export const toFormData = Object.toFormData = (data)=>{
const formData = new FormData();
buildFormData(formData, data);
return formData;
}