UNPKG

@checksub_team/peaks_timeline

Version:

JavaScript UI component for displaying audio waveforms

434 lines (353 loc) 10.7 kB
/** * @file * * Some general utility functions. * * @module utils */ define([ 'uuid' ], function(UUID) { 'use strict'; if (typeof Number.isFinite !== 'function') { Number.isFinite = function isFinite(value) { if (typeof value !== 'number') { return false; } // Check for NaN and infinity // eslint-disable-next-line no-self-compare if (value !== value || value === Infinity || value === -Infinity) { return false; } return true; }; } function zeroPad(number) { return number < 10 ? '0' + number : number; } return { /** * Returns a formatted time string. * * @param {Number} time The time to be formatted, in seconds. * @param {Boolean} dropHundredths Don't display hundredths of a second if true. * @returns {String} */ formatTime: function(time, dropHundredths) { var result = []; time = this.roundTime(time); var hundredths = Math.round((time % 1) * 100); var seconds = Math.floor(time); var minutes = Math.floor(seconds / 60); var hours = Math.floor(minutes / 60); if (hours > 0) { result.push(hours); // Hours } result.push(minutes % 60); // Mins result.push(seconds % 60); // Seconds for (var i = 0; i < result.length; i++) { result[i] = zeroPad(result[i]); } result = result.join(':'); if (!dropHundredths) { result += '.' + zeroPad(hundredths); } return result; }, /** * Rounds the given value up to the nearest given multiple. * * @param {Number} value * @param {Number} multiple * @returns {Number} * * @example * roundUpToNearest(5.5, 3); // returns 6 * roundUpToNearest(141.0, 10); // returns 150 * roundUpToNearest(-5.5, 3); // returns -6 */ roundUpToNearest: function(value, multiple) { if (multiple === 0) { return 0; } var multiplier = 1; if (value < 0.0) { multiplier = -1; value = -value; } var roundedUp = Math.ceil(value); return multiplier * (((roundedUp + multiple - 1) / multiple) | 0) * multiple; }, roundUpToNearestPositive: function(value, multiple) { if (multiple === 0) { return 0; } var multiplier = 1; if (value < 0.0) { value = 0; } var roundedUp = Math.ceil(value); return multiplier * (((roundedUp + multiple - 1) / multiple) | 0) * multiple; }, clamp: function(value, min, max) { if (value < min) { return min; } else if (value > max) { return max; } else { return value; } }, extend: function(to, from) { for (var key in from) { if (this.objectHasProperty(from, key)) { to[key] = from[key]; } } return to; }, /** * Checks whether the given array contains values in ascending order. * * @param {Array<Number>} array The array to test * @returns {Boolean} */ isInAscendingOrder: function(array) { if (array.length === 0) { return true; } var value = array[0]; for (var i = 1; i < array.length; i++) { if (value >= array[i]) { return false; } value = array[i]; } return true; }, /** * Checks whether the given value is a boolean. * * @param {Boolean} value The value to test * @returns {Boolean} */ isBoolean: function(value) { return typeof value === 'boolean'; }, /** * Checks whether the given value is a number. * * @param {Number} value The value to test * @returns {Boolean} */ isNumber: function(value) { return typeof value === 'number'; }, /** * Checks whether the given value is an integer. * * @param {Number} value The value to test * @returns {Boolean} */ isInteger: function(value) { return typeof value === 'number' && Number.isInteger(value); }, /** * Checks whether the given value is a valid timestamp. * * @param {Number} value The value to test * @returns {Boolean} */ isValidTime: function(value) { return (typeof value === 'number') && Number.isFinite(value); }, /** * Checks whether the given value is a valid object. * * @param {Object|Array} value The value to test * @returns {Boolean} */ isObject: function(value) { return (value !== null) && (typeof value === 'object') && !Array.isArray(value); }, /** * Checks whether the given value is a valid string. * * @param {String} value The value to test * @returns {Boolean} */ isString: function(value) { return typeof value === 'string'; }, /** * Checks whether the given value is a valid ArrayBuffer. * * @param {ArrayBuffer} value The value to test * @returns {Boolean} */ isArrayBuffer: function(value) { return Object.prototype.toString.call(value).includes('ArrayBuffer'); }, /** * Checks whether the given value is null or undefined. * * @param {Object} value The value to test * @returns {Boolean} */ isNullOrUndefined: function(value) { return value === undefined || value === null; }, /** * Checks whether the given value is a function. * * @param {Function} value The value to test * @returns {Boolean} */ isFunction: function(value) { return typeof value === 'function'; }, /** * Checks whether the given value is a valid HTML element. * * @param {HTMLElement} value The value to test * @returns {Boolean} */ isHTMLElement: function(value) { return value instanceof HTMLElement; }, /** * Checks whether the given value is a valid CSS color. * * @param {String} value The value to test * @returns {Boolean} */ isValidColor: function(value) { var s = new Option().style; s.color = value; return s.color !== ''; }, isValidIndicatorType: function(value) { return ['volume', 'noVolume', 'visibility', 'noVisibility', 'default'].includes(value); }, objectHasProperty: function(object, field) { return Object.prototype.hasOwnProperty.call(object, field); }, roundTime: function(rawTime) { return parseFloat((Math.round(rawTime * 100) / 100).toFixed(2)); }, removeLineBreaks: function(rawText) { var text = rawText.replace(/(\r\n|\n|\r)/gm, ' '); return text.replace(/ +(?= )/g,''); }, createUuidv4: function() { return UUID.v4(); }, shadeColor: function(color, percent) { var R, G, B; if (color.length === 4) { R = parseInt(2 * color[1], 16); G = parseInt(2 * color[2], 16); B = parseInt(2 * color[3], 16); } else { R = parseInt(color.substring(1,3), 16); G = parseInt(color.substring(3,5), 16); B = parseInt(color.substring(5,7), 16); } R = Math.round(R * (100 + percent) / 100); G = Math.round(G * (100 + percent) / 100); B = Math.round(B * (100 + percent) / 100); R = (R < 255) ? R : 255; G = (G < 255) ? G : 255; B = (B < 255) ? B : 255; var RR = ((R.toString(16).length === 1) ? '0' + R.toString(16) : R.toString(16)); var GG = ((G.toString(16).length === 1) ? '0' + G.toString(16) : G.toString(16)); var BB = ((B.toString(16).length === 1) ? '0' + B.toString(16) : B.toString(16)); return '#' + RR + GG + BB; }, // ==================== Performance Utilities ==================== /** * Schedules work during browser idle time. * Falls back to setTimeout if requestIdleCallback is not available. * * @param {Function} callback Function to execute * @param {Object} options Options object with timeout property * @returns {Number} ID that can be used to cancel */ scheduleIdle: function(callback, options) { options = options || { timeout: 50 }; if (typeof window !== 'undefined' && window.requestIdleCallback) { return window.requestIdleCallback(callback, options); } return setTimeout(function() { callback({ didTimeout: true, timeRemaining: function() { return 0; } }); }, 0); }, /** * Cancels a scheduled idle callback. * * @param {Number} id The ID returned by scheduleIdle */ cancelIdle: function(id) { if (typeof window !== 'undefined' && window.cancelIdleCallback) { window.cancelIdleCallback(id); } else { clearTimeout(id); } }, /** * Creates a simple LRU (Least Recently Used) cache. * * @param {Number} maxSize Maximum number of items to cache * @returns {Object} Cache with get(), set(), has(), delete(), clear() methods */ createLRUCache: function(maxSize) { var cache = new Map(); maxSize = maxSize || 100; return { get: function(key) { if (!cache.has(key)) { return undefined; } // Move to end (most recently used) var value = cache.get(key); cache.delete(key); cache.set(key, value); return value; }, set: function(key, value) { if (cache.has(key)) { cache.delete(key); } else if (cache.size >= maxSize) { // Delete oldest (first) entry var firstKey = cache.keys().next().value; cache.delete(firstKey); } cache.set(key, value); }, has: function(key) { return cache.has(key); }, delete: function(key) { return cache.delete(key); }, clear: function() { cache.clear(); }, size: function() { return cache.size; } }; } }; });