Source: widgets/SpwToc.js

Retour à la documentation
/**
 * @class spw.widgets.SpwToc
 */
define([
    "dojo/_base/declare", "spw/api/SpwBaseWidget", "spw/api/SpwBaseTemplatedWidget", "dojo/dnd/Source", "dojo/dom-construct",
    "dojo/dnd/common", "dojo/dom", "dojo/_base/lang", "dojo/query", "dijit/registry", "spw/api/ConfigLoader", "spw/api/StateManager", "dojo/Evented",
    "dojo/text!./templates/SpwTocItem.html", "dojo/text!./templates/SpwLayerItem.html", "dojo/_base/array", "dojo/aspect",
    "dojo/i18n!./nls/SpwToc", "spw/api/MapService", "dijit/form/HorizontalSlider", "dijit/form/HorizontalRule",
    "dijit/form/HorizontalRuleLabels", "dojo/dom-attr", "dijit/Dialog", "dojo/on", "spw/api/Utils",
    "spw/api/MapServiceFactory", "dijit/form/CheckBox"
], function (declare, SpwBaseWidget, SpwBaseTemplatedWidget, dndSource, domConstruct, dnd, dom, lang, query, registry,
             ConfigLoader, StateManager, Evented, SpwTocItemTmpl, SpwLayerItemTmpl, array, aspect, labels, MapService, HorizontalSlider,
             HorizontalRule, HorizontalRuleLabels, domAttr, Dialog, on, Utils, MapServiceFactory) {

    if (!Array.prototype.indexOf) {
        Array.prototype.indexOf = function (obj, start) {
            for (var i = (start || 0), j = this.length; i < j; i++) {
                if (this[i] === obj) {
                    return i;
                }
            }
            return -1;
        };
    }




    ///////////////////////////////////////////////////////////////////
    //////////////////////////////////////////////////////////////////
    ////////////////////////////SPW TOC//////////////////////////
    //////////////////////////////////////////////////////////////////
    //////////////////////////////////////////////////////////////////

    var SpwToc = null;
    SpwToc = declare("spw.widgets.SpwToc", [SpwBaseWidget], /** @lends spw.widgets.SpwToc.prototype */{

        /* START widget config */
        preselectedServices: [],
        emptyTocLabel: null,
        notEmptyTocLabel: null,
        widgetTitle: labels.widgetTitle,
        rejectedServiceIds: null,
        /* END widget config */

        labels: labels,
        _dndSource: null,
        _dndContainerDiv: null,
        tocItems: null,
        emptyTocLabelDiv: null,
        notEmptyTocLabelDiv: null,
        _originalTitle: null,
        dragAndDropEnable: true,

        /**
         * @constructs
         * @param config
         */
        constructor: function () {
            StateManager.getInstance().register(StateManager.MAP_SERVICES_ID,
                lang.hitch(this, this.getMapServicesState)
            );
            this["class"] = "spwTocContainer";
        },

        postMixInProperties: function () {
            this.inherited(arguments);
            this.tocItems = {};
            this._originalTitle = this.widgetTitle;
        },

        /**
         * Obtenir l'état des services sur base du catalogue
         * @returns {String} état des services du catalogue
         */
        getMapServicesState: function (opts) {
            opts = opts || [];

            var mapServices = this.spwViewer.get('spwMap').getMapServices({
                isBaseMap: false,
                inTOC: true
            });

            // on récupère tous les ids présents dans le catalog.json
            // pour savoir quels services il faut stocker en localstorage
            var catalog = ConfigLoader.getInstance().get('catalog');
            var idsInCatalog = [];

            array.forEach(catalog, lang.hitch(this, function (serviceGroup) {
                if (serviceGroup.code === 'ADDITIONAL_SERVICES') {
                    return;
                }

                var services = this.spwViewer.get('spwMap').getServicesFromGroup(serviceGroup);

                return array.forEach(services, lang.hitch(this, function (service) {
                    idsInCatalog.push(service.serviceId);
                }));
            }));

            var arrayOfCfg = [];
            var ko = false;

            array.forEach(mapServices, lang.hitch(this,
                function (mapService) {
                    var cfg = mapService.getServiceConfig();
                    var idx = -1;

                    // si présent dans le catalogue, pas besoin de stocker le tout dans le storage
                    if ((idx = idsInCatalog.indexOf(mapService.get('serviceId'))) >= 0) {
                        idsInCatalog.splice(idx, 1);
                        arrayOfCfg.push(cfg);
                    }
                    else if (cfg.url) {
                        arrayOfCfg.push(cfg);
                    }
                    else if (opts.full) {

                        if (opts.storage == null) {
                            arrayOfCfg.push(cfg);
                        }
                        else if (opts.storage === 'local') {
                            // store in localStorage + add to config
                            var guid = Utils.guid();

                            if (LocalStorageManager.instance().storeItem(guid, cfg)) {
                                arrayOfCfg.push({
                                    serviceId: guid,
                                    storage: 'local'
                                });
                            }
                            else {
                                ko = true;
                            }
                        }
                    }
                })
            );

            if (ko) {
                return null;
            }

            array.forEach(idsInCatalog, function (id) {
                arrayOfCfg.push({
                    serviceId: id,
                    deleted: true
                });
            });

            return JSON.stringify(arrayOfCfg);
        },

        postCreate: function () {
            this.inherited(arguments);
            this._dndContainerDiv = domConstruct.create("div", {}, this.domNode);

            var accept = "";
            if (this.dragAndDropEnable) {
                accept = "SpwTocItem";
            }

            this._dndSource = new dndSource(this._dndContainerDiv, {
                accept: accept,
                creator: lang.hitch(this, this.createDndAvatar),
                singular: true
            });
            this._dndSource.on("DropInternal", lang.hitch(this, this.reorderMapService));

            this.displayEmptyTocText(true);

            //Add toc item for MapService visible
            this.buildTocView(ConfigLoader.getInstance().get("catalog"));


            var spwMap = this.spwViewer.get('spwMap');
            this.own(
                this.MapServiceAddedHdl = spwMap.on(spwMap.events.MapServiceAdded, lang.hitch(this, this.onMapServiceAdded)),
                this.MapServiceRemovedHdl = spwMap.on(spwMap.events.MapServiceRemoved, lang.hitch(this, this.onMapServiceRemoved))
            );
            this.spwViewer.get("spwMap").on('MapCreated', lang.hitch(this, function(){
                var spwMap = this.spwViewer.get('spwMap');
                if(this.MapServiceAddedHdl){this.MapServiceAddedHdl.remove();}
                if(this.MapServiceRemovedHdl){this.MapServiceRemovedHdl.remove();}
                this.own(
                    this.MapServiceAddedHdl = spwMap.on(spwMap.events.MapServiceAdded, lang.hitch(this, this.onMapServiceAdded)),
                    this.MapServiceRemovedHdl = spwMap.on(spwMap.events.MapServiceRemoved, lang.hitch(this, this.onMapServiceRemoved))
                );
            }));
            this.spwViewer.get("spwMap").on('MapDestroyed', lang.hitch(this, function(){
                if(this.MapServiceAddedHdl){this.MapServiceAddedHdl.remove();}
                if(this.MapServiceRemovedHdl){this.MapServiceRemovedHdl.remove();}
            }));

            this.set('widgetTitle', this._originalTitle.replace("{NB_SELECTION}", this.get('tocItems').length));
        },

        buildTocView: function (catalogConfigs) {

            aspect.after(this, "addTocItem", lang.hitch(this, this.tocItemsChanged));
            aspect.after(this, "removeTocItem", lang.hitch(this, this.tocItemsChanged));

            this.setTOCState(StateManager.getInstance().getStateFromURL("TOC"));

            var services = [];
            array.forEach(catalogConfigs, lang.hitch(this, function (serviceGroup) {
                services = services.concat(this.getServicesFromGroup(serviceGroup));
            }));

            array.map(Utils.findInList(services, {toLoad: true}), lang.hitch(this, function (service) {
                for (var i = 0; i < this.preselectedServices.length; i++) {
                    var _service = this.preselectedServices[i];
                    var _serviceId = lang.isObject(_service) ? _service.serviceId : _service;
                    if (_serviceId == service.serviceId) {
                        if (lang.isObject(_service) && !StateManager.getInstance().getStateFromURL("MSS")) {
                            lang.mixin(service, _service);
                        }
                        return service;
                    }
                }
                this.addTocItem(service);
            }));

            var tocItemsPreselectedToAdd = Utils.findInList(this.preselectedServices, {});
            for (var i = tocItemsPreselectedToAdd.length - 1; i >= 0; i--) {
                var _service = tocItemsPreselectedToAdd[i];
                var _serviceId = lang.isObject(_service) ? _service.serviceId : _service;
                var service = Utils.findInList(services, {serviceId: _serviceId})[0];
                if (lang.isObject(_service) && !StateManager.getInstance().getStateFromURL("MSS")) {
                    lang.mixin(service, _service);
                }
                if (service && service.toLoad) {
                    this.addTocItem(service);
                }
            }

            //Synchronize map service order based on toc
            this.reorderMapService();

            StateManager.getInstance().register("TOC", lang.hitch(this, this.getTOCState));
        },

        setTOCState: function (TOCState) {
            var preselectedServicesMergedWithState = new Array();
            var TOCServiceOrder = TOCState ? TOCState.split(",") : [];
            if (TOCServiceOrder.length > 0) {
                array.forEach(TOCServiceOrder, lang.hitch(this, function (serviceId) {
                    serviceId = isNaN(serviceId) ? serviceId : parseInt(serviceId);
                    var found = false;
                    for (var i = 0; i < this.preselectedServices.length; i++) {
                        var _service = this.preselectedServices[i];
                        var _serviceId = lang.isObject(_service) ? _service.serviceId : _service;
                        if (_serviceId == serviceId) {
                            preselectedServicesMergedWithState.push(_service);
                            this.preselectedServices.splice(i, 1);
                            found = true;
                            break;
                        }
                    }

                    if (!found) {
                        preselectedServicesMergedWithState.push(serviceId);
                    }
                }));

                array.forEach(this.preselectedServices, lang.hitch(this, function (service) {
                    preselectedServicesMergedWithState.push(service);
                }));

                this.preselectedServices = preselectedServicesMergedWithState;
            }
        },

        getTOCState: function () {
            var TOCState = "";
            array.forEach(this._dndSource.getAllNodes(), lang.hitch(this, function (serviceNode) {
                TOCState += serviceNode.serviceId + ",";
            }));
            if (TOCState && TOCState.length > 0) {
                TOCState = TOCState.substring(0, TOCState.length - 1);
            }
            return TOCState;
        },

        getServicesFromGroup: function (serviceGroup) {
            var services = [];

            if (serviceGroup.mapServices) {
                services = services.concat(serviceGroup.mapServices);
            }
            if (serviceGroup.groups) {
                array.forEach(serviceGroup.groups, lang.hitch(this, function (group) {
                    services = services.concat(this.getServicesFromGroup(group));
                }));
            }
            return services;
        },

        isServicePreselected: function (serviceId) {
            for (var i = this.preselectedServices.length - 1; i >= 0; i--) {
                var _service = this.preselectedServices[i];
                var _serviceId = lang.isObject(_service) ? _service.serviceId : _service;
                if (_serviceId == serviceId) {
                    return true;
                }
            }
            return false;
        },

        tocItemsChanged: function () {
            if (this.emptyTocLabel && this.get('tocItems').length == 0) {
                this.displayEmptyTocText(true);
            } else {
                this.displayEmptyTocText(false);
            }

            if (this.notEmptyTocLabel && this.get('tocItems').length != 0) {
                this.displayNotEmptyTocText(true);
            } else {
                this.displayNotEmptyTocText(false);
            }
        },

        displayEmptyTocText: function (visible) {
            if (!this.emptyTocLabelDiv) {
                this.emptyTocLabelDiv = domConstruct.create("div", {
                    innerHTML: this.emptyTocLabel,
                    style: "display:" + visible ? "block" : "none"
                }, this.domNode);
            } else {
                this.emptyTocLabelDiv.style.display = visible ? "block" : "none";
            }
        },

        displayNotEmptyTocText: function (visible) {
            if (!this.notEmptyTocLabelDiv) {
                if (this.notEmptyTocLabelPosition && this.notEmptyTocLabelPosition == "top") {
                    this.notEmptyTocLabelDiv = domConstruct.create("div", {
                        innerHTML: this.notEmptyTocLabel ? this.notEmptyTocLabel : "",
                        style: "display:" + visible ? "block" : "none"
                    }, this.domNode, "first");
                }
                else {
                    this.notEmptyTocLabelDiv = domConstruct.create("div", {
                        innerHTML: this.notEmptyTocLabel ? this.notEmptyTocLabel : "",
                        style: "display:" + visible ? "block" : "none"
                    }, this.domNode, "last");
                }

            } else {
                this.notEmptyTocLabelDiv.style.display = visible ? "block" : "none";
            }
        },

        createDndAvatar: function (item, mode) {
            var tmp = domConstruct.create("div", {innerHTML: item});
            var textToShow = query(".spwTocItemLabelSpan", tmp)[0].innerHTML;

            var node = domConstruct.create("div", {id: dnd.getUniqueId()});
            domConstruct.create("div", {"class": "stateCanDrop", innerHTML: this.labels.dndValid}, node);
            domConstruct.create("div", {"class": "stateCannotDrop", innerHTML: this.labels.dndImpossible}, node);
            domConstruct.create("span", {innerHTML: textToShow, className: "dojoDndItem"}, node);

            return {node: node, data: item, type: ["SpwTocItem"]};
        },

        onMapServiceAdded: function (mapService) {
        	if(mapService.get('inTOC') === false) return;
            if (this.preselectedServices) {
                for (var i = 0; i < this.preselectedServices.length; i++) {
                    var _service = this.preselectedServices[i];
                    var _serviceId = lang.isObject(_service) ? _service.serviceId : _service;
                    if (_serviceId == mapService.get('serviceId')) {
                        if (lang.isObject(_service)) {
                            lang.mixin(mapService, _service);
                        }
                        break;
                    }
                }
            }

            if (!this.getTocItemById(mapService.get('serviceId'))) {
                this.addTocItem({
                    spwViewer: this.spwViewer,
                    serviceId: mapService.get('serviceId'),
                    mapService: mapService
                });

                //Synchronize map service order based on toc
                this.reorderMapService();
            }
        },

        onMapServiceRemoved: function (mapService) {
            if (this.getTocItemById(mapService.get('serviceId'))) {
                this.removeTocItem(mapService.get('serviceId'));
            }
        },

        isMapServiceAllowed: function (mapServiceId) {
            return !(this.rejectedServiceIds && this.rejectedServiceIds.indexOf(mapServiceId) > -1);
        },

        addTocItem: function (service) {
            if (this.isMapServiceAllowed(service.serviceId)) {
                lang.mixin(service, {
                    spwViewer: this.spwViewer,
                    labels: this.labels,
                    imagesPath: this.imagesPath,
                    spwToc: this
                });
                var spwTocItem = new this.SpwTocItem(service, domConstruct.create("div", {}, this._dndContainerDiv, "first"));
                spwTocItem.domNode["serviceId"] = service.serviceId;
                this.tocItems[service.serviceId] = spwTocItem;

                this.spwViewer.trackEvent('SpwToc', 'addTocItem', spwTocItem.get('label'));

                this.set('widgetTitle', this._originalTitle.replace("{NB_SELECTION}", this.get('tocItems').length));
                if (this._dndSource)
                    this._dndSource.startup();
                return spwTocItem;
            }
        },

        _setWidgetTitleAttr: function (value) {
            this.inherited(arguments);

            if (this.getParent && this.getParent() && this.getParent().title) {
                this.getParent().set('title', this.get('widgetTitle'));
            }
        },

        getTocItemById: function (serviceId) {
            return this.tocItems[serviceId];
        },

        _getTocItemsAttr: function () {
            var items = [];
            for (key in this.tocItems) {
                items.push(this.tocItems[key]);
            }
            return items;
        },

        removeTocItem: function (serviceId) {
            var tocItem = this.getTocItemById(serviceId);
            if (tocItem) {
                this.spwViewer.trackEvent('SpwToc', 'removeTocItem', tocItem.get('label'));

                delete this.tocItems[serviceId];
                tocItem.destroy();
                if (this._dndSource)
                    this._dndSource.startup();
                this.set('widgetTitle', this._originalTitle.replace("{NB_SELECTION}", this.get('tocItems').length));
            }
        },

        reorderMapService: function () {
            var sortedMapServicesId = new Array();
            array.forEach(this._dndSource.getAllNodes().reverse(), lang.hitch(this, function (serviceNode) {
                sortedMapServicesId.push(serviceNode.serviceId);
            }));
            this.spwViewer.get('spwMap').setAllMapServiceNotBaseMapOrder(sortedMapServicesId);
        },





        ///////////////////////////////////////////////////////////////////
        //////////////////////////////////////////////////////////////////
        ////////////////////////////SPW TOC ITEM//////////////////////////
        //////////////////////////////////////////////////////////////////
        //////////////////////////////////////////////////////////////////


        SpwTocItem: declare("spw.widgets.SpwTocItem", [SpwBaseTemplatedWidget, Evented], {
            templateString: SpwTocItemTmpl,

            /*START from Config : catalog.json*/
            serviceId: null,
            label: null,
            visible: false,
            alpha: 100,
            metadataUrl: null,
            changeVisibility: true,
            /*END from Config : catalog.json*/

            /*START from Config : widgets.json*/
            legendOpen: false,
            openLayersLegend: null,
            /*END from Config : widgets.json*/

            scaleTootltip: "",
            _mapService: null,
            mapExtentChangedHandler: null,
            layerItems: null,
            disabled: false,
            loadingImg: null,

            constructor: function (config, domNode) {
                this.inherited(arguments);

                if (config.mapService && config.mapService.declaredClass
                    && config.mapService.declaredClass == "spw.api.MapService") {
                    this._mapService = config.mapService;
                } else {
                    this._mapService = config.spwViewer.get('spwMap').getMapServiceById(config.serviceId);
                    if (!this._mapService) {
                        this._mapService = config.spwViewer.get('spwMap').addMapService(config);
                    }
                }
                this.serviceId = this._mapService.get('serviceId');
                this.label = this._mapService.get('label');
                this.visible = this._mapService.get('visible');
                this.alpha = this._mapService.get('alpha');
                this.changeVisibility = this._mapService.get('changeVisibility');
                if (this._mapService.get('metadataUrl')) {
                    this.metadataUrl = this._mapService.get('metadataUrl');
                }
                this.legendOpen = this._mapService.get('legendOpen');
                if (this._mapService.get('openLayersLegend')) {
                    this.openLayersLegend = this._mapService.get('openLayersLegend');
                } else {
                    this.openLayersLegend = [];
                }
                this.layerItems = [];
            },

            buildRendering: function () {
                this.inherited(arguments);

                if (this.metadataUrl == null) {
                    domConstruct.destroy(this.spwTocMetawalDiv);
                } else if (this._mapService.metadataPopup) {
                    domAttr.set(this.metawalLink, {href: "javascript:void(0);", target: "_self"});
                    this.own(
                        on(this.metawalLink, "click", lang.hitch(this, function () {
                            var width = this._mapService.metadataPopup.width != null ? this._mapService.metadataPopup.width : "750px";
                            var height = this._mapService.metadataPopup.height != null ? this._mapService.metadataPopup.height : "800px";
                            new Dialog({
                                title: this.labels.geodataInfo,
                                content: "<iframe width=" + width + " height=" + height + " src=" + this.metadataUrl + "></iframe>"
                            }).show();
                        }))
                    );
                }

                this.spwExpandTocLayers.style.display = "none";
                this.spwNoTocLayers.style.display = "block";
                this.loadingImg = domConstruct.create("img", {
                    src: this.imagesPath + "ajax-loader.gif",
                    style: 'margin:0 3px -2px 3px; width:16px; height:16px;',
                    title: this.labels.loading
                }, this.labelSpan, 'first');

                if (!this._mapService.get('loaded') && !this._mapService.get('inError')) {
                    if (this._mapService.get('type') != MapServiceFactory.types.TIMER) {
                        this.own(this._mapService.on(this._mapService.events.MapServiceLoaded, lang.hitch(this, this.displayLayers)));
                    } else {
                        this.own(this._mapService.on(this._mapService.events.MapServiceLoaded, lang.hitch(this, function () {
                            domConstruct.destroy(this.loadingImg);
                        })));
                    }
                    this.own(this._mapService.on(this._mapService.events.MapServiceError, lang.hitch(this, this.displayServiceError)));
                } else if (!this._mapService.get('inError')) {
                    this.displayLayers();
                } else {
                    this.displayServiceError(this._mapService.get('errorMessage'));
                }

                if (this._mapService.get('type') === MapServiceFactory.types.TIMER) {
                    if (this._mapService.get('areTimeLayerLoaded')) {
                        this.displayTimerSlider();
                    } else {
                        this._mapService.watch('areTimeLayerLoaded', lang.hitch(this, this.displayTimerSlider));
                    }
                }
            },

            postCreate: function () {
                this.inherited(arguments);
                if (this.legendOpen) {
                    this.expandLegendDiv();
                }
                var spwMap = this.spwViewer.get('spwMap');
                var esriLayer = this._mapService.get('layer');
                if (!this._mapService.get('added')) {
                    this._mapService.watch('added', lang.hitch(this, function () {
                        this.set('disabled', esriLayer.visibleAtMapScale);
                        this._displayScaleInfo(this._mapService.get('errorMessage'));
                    }));
                } else {
                    this.set('disabled', esriLayer.visibleAtMapScale);
                    this._displayScaleInfo(this._mapService.get('errorMessage'));
                }
                this.own(
                    this.mapExtentChangedHandler = spwMap.on(spwMap.events.MapExtentChanged, lang.hitch(this, function (extentEvent) {
                        this.set('disabled', esriLayer.visibleAtMapScale);
                        this.refreshLayers();
                    })),
                    spwMap.on(spwMap.events.MapServiceVisibilityChanged, lang.hitch(this, this.onMapServiceVisibilityChanged))
                );
                this.spwViewer.get("spwMap").on('MapCreated', lang.hitch(this, function(){
                    var spwMap = this.spwViewer.get('spwMap');
                    var esriLayer = this._mapService.get('layer');
                    setTimeout(lang.hitch(this, function(){
                        this.set('disabled', esriLayer.visibleAtMapScale);
                        this.refreshLayers();
                    }), 2000);
                    this.own(
                        this.mapExtentChangedHandler = spwMap.on(spwMap.events.MapExtentChanged, lang.hitch(this, function (extentEvent) {
                            this.set('disabled', esriLayer.visibleAtMapScale);
                            this.refreshLayers();
                        }))
                    );
                }));
                this.spwViewer.get("spwMap").on('MapDestroyed', lang.hitch(this, function(){
                    if(this.mapExtentChangedHandler){this.mapExtentChangedHandler.remove();}
                    if(this.MapServiceRemovedHdl){this.MapServiceRemovedHdl.remove();}
                }));

                this.spwTocSliderDiv.watch("value", lang.hitch(this, function () {
                    this.alphaChanged(this.spwTocSliderDiv.value);
                }));
            },

            onMapServiceVisibilityChanged: function(evt){
                if(evt.id == this._mapService.id){
                    if (evt.visible) {
                        this.visibleCheckbox.set('checked', true);
                        this.enableLayerItems();
                        this.refreshLayers();
                        this.visible = true;
                    } else {
                        this.visibleCheckbox.set('checked', false);
                        this.disableLayerItems();
                        this.visible = false;
                    }
                }
            },

            _setDisabledAttr: function (value) {
                if(this.domNode){
                    this.inherited(arguments);
                    this.spwTocSliderDiv.set('disabled', !value);

                    if (this.changeVisibility) {
                        this.visibleCheckbox.set('disabled', !value);
                    }
                    else {
                        this.visibleCheckbox.set('disabled', true);
                    }

                    if (!value || !this._mapService.get('visible')) {
                        this.disableLayerItems();
                    } else {
                        this.enableLayerItems();
                        this.refreshLayers();
                    }
                }
            },

            displayServiceError: function (error) {
                if (!this._mapService.get('loaded')) {
                    domConstruct.destroy(this.loadingImg);
                    domConstruct.create("img", {
                        src: this.imagesPath + "error.png",
                        style: 'margin:0 3px -2px 3px;'
                    }, this.labelSpan, 'first');
                    this._displayScaleInfo(error);
                }
            },

            displayTimerSlider: function () {
                if (this._mapService.get('hasLegend')) {
                    this.spwExpandTocLayers.style.display = "block";
                    this.spwNoTocLayers.style.display = "none";

                    sliderNode = domConstruct.create("div", {}, this.spwTocItemTreeDiv, "first");
                    this.spwTocItemTreeDiv.style.marginBottom = "16px";

                    var timerCount = this._mapService.get('timeLayers').length;
                    new HorizontalRule({
                        count: timerCount,
                        container: "bottomDecoration"
                    }, domConstruct.create("div", {}, sliderNode, "last"));

                    var labels = [];
                    array.forEach(this._mapService.get('timeLayers'), function (timeLayer) {
                        labels.push(timeLayer.ruleLabel);
                    });
                    new HorizontalRuleLabels({
                        count: timerCount,
                        container: "bottomDecoration",
                        labels: labels
                    }, domConstruct.create("div", {}, sliderNode, "last"));

                    var slider = new HorizontalSlider({
                        name: "slider",
                        value: 0,
                        minimum: 0,
                        maximum: 100,
                        discreteValues: 101,
                        intermediateChanges: true,
                        style: "width:100%;",
                        onChange: lang.hitch(this, function (value) {
                            this._mapService.setTime(value, (slider.get('maximum') - (slider.get('minimum'))));
                        })
                    }, sliderNode);
                } else {
                    this.spwExpandTocLayers.style.display = "none";
                    this.spwNoTocLayers.style.display = "none";
                }
            },

            displayLayers: function () {
                domConstruct.destroy(this.loadingImg);
                if (this._mapService.get('hasLegend')) {
                    this.spwExpandTocLayers.style.display = "block";
                    this.spwNoTocLayers.style.display = "none";

                    var layers = this._mapService.getParentMapServiceLayers();
                    for (var i = 0; i < layers.length; i++) {
                        var mapServiceLayer = this._mapService.getParentMapServiceLayers()[i];
                        this.layerItems.push(new SpwLayerItem({
                                mapServiceLayer: mapServiceLayer,
                                labels: this.labels,
                                openLayersLegend: this.openLayersLegend,
                                spwViewer: this.spwViewer,
                                mapService: mapServiceLayer.mapService
                            },
                            domConstruct.create("div", {}, this.spwTocItemTreeDiv, "last")));
                    }

                    if (!this._mapService.get('legendLoaded')) {
                        this._mapService.on(this._mapService.events.MapServiceLegendLoaded, lang.hitch(this, this.displayLayersLegend));
                    } else {
                        this.displayLayersLegend();
                    }
                    this.refreshLayers();

                    if (this.layerItems && this.layerItems.length == 1 && this.layerItems[0] && this.layerItems[0].subLayersItems && this.layerItems[0].subLayersItems.length == 0) {
                        this.layerItems[0].layerNameDiv.style.display = "none";

                        if (this.layerItems[0].subLayerItem) {
                            this.layerItems[0].subLayerItem.style.display = "block";
                        }
                    }
                } else {
                    this.spwExpandTocLayers.style.display = "none";
                    this.spwNoTocLayers.style.display = "block";
                }
            },

            refreshLayers: function () {
                if (this._mapService.get('visible')) {
                    var currentScale = this.spwViewer.get('spwMap').esriMap.getScale();
                    array.forEach(this.getAllLayersItem(this.layerItems), lang.hitch(this, function (layerItem) {
                        // if (layerItem.mapServiceLayer.maxScale != 0 && currentScale < layerItem.mapServiceLayer.maxScale) {
                        //     layerItem.set('disabled', true);
                        // }
                        // else {
                        //     if (layerItem.mapServiceLayer.minScale != 0 && currentScale > layerItem.mapServiceLayer.minScale) {
                        //         layerItem.set('disabled', true);
                        //     }
                        //     else {
                        //         layerItem.set('disabled', false);
                        //     }
                        // }
                        layerItem.set('disabled', !layerItem.mapServiceLayer.visibleAtCurrentScale());
                    }));
                }
            },

            getAllLayersItem: function (layersItem) {
                var layers = [];
                array.forEach(layersItem, lang.hitch(this, function (layerItem) {
                    layers.push(layerItem);
                    if (layerItem.subLayersItems && layerItem.subLayersItems.length > 0) {
                        layers = layers.concat(this.getAllLayersItem(layerItem.subLayersItems));
                    }
                }));
                return layers;
            },

            displayLayersLegend: function () {
                var layers = this._mapService.get('mapServiceLayers');
                for (var i = 0; i < layers.length; i++) {
                    var layerItem = this.getLayerItemById(layers[i].get('layerId'));
                    if (layerItem) {
                        layerItem.displayLegend();
                    }
                }
            },

            getLayerItemById: function (mapServiceLayerId) {
                var returnLayerItem = null;
                array.every(this.layerItems, lang.hitch(this, function (layerItem) {
                    var l = layerItem.getLayerItemById(mapServiceLayerId);
                    if (l) {
                        returnLayerItem = l;
                        return false;
                    }
                    return true;
                }));
                return returnLayerItem;
            },

            alphaChanged: function (value) {
                this._mapService.set('alpha', value);
            },

            alphaFixed: function () {
            },

            checkedChanged: function (checked) {
                if (checked) {
                    this._mapService.set('visible', true);
                    this.enableLayerItems();
                    this.refreshLayers();
                } else {
                    this._mapService.set('visible', false);
                    this.disableLayerItems();
                }
            },

            disableLayerItems: function () {
                array.forEach(this.layerItems, lang.hitch(this, function (layerItem) {
                    layerItem.set('disabled', true);
                }));
            },

            enableLayerItems: function () {
                array.forEach(this.layerItems, lang.hitch(this, function (layerItem) {
                    layerItem.set('disabled', false);
                }));
            },

            expandLegendDiv: function () {
                this.expendLayers.style.display = this.expendLayers.style.display == "none" ? "inline" : "none";
                this.collapseLayers.style.display = this.expendLayers.style.display == "none" ? "inline" : "none";
                this.spwTocItemTreeDiv.style.display = this.expendLayers.style.display == "none" ? "block" : "none";
            },

            _displayScaleInfo: function (error) {
                if(this.domNode){
                    var tt = "";
                    if (!this._mapService.get('inError')) {
                        var max = this._mapService.get('maxScale');
                        var min = this._mapService.get('minScale');
                        if (max == 0 && min == 0) {
                            //dataAllScales:"Cette donnée s'affiche quel que soit le niveau d'échelle."
                            tt = this.labels.dataAllScales;
                        } else if (max == 0 && min > 0) {
                            //dataFrom:"Cette donnée s'affiche uniquement en dessous du 1:MIN_SCALE."
                            tt = this.labels.dataFrom.replace("MIN_SCALE", min);
                        } else if (max > 0 && min == 0) {
                            //dataTo:"Cette donnée s'affiche uniquement au dessus du 1:MAX_SCALE."
                            tt = this.labels.dataTo.replace("MAX_SCALE", max);
                        } else if (max > 0 && min > 0) {
                            //dataFromTo:"Cette donnée s'affiche uniquement du 1:MIN_SCALE au 1:MAX_SCALE."
                            tt = this.labels.dataFromTo.replace("MIN_SCALE", min).replace("MAX_SCALE", max);
                        } else if (max == -1 && min == -1) {
                            //dataScaleNotAvailable:"Echelle non disponible."
                            tt = this.labels.dataScaleNotAvailable;
                        } else {
                            tt = this.labels.dataScaleError;
                        }
                    } else {
                        tt = error || this.labels.serviceUnavailable;
                    }
                    this.labelSpanRow.title = (tt && tt instanceof Object && "errorMessage" in tt) ? tt.errorMessage : tt;
                }
            }

        })
    });




    ///////////////////////////////////////////////////////////////////
    //////////////////////////////////////////////////////////////////
    ////////////////////////////SPW LAYER ITEM//////////////////////////
    //////////////////////////////////////////////////////////////////
    //////////////////////////////////////////////////////////////////

    var SpwLayerItem = null;
    SpwLayerItem = declare("spw.widgets.SpwLayerItem", [SpwBaseTemplatedWidget, Evented], {
        templateString: SpwLayerItemTmpl,

        mapServiceLayer: null,

        layerScaleInfo: null,
        visible: true,
        disabled: false,
        openLayersLegend: null,

        parentLayerItem: null,
        subLayersItems: null,

        constructor: function (config) {
            this.inherited(arguments);
            this.subLayersItems = [];
        },

        postMixInProperties: function () {
            this.inherited(arguments);
            this.layerScaleInfo = this._createLayerScaleInfo();
            this.visible = this.mapServiceLayer.get('defaultVisibility');
            this.disabled = this.parentLayerItem != null ? !this.parentLayerItem.get('disabled') : !this.mapServiceLayer.get('mapService').get('visible');
            if(this.spwViewer){
                var spwMap = this.spwViewer.get('spwMap');
                spwMap.on(spwMap.events.MapServiceVisibilityChanged, lang.hitch(this, this.onMapServiceLayerVisibilityChanged))
            }
        },

        onMapServiceLayerVisibilityChanged: function(evt){
            if(evt && evt.visibleLayersIds && evt.serviceId == this.mapServiceLayer.mapService.serviceId){
                if(evt.visibleLayersIds.indexOf(this.mapServiceLayer.layerId) == -1){
                    if(this.visibilityControl!=undefined) {
                        this.visibilityControl.set('checked', false);
                        this.set('visible', false);
                    }
                }
                else if(evt.serviceId == this.mapServiceLayer.mapService.serviceId){
                    if(this.visibilityControl!=undefined) {
                        this.visibilityControl.set('checked', true);
                        // this.visibilityControl.set('disabled', false);
                        this.set('visible', true);
                    }
                }
            }
        },

        _createLayerScaleInfo: function () {
            var max = this.mapServiceLayer.maxScale;
            var min = this.mapServiceLayer.minScale;

            if (max == 0 && min == 0) {
                //dataAllScales:"Cette donnée s'affiche quel que soit le niveau d'échelle."
                return this.labels.dataAllScales;
            } else if (max == 0 && min > 0) {
                //dataFrom:"Cette donnée s'affiche uniquement en dessous du 1:MIN_SCALE."
                return this.labels.dataFrom.replace("MIN_SCALE", min);
            } else if (max > 0 && min == 0) {
                //dataTo:"Cette donnée s'affiche uniquement au dessus du 1:MAX_SCALE."
                return this.labels.dataTo.replace("MAX_SCALE", max);
            } else if (max > 0 && min > 0) {
                //dataFromTo:"Cette donnée s'affiche uniquement du 1:MIN_SCALE au 1:MAX_SCALE."
                return this.labels.dataFromTo.replace("MIN_SCALE", min).replace("MAX_SCALE", max);
            } else {
                return this.labels.dataScaleError;
            }
        },

        buildRendering: function () {
            this.inherited(arguments);

            if (this.openLayersLegend.indexOf(this.mapServiceLayer.get('layerId')) > -1) {
                this.onClickTreeButton();
            }

            if (this.mapServiceLayer.get('subLayers').length > 0) {
                for (var i = 0; i < this.mapServiceLayer.get('subLayers').length; i++) {
                    var mapServiceLayer = this.mapServiceLayer.get('subLayers')[i];
                    this.subLayersItems.push(new SpwLayerItem({
                            mapServiceLayer: mapServiceLayer,
                            parentLayerItem: this,
                            labels: this.labels,
                            openLayersLegend: this.openLayersLegend,
                            spwViewer: this.spwViewer
                        },
                        domConstruct.create("div", {}, this.spwTocLayerSubLayersDiv, "last")));
                }
            } else {
                this.treeButton.style.visibility = "hidden";

                if (this.mapServiceLayer.get('clusterLayer') != null) {
                    this.clusterLayerImg.style.display = "inline";
                    if (this.mapServiceLayer.get('clusterLayer').visible) {
                        this.clusterLayerImg.src = this.imagesPath + "clusterlayer_remove_icon.png";
                    }
                }

                if (this.mapServiceLayer.get('heatLayer') != null) {
                    this.heatLayerImg.style.display = "inline";
                    if (this.mapServiceLayer.get('heatLayer').visible) {
                        this.heatLayerImg.src = this.imagesPath + "heatlayer_remove_icon.png";
                    }
                }
            }
        },

        postCreate: function () {
            this.inherited(arguments);
            if (this.mapServiceLayer.get('mapService').get('type') == MapServiceFactory.types.TILED) {
                this.visibilityControl.domNode.style.display = "none";
            }
        },

        _setVisibleAttr: function (visible) {
            this.visible = visible;
            this.visibilityControl.set('checked', visible);
            // if(visible && this.mapServiceLayer) {
            //     this.mapServiceLayer.show()
            // } else {
            //     this.mapServiceLayer.hide()
            // }
            // this.mapServiceLayer.set('visible', visible);
            array.forEach(this.subLayersItems, lang.hitch(this, function (subLayerItem) {
                subLayerItem.set('disabled', !visible);
            }));
        },

        _setDisabledAttr: function (disabled) {
            if(this.domNode){
                var parentDisabled = this.parentLayerItem != null ? this.parentLayerItem.get('disabled') : (this.mapServiceLayer != null && this.mapServiceLayer.get('disabled'));
                var parentVisible = this.parentLayerItem != null ? this.parentLayerItem.get('visible') : (this.mapServiceLayer != null && this.mapServiceLayer.get('mapService').get('visible'));

                var realDisabled = disabled ? disabled : (!this.get('mapServiceLayer').visibleAtCurrentScale() || parentDisabled || !parentVisible);

                this.disabled = realDisabled;
                this.visibilityControl.set('disabled', realDisabled);
                array.forEach(this.subLayersItems, lang.hitch(this, function (subLayerItem) {
                    subLayerItem.set('disabled', realDisabled);
                }));
            }
        },

        displayLegend: function () {
            if(this.treeButton){
                this.treeButton.style.visibility = "visible";
            }
            if(this.spwTocLayerLegendDiv){
                domConstruct.place(this.mapServiceLayer.generateHtmlLegend(), this.spwTocLayerLegendDiv, "only");
            }
        },

        getLayerItemById: function (layerId) {
            if (this.mapServiceLayer.get('layerId') == layerId) {
                return this;
            } else if (this.subLayersItems.length > 0) {
                var l = null;
                for (var i = 0; i < this.subLayersItems.length; i++) {
                    l = this.subLayersItems[i].getLayerItemById(layerId);
                    if (l) {
                        break;
                    }
                }
                return l;
            }
        },

        onClickTreeButton: function () {
            this.treeButton.src = this.treeButton.src.indexOf("Expanded") > -1 ?
                this.treeButton.src.replace("Expanded", "Collapsed") :
                this.treeButton.src.replace("Collapsed", "Expanded");
            this.subLayerItem.style.display = this.treeButton.src.indexOf("Expanded") > -1 ? "block" : "none";
        },

        onClickCheckbox: function () {
            this.set('visible', this.visibilityControl.get('checked'));
            if (this.visibilityControl.get('checked')) {
                this.mapServiceLayer.show();
                //this.mapServiceLayer.mapService.show();
                // this.mapServiceLayer.mapService.spwMap.getMapServiceById(this.mapServiceLayer.mapService.serviceId).mapServiceLayers[this.mapServiceLayer.layerId].show();
            } else {
                this.mapServiceLayer.hide();
                //this.mapServiceLayer.mapService.hide();
                // this.mapServiceLayer.mapService.spwMap.getMapServiceById(this.mapServiceLayer.mapService.serviceId).mapServiceLayers[this.mapServiceLayer.layerId].hide();
            }
        },

        onClickClusterLayerImg: function () {
            if (this.mapServiceLayer.get('clusterLayer') != null) {
                if (this.mapServiceLayer.get('clusterLayer').visible) {
                    this.mapServiceLayer.get('clusterLayer').hide();
                    this.clusterLayerImg.src = this.imagesPath + "clusterlayer_icon.png";
                }
                else {
                    this.mapServiceLayer.get('clusterLayer').show();
                    this.clusterLayerImg.src = this.imagesPath + "clusterlayer_remove_icon.png";
                }
            }
        },

        onClickHeatLayerImg: function () {
            if (this.mapServiceLayer.get('heatLayer') != null) {
                if (this.mapServiceLayer.get('heatLayer').visible) {
                    this.mapServiceLayer.get('heatLayer').hide();
                    this.heatLayerImg.src = this.imagesPath + "heatlayer_icon.png";
                }
                else {
                    this.mapServiceLayer.get('heatLayer').show();
                    this.heatLayerImg.src = this.imagesPath + "heatlayer_remove_icon.png";
                }
            }
        }

    });


    return SpwToc;
});