Awesome JavaScript Without Its Third-party Libraries

Updated on October 23, 2023 View Times: 12147

Catogery: develop
Share on Twitter

Range of random numbers

We sometimes need a specified range of random numbers, such as randomly generating random numbers between 1-100

const rand = (min, max) => {
  return parseInt(Math.random()*(max - min + 1) + min, 10);
}
rand(1, 100);

Randomly getting an item from an array

const items = ["apple", "banana", "orange", "pear", "grape"];
const randomPickFromArray = (array) => {
  const rand = (min, max) => {
    return parseInt(Math.random()*(max - min + 1) + min, 10);
  };
  return array[rand(0, array.length-1)];
}
console.log(randomPickFromArray(items))

random string

A string is randomly generated

const rand = (min, max) => {
    return parseInt(Math.random() * (max - min + 1) + min, 10);
};
const getRandStr = (len = 12) => {
    const base = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
    const max = base.length - 1;
    return Array(len).fill().map((_, idx) => base[rand(idx === 0 ? 10 : 0, max)]).join('');
};
getRandStr(32);

Load javascript By URL

Load remote JS files asynchronously

function loadScriptSync(url, props) {
  return new Promise((resolve) => {
    const script = document.createElement('script');
    if (script.readyState) {
      script.onreadystatechange = function () {
        if (script.readyState == 'loaded' || this.readyState == 'complete') {
          resolve();
        }
      };
    } else {
      script.onload = () => {
        resolve();
      };
    }
    script.src = url;
    Object.keys(props || {}).forEach((key) => {
      script.setAttribute(key, props[key]);
    });
    document.head.appendChild(script);
  });
}

Check Element Visible

Determine whether the file is in the visible area

function isElementInVisibleArea(elem, areaNode) {
  let viewport;
  if (areaNode) {
    viewport = areaNode.getBoundingClientRect();
  } else {
    viewport = {
      top: window.scrollY,
      left: window.scrollX,
      right: 0,
      bottom: 0
    };
    viewport.right = viewport.left + window.innerWidth;
    viewport.bottom = viewport.top + window.innerHeight;
  }

  const width = elem.offsetWidth;
  const height = elem.offsetHeight;
  const bodyRect = document.body.getBoundingClientRect();
  const elemRect = { ...elem.getBoundingClientRect() };
  elemRect.bottom = window.innerHeight - elemRect.top - elemRect.height;
  const bounds = {
    top: elemRect.top - bodyRect.top,
    right: 0,
    bottom: 0,
    left: elemRect.left - bodyRect.left
  };

  bounds.right = bounds.left + width;
  bounds.bottom = bounds.top + height;

  return !(viewport.right < bounds.left || viewport.left > bounds.right || viewport.bottom < bounds.top || viewport.top > bounds.bottom);
}

Get Element Position

Gets the coordinates of the element within the screen

const getNodePosition = (o) => {
    let x = 0;
    let y = 0;
    while (o.offsetParent) {
        x += o.offsetLeft;
        y += o.offsetTop;
        o = o.offsetParent;
    }
    return {'x':x,'y':y};
}

Get URL Params

Gets the parameter values of the URL

function getURLParams(key, url = window?.location?.href) {
    try {
        const r = (((url || '').split('?')[1] || '').split('#')[0] || '').match(new RegExp('(^|&)' + key + '=([^&]*)(&|$)', 'i'));

        if (r != null) {
            return decodeURIComponent(r[2]);
        }

        return '';
    } catch (error) {
        return '';
    }
}

Gets the text content selected by the page

Get the content of the selected Chinese

const SelectText = () => {
    try {
        const selecter = window.getSelection().toString();
        if (selecter != null && selecter.trim() != '') {
            return selecter;
        }
    } catch (err) {
        const selecter = document.selection.createRange();
        const s = selecter.text;
        if (s != null && s.trim() != '') {
            return s;
        }
    }
}

Download Text As File

Download the string as a text file

function downloadText(text, fileName) {
  const dataURL = `data:text/plain;charset=utf-8,${encodeURIComponent(text)}`;
  const a = document.createElement('a');
  const filename = fileName || `s_${+new Date()}.md`;
  a.href = dataURL;
  a.setAttribute('download', filename);
  a.innerHTML = 'downloading...';
  a.style.display = 'none';
  document.body.appendChild(a);
  setTimeout(() => {
    a.click();
    document.body.removeChild(a);
  }, 66);
}
downloadText('demo-text', 'test.js');

Base64 to binary

Base64 string to binary data

const dataURLtoFile = (dataurl, filename) => {
    const arr = dataurl.split(',');
    const mime = arr[0].match(/:(.*?);/)[1];
    const bstr = atob(arr[1]);
    let n = bstr.length;
    const u8arr = new Uint8Array(n);

    while (n) {
        n -= 1;
        u8arr[n] = bstr.charCodeAt(n);
    }

    return new File([u8arr], filename, { type: mime });
};

XML To JSON

XML objects are converted to JSON data

function xml2json(xml, obj) {
    obj = obj || {};
    if (xml && xml.childNodes && xml.childNodes.length) {
        var childs = xml.childNodes,
            len = xml.childNodes.length;
        var item;
        if (len === 1 && (childs[0].nodeType === 3 || childs[0].nodeType === 4)) {
            if (isArray(obj)) {
                obj.push(childs[0].nodeValue);
            } else {
                obj = childs[0].nodeValue;
            }
        } else {
            for (var i = 0; i < len; i++) {
                item = childs[i];
                if (item.nodeType === 1) {
                    if (obj.hasOwnProperty(item.nodeName) &&
                        !isArray(obj[item.nodeName])) {
                        obj[item.nodeName] = [obj[item.nodeName]];
                    }
                    if (isArray(obj[item.nodeName])) {
                        obj[item.nodeName].push(xml2json(item, {}));
                    } else {
                        obj[item.nodeName] = xml2json(item, {});
                    }
                }
            }
        }
    } else {
        obj = xml.nodeValue || '';
    }
    function isArray(a) {
        if (typeof a === 'object' && a.constructor === Array) return true;
        return false;
    }
    return obj
}

Check the object type

Determine the data type of the object

function checkObjectTypeof(obj) {
    const toString = Object.prototype.toString;
    const map = {
        '[object Boolean]':     'boolean',
        '[object Number]':      'number',
        '[object Undefined]':   'undefined',
        '[object Null]':        'null',
        '[object String]':      'string',
        '[object Object]':      'object',
        '[object Function]':    'function',
        '[object Array]':       'array',
        '[object Date]':        'date',
        '[object RegExp]':      'regExp',
        '[object Symbol]':      'symbol'
    };
    return map[toString.call(obj)];
}

Document Title To URL Format

For example, the title of the article is: JavaScript Utils Functions. We need javascript-utils-functions

const slugify = (string, separator = "-") => {
  return string
    .toString() // Cast to string (optional)
    .toLowerCase() // Convert the string to lowercase letters
    .trim() // Remove whitespace from both sides of a string (optional)
    .replace(/\s+/g, separator) // Replace spaces with -
    .replace(/[^\w\-]+/g, "") // Remove all non-word chars
    .replace(/\_/g, separator) // Replace _ with -
    .replace(/\-\-+/g, separator) // Replace multiple - with single -
    .replace(/\-$/g, ""); // Remove trailing -
};

slugify("Hello, World!");
// Expected output: "hello-world"

slugify("Hello, Universe!", "_");
// Expected output: "hello_universe"

Invoke promise one by one

We know that promise.all executes all promise queues concurrently, but there are scenarios where we need to control the limit of the number of concurrency, for example, uploading videos, we need to control the limit of concurrent upload of video parts

const removeOneFromArray = (v, array) => array.filter(item => item !== v);
const promiseFormation = (promiseList, max = 1, options) => {
    let running = [];
    let tasks = promiseList.slice(0);
    let isSuccess = true;
    const result = [];
    const next = (resolve, reject) => {
        // tasks all done
        const isTaskFinish = tasks.length === 0 && running.length === 0;
        const isBreakOff = options && options.stop;
        if (isTaskFinish || isBreakOff) {
            if (isBreakOff || !isSuccess) {
                reject(result);
            }
            else {
                resolve(result);
            }
        }
        // nextTick
        else {
            const availableNumber = max - running.length;
            if (availableNumber > 0) {
                tasks.slice(0, availableNumber).forEach((task) => {
                    const index = promiseList.indexOf(task);
                    tasks = removeOneFromArray(task, tasks);
                    running.push(task);
                    task()
                        .then((res) => {
                        if (typeof result[index] === "undefined") {
                            result[index] = res;
                        }
                        running = removeOneFromArray(task, running);
                        next(resolve, reject);
                    })
                        .catch((err) => {
                        isSuccess = false;
                        running = removeOneFromArray(task, running);
                        if (typeof result[index] === "undefined") {
                            result[index] = err;
                        }
                        next(resolve, reject);
                    });
                });
            }
        }
    };
    return new Promise((resolve, reject) => {
        if (options && !options.addOne) {
            // eslint-disable-next-line no-param-reassign
            options.addOne = (fn) => {
                promiseList.push(fn);
                tasks.push(fn);
                next(resolve, reject);
            };
        }
        // stop current promise and skip next
        if (options && !options.stopOne) {
            // eslint-disable-next-line no-param-reassign
            options.stopOne = (taskId) => {
                const runningIndex = running.map(item => item.id).indexOf(taskId);
                // no task
                if (runningIndex === -1) {
                    const taskIdx = tasks.map((item) => item.id).indexOf(taskId);
                    if (taskIdx > -1) {
                        const tsk = tasks[taskIdx];
                        tasks = removeOneFromArray(tsk, tasks);
                        const rIndex = promiseList
                            .map((item) => item.id)
                            .indexOf(taskId);
                        result[rIndex] = new Error("cancel");
                    }
                    return;
                }
                const taskIndex = promiseList
                    .map((item) => item.id)
                    .indexOf(taskId);
                const task = running[runningIndex];
                running = removeOneFromArray(task, running);
                result[taskIndex] = new Error("cancel");
                next(resolve, reject);
            };
        }
        // start
        next(resolve, reject);
    });
};

Here is Usage:

const p1 = () =>
  new Promise(resolve => {
    setTimeout(() => {
      console.log(1);
      resolve("A");
    }, 3);
  });
const p2 = () =>
  new Promise(resolve => {
    setTimeout(() => {
      console.log(2);
      resolve("B");
    }, 2);
  });
const p3 = () =>
  new Promise(resolve => {
    setTimeout(() => {
      console.log(3);
      resolve("C");
    }, 1);
  });

promiseFormation([p1, p2, p3]).then(rs => {
  console.log(rs);
  // 1
  // 2
  // 3
  // ["A", "B", "C"]
});