Viewing File: /usr/local/cpanel/base/sharedjs/chart_utilities.js

( function(window) {

    "use strict";

    var max_number_divisions = {
        1: 5,
        1.2: 4,
        1.5: 5,
        1.6: 4,
        2: 5,
        2.5: 5,
        3: 3,
        4: 4,
        5: 5,
        6: 3,
        8: 4,
        9: 3
    };

    // Lex sort works out here the same as a numeric sort.
    var max_numbers = Object.keys(max_number_divisions).sort().map(Number);

    // We can’t rely on D3.js to give us “pretty” tick numbers because
    // LOCALE.format_bytes() uses powers of 1,024 rather than powers of 10
    // to format the numbers. (Heh, that is, as long as the number it’s
    // formatting isn’t itself under 1,024!)
    //
    // For example, if we depended on D3.js, we’d get stuff like:
    //
    // [ "0 bytes", "97,66 KB", "195,31 KB", "292,97 KB", "390,63 KB" ]
    //
    // ...rather than the “friendlier”:
    //
    // [ "0 bytes", "100 KB", "200 KB", "300 KB", "400 KB" ]
    //
    // This function, then, “second guesses” format_bytes() in order
    // to arrive at numbers that will look logical visually on the graph
    // when run through format_bytes().
    //
    function get_tick_values_for_format_bytes(highest_datum) {

        var ticks = [0];

        // No such thing as fractional bytes, so just return
        if (highest_datum < 3) {
            ticks.push(1);
            if (highest_datum > 1) {
                ticks.push(2);
            }
        } else {
            var max_tick;

            var binary_power = 0;  // gets incremented right away

            // base_max_number refers to the “reduced” numbers in the
            // max_number_divisions hash above.
            var base_max_number, binary_multiple, decimal_multiple;

            // At this point we know that at least the top tick will
            // need to be a multiple of 1,024. The trick is that, while
            // looping through powers of 1,024, we still need to check powers
            // of 10.
            TICK_LOOP:
            while (!max_tick) {

                // e.g., whatever byte total counts as 1 of the unit that
                // corresponds with the power of 1,024 that we’re on.
                binary_multiple = Math.pow( 1024, binary_power );

                // NOTE: There is only one special case that allows dec === 3.
                // See below.
                for (var dec = 0; dec <= 3; dec++ ) {
                    decimal_multiple = Math.pow( 10, dec );

                    var multiple = binary_multiple * decimal_multiple;
                    for (var m = 0; m < max_numbers.length; m++) {
                        base_max_number = max_numbers[m];

                        var maybe_max_tick = multiple * base_max_number;

                        // The only case where we actually allow 3 as a decimal
                        // power is the number 1,000.
                        if ((dec === 3) && (maybe_max_tick !== 1000)) {
                            continue;
                        }

                        if ( maybe_max_tick >= highest_datum) {
                            max_tick = maybe_max_tick;
                            break TICK_LOOP;
                        }
                    }
                }

                binary_power++;
                if (binary_power > 10) {
                    throw "Excessive power of 1,024: " + binary_power;
                }
            }

            var tick_count = max_number_divisions[base_max_number];

            var base_tick_interval = base_max_number / tick_count;

            // i.e., the number that will display
            var format_bytes_number = max_tick / binary_multiple;

            for (var t = 1; t < tick_count; t++) {
                var new_tick;

                // Normally we can just add new ticks in simple arithmetic
                // intervals, and everything is fine. If we just stopped there,
                // though, we’d get stuff like:
                //
                // [ "0 bytes", "307.2 KB", "614.4 KB", "921.6 KB", "1.2 MB" ]
                //
                // To guard against this, for numbers over 1,000 replace
                // anything that uses a lower unit than the max tick with the
                // equivalent modifier from the previous “level” of multiplier:
                // reduce the power of 1,024 by 1, then take that times 10^2
                // times whichever level of multiplier. The end goal is that
                // we want, e.g., instead of the above, something like:
                //
                // [ "0 bytes", "300 KB", "600 KB", "900 KB", "1.2 MB" ]
                //
                if ((format_bytes_number < 10) && (max_tick > 1000) && ((t * base_tick_interval) < 1)) {
                    new_tick = t * base_tick_interval * 10 * 100 * Math.pow( 1024, binary_power - 1 );
                } else {

                    // The below *would* work but for JavaScript’s lossy algebra:
                    // new_tick = t * (base_max_number / tick_count) * decimal_multiple * binary_multiple;

                    // This gives the same result algebraically, and JavaScript won’t turn it
                    // into e.g., 89.999999999999.
                    new_tick = t * max_tick / tick_count;
                }
                ticks.push(new_tick);
            }

            ticks.push(max_tick);
        }

        return ticks;
    }

    window.Chart_Utilities = {
        get_tick_values_for_format_bytes: get_tick_values_for_format_bytes
    };

}(window) );
Back to Directory File Manager