/////////////////////////////////////////////////////////////////////////// // Copyright © 2014 - 2018 Esri. All Rights Reserved. // // Licensed under the Apache License Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. /////////////////////////////////////////////////////////////////////////// define([ 'dojo/on', 'dojo/_base/declare', 'dojo/promise/all', 'dojo/_base/lang', 'dojo/_base/html', 'dojo/_base/array', 'jimu/dijit/CheckBox', 'jimu/dijit/LayerChooserFromMap', 'jimu/LayerStructure' ], function(on, declare, all, lang, html, array, CheckBox, LayerChooserFromMap, LayerStructure) { var LayerChooser = declare([LayerChooserFromMap], { templateString:'
' + '
' + '' + '' + '${nls.noLayersTip}' + '
' + '
' + '' + '
' + '
', //constructor options: //multiple: false, //Can select multiple layers or a single layer. //onlyShowVisible: false, //optional //updateWhenLayerInfosIsShowInMapChanged: false, //optional map: null, //optional layerStateController: null, //optional layerState: null, //optional customFilter: null, //optional onlySelectLeafLayer: false, //optional displayLayerTypeIcon: true, //optional showTables: true, //optional viewMode: false, //optional onlyShowWebMapLayers: false, //optional //public methods: //getSelectedItems //events: //tree-click //update layerStructure: null, _layerDatas: null, _eventHandles: null, postMixInProperties:function(){ this.nls = window.jimuNls.basicLayerChooserFromMap; }, postCreate: function() { //this.inherited(arguments); html.addClass(this.domNode, 'jimu-basic-layer-chooser-from-map'); html.addClass(this.domNode, 'jimu-basic-layer-chooser-from-map-lite'); /* this.shelter = new LoadingIndicator({hidden:true}); this.shelter.placeAt(this.domNode); this.shelter.startup(); */ // init properties this._layerDatas = {}; this._eventHandles = []; // init layerStructure if(this.map){ this.layerStructure = LayerStructure.createInstance(this.map); } else { this.layerStructure = LayerStructure.getInstance(); } this.layerInfosObj = this.layerStructure._layerInfos; // clear layer state this.layerState = this._clearLayerState(this.layerState) || {}; /* this.own(on(this.layerStructure, LayerStructure.EVENT_STRUCTURE_CHANGE, lang.hitch(this, this._onLayerInfosChanged))); if(this.updateWhenLayerInfosIsShowInMapChanged) { this.own(on(this.layerStructure, LayerStructure.EVENT_VISIBILITY_CHANGE, lang.hitch(this, this._onLayerInfosIsShowInMapChanged))); } */ // init layerStateController if(!this.layerStateController) { this.layerStateController = new LayerChooser.LayerStateController(); } // init filter var filter; if(this.customFilter) { filter = lang.hitch(this, this.customFilter); } else { filter = lang.hitch(this, this.filter); } this.filter = LayerChooserFromMap.andCombineFilters([this.basicFilter, filter]); // create tree this._createTree(); }, _createTree: function() { var layerNodes, tableNodes; if(this.onlyShowWebMapLayers) { layerNodes = this.layerStructure.getWebmapLayerNodes(); tableNodes = this.layerStructure.getWebmapTableNodes(); } else { layerNodes = this.layerStructure.getLayerNodes(); tableNodes = this.layerStructure.getTableNodes(); } var createdCount = this._createLayerNodes(layerNodes.concat(this.showTables ? tableNodes : []), this.treeUl); if(createdCount > 0) { html.setStyle(this.errorTipSection, 'display', 'none'); this.layerStateController.restoreState(this.layerState, this.layerStructure); } }, _createLayerNodes: function(layerNodes, nodeUl) { var filterDefs = array.map(layerNodes, function(layerNode) { return this.filter(layerNode._layerInfo); }, this); var createdCount = 0; all(filterDefs).then(lang.hitch(this, function(results) { array.forEach(results, function(isPass, index) { if(isPass) { this._createLayerNode(layerNodes[index], nodeUl); createdCount++; } }, this); })); return createdCount; }, _createLayerNode: function(layerNode, nodeUl) { var handle; var layerNodeLi = html.create('li', { 'class': 'tree-node-li', 'id': 'layerchooserlite-tree-node-li-' + layerNode.id //'style': 'display:none' }, nodeUl); var layerNodeDiv = html.create('div', { 'class': 'tree-node-div' }, layerNodeLi); var collapseSpan = html.create('span', { 'class': 'tree-node-column-span collapse-span' }, layerNodeDiv); var checkBoxSpan = html.create('span', { 'class': 'tree-node-column-span check-box-span' }, layerNodeDiv); var checkBoxDiv = html.create('div', { 'class': 'tree-node-column-div check-box-div' }, checkBoxSpan); var displayIconClass = this.displayLayerTypeIcon ? "display" : ""; var iconSpan = html.create('span', { 'class': 'tree-node-column-span icon-span ' + displayIconClass }, layerNodeDiv); /* var iconDiv = html.create('div', { 'class': 'tree-node-column-div icon-div', 'style': iconSpanStyle }, iconSpan); */ // restore layer state var state; var oldState = this.layerState[layerNode.id]; if(oldState) { state = oldState.selected; } else { state = this.layerStateController.getState(layerNode); } var checkBox = new CheckBox({ 'checked': state }, checkBoxDiv); var titleSpan = html.create('span', { 'class': 'tree-node-column-span title-span', 'innerHTML': layerNode.title }, layerNodeDiv); // create subLayerNode ul var subLayerNodeUl = html.create('ul', { 'class': 'tree-ul tree-subnode-ul', 'style': 'display:none; ' }, layerNodeLi); var layerData = { layerNode: layerNode, layerNodeLi: layerNodeLi, layerNodeDiv: layerNodeDiv, collapseSpan: collapseSpan, iconSpan: iconSpan, checkBox: checkBox, subLayerNodeUl: subLayerNodeUl, hasBeenOpened: false }; this._layerDatas[layerNode.id] = layerData; if(!layerNode.isLeaf()) { html.addClass(collapseSpan, 'is-leaf'); html.addClass(titleSpan, 'is-leaf'); handle = on(collapseSpan, 'click', lang.hitch(this, this._onCollapse, layerData)); this._eventHandles.push(handle); handle = on(titleSpan, 'click', lang.hitch(this, this._onCollapse, layerData)); this._eventHandles.push(handle); if(this.onlySelectLeafLayer) { checkBox.setStatus(false); html.setStyle(checkBoxDiv, 'display', 'none'); } } if(this.viewMode === true) { checkBox.setStatus(false); } //this.own(on(checkBox, 'change', lang.hitch(this, this._onCheckBoxChange, layerData))); handle = on(checkBox.domNode, 'click', lang.hitch(this, this._onCheckBoxChange, layerData)); this._eventHandles.push(handle); this._setIconImage(layerData, false); return layerData; }, _setIconImage: function(layerData, opened) { if(!this.displayLayerTypeIcon) { return; } var layerNode = layerData.layerNode; var layerTypeDef = layerNode.getLayerType(); var layerObjectDef = layerNode.getLayerObject(); all({ layerType: layerTypeDef, layerObject: layerObjectDef }).then(lang.hitch(this, function(result) { var item; if(result.layerType && result.layerObject) { item = { type: result.layerType, layerInfo: layerNode._layerInfo }; var baseUrl = window.location.protocol + "//" + window.location.host + require.toUrl("jimu"); var imageName = this._getIconImageName(item, opened); if (imageName) { var backgroundImageUrl = "url(" + baseUrl + "/css/images/" + imageName + ")"; html.setStyle(layerData.iconSpan, 'background-image', backgroundImageUrl); } } })); }, _getCheckBoxValue: function(checkBox) { return checkBox.getStatus() ? checkBox.getValue() : false; }, _clearLayerState: function(layerState) { var newLayerState = {}; if(layerState) { this.layerStructure.traversal(lang.hitch(this, function(layerNode) { if(layerState[layerNode.id]) { newLayerState[layerNode.id] = { selected: layerState[layerNode.id].selected }; } })); } return newLayerState; }, _selectOrDeselectLayer: function(layerId, isSelect) { var layerData = this._layerDatas[layerId]; if(layerData) { layerData.checkBox.setValue(isSelect); this._onCheckBoxChange(layerData); } }, selectLayer: function(layerId) { this._selectOrDeselectLayer(layerId, true); }, deselectLayer: function(layerId) { this._selectOrDeselectLayer(layerId, false); }, // layerState: { // id: { // selected: true/false // } // } getState: function() { var layerState = lang.clone(this.layerState); for (var id in this._layerDatas) { if(this._layerDatas.hasOwnProperty(id) && (typeof this._layerDatas[id] !== 'function')) { var layerData = this._layerDatas[id]; var checkBox = layerData.checkBox; if(this._getCheckBoxValue(checkBox)) { layerState[id] = {selected: true}; } else { layerState[id] = {selected: false}; } } } return layerState; }, // layerState: { // id: { // selected: true/false // } // } restoreState: function(layerState) { this.layerState = this._clearLayerState(layerState); for (var id in this._layerDatas) { if(this._layerDatas.hasOwnProperty(id) && (typeof this._layerDatas[id] !== 'function')) { var layerData = this._layerDatas[id]; var checkBox = layerData && layerData.checkBox; var state = this.layerState[id]; if(state) { checkBox.setValue(state.selected); } else { checkBox.setValue(this.layerStateController.getState(layerData.layerNode)); } } } this.layerStateController.restoreState(this.layerState, this.layerStructure); }, setViewMode: function(viewMode) { for (var id in this._layerDatas) { if(this._layerDatas.hasOwnProperty(id) && (typeof this._layerDatas[id] !== 'function')) { var layerData = this._layerDatas[id]; var checkBox = layerData && layerData.checkBox; if(viewMode === true) { this.viewMode = true; checkBox.setStatus(false); } else { this.viewMode = false; checkBox.setStatus(true); } } } }, getSelectedLayerNodes: function() { // some selected layers may have not been loaded. var selectedLayerNodes = []; var layerState = this.getState(); for (var id in layerState) { if(layerState.hasOwnProperty(id) && (typeof layerState[id] !== 'function')) { if(layerState[id].selected) { var layerNode = this.layerStructure.getNodeById(id); if(layerNode) { selectedLayerNodes.push(layerNode); } } } } return selectedLayerNodes; }, getLoadedLayerNodes: function() { var loadedLayerNodes = []; for(var id in this._layerDatas) { if(this._layerDatas.hasOwnProperty(id) && (typeof this._layerDatas[id] !== 'function')) { var layerNode = this.layerStructure.getNodeById(id); if(layerNode) { loadedLayerNodes.push(layerNode); } } } return loadedLayerNodes; }, getLayerAssociateDomNodesById: function(layerId) { var domNodes = null; var layerData = this._layerDatas[layerId]; if(layerData) { domNodes = { collapseIcon: layerData.collapseSpan, checkBox: layerData.checkBox.domNode, layerTypeIcon: layerData.iconSpan }; } return domNodes; }, //compatible with the LayerChooserFromMap //return an array, each element has 'name', 'url' and 'layerInfo' attribute getSelectedItems: function(){ var handledItems = []; handledItems = array.map(this.getSelectedLayerNodes(), function(layerNode) { return { name: layerNode.title, url: layerNode.getUrl(), layerInfo: layerNode._layerInfo }; }, this); return handledItems; }, //compatible with the LayerChooserFromMap //return an array, each element has 'name', 'url' and 'layerInfo' attribute getAllItems: function(){ var handledItems = []; return handledItems; }, _clear:function(){ // clear this._layerDatas this._layerDatas = {}; // clear this._eventHandles array.forEach(this._eventHandles, function(eventHandle) { eventHandle.remove(); }, this); this._eventHandles = []; // clear tree html.empty(this.treeUl); }, destroy: function(){ this._clear(); if(this.map) { this.layerStructure.destroy(); } if(this.shelter){ this.shelter.destroy(); this.shelter = null; } this.inherited(arguments); }, /***************************** * Events *****************************/ _onCollapse: function(layerData) { var displayOfSubLayerUl = html.getStyle(layerData.subLayerNodeUl, 'display'); var collapsed = (displayOfSubLayerUl === "none") ? true : false; if(collapsed) { html.setStyle(layerData.subLayerNodeUl, 'display', 'block'); html.addClass(layerData.collapseSpan, 'opened'); } else { html.setStyle(layerData.subLayerNodeUl, 'display', 'none'); html.removeClass(layerData.collapseSpan, 'opened'); } this._setIconImage(layerData, collapsed); if(!layerData.hasBeenOpened) { this._createLayerNodes(layerData.layerNode.getSubNodes(), layerData.subLayerNodeUl); layerData.hasBeenOpened = true; } }, _onCheckBoxChange: function(layerData, evt) { this.layerStateController.setState(layerData.layerNode, this._getCheckBoxValue(layerData.checkBox)); this.emit('selection-change', layerData.layerNode, this._getCheckBoxValue(layerData.checkBox)); this._onTreeClick(layerData, evt); }, _onLayerInfosChanged: function() { /*jshint unused: false*/ // need to filter the layer. this._createTree(); this.emit('update'); }, _onLayerInfosIsShowInMapChanged: function(){ /*jshint unused: false*/ // need to filter the layer. this._createTree(); this.emit('update'); }, //to be override //send 'tree-click' event for compatible with the LayerChooserFromMap _onTreeClick: function(layerData, evt){ /*jshint unused: false*/ var item = { name: layerData.layerNode.title || "", parent: null, layerInfo: layerData.layerNode._layerInfo, type: null, layerClass: null, id: null, isLeaf: layerData.layerNode.isLeaf(), hasChildren: layerData.layerNode.isLeaf() ? false : true }; this.emit('tree-click', item, null, evt); } }); LayerChooser.LayerStateController = declare(null, { // get state for single layer getState: function(layerNode) { /*jshint unused: false*/ return true; }, // set state for single layer setState: function(layerNode, selected) { /*jshint unused: false*/ return this; }, restoreState: function(layerState, layerStructure) { /*jshint unused: false*/ return this; } }); LayerChooser.LayerVisibilityStateController = declare(LayerChooser.LayerStateController, { getState: function(layerNode) { return layerNode.isToggledOn(); }, setState: function(layerNode, selected) { /*jshint unused: false*/ layerNode.toggle(); return this; }, restoreState: function(layerState, layerStructure) { var options = {layerOptions: {}}; for (var id in layerState) { if(layerState.hasOwnProperty(id) && (typeof layerState[id] !== 'function')) { var state = layerState[id]; options.layerOptions[id] = {visible: state.selected}; } } layerStructure.restoreState(options); return this; } }); LayerChooser.layerVisibilityStateController = new LayerChooser.LayerVisibilityStateController(); LayerChooser.LayerLegendStateController = declare(LayerChooser.LayerStateController, { getState: function(layerNode) { //return layerNode.isToggledOnLegendFromWebMap(); return layerNode.isShowLegend(); } }); LayerChooser.layerLegendStateController = new LayerChooser.LayerLegendStateController(); return LayerChooser; });