269 JavaScript utility functions to improve your work efficiency

130.blob to file

 /**
     *  @param { blob } blob
     *  @param { string } fileName
        */

    export const blobToFile = (blob, fileName) => {
     blob.lastModifiedDate = new Date();
     blob.name = fileName;
     return blob;
     };

131.file to base64

 /**
     * @param { * } file Picture file
       */

       export const fileToBase64 = file => {
       let reader = new FileReader();
       reader.readAsDataURL(file);
   reader.onload = function (e{
        return e.target.result
    };
    };

132. Recursively generate tree structure

export function getTreeData(data, pid, pidName = 'parentId', idName = 'id', childrenName = 'children', key{
    let arr = [];

    for (let i = 0; i < data.length; i++) {
        if (data[i][pidName] == pid) {
            data[i].key = data[i][idName];
            data[i][childrenName] = getTreeData(data, data[i][idName], pidName, idName, childrenName);
            arr.push(data[i]);
        }
    }

    return arr;

}

133. Traversal tree node

export function foreachTree(data, childrenName = 'children', callback{
    for (let i = 0; i < data.length; i++) {
        callback(data[i]);
        if (data[i][childrenName] && data[i][childrenName].length > 0) {
            foreachTree(data[i][childrenName], childrenName, callback);
        }
    }
}

134. Trace parent node

export function traceParentNode(pid, data, rootPid, pidName = 'parentId', idName = 'id', childrenName = 'children'{
    let arr = [];
    foreachTree(data, childrenName, (node) => {
        if (node[idName] == pid) {
            arr.push(node);
            if (node[pidName] != rootPid) {
                arr = arr.concat(traceParentNode(node[pidName], data, rootPid, pidName, idName));
            }
        }
    });
    return arr; 
}

135. Find all child nodes

export function traceChildNode(id, data, pidName = 'parentId', idName = 'id', childrenName = 'children'{
    let arr = [];
    foreachTree(data, childrenName, (node) => {
        if (node[pidName] == id) {
            arr.push(node);
            arr = arr.concat(traceChildNode(node[idName], data, pidName, idName, childrenName));
        }
    });
    return arr;
}

136. Generate tree structure based on pid

 /**
     *  @param { object } items Data acquired in the background
 *  @param { * } id id in data
  *  @param { * } link The basis of generating tree structure
     */

     export const createTree = (items, id = null, link = 'pid') =>{
     items.filter(item => item[link] === id).map(item => ({ ...item, children: createTree(items, item.id) }));
     };

137. Query whether an element exists in the array and return the subscript of the first occurrence of the element

 /** 
     * @param {*} item 
     * @param { array } data
       */

       export function inArray(item, data{
       for (let i = 0; i < data.length; i++) {
           if (item === data[i]) {
           return i;
        }
    }
    return -1;
    }

138.Windows judges the current system name according to the detailed version number

 /**
     * @param { string } osVersion 
       */

       export function OutOsName(osVersion{
       if(!osVersion){
           return
       }
       let str = osVersion.substr(03);
       if (str === "5.0") {
           return "Win 2000"
       } else if (str === "5.1") {
           return "Win XP"
       } else if (str === "5.2") {
           return "Win XP64"
       } else if (str === "6.0") {
           return "Win Vista"
       } else if (str === "6.1") {
           return "Win 7"
       } else if (str === "6.2") {
           return "Win 8"
       } else if (str === "6.3") {
           return "Win 8.1"
       } else if (str === "10.") {
           return "Win 10"
   } else {
        return "Win"
    }
    }

139. Judge whether the mobile phone is andord or IOS

 /**
     *  0: ios
     *  1: android
     *  2: other
        */

        export function getOSType({
        let u = navigator.userAgent, app = navigator.appVersion;
        let isAndroid = u.indexOf('Android') > -1 || u.indexOf('Linux') > -1;
        let isIOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);
        if (isIOS) {
            return 0;
    }
     if (isAndroid) {
         return 1;
     }
     return 2;
     }

140. Function anti shake

 /**
     * @param { function } func

     * @param { number } wait Delay execution milliseconds

 * @param { boolean } immediate  true Table is executed immediately, false table is not executed immediately
       */

       export function debounce(func,wait,immediate{
       let timeout;
       return function ({
           let context = this;
           let args = arguments;

           if (timeout) clearTimeout(timeout);
           if (immediate) {
               let callNow = !timeout;
               timeout = setTimeout(() => {
                   timeout = null;
               }, wait);
               if (callNow) func.apply(context, args)
       }
        else {
            timeout = setTimeout(() => {
                func.apply(context, args)
            }, wait);
        }

    }
    }

145. Function throttling

 /**
     * @param { function } func function

     * @param { number } wait Delay execution milliseconds

     * @param { number } type 1 Table time stamp version, 2 table timer version
       */

       export function throttle(func, wait ,type{
       let previous, timeout;
       if(type===1){
           previous = 0;
       }else if(type===2){
       timeout = null;
       }
       return function({
           let context = this;
           let args = arguments;
           if(type===1){
               let now = Date.now();

               if (now - previous > wait) {
                   func.apply(context, args);
                   previous = now;
               }
           }else if(type===2){
           if (!timeout) {
                   timeout = setTimeout(() => {
                   timeout = null;
                    func.apply(context, args)
                }, wait)
            }
        }

    }
    }

146. Judge data type

 /**
     * @param {*} target 
       */

       export function type(target{
       let ret = typeof(target);
       let template = {
           "[object Array]""array",
           "[object Object]":"object",
           "[object Number]":"number - object",
       "[object Boolean]":"boolean - object",
           "[object String]":'string-object'
       };

       if(target === null) {
           return 'null';
       }else if(ret == "object"){
           let str = Object.prototype.toString.call(target);
           return template[str];
   }else{
        return ret;
    }
    }

147. Generate random number in specified range

 /**
  * @param { number } min 
  * @param { number } max 
    */

    export const RandomNum = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;

148. Array disorder

 /**
     * @param {array} arr
       */

       export function arrScrambling(arr{
       let array = arr;
       let index = array.length;
       while (index) {
           index -= 1;
           let randomIndex = Math.floor(Math.random() * index);
           let middleware = array[index];
           array[index] = array[randomIndex];
       array[randomIndex] = middleware
    }
    return array
    }

150. Array intersection

 /**
  * @param { array} arr1
  * @param { array } arr2
    */

    export const similarity = (arr1, arr2) => arr1.filter(v => arr2.includes(v));

151. Number of occurrences of an element in the array

 /**

     * @param { array } arr
 * @param {*} value
    */

    export function countOccurrences(arr, value{
    return arr.reduce((a, v) => v === value ? a + 1 : a + 00);
    }

152. Additive function (precision loss problem)

 /**
     * @param { number } arg1
     * @param { number } arg2
       */

       export function add(arg1, arg2{
       let r1, r2, m;
   try { r1 = arg1.toString().split(".")[1].length } catch (e) { r1 = 0 }
    try { r2 = arg2.toString().split(".")[1].length } catch (e) { r2 = 0 }
    m = Math.pow(10Math.max(r1, r2));
    return (arg1 * m + arg2 * m) / m
    }

153. Subtraction function (precision loss problem)

 /**
     * @param { number } arg1
     * @param { number } arg2
       */

       export function sub(arg1, arg2{
       let r1, r2, m, n;
       try { r1 = arg1.toString().split(".")[1].length } catch (e) { r1 = 0 }
   try { r2 = arg2.toString().split(".")[1].length } catch (e) { r2 = 0 }
    m = Math.pow(10Math.max(r1, r2));
    n = (r1 >= r2) ? r1 : r2;
    return Number(((arg1 * m - arg2 * m) / m).toFixed(n));
    }

154. division function (accuracy loss problem)

 /**
     * @param { number } num1
     * @param { number } num2
       */

       export function division(num1,num2){
       let t1,t2,r1,r2;
       try{
           t1 = num1.toString().split('.')[1].length;
       }catch(e){
           t1 = 0;
       }
       try{
           t2=num2.toString().split(".")[1].length;
       }catch(e){
           t2=0;
   }
    r1=Number(num1.toString().replace(".",""));
    r2=Number(num2.toString().replace(".",""));
    return (r1/r2)*Math.pow(10,t2-t1);
    }

155. Multiplication function (precision loss problem)

 /**
     * @param { number } num1
     * @param { number } num2
       */

       export function mcl(num1,num2){
   let m=0,s1=num1.toString(),s2=num2.toString();
    try{m+=s1.split(".")[1].length}catch(e){}
    try{m+=s2.split(".")[1].length}catch(e){}
    return Number(s1.replace(".",""))*Number(s2.replace(".",""))/Math.pow(10,m);
    }

156. Recursive optimization (tail recursion)

 /**
     * @param { function } f
       */

       export function tco(f{
   let value;
       let active = false;
       let accumulated = [];

       return function accumulator({
           accumulated.push(arguments);
           if (!active) {
               active = true;
               while (accumulated.length) {
                   value = f.apply(this, accumulated.shift());
               }
               active = false;
           return value;
        }
    };
    }

157. Generating random integers

export function randomNumInteger(min, max{
    switch (arguments.length) {
        case 1:
            return parseInt(Math.random() * min + 110);
        case 2:
            return parseInt(Math.random() * (max - min + 1) + min, 10);
        default:
            return 0
    }
}

158. Remove spaces

 /**
     * @param { string } str Pending string
     * @param  { number } type Remove space type 1 - all spaces 2 - before and after spaces 3 - before and after spaces 4 - after spaces default to 1
       */

       export function trim(str, type = 1{
       if (type && type !== 1 && type !== 2 && type !== 3 && type !== 4return;
       switch (type) {
           case 1:
               return str.replace(/\s/g"");
           case 2:
               return str.replace(/(^\s)|(\s*$)/g"");
           case 3:
               return str.replace(/(^\s)/g"");
           case 4:
           return str.replace(/(\s$)/g"");
        default:
            return str;
    }
    }

159. Case conversion

/**
 * @param { string } str String to be converted
 * @param { number } type 1-All capital 2 - all lowercase 3 - initial capital other - no conversion
   */


export function turnCase(str, type{
    switch (type) {
        case 1:
            return str.toUpperCase();
        case 2:
            return str.toLowerCase();
        case 3:
            return str[0].toUpperCase() + str.substr(1).toLowerCase();
        default:
            return str;
    }
}

160. Random hex color hexColor

 /**
 * Method 1
       */

       export function hexColor({

       let str = '#';
       let arr = [0123456789'A''B''C''D''E''F'];
       for (let i = 0; i < 6; i++) {
           let index = Number.parseInt((Math.random() * 16).toString());
       str += arr[index]
    }
    return str;
    }

161. Random hex colorcode

 /**
     * Method 2
       */

   export const randomHexColorCode = () => {
    let n = (Math.random() * 0xfffff * 1000000).toString(16);
    return '#' + n.slice(06);
    };

162. Escape HTML (anti XSS attack)

export const escapeHTML = str =>{
    str.replace(
        /[&<>'"]/g,
        tag =>
            ({
                '&''&amp;',
                '<''&lt;',
                '>''&gt;',
                "'"'&#39;',
                '"''&quot;'
            }[tag] || tag)
    );
};

163. Detect mobile / PC devices

export const detectDeviceType = () => { return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ? 'Mobile' : 'Desktop'; };

164. Hide all specified labels

 /**
  * Example: hide( document.querySelectorAll ('img'))
    */

    export const hideTag = (...el) => [...el].forEach(e => (e.style.display = 'none'));

165. Returns the effective style of the specified element

 /**
  * @param { element} el  Element node
  * @param { string } ruleName  Specifies the name of the element
    */

    export const getStyle = (el, ruleName) => getComputedStyle(el)[ruleName];

166. Check for child elements

 /**
  * @param { element } parent
  * @param { element } child
  * Example: elementcontains( document.querySelector ('head'),  document.querySelector('title')); // true
    */

    export const elementContains = (parent, child) => parent !== child && parent.contains(child);

167. If the number exceeds the specified size plus "+", 99 will be displayed+

 /**
     * @param { number } val Number entered
     * @param { number } maxNum Numerical limit
       */

       export const outOfNum = (val, maxNum) =>{
       val = val ? val-0 :0;
       if (val > maxNum ) {
       return `${maxNum}+`
    }else{
        return val;
    }
    };

168. How to hide all specified elements

 const hide = (el) => Array.from(el).forEach(e => (e.style.display = 'none'));

 //Example: hide all elements on the page?
 hide(document.querySelectorAll('img'))

169. How do I check if an element has a specified class?

There is a classList object on each node in the page DOM. The programmer can add, delete and modify CSS classes on the node by using the methods in it. With classList, programmers can also use it to determine whether a node is given a CSS class.

 const hasClass = (el, className) => el.classList.contains(className)

 //Examples
 hasClass(document.querySelector('p.special'), 'special'// true

170. How to switch the class of an element?

 const toggleClass = (el, className) => el.classList.toggle(className)

 //Remove the special class with class' special 'from case p
 toggleClass(document.querySelector('p.special'), 'special')

171. How to get the scroll position of the current page?

 const getScrollPosition = (el = window) => ({
   x: el.pageXOffset !== undefined ? el.pageXOffset : el.scrollLeft,
   y: el.pageYOffset !== undefined ? el.pageYOffset : el.scrollTop
 });

 //Examples
 getScrollPosition(); // {x: 0, y: 200}

172. How to smoothly scroll to the top of the page

 const scrollToTop = () => {
   const c = document.documentElement.scrollTop || document.body.scrollTop;
   if (c > 0) {
     window.requestAnimationFrame(scrollToTop);
     window.scrollTo(0, c - c / 8);
   }
 }

 //Examples
 scrollToTop()
window.requestAnimationFrame() tell the browser that you want to execute an animation and ask the browser to update the animation before calling the specified callback function before the next redraw. This method needs to pass in a callback function as a parameter, which will execute before the browser's next redraw.
requestAnimationFrame: advantage: it's up to the system to decide when to execute the callback function. If the refresh frequency is 60Hz, then a callback function will be executed in the interval of each refresh, which will not cause frame loss or jam.

window.requestAnimationFrame() tell the browser that you want to execute an animation and ask the browser to update the animation before calling the specified callback function before the next redraw. This method needs to pass in a callback function as a parameter, which will execute before the browser's next redraw.
requestAnimationFrame: advantage: it's up to the system to decide when to execute the callback function. If the refresh frequency is 60Hz, then a callback function will be executed in the interval of each refresh, which will not cause frame loss or jam.

173. How to check whether the parent element contains child elements?

 const elementContains = (parent, child) => parent !== child && parent.contains(child);

 //Examples
 elementContains(document.querySelector('head'), document.querySelector('title')); 
 // true
 elementContains(document.querySelector('body'), document.querySelector('body')); 
 // false

174. How do I check that the specified elements are visible in the viewport?

 const elementIsVisibleInViewport = (el, partiallyVisible = false) => {
   const { top, left, bottom, right } = el.getBoundingClientRect();
   const { innerHeight, innerWidth } = window;
   return partiallyVisible
     ? ((top > 0 && top < innerHeight) || (bottom > 0 && bottom < innerHeight)) &&
         ((left > 0 && left < innerWidth) || (right > 0 && right < innerWidth))
     : top >= 0 && left >= 0 && bottom <= innerHeight && right <= innerWidth;
 };

 //Examples
 elementIsVisibleInViewport(el); //Need to be visible left and right
 elementIsVisibleInViewport(el, true); //Need full screen (up, down, left and right) to see

175. How do I get all the images in an element?

 const getImages = (el, includeDuplicates = false) => {
   const images = [...el.getElementsByTagName('img')].map(img => img.getAttribute('src'));
   return includeDuplicates ? images : [...new Set(images)];
 };

 //Case: includeDuplicates is true, indicating that duplicate elements need to be excluded
 getImages(documenttrue); // ['image1.jpg', 'image2.png', 'image1.png', '...']
 getImages(documentfalse); // ['image1.jpg', 'image2.png', '...']

176. How to determine whether the device is a mobile device or a desktop / laptop computer?

 const detectDeviceType = () =>
   /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)
     ? 'Mobile'
     : 'Desktop';

 //Examples
 detectDeviceType(); // "Mobile" or "Desktop"

177.How to get the current URL?

 const currentURL = () => window.location.href

 //Examples
 currentURL() // 'https://google.com'

178. How to create an object with the current URL parameter?

 const getURLParameters = url =>
   (url.match(/([^?=&]+)(=([^&]*))/g) || []).reduce(
     (a, v) => ((a[v.slice(0, v.indexOf('='))] = v.slice(v.indexOf('=') + 1)), a),
     {}
   );

 //Examples
 getURLParameters('http://url.com/page?n=Adam&s=Smith'); // {n: 'Adam', s: 'Smith'}
 getURLParameters('google.com'); // {}

179. How do I convert a set of form elements to objects?

 const formToObject = form =>
   Array.from(new FormData(form)).reduce(
     (acc, [key, value]) => ({
       ...acc,

[key]: value

     }),
     {}
   );

 //Examples
 formToObject(document.querySelector('#form')); 
 // { email: 'test@email.com', name: 'Test Name' }

180. How to retrieve a set of properties indicated by a given selector from an object?

 const get = (from, ...selectors) =>
   [...selectors].map(s =>
     s
       .replace(/\[([^\[\]]*)\]/g'.$1.')
       .split('.')
       .filter(t => t !== '')
       .reduce((prev, cur) => prev && prev[cur], from)
   );
 const obj = { selector: { to: { val'val to select' } }, target: [12, { a'test' }] };

 // Example
 get(obj, 'selector.to.val''target[0]''target[2].a'); 
 // ['val to select', 1, 'test']

181. how do I call the supplied function after waiting for the specified time?

 const delay = (fn, wait, ...args) => setTimeout(fn, wait, ...args);
 delay(
   function(text{
     console.log(text);
   },
   1000,
   'later'
 ); 

 //Print 'later' in 1 second

182. How to trigger specific events on a given element and optionally pass custom data?

 const triggerEvent = (el, eventType, detail) =>
   el.dispatchEvent(new CustomEvent(eventType, { detail }));

 //Examples
 triggerEvent(document.getElementById('myId'), 'click');
 triggerEvent(document.getElementById('myId'), 'click', { username'bob' });
Functions for custom events are Event,CustomEvent and dispatchEvent
 //Send a resize built-in event to window
 window.dispatchEvent(new Event('resize'))


 //To customize an Event directly, use the Event constructor:
 var event = new Event('build');
 var elem = document.querySelector('#id')
 //Listening events
 elem.addEventListener('build'function (e{ ... }, false);
 //Trigger event
 elem.dispatchEvent(event);
CustomEvent You can create a more highly customized event and attach some data. The specific usage is as follows:
 var myEvent = new CustomEvent(eventname, options);
 among options It can be:
 {
   detail: {
     ...
   },
   bubblestrue,    //Bubble or not
   cancelable: false //Cancel default event
 }
among detail It can store some initialization information, which can be called when triggering. Other properties are to define whether the event has bubbling and other functions.
 The built-in events will be triggered by the browser according to certain operations, and the customized events need to be triggered manually.
 dispatchEvent Function is used to trigger an event:
 element.dispatchEvent(customEvent);

 The above code indicates that element Triggered above customEvent This incident.
 // add an appropriate event listener
 obj.addEventListener("cat"function(e{ process(e.detail) });

 // create and dispatch the event
 var event = new CustomEvent("cat", {"detail":{"hazcheeseburger":true}});
 obj.dispatchEvent(event);
 Using custom events requires attention to compatibility issues, while using jQuery It's much simpler:

 //Binding custom events
 $(element).on('myCustomEvent'function(){});

 //Trigger event
 $(element).trigger('myCustomEvent');
 //In addition, you can pass more parameter information when a custom event is triggered:

 $( "p" ).on( "myCustomEvent"function( event, myName {
   $( this ).text( myName + ", hi there!" );
 });
 $( "button" ).click(function ({
   $( "p" ).trigger( "myCustomEvent", [ "John" ] );
 });

183. How do I remove an event listener from an element?

 const off = (el, evt, fn, opts = false) => el.removeEventListener(evt, fn, opts);

 const fn = () => console.log('!');
 document.body.addEventListener('click', fn);
 off(document.body, 'click', fn); 

184. How do I get a readable format for a given number of milliseconds?

 const formatDuration = ms => {
   if (ms < 0) ms = -ms;
   const time = {
     dayMath.floor(ms / 86400000),
     hourMath.floor(ms / 3600000) % 24,
     minuteMath.floor(ms / 60000) % 60,
     secondMath.floor(ms / 1000) % 60,
     millisecondMath.floor(ms) % 1000
   };
   return Object.entries(time)
     .filter(val => val[1] !== 0)
     .map(([key, val]) => `${val} ${key}${val !== 1 ? 's' : ''}`)
     .join(', ');
 };

 //Examples
 formatDuration(1001); // '1 second, 1 millisecond'
 formatDuration(34325055574); 
 // '397 days, 6 hours, 44 minutes, 15 seconds, 574 milliseconds'

185. How to get the difference between two dates (in days)?

 const getDaysDiffBetweenDates = (dateInitial, dateFinal) =>
   (dateFinal - dateInitial) / (1000 * 3600 * 24);

 //Examples
 getDaysDiffBetweenDates(new Date('2017-12-13'), new Date('2017-12-22')); // 9

186. How do I make a GET request to the passed URL?

 const httpGet = (url, callback, err = console.error) => {
   const request = new XMLHttpRequest();
   request.open('GET', url, true);
   request.onload = () => callback(request.responseText);
   request.onerror = () => err(request);
   request.send();
 };

 httpGet(
   'https://jsonplaceholder.typicode.com/posts/1',
   console.log
 ); 

 // {"userId": 1, "id": 1, "title": "sample title", "body": "my text"}

187. How do I POST a pass through URL?

 const httpPost = (url, data, callback, err = console.error) => {
   const request = new XMLHttpRequest();
   request.open('POST', url, true);
   request.setRequestHeader('Content-type''application/json; charset=utf-8');
   request.onload = () => callback(request.responseText);
   request.onerror = () => err(request);
   request.send(data);
 };

 const newPost = {
   userId1,
   id1337,
   title'Foo',
   body'bar bar bar'
 };
 const data = JSON.stringify(newPost);
 httpPost(
   'https://jsonplaceholder.typicode.com/posts',
   data,
   console.log
 ); 

 // {"userId": 1, "id": 1337, "title": "Foo", "body": "bar bar bar"}

188. How do I create a counter with a specified range, step, and duration for a specified selector?

 const counter = (selector, start, end, step = 1, duration = 2000) => {
   let current = start,
     _step = (end - start) * step < 0 ? -step : step,
     timer = setInterval(() => {
       current += _step;
       document.querySelector(selector).innerHTML = current;
       if (current >= end) document.querySelector(selector).innerHTML = end;
       if (current >= end) clearInterval(timer);
     }, Math.abs(Math.floor(duration / (end - start))));
   return timer;
 };

 //Examples
 counter('#my-id'1100052000); 
 //Let the 'id = "my ID" element create a 2-second timer

189. how do I copy a string to the clipboard?

   const el = document.createElement('textarea');
   el.value = str;
   el.setAttribute('readonly''');
   el.style.position = 'absolute';
   el.style.left = '-9999px';
   document.body.appendChild(el);
   const selected =
     document.getSelection().rangeCount > 0 ? document.getSelection().getRangeAt(0) : false;
   el.select();
   document.execCommand('copy');
   document.body.removeChild(el);
   if (selected) {
     document.getSelection().removeAllRanges();
     document.getSelection().addRange(selected);
   }
 };

 //Examples
 copyToClipboard('Lorem ipsum'); 
 // 'Lorem ipsum' copied to clipboard

190. How to determine whether the browser tab of the page is focused?

 const isBrowserTabFocused = () => !document.hidden;

 //Examples
 isBrowserTabFocused(); // true

191. How do I create a directory if it doesn't exist?

 const fs = require('fs');
 const createDirIfNotExists = dir => (!fs.existsSync(dir) ? fs.mkdirSync(dir) : undefined);

 //Examples
 createDirIfNotExists('test'); 
Most of the methods are practical and can solve many development process problems. Let's make good use of them.

192. Date function encapsulation

function formatTime(date{
  if(!!date){
    if(!(date instanceof Date))
    date = new Date(date);
    var month = date.getMonth() + 1
    var day = date.getDate()
    return `${month}month${day}day`;
  }
}

function formatDay(date{
  if(!!date){
    var year = date.getFullYear()
    var month = date.getMonth() + 1
    var day = date.getDate()
    return [year, month, day].map(formatNumber).join('-');
  }
}

function formatDay2(date{
  if(!!date){
    var&nb

Keywords: Mobile Android iOS Google

Added by Mikester on Mon, 15 Jun 2020 08:00:19 +0300