Reusable Accessible Mapping Platform

API Docs for: 5.0.0
Show:

File: src\js\RAMP\Modules\layerGroup.js

/* global define, tmpl, $, console */

/**
* @module RAMP
* @submodule FilterManager
* @main FilterManager
*/

/**
* 
* ####Imports RAMP Modules:
* {{#crossLink "TmplHelper"}}{{/crossLink}}  
* {{#crossLink "Array"}}{{/crossLink}}  
* {{#crossLink "LayerItem"}}{{/crossLink}}  
*  
* ####Uses RAMP Templates:
* {{#crossLink "templates/layer_selector_template.json"}}{{/crossLink}}
* 
* @class LayerGroup
* @constructor
* @uses dojo/Evented
* @uses dojo/_base/declare
* @uses dojo/_base/lang
* @uses dojo/_base/array
*
* @param {Array} layers an array of layer config definitions to be added to the group
* @param {Object} [options] Additional options
* 
* @param {String} [options.groupType] Specifies type of this LayerGroup and the name of the layer group template to use
* @param {String} [options.layerState] Specifies the initial state of any LyerItem added to this group; must be one of the `LayerItem.state` defaults
* @param {String} [options.layerType] Specifies type of any LayerItem added to this group and the name of the layer item template to use
* 
* @param {Object} [options.stateMatrix] additional state matrix records to be mixed into the default
* @param {Object} [options.transitionMatrix] additional state transition matrix records to be mixed into the default

*
* @return {LayerGroup} A control object representing a group of layers allowing to dynamically change their states.
*/

define([
    "dojo/Evented", "dojo/_base/declare", "dojo/_base/lang", "dojo/_base/array",

    /* Text */
    "dojo/text!./templates/layer_selector_template.json",

    /* Util */
    "utils/tmplHelper", "utils/array", "utils/dictionary",

    /* RAMP */
    "ramp/layerItem"
],
    function (
        Evented, declare, lang, dojoArray,
        layer_selector_template,
        TmplHelper, UtilArray, UtilDict,
        LayerItem) {
        "use strict";

        return declare([Evented], {
            constructor: function (layers, options) {
                var that = this;

                // declare individual properties inside the constructor: http://dojotoolkit.org/reference-guide/1.9/dojo/_base/declare.html#id6
                lang.mixin(this,
                    {
                        /**
                         * A node of the LayerGroup.
                         *
                         * @property node
                         * @type JObject
                         * @default null
                         */
                        node: null,

                        /**
                         * A node of the list in the LayerGroup.
                         *
                         * @property node
                         * @private
                         * @type JObject
                         * @default null
                         */
                        _listNode: null,

                        /**
                         * Templates to be used in construction of the layer nodes.
                         *
                         * @property templates
                         * @type Object
                         * @default layer_selector_template.json
                         */
                        templates: JSON.parse(TmplHelper.stringifyTemplate(layer_selector_template)),

                        /**
                         * Specifies type of this LayerGroup and the name of the layer group template to use; is set by `groupType` value;
                         *
                         * @property groupType
                         * @type String
                         * @default "layer_group"
                         */
                        groupType: "layer_group",

                        /**
                         * Specifies type of any LayerItem added to this group during initialization and the name of the layer item template to use; is set by `layerType` value;; can be overwritten when adding individual layers by `options.type`.
                         *
                         * @property type
                         * @type String
                         * @default null
                         */
                        layerType: null,

                        /**
                         * State of any LayerItem added to this group during its initialization; is set by `layerSate` value; can be overwritten when adding individual layers by `options.state`.
                         *
                         * @property state
                         * @type String
                         * @default LayerItem.state.DEFAULT
                         */
                        layerState: LayerItem.state.DEFAULT,

                        /**
                         * An array of layer config definitions to be added to the group during initialization; is set to `layers` value.
                         *
                         * @property layers
                         * @type Array
                         * @default []
                         */
                        layers: [],

                        /**
                         * An array of resulting LayerItem objects.
                         *
                         * @property layerItems
                         * @type Array
                         * @default []
                         */
                        layerItems: []
                    },
                    options,
                    {
                        layers: layers
                    }
                );

                // create group node from the template
                this.node = $(this._template(this.groupType));
                this._listNode = this.node.find("ul");

                console.debug(LayerItem.state);

                this.layers.forEach(function (layer) {
                    that.addLayerItem(layer);
                });
            },

            /**
             * Constructs and adds a LayerItem to the LayerGroup.
             *
             * @param {Object} layer config of the layer to be added
             * @param {Object} options additional options allowing for customization
             * @method addLayerItem
             * @return {Object} the item that was added
             */
            addLayerItem: function (layer, options) {
                var layerItem,
                    layerItemOptions = {
                        stateMatrix: this._constructStateMatrix(layer)
                    };

                lang.mixin(layerItemOptions,
                    {
                        state: this.layerState,
                        type: this.layerType
                    },
                    options
                );

                layerItem = new LayerItem(layer, layerItemOptions);

                this.layerItems.push(layerItem);
                this._listNode.prepend(layerItem.node);

                if (this.layerItems.length === 1) {
                    this.node.show();
                }

                return layerItem;
            },

            /**
             * Removes the specified LayerItem from the LayerGroup.
             *
             * @param {String} layerId id of the layer to be removed
             * @method removeLayerItem
             * @return {Object} this LayerGroup for chaining
             */
            removeLayerItem: function (layerId) {
                var layerItem = this.getLayerItem(layerId);

                // remove layerItem from DOM
                layerItem.node.remove();

                // remove layerItem from the list
                UtilArray.remove(this.layerItems, layerItem, function (l) {
                    return l.id === layerItem.id;
                });

                if (this.layerItems.length === 0) {
                    this.node.hide();
                }

                return this;
            },

            /**
             * Modifies the state matrix of the layer to accommodate types of layers that might not use/have all the default controls or have extra controls.
             *
             * @param {Object} layerConfig layer config
             * @method _constructStateMatrix
             * @private
             * @return {Object} modified layer state matrix
             */
            _constructStateMatrix: function (layerConfig) {
                var stateMatrix = lang.clone(LayerItem.stateMatrix);

                if (!layerConfig.settings.panelEnabled) {
                    this._removeStateMatrixPart(stateMatrix, "controls", LayerItem.controls.SETTINGS);
                }

                // remove bounding box toggle if there is no layer extent property - layer is a wms layer
                if (!layerConfig.layerExtent || layerConfig.isStatic) {
                    this._removeStateMatrixPart(stateMatrix, "toggles", LayerItem.toggles.BOX);
                    this._addStateMatrixPart(stateMatrix, "toggles", LayerItem.toggles.PLACEHOLDER);
                }

                return stateMatrix;
            },

            /**
             * Modifies the state matrix by adding specified partKey to the specified partType collection
             *
             * @param {Object} stateMatrix matrix to modify
             * @param {String} partType type of the parts to modify: `controls`, `toggles`, `notices`
             * @param {String} partKey part key to be inserted into the collection
             * @method _addStateMatrixPart
             * @private
             */
            _addStateMatrixPart: function (stateMatrix, partType, partKey) {
                UtilDict.forEachEntry(stateMatrix, function (state, data) {
                    data[partType].push(partKey);
                });
            },

            /**
             * Modifies the state matrix by removing specified partKey to the specified partType collection
             *
             * @param {Object} stateMatrix matrix to modify
             * @param {String} partType type of the parts to modify: `controls`, `toggles`, `notices`
             * @param {String} partKey part key to be removed into the collection
             * @method _addStateMatrixPart
             * @private
             */
            _removeStateMatrixPart: function (stateMatrix, partType, partKey) {
                UtilDict.forEachEntry(stateMatrix, function (state, data) {
                    UtilArray.remove(data[partType], partKey);
                });
            },

            /**
             * Constructs and adds a LayerItem to the LayerGroup.
             *
             * @param {String} layerId an id of the LayerItem to set the state on
             * @param {String} state state to be set; must be one of the `LayerItem.state` defaults
             * @param {Object} options additional options allowing for customization
             * @method setState
             */
            setState: function (layerId, state, options) {
                var layerItem = this.getLayerItem(layerId);

                if (layerItem) {
                    layerItem.setState(state, options);
                }
            },

            /**
             * Finds and returns a LayerItem object with the specified id. If none found, returns null.
             *
             * @param {String} layerId an id of the LayerItem to return
             * @return {LayerItem} a LayerItem with the specified id
             * @method getLayerItem
             */
            getLayerItem: function (layerId) {
                var layerItem;

                layerItem = UtilArray.find(this.layerItems, function (li) {
                    return li.id === layerId;
                });

                return layerItem;
            },

            /**
             * Populates a template specified by the key with the supplied data.
             *
             * @param {String} key template name
             * @param {Object} data data to be inserted into the template
             * @method _template
             * @private
             * @return {String} a string template filled with supplied data
             */
            _template: function (key, data) {
                tmpl.cache = {};
                tmpl.templates = this.templates;

                data = data || {};

                return tmpl(key, data);
            }
        });
    });