util.js 7.7 KB
/*
 * ADOBE CONFIDENTIAL
 * __________________
 *
 *  Copyright 2015 Adobe Systems Incorporated
 *  All Rights Reserved.
 *
 * NOTICE:  All information contained herein is, and remains
 * the property of Adobe Systems Incorporated and its suppliers,
 * if any.  The intellectual and technical concepts contained
 * herein are proprietary to Adobe Systems Incorporated and its
 * suppliers and are protected by trade secret or copyright law.
 * Dissemination of this information or reproduction of this material
 * is strictly forbidden unless prior written permission is obtained
 * from Adobe Systems Incorporated.
 */

/**
 * @module screens/player/shared/util
 */
define('screens/player/shared/util', ['underscore'], function(_) {
    'use strict';

    var SAVE_CHARS = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';

    var Util = {

        /**
         * String array of units for digital information in metric form (multiples of 1000 bytes)
         */
        UNITS_DI_METRIC: [1000, 'bytes', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'],

        /**
         * String array of units for digital information in IEC form (multiples of 1024 bytes)
         */
        UNITS_DI_IEC: [1024, 'bytes', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'],

        makePath: function(path) {
            var segments = _.isArray(path) ? path : [].slice.call(arguments);
            var ret = '';
            for (var i = 0; i < segments.length; i++) {
                var s = segments[i];
                var l = s.length;
                if (l > 0) {
                    if (i > 0 && s.charAt(0) !== '/') {
                        ret += '/';
                    }
                    if (s.charAt(l - 1) === '/') {
                        ret += s.substring(0, l - 1);
                    } else {
                        ret += s;
                    }
                }
            }
            return ret;
        },

        makeId: function(path) {
            return path.replace(/\//g, '.').substring(1);
        },

        /**
         * Generates a random 32 char id.
         * @param {Number} [length=32] Length of the id
         * @param {String} [chars] character set to choose from
         *
         * @returns {String} the generated id
         */
        randomId: function(length, chars) {
            if (!length) {
                length = 32;
            }
            if (!chars) {
                chars = SAVE_CHARS;
            }
            var d = _.now();
            var result = '';
            while (length--) {
                result += chars[Math.round(d + Math.random() * chars.length) % chars.length];
            }
            return result;
        },

        /**
         * Formats the given value to best unit available.
         *
         * @param {Number} value The value to format
         * @param {Array} units Array of units. The first unit specifies the base.
         * @param {Number} decimals The number of decimals to show, if required.
         * @return {String} the formatted string.
         */
        formatUnit: function(value, units, decimals) {
            if (_.isUndefined(value)) {
                return 'NaN';
            }
            if (_.isUndefined(units)) {
                units = Util.UNITS_DI_IEC;
            }
            var sign = '';
            var base = units[0];
            var i = 1;
            if (value < 0) {
                value = -value;
                sign = '-';
            }
            while (value >= base && i < units.length - 1) {
                value /= base;
                i++;
            }
            return sign + value.toFixed(decimals) + ' ' + units[i];
        },

        /**
         * Removes the trailing slashes from the given string
         * @param {String} str the string
         * @returns {String} the sanitized string.
         */
        trimTrailingSlash: function(str) {
            var i = str.length - 1;
            while (i > 0 && str.charAt(i) === '/') {
                i--;
            }
            return str.substring(0, i + 1);
        },

        /**
         * Gets the value at path of object. If the resolved value is undefined, the defaultValue is used in its place.
         * Note: this is a very simple implementation that only supports dotted notation. this can be replaced with _.get(),
         * once we have updated to lodash v3.7.0
         *
         * @param {Object} object the object to query
         * @param {String} path The path of property to get.
         * @param {*} defaultValue The value returned for undefined resolved values.
         * @return {*} Returns the accumulated value.
         */
        get: function(object, path, defaultValue) {
            var segments = path.split('.');
            for (var i = 0; i < segments.length; i++) {
                var key = segments[i];
                if (_.isUndefined(object[key])) {
                    return defaultValue;
                }
                object = object[key];
            }
            return object;
        },

        /**
         * Sets the value at path of object. If a portion of path doesn’t exist, it’s created.
         * Note: this is a very simple implementation that only supports dotted notation. this can be replaced with _.set(),
         * once we have updated to lodash v3.7.0
         *
         * @param {Object} object The object to modify.
         * @param {String} path The path of the property to set.
         * @param {*} value The value to set
         * @return {*} Returns `object`
         */
        set: function(object, path, value) {
            var segments = path.split('.');
            var obj = object;
            for (var i = 0; i < segments.length - 1; i++) {
                var key = segments[i];
                if (obj[key]) {
                    obj = obj[key];
                } else {
                    obj = obj[key] = {};
                }
            }
            obj[segments[segments.length - 1]] = value;
            return object;
        },

        /**
         * Tries to parse the schedule text (later.js' text or cron syntax) and return the corresponding later#Schedule
         *
         * @param {Object} later        The later.js library
         * @param {String} scheduleText String containing later.js' text or cron syntax
         *
         * @returns {later#Schedule} The parsed later#Schedule or null if string could not be parsed
         */
        getSchedule: function(later, scheduleText) {
            if (!later || !scheduleText) {
                return null;
            }

            var schedule = later.parse.text(scheduleText);
            if (schedule.error !== -1) {
                schedule = later.parse.cron(scheduleText, true);
            }

            return schedule.error === -1 ? schedule : null;
        },

        /**
         * Gets the next scheduled occurence date from the specified schedule.
         *
         * @param  {Object}         later          The later.js library
         * @param  {later#Schedule} parsedSchedule The parsed schedule
         *
         * @return {Date} The next date that matches the schedule
         */
        getNextScheduleOccurance: function(later, parsedSchedule) {
            if (!later || !parsedSchedule) {
                return null;
            }

            var schedule = later.schedule(parsedSchedule);

            var next = schedule.next();
            // if we are in the same second than the schedule, the "next" will be now. While setTimeout will do the proper scheduling (i.e. not now),
            // we need to get the next of the next to have the correct date.
            if (schedule.isValid(new Date())) {
                next = schedule.next(2)[1];
            }
            return next;
        }
    };

    return Util;
});