Retour à la documentation
/**
* @class spw.widgets.SpwWriterQueryForm
*/
define(["dojo/_base/declare","spw/api/SpwBaseWidget", "dojo/on", "dojo/_base/lang",
"esri/tasks/IdentifyTask", "esri/tasks/IdentifyParameters", "esri/geometry/Point",
"spw/api/Utils", "dojo/_base/array", "esri/tasks/QueryTask", "esri/tasks/query",
"esri/tasks/BufferParameters", "dojo/dom-construct", "dgrid/OnDemandGrid",
"dgrid/extensions/ColumnHider", "dgrid/extensions/ColumnResizer", "dojo/store/Memory",
"dojo/dom-class", "dgrid/Selection", "dgrid/util/mouse", "spw/api/MessageManager", "dojo/Evented",
"dojo/date/locale", "dojo/i18n!./nls/SpwWriterQueryForm", "dijit/form/Button"],
function(declare, SpwBaseWidget, on, lang, IdentifyTask, IdentifyParameters, Point,
Utils, array, QueryTask, Query, BufferParameters, domConstruct, OnDemandGrid,
ColumnHider, ColumnResizer, Memory, domClass, Selection, mouseUtil, MessageManager,
Evented, locale, labels, Button){
var QueryFormConnector = null;
QueryFormConnector = declare("spw.widgets.SpwWriterQueryForm", [SpwBaseWidget, Evented], /** @lends spw.widgets.SpwWriterQueryForm.prototype */{
/**
* Url du service de base utilisé pour récupérer les géométries sur base desquelles lancer l'identification des services
* @type String
*/
baseService:null,
/**
* Alias du(des) champs du service de base à afficher dans le tableau présentant la sélection de l'utilisateur
* @type string | Array.<String>
*/
serviceFieldAlias:null,
/**
* Nom du(des) champs du service de base à afficher dans le tableau présentant la sélection de l'utilisateur. Cette propriété est prioritaire par rapport à "serviceFieldAlias".
* @type string | Array.<String>
*/
serviceFieldName:null,
/**
* Identifiant du(des) champs du formulaire HTML qui seront remplis sur base des valeurs retournées par l'identification du service de base "baseService".
* Ce paramètre doit correspondre au type du paramètre "serviceFieldName" (ou "serviceFieldAlias") : si un tableau est utilisé, le matching field-value s'effectue via l'index de l'élément dans le tableau.
* @type string | Array.<String>
*/
formField:null,
/**
* Nombre maximum d'éléments autorisés lors de la sélection préalable de l'utilisateur. (venant du baseService)
*/
maxItemSelection:null,
/**
* Information permettant au viewer de zoomer lors de l'activation du widget.
* @property zoomInfo.x {Number} coordonnée x
* @property zoomInfo.y {Number} coordonnée y
* @property zoomInfo.radius {Number} rayon à appliquer à la coordonnée x,y lors du zoom, en mètres.
* @type Object
*/
zoomInfo: null,/*{
"x":150000,
"y":150000,
"radius":100
},*/
/**
* Indique si la sélection de l'utilisateur doit être consolidée (UNION) avant de lancer l'identification sur les services définis.
* Si vrai, le système vérifiera que le polygone formé est valide et n'est pas un multipart polygon
* @type Boolean
*/
unionServiceQuery: false,
/**
* Séparateur utilisé pour séparer les différents appels d'identification (plusieurs géométries dans la sélection utilisateur).
* @type String
*/
serviceSeparator: "|#|",
/**
* Définition des services à interroger ainsi que le mapping service field - form field.
* @property Object.serviceUrl {String} Url du layer à interroger (layer d'un MapService esri)
* @property Object.serviceFieldName {String | Array.<String>} Nom du(des) champs du service à utiliser pour remplir le(les) champs correspondants du formulaire HTML.
* @property Object.formField {String | Array.<String>} Identifiant du(des) champs du formulaire HTML qui seront remplis sur base des valeurs retournées par l'identification du service.
* @property Object.queryBuffer {Number} Buffer de proximité à appliquer sur la sélection utilisateur lors de l'identification de cette couche.
* @property Object.queryType {String} Type de requête spatiale à effectuer : PARTIAL = polygone contenu partiellement dans l'objet identifié ou TOTAL = le polygone est entièrement contenu dans l'objet identifié.
* @type Array.<Object>
*/
services: null,/*[
{
serviceUrl: "http://webgisdgo4.spw.wallonie.be/ArcGIS/rest/services/DGO4/PDS_5000/MapServer/19",
serviceFieldName:"DESCRIPTION",
formField:"myFormField2",
queryBuffer: 0,
queryType:"PARTIAL"
},
{
serviceUrl: "http://geoservices.wallonie.be/arcgis/rest/services/NATURA2000/NATURA2000_EP/MapServer/1",
serviceFieldName:["NOM", "CODE_SITE"],
formField:["myFormField3", "myFormField3_2"],
queryBuffer: 2000,
queryType:"PARTIAL"
}],*/
/**
* Identifiant du champs du formualire HTML. Si précisé, ce champs est rempli avec les coordonnées x et y du point cliqué sur la carte.
* @type string
*/
xyField:null,
valueSeparator:",",
noResultValue: "|$|NO_RESULT|$|",
serviceErrorValue: "|$|SERVICE_ERROR|$|",
unavailableErrorValue: "|$|UNAVAILABLE_ERROR|$|",
instructionMessage:"Veuillez sélectionner une ou plusieurs parçelles adjaçentes.",
maxSelectionMessage:"Le nombre maximum de sélection est atteint.",
invalidSelectionMessage:"La sélection n'est pas valide. Veuillez sélectionner des éléments adjaçents.",
noSelectionMessage:"Aucun élément sélectionné. Veuillez sélectionner au minimum un élément.",
processingMessage:"Traitement en cours. Veuillez patienter.",
validateButtonMessage:"Sauver et revenir au formulaire",
dateFormat:null,
globalConfigObjectName: "geoviewerQueryFormTransfert",
_baseServiceOIDFieldName: null,
_mapClickHandler: null,
_features: null,
_selectionGrid: null,
_containerDiv: null,
_btnValidate: null,
_xy: null,
queryCount: 0,
events: { QueriesCompleted: "QueryFormConnector_QueriesCompleted" },
/**
* @constructs
* @param config
*/
constructor: function (config) {
this._features = [];
lang.mixin(this, labels);
},
postCreate: function() {
this.inherited(arguments);
this._containerDiv = domConstruct.create("div", {innerHTML:this.instructionMessage, class: "spwWriterQueryForm", style:"padding:8px;"}, this.domNode);
this._xy = [];
},
onActivate: function(){
this.inherited(arguments);
if(window && window[this.globalConfigObjectName]){
lang.mixin(this, window[this.globalConfigObjectName]);
}
if(this.zoomInfo){
this.spwViewer.get('spwMap').zoomToPoint(this.zoomInfo.x, this.zoomInfo.y, this.zoomInfo.radius);
}
this._mapClickHandler = this.spwViewer.get('spwMap').on("MapClicked", lang.hitch(this, this.identifyBaseService));
},
onDeactivate: function(){
this.inherited(arguments);
if(this._mapClickHandler){
this._mapClickHandler.remove();
}
if(this._btnValidate){
this._btnValidate.destroy();
this._btnValidate = null;
}
if(this._features && this._features.length > 0){
while (this._features.length > 0){
this.deselectFeature(this._features[0]);
}
}
if(this._selectionGrid){
this._selectionGrid.destroy();
this._selectionGrid = null;
}
},
identifyBaseService: function(x, y){
this._xy.push(x+","+y);
if(this.xyField){
var formField = document.getElementById(this.xyField);
if(formField){
formField.value = this._xy.join(this.serviceSeparator);
}
}
var query = new Query();
query.geometry = new Point(x, y, this.spwViewer.get('spatialReference'));
query.outFields = ["*"];
query.returnGeometry = true;
return new QueryTask(this.baseService).execute(query, lang.hitch(this, function(queryResult) {
if(queryResult && queryResult.features && queryResult.features.length > 0){
this._baseServiceOIDFieldName = this.getEsriOIDFieldName(queryResult);
if(!this.serviceFieldName){
this.serviceFieldName = this.aliasesToNames(queryResult);
}
if(this.dateFormat){
this.formatResultsDates(queryResult);
}
var selectedFeature = this.getSelectedFeature(queryResult.features[0].attributes[this._baseServiceOIDFieldName]);
if(selectedFeature){
this.deselectFeature(selectedFeature);
} else {
if(this._features && this.maxItemSelection && this._features.length >= this.maxItemSelection){
MessageManager.getInstance().notifyInfo(this.maxSelectionMessage);
} else {
this.selectFeature(queryResult.features[0]);
}
}
}
}));
},
formatResultsDates: function(queryResult) {
array.forEach(queryResult.fields, function(field){
if(field.type == "esriFieldTypeDate"){
array.forEach(queryResult.features, function(feature){
feature.attributes[field.name] = locale.format(new Date(feature.attributes[field.name]), {datePattern: this.dateFormat});
});
}
});
},
aliasesToNames: function(queryResults) {
if(typeof(this.serviceFieldAlias) == 'string'){
var f = "";
array.some(queryResults.fields, function(field){
if(field.alias == this.serviceFieldAlias){
f = field.name;
return true;
}
return false;
});
return f;
} else {
var f = [];
array.forEach(this.serviceFieldAlias, function(alias){
array.some(queryResults.fields, function(field){
if(field.alias == alias){
f.push(field.name);
return true;
}
return false;
});
});
return f;
}
},
baseServiceRedefined: function(){
var serviceDef = null;
array.some(this.services, lang.hitch(this, function(service){
var serviceUrl = service.serviceUrl;
if(serviceUrl[serviceUrl.length-1] == '/'){
serviceUrl = serviceUrl.substring(0, serviceUrl.length-1);
}
var baseServiceUrl = this.baseService;
if(baseServiceUrl[baseServiceUrl.length-1] == '/'){
baseServiceUrl = baseServiceUrl.substring(0, baseServiceUrl.length-1);
}
if(baseServiceUrl == serviceUrl){
serviceDef = service;
return true;
};
return false;
}));
return serviceDef;
},
getEsriOIDFieldName: function(queryResults){
var f = "";
array.forEach(queryResults.fields, lang.hitch(this, function(field){
if(field.type == "esriFieldTypeOID"){
f = field.name;
}
}));
return f;
},
getSelectedFeature: function(objectid){
for(var i=0; i < this._features.length; i++){
if(this._features[i].attributes[this._baseServiceOIDFieldName] == objectid){
return this._features[i];
}
}
return null;
},
deselectFeature: function(feature){
this.spwViewer.get('spwMap').removeFeature(feature);
this._features.splice(this._features.indexOf(feature), 1);
this._buildSelectionArray();
},
selectFeature: function(feature){
feature.geometry.spatialReference = this.spwViewer.get('spatialReference');
this.spwViewer.get('spwMap').showFeature(feature);
this._features.push(feature);
this._buildSelectionArray();
},
resize: function(){
if(this._selectionGrid) {
this._selectionGrid.resize();
}
},
_buildSelectionArray: function(){
if(!this._selectionGrid) {
var columns = {};
for(var key in this._features[0].attributes){
columns[key.replace(' ', '')] = {};
lang.mixin(columns[key.replace(' ', '')], {
label:key,
hidden: ((typeof(this.serviceFieldName) === 'string') ? (key != this.serviceFieldName) : (this.serviceFieldName.indexOf(key) < 0))
});
}
columns.editorbtn = {
label:"",
sortable:false,
hidden:false,
unhidable:true,
resizable: false,
width:40,
renderCell: lang.hitch(this, function(object, value, node, options){
var lnk = domConstruct.create("img", {src:this.imagesPath + "icon-delete.png", title:labels.deleteImg, alt:labels.deleteImg, style:"cursor:pointer;"}, domConstruct.create("div", {style:"text-align:center;"}, node));
on(lnk, "click", lang.hitch(this, function(){
var selectedFeature = this.getSelectedFeature(object[this._baseServiceOIDFieldName]);
if(selectedFeature){
this.deselectFeature(selectedFeature);
}
}));
})
};
this._selectionGrid = new (declare([OnDemandGrid, Selection, ColumnHider, ColumnResizer]))({
className: "dgrid-autoheight",
addUiClasses: false,
columns: columns
}, domConstruct.create("div", {style:"height:190px;overflow-y:auto;"}, this._containerDiv));
this._selectionGrid.on(mouseUtil.enterRow, lang.hitch(this, this.gridRowEntered));
this._selectionGrid.on(mouseUtil.leaveRow, lang.hitch(this, this.gridRowLeaved));
this._btnValidate = new Button({
style: 'float: right;',
label: this.validateButtonMessage
}, domConstruct.create("button", null, this._containerDiv));
on(this._btnValidate, "click", lang.hitch(this, this.validateSelection));
}
this.refreshGrid();
},
gridRowEntered: function(event){
var data = this._selectionGrid.row(event);
if(data){
var selectedFeature = this.getSelectedFeature(data.data[this._baseServiceOIDFieldName]);
if(selectedFeature){
this.spwViewer.get('spwMap').highlightFeature(selectedFeature);
}
}
},
gridRowLeaved: function(event){
var data = this._selectionGrid.row(event);
if(data){
var selectedFeature = this.getSelectedFeature(data.data[this._baseServiceOIDFieldName]);
if(selectedFeature){
this.spwViewer.get('spwMap').unhighlightFeature(selectedFeature);
}
}
},
refreshGrid: function() {
if(this._selectionGrid){
var store = new Memory({idProperty: this._baseServiceOIDFieldName, data:array.map(this._features, function(feature){
for(var key in feature.attributes){
if(key.indexOf(' ') > -1){
feature.attributes[key.replace(' ', '')] = feature.attributes[key];
}
}
return feature.attributes;
})});
this._selectionGrid.set('store', store);
}
},
validateSelection: function(){
if(this._features && this._features.length > 1 && this.unionServiceQuery){
this.spwViewer.get('geometryService').union(array.map(this._features, function(feature){return feature.geometry;}), lang.hitch(this, function(geometry){
if(!geometry || !geometry.rings || this.isMultipartPolygon(geometry)){
MessageManager.getInstance().notifyWarning(this.invalidSelectionMessage);
} else {
geometry.spatialReference = this._features[0].geometry.spatialReference;
this.fillBaseServiceFields();
this.queryServices(geometry);
}
}), function(){
MessageManager.getInstance().notifyError(labels.constraintError);
});
} else if (this._features && this._features.length == 1){
this.fillBaseServiceFields();
this.queryServices(this._features[0].geometry);
} else if(this._features && this._features.length > 1 && !this.unionServiceQuery){
this.fillBaseServiceFields();
array.forEach(this._features, lang.hitch(this, function(feature){
this.queryServices(feature.geometry);
}));
}
else {
MessageManager.getInstance().notifyWarning(this.noSelectionMessage);
}
},
fillBaseServiceFields: function() {
var formFields = this.formField;
var fieldsToFetch = this.serviceFieldName;
var serviceRedef = this.baseServiceRedefined();
if(serviceRedef){
fieldsToFetch = serviceRedef.serviceFieldName;
formFields = serviceRedef.formField;
}
if(typeof(fieldsToFetch) === 'string'){
fieldsToFetch = [fieldsToFetch];
}
if(typeof(formFields) === 'string'){
formFields = [formFields];
}
array.forEach(fieldsToFetch, lang.hitch(this, function(field, idx){
var fieldValue = this._features && this._features.length > 0 ? this.joinBaseFeatureValues(this._features, field) : this.noResultValue;
var formField = document.getElementById(formFields[idx]);
if(formField){
formField.value = fieldValue;
}
}));
},
isMultipartPolygon: function(geometry){
var clockwiseCount = 0;
for(var i =0; i < geometry.rings.length; i++){
if(geometry.isClockwise(geometry.rings[i]) && ++clockwiseCount > 1){
return true;
}
}
return false;
},
queryServices: function(geometry) {
MessageManager.getInstance().displayModalMessage("<div>"+this.processingMessage+"</div>");
this.set("queryCount", this.get("queryCount") + this.services.length);
var watchHandler = this.watch("queryCount", lang.hitch(this, function(name, oldVal, newVal){
if(newVal <= 0){
watchHandler.remove();
MessageManager.getInstance().hideModalMessage();
this.emit("QueryFormConnector_QueriesCompleted");
}
}));
array.forEach(this.services, lang.hitch(this, function(service, idx){
if(service != this.baseServiceRedefined()){
try {
if(service.queryBuffer){
var params = new BufferParameters();
params.geometries = [ geometry ];
params.distances = [ service.queryBuffer ];
params.bufferSpatialReference = this.spwViewer.get('spatialReference');
params.outSpatialReference = this.spwViewer.get('spatialReference');
this.spwViewer.get('geometryService').buffer(params, lang.hitch(this, function(bufferedGeometry){
this.executeQuery(bufferedGeometry[0], service);
}), lang.hitch(this, function(error){
console.info(error);
this.fillQueryServiceFields(service, null, this.unavailableErrorValue);
this.set('queryCount', this.queryCount-1);
}));
} else {
this.executeQuery(geometry, service);
}
} catch(err) {
this.fillQueryServiceFields(service, null, this.unavailableErrorValue);
this.set('queryCount', this.queryCount-1);
}
} else {
this.set('queryCount', this.queryCount-1);
}
}));
},
fillQueryServiceFields: function(service, queryResult, errorText) {
console.log("========================");
console.log("Résultat query : ");
console.log("--- Service : ",service);
console.log("--- queryResult : ",queryResult);
console.log("--- errorText : ",errorText);
console.log("========================");
var fieldsToFetch = service.serviceFieldName;
var formFields = service.formField;
if(typeof(fieldsToFetch) === 'string'){
fieldsToFetch = [fieldsToFetch];
}
if(typeof(formFields) === 'string'){
formFields = [formFields];
}
array.forEach(fieldsToFetch, lang.hitch(this, function(field, idx){
if(errorText){
var formField = document.getElementById(formFields[idx]);
if(formField){
formField.value = formField.value != '' ? (formField.value + this.serviceSeparator + errorText) : errorText;
}
} else {
var fieldValue = queryResult && queryResult.features.length > 0 ? this.joinFeatureValues(queryResult.features, field) : this.noResultValue;
var formField = document.getElementById(formFields[idx]);
if(formField){
formField.value = formField.value != '' ? (formField.value + this.serviceSeparator + fieldValue) : fieldValue;
}
}
}));
},
executeQuery: function(geometry, service){
var query = new Query();
query.geometry = geometry;
query.spatialRelationship = (service.queryType != "TOTAL") ? Query.SPATIAL_REL_INTERSECTS : Query.SPATIAL_REL_WITHIN;
query.outFields = ["*"];
query.returnGeometry = false;
query.outSpatialReference = this.spwViewer.get('spatialReference');
return new QueryTask(service.serviceUrl).execute(query, lang.hitch(this, function(queryResult) {
if(this.dateFormat){
this.formatResultsDates(queryResult);
}
this.fillQueryServiceFields(service, queryResult);
this.set('queryCount', this.queryCount-1);
}), lang.hitch(this, function(){
this.fillQueryServiceFields(service, null, this.unavailableErrorValue);
this.set('queryCount', this.queryCount-1);
}));
},
joinFeatureValues: function(features, field){
return this.joinValues(features, field, this.valueSeparator);
},
joinBaseFeatureValues: function(features, field){
return this.joinValues(features, field, this.serviceSeparator);
},
joinValues: function(features, field, separator){
if(features[0] && typeof(features[0].attributes[field]) != 'undefined'){
var values = array.map(features, function(feature){return feature.attributes[field];});
return values.join(separator);
}
return this.serviceErrorValue;
}
});
return QueryFormConnector;
});