UNPKG

chimee-helper-utils

Version:
373 lines (345 loc) 12.5 kB
import _toConsumableArray from 'babel-runtime/helpers/toConsumableArray'; import _Promise from 'babel-runtime/core-js/promise'; import _Object$keys from 'babel-runtime/core-js/object/keys'; import _Array$from from 'babel-runtime/core-js/array/from'; import { isArray, isFunction } from 'toxic-predicate-functions'; // ********************** judgement ************************ /** * check if the code running in browser environment (not include worker env) * @returns {Boolean} */ var inBrowser = typeof window !== 'undefined' && Object.prototype.toString.call(window) !== '[object Object]'; // ********************** 对象操作 ************************ /** * 转变一个类数组对象为数组 */ function makeArray(obj) { return _Array$from(obj); } /** * sort Object attributes by function * and transfer them into array * @param {Object} obj Object form from numric * @param {Function} fn sort function * @return {Array} the sorted attirbutes array */ function transObjectAttrIntoArray(obj) { var fn = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : function (a, b) { return +a - +b; }; return _Object$keys(obj).sort(fn).reduce(function (order, key) { return order.concat(obj[key]); }, []); } /** * run a queue one by one.If include function reject or return false it will stop * @param {Array} queue the queue which we want to run one by one * @return {Promise} tell us whether a queue run finished */ function runRejectableQueue(queue) { for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { args[_key - 1] = arguments[_key]; } return new _Promise(function (resolve, reject) { var step = function step(index) { if (index >= queue.length) { resolve(); return; } var result = isFunction(queue[index]) ? queue[index].apply(queue, _toConsumableArray(args)) : queue[index]; if (result === false) return reject('stop'); return _Promise.resolve(result).then(function () { return step(index + 1); }).catch(function (err) { return reject(err || 'stop'); }); }; step(0); }); } /** * run a queue one by one.If include function return false it will stop * @param {Array} queue the queue which we want to run one by one * @return {boolean} tell the user if the queue run finished */ function runStoppableQueue(queue) { for (var _len2 = arguments.length, args = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) { args[_key2 - 1] = arguments[_key2]; } var step = function step(index) { if (index >= queue.length) { return true; } var result = isFunction(queue[index]) ? queue[index].apply(queue, _toConsumableArray(args)) : queue[index]; if (result === false) return false; return step(++index); }; return step(0); } function checkContinuation(uint8array, start, checkLength) { var array = uint8array; if (start + checkLength < array.length) { while (checkLength--) { if ((array[++start] & 0xC0) !== 0x80) { return false; } } return true; } return false; } // decodeUTF8 function decodeUTF8(uint8array) { var out = []; var input = uint8array; var i = 0; var length = uint8array.length; while (i < length) { if (input[i] < 0x80) { out.push(String.fromCharCode(input[i])); ++i; continue; } else if (input[i] < 0xC0) { // fallthrough } else if (input[i] < 0xE0) { if (checkContinuation(input, i, 1)) { var ucs4 = (input[i] & 0x1F) << 6 | input[i + 1] & 0x3F; if (ucs4 >= 0x80) { out.push(String.fromCharCode(ucs4 & 0xFFFF)); i += 2; continue; } } } else if (input[i] < 0xF0) { if (checkContinuation(input, i, 2)) { var _ucs = (input[i] & 0xF) << 12 | (input[i + 1] & 0x3F) << 6 | input[i + 2] & 0x3F; if (_ucs >= 0x800 && (_ucs & 0xF800) !== 0xD800) { out.push(String.fromCharCode(_ucs & 0xFFFF)); i += 3; continue; } } } else if (input[i] < 0xF8) { if (checkContinuation(input, i, 3)) { var _ucs2 = (input[i] & 0x7) << 18 | (input[i + 1] & 0x3F) << 12 | (input[i + 2] & 0x3F) << 6 | input[i + 3] & 0x3F; if (_ucs2 > 0x10000 && _ucs2 < 0x110000) { _ucs2 -= 0x10000; out.push(String.fromCharCode(_ucs2 >>> 10 | 0xD800)); out.push(String.fromCharCode(_ucs2 & 0x3FF | 0xDC00)); i += 4; continue; } } } out.push(String.fromCharCode(0xFFFD)); ++i; } return out.join(''); } function debounce(func, wait, immediate) { // immediate默认为false var timeout = void 0, args = void 0, context = void 0, timestamp = void 0, result = void 0; var later = function later() { // 当wait指定的时间间隔期间多次调用_.debounce返回的函数,则会不断更新timestamp的值,导致last < wait && last >= 0一直为true,从而不断启动新的计时器延时执行func var last = new Date() - timestamp; if (last < wait && last >= 0) { timeout = setTimeout(later, wait - last); } else { timeout = null; if (!immediate) { result = func.apply(context, args); if (!timeout) context = args = null; } } }; return function () { context = this; args = arguments; timestamp = new Date(); // 第一次调用该方法时,且immediate为true,则调用func函数 var callNow = immediate && !timeout; // 在wait指定的时间间隔内首次调用该方法,则启动计时器定时调用func函数 if (!timeout) timeout = setTimeout(later, wait); if (callNow) { result = func.apply(context, args); context = args = null; } return result; }; } /** * 函数节流(控制函数执行频率) * @param {Function} func 要节流控制的函数,必填 * @return {Number} wait 等待时长 * @return {Object} options { * leading<是否首次调用立即执行,否:则按wait设定等待到期后调用才执行>:false, * trailing<是否在调用并未到期时启用定时器,以保证一定执行>:true * } * @return {Object} cxt 上下文对象 * @return {Function} */ function throttle(func, wait, options, cxt) { /* options的默认值 * 表示首次调用返回值方法时,会马上调用func;否则仅会记录当前时刻,当第二次调用的时间间隔超过wait时,才调用func。 * options.leading = true; * 表示当调用方法时,未到达wait指定的时间间隔,则启动计时器延迟调用func函数,若后续在既未达到wait指定的时间间隔和func函数又未被调用的情况下调用返回值方法,则被调用请求将被丢弃。 * options.trailing = true; * 注意:当options.trailing = false时,效果与上面的简单实现效果相同 */ var context = void 0, args = void 0, result = void 0; var timeout = null; var previous = 0; if (!options) options = {}; var later = function later() { previous = options.leading === false ? 0 : new Date() - 0; timeout = null; result = func.apply(context, args); if (!timeout) context = args = null; }; wait = wait || 0; return function () { var now = new Date(); if (!previous && options.leading === false) previous = now; // 计算剩余时间 var remaining = wait - (now - previous); if (cxt) { context = cxt; } else { context = this; } args = arguments; // 当到达wait指定的时间间隔,则调用func函数 // 精彩之处:按理来说remaining <= 0已经足够证明已经到达wait的时间间隔,但这里还考虑到假如客户端修改了系统时间则马上执行func函数。 if (remaining <= 0 || remaining > wait) { // 由于setTimeout存在最小时间精度问题,因此会存在到达wait的时间间隔,但之前设置的setTimeout操作还没被执行,因此为保险起见,这里先清理setTimeout操作 if (timeout) { clearTimeout(timeout); timeout = null; } previous = now; result = func.apply(context, args); if (!timeout) context = args = null; } else if (!timeout && options.trailing !== false) { // options.trailing=true时,延时执行func函数 timeout = setTimeout(later, remaining); } return result; }; } // requestAnimationFrame var raf = inBrowser && (window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame || window.oRequestAnimationFrame) || function (cb) { return setTimeout(cb, 17); }; // cancelAnimationFrame var caf = inBrowser && (window.cancelAnimationFrame || window.mozCancelAnimationFrame || window.webkitCancelAnimationFrame || window.webkitCancelRequestAnimationFrame || window.msCancelAnimationFrame || window.oCancelAnimationFrame) || function (id) { clearTimeout(id); }; // 根据要求的位数,将9格式化为 09\009\0009... function strRepeat(num, bit) { var pBit = bit; num = '' + (num || ''); var numLen = num.length; bit = (bit || numLen) - numLen; var paddingStr = bit > 0 ? num.repeat ? '0'.repeat(bit) : new Array(bit + 1).join('0') : ''; return (paddingStr + num).slice(0, pBit); } // video 时间格式化 function formatTime(time) { var hh = Math.floor(time / 3600); time = Math.floor(time % 3600); var mm = strRepeat(Math.floor(time / 60), 2); time = Math.floor(time % 60); var ss = strRepeat(time, 2); return hh >= 1 ? hh + ':' + mm + ':' + ss : mm + ':' + ss; } /** * 追加样式代码到head的style标签,不存在则创建 * @param {String} cssText 样式文本 * @return {HTMLElement} */ function appendCSS(cssText) { var doc = document; var styleEl = doc.querySelector('style'); if (!styleEl) { styleEl = doc.createElement('style'); var header = doc.querySelector('head'); header && header.appendChild(styleEl); } styleEl.appendChild(doc.createTextNode(cssText)); return styleEl; } /** * 格式化日期对象为:年-月-日 时:分:秒.毫秒 * @param {Date} date Date日期对象 * @param {String} pattern 要输出的日期格式,默认:`yyyy-MM-dd hh:mm:ss.i` * @return {String} */ function formatDate() { var date = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : new Date(); var pattern = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'yyyy-MM-dd hh:mm:ss.i'; var year = date.getFullYear().toString(); var fields = { M: date.getMonth() + 1, d: date.getDate(), h: date.getHours(), m: date.getMinutes(), s: date.getSeconds(), i: date.getMilliseconds() }; pattern = pattern.replace(/(y+)/ig, function (_, yearPattern) { return year.substr(4 - Math.min(4, yearPattern.length)); }); var _loop = function _loop(i) { pattern = pattern.replace(new RegExp('(' + i + '+)', 'g'), function (_, pattStr) { return (fields[i] < 10 && pattStr.length > 1 ? '0' : '') + fields[i]; }); }; for (var i in fields) { _loop(i); } return pattern; } /** * 读取本地存储的值(不支持localStorage则降级到cookie) * @param {String} key 目标数据key * @return {String} */ function getLocalStorage(key) { try { return window.localStorage.getItem(key); } catch (e) { try { var regRt = document.cookie.match(new RegExp('(^| )' + key + '=([^;]*)(;|$)')); return isArray(regRt) ? unescape(regRt[2]) : ''; } catch (e) { return ''; } } } /** * 将指定key对应值写入本地存储(不支持localStorage则降级到cookie) * @param {String} key * @param {String} val * @return {String} */ function setLocalStorage(key, val) { try { window.localStorage.setItem(key, val); } catch (e) { var expires = new Date(); // 默认存储300天 expires.setTime(expires.getTime() + 24 * 3600 * 1000 * 300); try { document.cookie = key + '=' + escape(val) + ';expires=' + expires.toUTCString() + ';path=/;'; } catch (e) { console.error(e); } } } export { inBrowser, makeArray, transObjectAttrIntoArray, runRejectableQueue, runStoppableQueue, decodeUTF8, debounce, throttle, raf, caf, strRepeat, formatTime, appendCSS, formatDate, getLocalStorage, setLocalStorage };