Source: control2/container/SortedContainer.js

(function() {
    /**
     * @typedef {Help4.control2.container.Container.Params} Help4.control2.container.SortedContainer.Params
     * @property {string[]} [itemOrder = []] - default type of the hosted controls
     */

    /**
     * Will provide a sorted container with a predefined well-known item order
     * @augments Help4.control2.container.Container
     * @property {string[]} itemOrder - order of the container items
     */
    Help4.control2.container.SortedContainer = class extends Help4.control2.container.Container {
        /**
         * @override
         * @param {Help4.control2.container.SortedContainer.Params} [params]
         * @param {Help4.jscore.ControlBase.Params} [derived]
         */
        constructor(params, derived) {
            const {TYPES: T} = Help4.jscore.ControlBase;
            super(params, {
                params: {
                    // this defines the fixed order of all to-be-added items
                    // each item is identified by item.getOrder()
                    itemOrder: {type: T.array}
                },
                derived
            });
        }

        /**
         * adds controls in a sorted order
         * @param {Help4.control2.Control.Params} params - parameters for the to-be-created controls
         * @returns {?Help4.control2.Control|Array<?Help4.control2.Control>} the added control(s)
         */
        addSorted(...params) {
            const toAdd = params.length;
            const added = new Array(toAdd);
            for (const [index, item] of Help4.arrayEntries(params)) {
                added[index] = _addSorted.call(this, item);
            }
            return toAdd === 1 ? added[0] : added;
        }
    }

    /**
     * @memberof Help4.control2.container.SortedContainer#
     * @private
     * @param {Help4.control2.Control.Params} params
     * @returns {?Help4.control2.Control|Array<?Help4.control2.Control>}
     */
    function _addSorted(params) {
        const {itemOrder, _store} = this;
        const {_order: id} = params;
        const targetIndex = itemOrder.indexOf(id);
        if (targetIndex < 0) throw new Error(`SortedContainer: unable to add an unknown item "${id}"`);

        if (targetIndex === 0) {
            // simple, insert at front
            return this.insertAt(params, 0);
        } else if (targetIndex === itemOrder.length - 1) {
            // simple, insert at end
            return this.insertAt(params, targetIndex);
        }

        // predecessors and successors exist
        // attention: not all of them are already inserted
        const predecessors = itemOrder.slice(0, targetIndex);
        const successors = itemOrder.slice(targetIndex + 1);

        // this is the list of already inserted items
        const currentOrder = _store.map(control => control.getOrder());

        let position = 0;
        for (const [index, itemId] of Help4.arrayEntries(currentOrder)) {
            if (predecessors.indexOf(itemId) >= 0) {
                // insert position needs to be behind all predecessors
                position = index + 1;
                continue;
            }

            if (successors.indexOf(itemId) >= 0) {
                // the first available successor was found; insert before
                return this.insertAt(params, index);
            }
        }

        // no successor was found; insert behind last predecessor
        this.insertAt(params, position);
    }
})();