all files / src/ ordered-elements.js

100% Statements 33/33
95.45% Branches 21/22
100% Functions 8/8
100% Lines 33/33
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83                246× 246×       135×   172×         320× 294×     320×     316×     17×     17× 24×   17× 17×     299×     27×     27× 27× 35×   27× 27×     272×       18×       144×       99× 21× 23×     78× 78× 96×          
/* @flow */
const MAP_EXISTS = typeof Map !== 'undefined';
 
export default class OrderedElements {
    /* ::
    elements: {[string]: any};
    keyOrder: string[];
    */
 
    constructor() {
        this.elements = {};
        this.keyOrder = [];
    }
 
    forEach(callback /* : (string, any) => void */) {
        for (let i = 0; i < this.keyOrder.length; i++) {
            // (value, key) to match Map's API
            callback(this.elements[this.keyOrder[i]], this.keyOrder[i]);
        }
    }
 
    set(key /* : string */, value /* : any */) {
        if (!this.elements.hasOwnProperty(key)) {
            this.keyOrder.push(key);
        }
 
        if (value == null) {
            this.elements[key] = value;
            return;
        }
 
        if ((MAP_EXISTS && value instanceof Map) || value instanceof OrderedElements) {
            // We have found a nested Map, so we need to recurse so that all
            // of the nested objects and Maps are merged properly.
            const nested = this.elements.hasOwnProperty(key)
                ? this.elements[key]
                : new OrderedElements();
            value.forEach((value, key) => {
                nested.set(key, value);
            });
            this.elements[key] = nested;
            return;
        }
 
        if (!Array.isArray(value) && typeof value === 'object') {
            // We have found a nested object, so we need to recurse so that all
            // of the nested objects and Maps are merged properly.
            const nested = this.elements.hasOwnProperty(key)
                ? this.elements[key]
                : new OrderedElements();
            const keys = Object.keys(value);
            for (let i = 0; i < keys.length; i += 1) {
                nested.set(keys[i], value[keys[i]]);
            }
            this.elements[key] = nested;
            return;
        }
 
        this.elements[key] = value;
    }
 
    get(key /* : string */) /* : any */ {
        return this.elements[key];
    }
 
    has(key /* : string */) /* : boolean */ {
        return this.elements.hasOwnProperty(key);
    }
 
    addStyleType(styleType /* : any */) /* : void */ {
        if ((MAP_EXISTS && styleType instanceof Map) || styleType instanceof OrderedElements) {
            styleType.forEach((value, key) => {
                this.set(key, value);
            });
        } else {
            const keys = Object.keys(styleType);
            for (let i = 0; i < keys.length; i++) {
                this.set(keys[i], styleType[keys[i]]);
            }
        }
    }
}