Retour à la documentation
/**
* @class spw.widgets.SpwLegend
*/
define([
"dojo/_base/declare","spw/api/SpwBaseTemplatedWidget", "dojo/text!./templates/SpwLegend.html",
"dijit/form/CheckBox", "dojo/dom-construct", "dojo/_base/array", "dojo/_base/lang", "dojo/on",
"dojo/dom-style", "dojo/string", "dojo/store/Memory", "dijit/Tree", "dijit/tree/ObjectStoreModel",
"dojo/store/Observable", "dojo/text!./templates/CbTreeNode.html", "spw/api/Utils", "dojo/request/iframe",
"spw/api/ThreeStateCheckBox", "dojo/dom-class", "dojo/dom-geometry","dojo/promise/all", "dojo/Deferred",
"spw/api/MessageManager", "dojo/_base/config", "dojo/topic",
"dijit/TitlePane", "dijit/layout/BorderContainer", "dijit/layout/ContentPane"
],
function(declare, SpwBaseTemplatedWidget, tmpl, CheckBox, domConstruct, array, lang, on, domStyle, dojoString,
Memory, Tree, ObjectStoreModel, Observable, templateTreeNode, Utils, iframe, ThreeStateCheckBox, domClass,
domGeom, all, Deferred, MessageManager, dojoConfig, topic){
var SpwLegend = declare("spw.widgets.SpwLegend", [SpwBaseTemplatedWidget], /** @lends spw.widgets.SpwLegend.prototype */{
//@jsonSchema
jsonSchema: {
title:"Configuration spécifique",
type: "object",
description:"Ce widget permet d'afficher la légende des différents services visibles sur la carte.",
properties:{
showOnlyLegend:{
id: "showOnlyLegend",
title:"showOnlyLegend",
type: "boolean",
description:"Permet de cacher la partie choix des données et de n'afficher que la légende.",
required: false,
default: false
},
reportUrl: {
id: "reportUrl",
title: "reportUrl",
type: "string",
description: "URL du service de reporting permettant de générer un rapport contenant la légende sur base d'un template.",
default: "#js#dojo.config.geoviewerApiUrl + '/Report'",
required: true
},
noLegendText: {
title: "noLegendText",
type: "string",
description: "Texte affiché lorsqu'aucune légende ne peut être affichée.",
required: false,
default: "Aucune donnée visible dans « Ma sélection ». Ajoutez-y des données ou zoomez dans la carte pour faire apparaître la légende."
},
legendTitle: {
title: "legendTitle",
type: "string",
description: "Texte affiché comme titre du rapport.",
required: false,
default: "Légende"
}
}
},
widgetDocIgnoreProperties: ["legendTree", "dataTree", "storeLegend", "store", "zoomHandler", "selectedLayer", "selectedService"],
//@jsonSchema
templateString: tmpl,
selectedService: null,
selectedLayer: null,
showOnlyLegend: false,
legendTitle: 'Légende',
zoomHandler: null,
store: null,
storeLegend: null,
dataTree: null,
legendTree: null,
// "widgetTitle": "Légende",
// "position": "panel-light",
// // "helpContent": "http://geoportail.wallonie.be/aideWalOnMap",
// "iconClass": "legendIcon",
// "reportUrl": dojoConfig.geoviewerApiUrl + "/Report",
// "width": "400px",
// "height": "50vh",
// "right": "15px",
// "top": "85px",
// "resizable": true,
noLegendText: 'Aucune donnée visible dans « Ma sélection ». Ajoutez-y des données ou zoomez dans la carte pour faire apparaître la légende.',
/**
* @constructs
* @param config
*/
constructor: function (config) {
this.inherited(arguments);
},
postMixInProperties: function() {
this.inherited(arguments);
// pour être sûr que le titre ne contient pas de mauvais caractère pour le html (apostrophe, <, >...)
this.legendTitle = dojoString.substitute('${title}', {title: this.legendTitle}, dojoString.escape);
var spwMap = this.spwViewer.get('spwMap');
if (spwMap.loaded) {
var openLegend = this.spwViewer.get('spwMap').getMapServices({
isBaseMap: false,
openLayersLegend: true
});
this.activated = (openLegend != null && openLegend.length > 0);
}
else {
on.once(spwMap, spwMap.events.MapLoaded, lang.hitch(this, function() {
var openLegend = this.spwViewer.get('spwMap').getMapServices({
isBaseMap: false,
openLayersLegend: true
});
if (openLegend && openLegend.length > 0) {
this.onActivate();
}
}));
}
topic.subscribe('SPWBASEMAPCHOOSER_BASEMAP_CHANGED', lang.hitch(this, function(a) {
var newWkid = this.spwViewer.get('spwMap').get('esriMap').spatialReference.wkid;
if (this.activated && this._currentWkid != newWkid) {
this.onDeactivate();
setTimeout(lang.hitch(this, function() {
this.onActivate();
}), 500);
}
}))
},
updateSize: function() {
var size = domGeom.getMarginSize(this.domNode);
var botSize = domGeom.getMarginSize(this.formLegendDownload);
var titleSize = this.showOnlyLegend ? 28 : 28 * 2;
var totalH = size.h - botSize.h - titleSize; // total - bottom - titles
var bothOpened = !this.showOnlyLegend && this.dataChoiceNode && this.dataChoiceNode.open && this.titlePaneLegend && this.titlePaneLegend.open;
var realH = (bothOpened ? totalH / 2 : totalH);
if (this.dataChoiceNode && this.dataChoiceNode.containerNode) {
domStyle.set(this.dataChoiceNode.containerNode, 'height', realH + 'px');
}
if (this.titlePaneLegend && this.titlePaneLegend.containerNode) {
domStyle.set(this.titlePaneLegend.containerNode, 'height', realH + 'px');
}
},
resize: function() {
this.inherited(arguments);
this.updateSize();
},
postCreate: function() {
this.inherited(arguments);
if (this.showOnlyLegend) {
domClass.add(this.domNode, 'onlyLegend');
domStyle.set(this.dataChoiceNode.domNode, 'display', 'none');
}
this.own(
this.dataChoiceNode.watch('open', lang.hitch(this, this.updateSize)),
this.titlePaneLegend.watch('open', lang.hitch(this, this.updateSize)),
on(this.exportNode, 'click', lang.hitch(this, this.onExportClick))
);
},
onExportClick: function() {
MessageManager.getInstance().displayModalMessage("Nous préparons votre document<br>Cela peut prendre quelques secondes…");
if (this.storeLegend == null) {
return;
}
var data = [];
var store = this.storeLegend;
var sortLegendData = function(parent, level, datas){
var elems = array.filter(store.data, function(d){ return d.parent === parent.id; });
if(elems && elems.length > 0){
array.forEach(elems, function(e){
datas.push({
level: level,
label: (e.legend ? e.legend.label : (e.service == null ? e.layer.name : e.service.label)),
symbol: (e.legend ? (e.legend.url && e.legend.url.indexOf('http') > -1 ? e.legend.url : e.legend.imageData) : '')
});
sortLegendData(e, level + 1, datas);
});
}
};
var datas = [];
sortLegendData({id: 'root'}, 0, datas);
var defs = [];
array.forEach(datas, lang.hitch(this, function(d){
if(d.symbol && d.symbol.indexOf('http') > -1) {
var def = new Deferred(); defs.push(def);
var img = new Image();
img.crossOrigin = 'Anonymous';
img.onload = lang.hitch(this, function(){
var canvas = document.createElement('CANVAS'), ctx = canvas.getContext('2d'), dataURL;
canvas.height = img.height;
canvas.width = img.width;
ctx.drawImage(img, 0, 0);
dataURL = canvas.toDataURL('image/png');
d.symbol = Utils.getBase64dataFromUrl(dataURL);
canvas = null;
def.resolve();
});
img.src = this.spwViewer.get('proxyPageUrl') + '?' + d.symbol;
}
}));
all(defs).then(lang.hitch(this, function(e){
this.Data.value = JSON.stringify({Data: datas});
this.reportTitle.value = this.legendTitle.indexOf('Légende') > -1 ? '' : (domConstruct.create('textarea', {
innerHTML: this.legendTitle
}).innerHTML);
this.Properties.value = JSON.stringify({
header1: this.legendTitle
});
this.FileName.value = "rapport-" + new Date().toLocaleDateString().replace(/\//gim,'-').replace(/ /gim,'-');
this.Template.value = encodeURIComponent('defaultFileName:reportA4Portrait.jrxml');
this.formLegendDownload.action = this.reportUrl;
this.formLegendDownload.submit();
MessageManager.getInstance().hideModalMessage();
}));
},
onActivate: function(){
this.inherited(arguments);
this._currentWkid = this.spwViewer.get('spwMap').get('esriMap').spatialReference.wkid;
if (this.selectedService == null && this.selectedLayer == null && this.zoomHandler == null) {
var spwMap = this.spwViewer.get('spwMap');
this.own(
this.zoomHandler = on(spwMap, spwMap.events.MapZoomEnd, lang.hitch(this, this.buildLayerDomItems)),
this.serviceAddedHandler = on(spwMap, spwMap.events.MapServiceLoaded, lang.hitch(this, this.buildLayerDomItems)),
this.serviceRemovedHandler = on(spwMap, spwMap.events.MapServiceRemoved, lang.hitch(this, this.removeService)),
this.serviceRemovedHandler = on(spwMap, spwMap.events.MapServiceAddedToMap, lang.hitch(this, this.buildLayerDomItems)),
this.visibilityHandler = on(spwMap, spwMap.events.MapServiceVisibilityChanged, lang.hitch(this, this.buildLayerDomItems))
);
}
this.buildLayerDomItems();
},
onDeactivate: function() {
this.inherited(arguments);
if (this.zoomHandler) {
this.zoomHandler.remove();
this.zoomHandler = null;
}
if (this.visibilityHandler) {
this.visibilityHandler.remove();
this.visibilityHandler = null;
}
if (this.serviceAddedHandler) {
this.serviceAddedHandler.remove();
this.serviceAddedHandler = null;
}
if (this.serviceRemovedHandler) {
this.serviceRemovedHandler.remove();
this.serviceRemovedHandler = null;
}
},
removeService: function(service) {
if (this.store && this.storeLegend) {
this.removeItem(service.serviceId, this.store, this.storeLegend);
if (this.store.data.length > 1) {
this.showData();
}
else {
this.showEmpty();
}
this.buildLegendTree(this.storeLegend);
}
},
showEmpty: function(inLegend) {
if (inLegend) {
domStyle.set(this.emptyNode, 'display', '');
return;
}
domStyle.set(this.dataTree.domNode, 'display', 'none');
domStyle.set(this.subTitleNode, 'font-weight', 'normal');
domStyle.set(this.subTitleNode, 'padding-top', '15px');
domStyle.set(this.subTitleNode, 'text-transform', 'none');
domStyle.set(this.subTitleNode, 'text-align', 'center');
this.subTitleNode.innerHTML = this.noLegendText;
},
showData: function(inLegend) {
if (inLegend) {
domStyle.set(this.emptyNode, 'display', 'none');
return;
}
domStyle.set(this.dataTree.domNode, 'display', '');
domStyle.set(this.subTitleNode, 'font-weight', '');
domStyle.set(this.subTitleNode, 'padding-top', '');
domStyle.set(this.subTitleNode, 'text-transform', '');
domStyle.set(this.subTitleNode, 'text-align', '');
this.subTitleNode.innerHTML = 'Choisissez les données à afficher dans la légende :';
},
buildLayerDomItems: function() {
if (this.store == null || this.storeLegend == null) {
var raw = [];
var rawLegends = [];
var store = this.store = new Observable(Memory({
data: raw,
getChildren: function(object) {
return this.query({
parent: object.id
});
}
}));
var storeLegend = this.storeLegend = /*new Observable(*/new Memory({
data: rawLegends,
getChildren: function(object) {
return this.query({
parent: object.id,
visible: true
});
}
});//);
var rootItem = {
id: 'root',
name: 'Tout cocher / décocher'
};
raw.push(rootItem);
rawLegends.push({
id: 'root',
name: 'Légendes'
});
this.buildTree(this.store);
//this.buildLegendTree(this.storeLegend);
}
if (this.selectedLayer) {
if (this.selectedLayer.mapService == null) {
this.showEmpty(true);
return;
}
if (!this.selectedLayer.mapService.hasLegend) {
this.showEmpty(true);
return;
}
this.selectedService = this.selectedLayer.mapService;
if (!this.selectedLayer.mapService.legendLoaded) {
this.own(on.once(this.selectedLayer.mapService, this.selectedLayer.mapService.events.MapServiceLegendLoaded, lang.hitch(this, function() {
// this.addLayer(this.selectedLayer, 'root', this.store, this.storeLegend, true);
// this.showData();
if (this.addLayers(this.selectedService, this.store, this.storeLegend, true, null, true)) {
this.showData();
}
else {
this.showEmpty();
}
this.selectedService.openLayersLegend = false;
})));
this.selectedLayer.mapService.loadLegend();
}
else {
if (this.addLayers(this.selectedService, this.store, this.storeLegend, true, null, true)) {
this.showData();
}
else {
this.showEmpty();
}
this.selectedService.openLayersLegend = false;
}
}
else if (this.selectedService) {
if (this.addLayers(this.selectedService, this.store, this.storeLegend, true)) {
this.showData();
}
else {
this.showEmpty();
}
this.selectedService.openLayersLegend = false;
}
else {
var mapServices = this.spwViewer.get('spwMap').getMapServices({
isBaseMap: false
});
if (mapServices.length === 0) {
this.showEmpty();
return;
}
else {
this.showData();
}
var atLeastOne = false;
// création d'un widget pour afficher la légende pour chaque service
array.forEach(mapServices, lang.hitch(this, function(service) {
if (!service.visible || !service.hasLegend || !service.inTOC) {
this.removeItem(service.serviceId, this.store, this.storeLegend);
}
else {
atLeastOne = this.addLayers(service, this.store, this.storeLegend, null, false) || atLeastOne;
}
}));
this.buildLegendTree(this.storeLegend);
if (!atLeastOne) {
this.showEmpty();
}
}
},
buildTree: function(store) {
var model = new ObjectStoreModel({
store: store,
query: {
id: 'root'
},
mayHaveChildren: function(object) {
return object.id === 'root' || object.service || (object.layer && object.layer.subLayers && object.layer.subLayers.length > 0);
}
});
var customTreeNode = declare([Tree._TreeNode], {
templateString: templateTreeNode,
item: null,
spwLegend: null,
postCreate: function() {
this.inherited(arguments);
if (this.tree.model.mayHaveChildren(this.item)) {
this.item.checkbox = this.checkbox = new ThreeStateCheckBox({
checked: this.item.checked == null ? true : this.item.checked
}, this.checkboxNode);
}
else {
this.item.checkbox = this.checkbox = new CheckBox({
checked: this.item.checked == null ? true : this.item.checked
}, this.checkboxNode);
}
this.own(
on(this.checkbox, 'change', lang.hitch(this.spwLegend, this.spwLegend.ckChanged, this.item.id, this.checkbox)),
on(this.checkbox, 'click', lang.hitch(this.spwLegend, this.spwLegend.ckClicked, this.item))
);
}
});
var tree = this.dataTree = new Tree({
model: model,
autoExpand: true,
openOnClick: false,
getIconClass: function(item, opened) {
return '';
},
_createTreeNode: lang.hitch(this, function(args) {
var tnode = new customTreeNode(lang.mixin({
item: args.item,
spwLegend: this
}, args));
args.item.checkbox = tnode.checkbox;
return tnode;
})
});
tree.placeAt(this.treeNode);
tree.startup();
tree.expandAll();
},
buildLegendTree: function(store) {
if(this.legendTree){
this.legendTree.destroy();
}
var model = new ObjectStoreModel({
store: store,
labelType: 'html',
query: {
id: 'root'
},
mayHaveChildren: function(object) {
return object.legend == null;
}
});
var tree = this.legendTree = new Tree({
model: model,
showRoot: false,
autoExpand: true,
openOnClick: true,
getIconClass: function(item, opened) {
// pour enlever l'image 'dossier'
}
});
tree.placeAt(this.legendTreeNode);
tree.startup();
tree.expandAll();
},
removeItem: function(id, store, storeLegend) {
var children = store.query({
parent: id
});
children.forEach(lang.hitch(this, function(c) {
this.removeItem(c.id, store, storeLegend);
}));
var legends = storeLegend.query({
id: id
});
legends.forEach(lang.hitch(this, function(l) {
storeLegend.remove(l.id);
}));
store.remove(id);
storeLegend.remove(id);
},
addLayers: function(service, store, storeLegend, canBeInvisible, refreshLegendTree, onlySelectedLayer) {
var layers = [];
this.onlyOneSelectedLayer = onlySelectedLayer;
if(onlySelectedLayer){
layers = [this.selectedLayer];
}else{
layers = array.filter(service.get('mapServiceLayers'), lang.hitch(this, function(ms) {
if (!ms.inTOC || (!canBeInvisible && (!ms.visibleAtCurrentScale() || !ms.isVisible()))) {
this.removeItem(ms.id, store, storeLegend);
return false;
}
return true;
}));
}
if (layers.length === 0) {
this.removeItem(service.serviceId, store, storeLegend);
return false;
}
var item = {
id: service.serviceId,
name: service.label,
parent: 'root',
service: service,
checked: true
};
if (store.query({id: service.serviceId}).length === 0) {
store.add(item);
console.log('STORE DATA 1:', store.data);
}
else {
var item = store.query({id:service.serviceId})[0];
if(item.checkbox)
item.checked = item.checkbox.get('checked');
store.remove(service.serviceId);
store.add(item);
console.log('STORE DATA 2:', store.data);
}
if (storeLegend.query({id:service.serviceId}) == 0) {
storeLegend.add({
id: service.serviceId,
name: service.label,
parent: 'root',
service: service,
visible: true
});
console.log('LEGEND STORE DATA 1:', storeLegend.data);
}
else {
var item = storeLegend.query({id:service.serviceId})[0];
storeLegend.remove(service.serviceId);
storeLegend.add(item);
console.log('LEGEND STORE DATA 2:', storeLegend.data);
}
var loopLayers = lang.hitch(this, function() {
//setTimeout(lang.hitch(this, function(){
array.forEach(layers, lang.hitch(this, function(layer) {
this.addLayer(layer, layer.get('parentLayer') ? layer.get('parentLayer').id : service.serviceId, store, storeLegend, canBeInvisible);
}));
// if(refreshLegendTree !== false){
this.buildLegendTree(this.storeLegend);
// }
//}), 50);
});
if (!service.legendLoaded) {
this.own(
on.once(service, service.events.MapServiceLegendLoaded, lang.hitch(this, loopLayers))
);
service.loadLegend();
} else {
lang.hitch(this, loopLayers)();
}
return true;
},
/**
* HAS TO BE CALLED AFTER LEGEND IS LOADED
*/
addLayer: function(layer, parent, store, storeLegend, addSubLayers) {
if (!layer.inTOC) {
return;
}
var item = {
id: layer.id,
name: layer.name,
parent: parent,
layer: layer
};
if (store.query({id:layer.id}).length == 0) {
store.add(item);
console.log('STORE DATA 3:', store.data);
}
else {
var item = store.query({id:layer.id})[0];
if(item.checkbox)
item.checked = item.checkbox.get('checked');
store.remove(layer.id);
store.add(item);
console.log('STORE DATA 4:', store.data);
}
var layerAdded = false;
// if (addSubLayers || (layer.subLayers && layer.subLayers.length > 0)) {
if (storeLegend.query({id:layer.id}).length == 0) {
storeLegend.add({
id: layer.id,
name: layer.name,
parent: parent,
layer: layer,
visible: true
});
console.log('LEGEND STORE DATA 3:', storeLegend.data);
}
else {
var item = storeLegend.query({id:layer.id})[0];
storeLegend.remove(layer.id);
storeLegend.add(item);
console.log('LEGEND STORE DATA 4:', storeLegend.data);
}
layerAdded = true;
// }
var datas = storeLegend.data;
var legendUrl = layer.get('legendUrl') || layer.mapService.get('legendUrl');
if(legendUrl){
if(array.filter(datas, function(d){ return d.id === (layer.id + '-legend-url');}).length == 0) {
var clickAction = "window.open('"+legendUrl+"')";
datas.push({
id: layer.id + '-legend-url',
name: '<a href="javascript:void(0)" onclick="'+clickAction+'">Télécharger la légende</a>',
parent: layerAdded ? layer.id : parent,
layer: layer,
layerId: layer.id,
legend: {},
visible: true
});
}
} else {
array.forEach(layer.legends, lang.hitch(this, function(leg, idx) {
//if(idx > 0) return;
var newId = layer.id + '-legend' + idx;
if (array.filter(datas, function(d){ return d.id === newId;}).length == 0) {
var label = '<img class="legendSymbol" style="width: 16px; padding-right: 10px;" ' +
'src="data:' + leg.contentType + ';base64,' + leg.imageData + '"/> ' +
(leg.label ? leg.label : layer.name);
if(leg.url && leg.url.indexOf("http") === 0){
label = '<img class="legendSymbol" style="padding-right: 10px;" ' +
'src="' + leg.url + '"/> ';
}
//storeLegend.add({
datas.push({
id: newId,
name: label,
parent: layerAdded ? layer.id : parent,
layer: layer,
layerId: layer.id,
legend: leg,
visible: true
});
}
else {
// if(array.filter(datas, function(d){ return d.id === newId;}).length > 0){
// var item = array.filter(datas, function(d){ return d.id === newId;})[0];
// //datas.push(item);
// }
//storeLegend.remove(newId);
//storeLegend.add(item);
}
}));
}
if (this.onlyOneSelectedLayer) {
this.checkLayerIsLinkedToRoot(layer);
}
if(datas) {
storeLegend.setData(datas);
}
if (addSubLayers) {
array.forEach(layer.subLayers, lang.hitch(this, function(subLayer) {
this.addLayer(subLayer, layer.id, store, storeLegend, true);
}));
}
},
checkLayerIsLinkedToRoot: function(layer) {
if (layer.parentLayer != null) {
var parentLayer = layer.parentLayer;
if (this.storeLegend.query({id: layer.parentLayer.id}).length == 0 && this.storeLegend.data.length > 1) {
var item = {
id: parentLayer.id,
name: parentLayer.name,
parent: parentLayer.parentLayer ? parentLayer.parentLayer.id : this.selectedService.serviceId,
service: this.selectedService,
layer: parentLayer,
visible: true
};
this.storeLegend.add(item);
if (parentLayer.parentLayer != null && this.storeLegend.query({id: parentLayer.parentLayer.id}).length == 0) {
this.checkLayerIsLinkedToRoot(parentLayer);
}
}
}
},
ckClicked: function(item) {
var cb = item.checkbox;
var store = this.store;
if (cb == null) {
return;
}
var checked = cb.get('checked');
var parent = item.parent;
var toggleParents = function(parent) {
if (parent == null) {
return;
}
var itemParent = array.filter(store.data, function(d){ return d.id === parent;});
if (itemParent.length > 0) {
itemParent = itemParent[0];
if (itemParent && itemParent.checkbox) {
var children = store.query({parent: parent});
var countChecked = 0;
array.forEach(children, function(c) {
if (c.checkbox && c.checkbox.get('checked')) {
countChecked += 1;
}
});
itemParent.checkbox.set('checked', countChecked === children.length ? true : countChecked > 0 ? 'mixed' : false);
if (parent !== 'root') {
toggleParents(itemParent.parent);
}
}
}
};
toggleParents(item.parent);
var toggleChildren = function(item) {
var children = store.query({parent: item.id});
if (children == null || children.length === 0) {
return;
}
array.forEach(children, function(c) {
if (c.checkbox) {
c.checkbox.set('checked', checked);
toggleChildren(c);
}
});
};
toggleChildren(item);
setTimeout(lang.hitch(this, function(){
this.buildLegendTree(this.storeLegend);
}), 200);
},
ckChanged: function(id, cb) {
var checked = cb.get('checked');
var store = this.store;
var storeLegend = this.storeLegend;
storeLegend.get(id).visible = !!(checked);
var legends = storeLegend.query({
layerId: id
});
legends.forEach(function(i) {
i.visible = !!(checked);
//storeLegend.notify(i, i.id);
});
var item = array.filter(store.data, function(d){ return d.id === id;});;
item.forEach(function(i) {
i.visible = !!(checked);
//storeLegend.notify(i, i.id);
});
}
});
return SpwLegend;
});