Source: widgets/SpwQuerySearch.js

Retour à la documentation
/**
 * @class spw.widgets.SpwQuerySearch
 */
define(["dojo/_base/declare", "spw/api/SpwBaseTemplatedWidget", "dojo/text!./templates/SpwQuerySearch.html",
        "dijit/form/FilteringSelect", "esri/tasks/query", "esri/tasks/QueryTask", "dojo/_base/lang",
        "dojo/store/Memory", "dojo/store/util/SimpleQueryEngine", "spw/api/Utils", "dojo/_base/array", "esri/request",
        "spw/api/MessageManager", "dojo/i18n!./nls/SpwQuerySearch", "dojo/dom-style", "dojo/dom-construct", "spw/api/GeometryConverter", "spw/api/ConfigLoader",

        "dijit/form/Button"],
        function(declare, SpwBaseTemplatedWidget, template,
                FilteringSelect, Query, QueryTask, lang,
                Memory, SimpleQueryEngine, Utils, array, request,
                MessageManager, labels, domStyle, domConstruct, GeometryConverter, ConfigLoader) {

    return declare("spw.widgets.SpwQuerySearch", [SpwBaseTemplatedWidget], /** @lends spw.widgets.SpwQuerySearch.prototype */{

        templateString: template,
        labels: labels,

        searchLabel: null,
        comboBoxServiceFields: null,
        orderByField: null,
        displayFieldsTemplate: null,
        queryServiceUrl: null,

        searchFilteringSelect: null,
        serviceMainField: null,
        configurationValide: false,

        resultFeature: null,
        maxRecordCountService:100,
        esriOIDField: null,

        distinctValues: true,

        _layerInfo: null,

        /**
         * @constructs
         * @param config
         */
        constructor: function(config){
            if (config == null) {
                MessageManager.getInstance().notifyError("L'outil de query ne fonctionnera pas car il manque des paramètres obligatoires.");
                this.configurationValide = false;
                return;
            }
            var viewerConfig = ConfigLoader.getInstance().get('viewer');
            if(config.tokenSecured && viewerConfig.secureServerUrl){
                config.queryServiceUrl = viewerConfig.secureServerUrl + "?service=" + config.queryServiceUrl;
            } else if(config.networkSecured && viewerConfig.secureServerUrl){
                config.queryServiceUrl = viewerConfig.secureServerUrl + "?noToken=true&service=" + config.queryServiceUrl;
            }

            if (config.layer && config.layer.mapService && config.layer.mapService.type === "WMS") {
            	config.serviceType = "WMS";
                config.queryServiceUrl = config.layer.mapService.get('url').replace("/wms", "/ows");
                config.searchLabel = config.layer.queryableLabel;
                config.comboBoxServiceFields = config.layer.queryableFields;
                config.displayFieldsTemplate = config.layer.queryableTemplate;
                config.orderByField = config.layer.queryableOrder;
                config.distinctValues = config.layer.distinctValues == null ? true : config.layer.distinctValues;
                if(!config.layer.queryableFields){
                	this.configurationValide = false;
                	return;
                }
            } else if(config.layer){
                config.queryServiceUrl = config.layer.mapService.get('url') + "/" + config.layer.layerId;
                config.searchLabel = config.layer.queryableLabel;
                config.comboBoxServiceFields = config.layer.queryableFields;
                config.displayFieldsTemplate = config.layer.queryableTemplate;
                config.orderByField = config.layer.queryableOrder;
                config.distinctValues = config.layer.distinctValues == null ? true : config.layer.distinctValues;
            }

            if (config.queryServiceUrl == null) {
                MessageManager.getInstance().notifyError("L'outil de query ne fonctionnera pas car il manque des paramètres obligatoires.");
                this.configurationValide = false;
                return;
            }

            if (config.comboBoxServiceFields != null) {
                this.comboBoxServiceFields = config.comboBoxServiceFields;
            }
            else {
                this.comboBoxServiceFields = null;
            }

            if (config.searchLabel != null) {
                this.searchLabel = config.searchLabel;
            } else {
                this.searchLabel = "Données";
            }

            if (config.orderByField != null) {
                this.orderByField = config.orderByField;
            } else {
                this.orderByField = this.comboBoxServiceFields == null ? null : this.comboBoxServiceFields[0];
            }

            if (config.displayFieldsTemplate != null) {
                this.displayFieldsTemplate = config.displayFieldsTemplate;
            } else {
                this.displayFieldsTemplate = null;
            }

            this.configurationValide = true;
        },

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

            this.searchFilteringSelect = new FilteringSelect({
                hasDownArrow: true,
                autoComplete: false
            }, this.searchFilteringSelectDiv);

            if (this.configurationValide) {
                // get the max number of records return by services
                this.showLoading(null, labels.dataLoading);

                this.getJSON(this.queryServiceUrl,
                    lang.hitch(this, function(response) {
                        this._layerInfo = response;

                        if(response.maxRecordCount) {
                            this.maxRecordCountService = response.maxRecordCount;
                        }

                        if(!this.esriOIDField) {
                            this.esriOIDField = this.parseEsriOIDField(response);
                        }

                        this.getAllResults();
                    }),
                    lang.hitch(this,function(error){
                        this.hideLoading();

                        this.enableForm(false);
                        console.info("[SpwQuerySearch] getJSON service failed");
                        // MessageManager.getInstance().notifyError("L'outil de query ne fonctionnera pas car le service ne répond pas. ["+this.queryServiceUrl+"]");
                    })
                );

            } else {
                this.enableForm(false);
            }
        },

        parseEsriOIDField: function(response) {
            var esriFieldTypeOID = "OBJECTID";

            if(response && response.fields && response.fields.length > 0) {
                array.some(response.fields, function(field) {
                    if(field.type == "esriFieldTypeOID") {
                        esriFieldTypeOID = field.name;
                        return true;
                    }

                    return false;
                });
            }

            return esriFieldTypeOID;
        },

        linkQueryResultsToSelect: function(featureSet){
            var resultFeatures = featureSet.features;

            if(!this.serviceMainField){
                this.serviceMainField = featureSet.displayFieldName;
            }

            var dataSelect = [];

            if (this.comboBoxServiceFields == null) {
                this.displayLabelNode.innerHTML = this.serviceMainField + ' : ';
            }

            for (var i=0, il = resultFeatures.length; i < il; i++) {

                resultFeatures[i].attributes.displayLabel = this.displayFieldsTemplate == null ?
                                                                resultFeatures[i].attributes[this.serviceMainField] : this.displayFieldsTemplate;
                resultFeatures[i].attributes.searchLabel = "";

                if (this.comboBoxServiceFields == null) {
                    resultFeatures[i].attributes.searchLabel = resultFeatures[i].attributes[this.serviceMainField];
                }
                else {
                    for (var j = 0; j < this.comboBoxServiceFields.length; j++) {
                        resultFeatures[i].attributes.displayLabel = resultFeatures[i].attributes.displayLabel.replace("${"+this.comboBoxServiceFields[j]+"}", resultFeatures[i].attributes[this.comboBoxServiceFields[j]]);
                        resultFeatures[i].attributes.searchLabel += resultFeatures[i].attributes[this.comboBoxServiceFields[j]]+" - ";
                    }

                    resultFeatures[i].attributes.searchLabel = resultFeatures[i].attributes.searchLabel.substring(0, resultFeatures[i].attributes.searchLabel.length-3);
                }


                resultFeatures[i].attributes.searchValue = Utils.removeAccent(resultFeatures[i].attributes.searchLabel);
                resultFeatures[i].attributes.serviceMainField = resultFeatures[i].attributes[this.serviceMainField];

                dataSelect[i] = resultFeatures[i].attributes;
                dataSelect[i].feature = resultFeatures[i];
            }

            var memoryStore = new Memory({
                data: dataSelect
            });

            if (this.displayFieldsTemplate != null) {
                memoryStore.queryEngine = lang.hitch(this, this.createQueryEngine);
            }
            else {
                this.searchFilteringSelect.set('fetchProperties', {
                    sort: [{
                        attribute: 'displayLabel'
                    }]
                });
            }

            this.searchFilteringSelect.set('store', memoryStore);

            this.searchFilteringSelect.set('searchAttr', 'searchLabel');
            this.searchFilteringSelect.set('labelAttr', 'displayLabel');
            this.searchFilteringSelect.set('labelType', 'html');
            this.searchFilteringSelect.set('queryExpr', '${0}*');

            this.hideLoading();
        },

        createQueryEngine: function(query, options) {
            var qS = query.searchLabel;

            qS.compile(Utils.removeAccent(qS.source));

            var filteringFunction = function(object){
                return qS.test(object.searchValue);
            };

            var orderField = this.orderByField;

            var execute = function(arr) {
                var ar = array.filter(arr, filteringFunction);
                ar.sort(function(a,b){
                    if (a[orderField] == b[orderField]) return 0;
                    if (a[orderField] < b[orderField]) return -1;
                    return 1;
                });
                return ar;
            };

            execute.matches = filteringFunction;

            return execute;
        },

        showLoading: function(node, msg) {
            this.inherited(arguments);

            this.loadingText.innerHTML = msg;
        },

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

            this.loadingText.innerHTML = '';
        },

        buttonGoClicked: function(){
        	if(this.searchFilteringSelect.item && this.searchFilteringSelect.item.feature && this.searchFilteringSelect.item.feature.geometry){
        		this.displayResultAndZoom({features: [this.searchFilteringSelect.item.feature]});
        		return;
        	}
        	
        	var queryFieldUsed = this.serviceMainField;

            if(this.queryField) {
                queryFieldUsed = this.queryField;
            }

            if(this.searchFilteringSelect.item != null && this.searchFilteringSelect.item[queryFieldUsed] != null){
            	
                this.showLoading(null, labels.searchingTxt);

                var query = new Query();

                query.returnGeometry = true;
                query.outFields = ["*"];

                if(this.getFieldItemType(queryFieldUsed) == 'esriFieldTypeString'){
                    query.where = queryFieldUsed + "='"+this.searchFilteringSelect.item[queryFieldUsed].toString().replace(/'/gim, "''")+"'";
                } else {
                    query.where = queryFieldUsed + "="+this.searchFilteringSelect.item[queryFieldUsed];
                }

                var queryTask = new QueryTask(this.queryServiceUrl);
                queryTask.execute(query,lang.hitch(this, this.displayResultAndZoom));
            }
            else {
                MessageManager.getInstance().notifyError(this.labels.invalidSelection);
            }
        },

        getFieldItemType: function(queryField){
            var type = '';
            if(this._layerInfo && this._layerInfo.fields && this._layerInfo.fields.length > 0){
                array.some(this._layerInfo.fields, function(field){
                    if(field.name == queryField){
                        type = field.type;
                        return true;
                    }
                    return false;
                });
            }
            return type;
        },

        displayResultAndZoom: function(featureSet){
            this.hideLoading();

            if(this.resultFeature){
                this.spwViewer.get('spwMap').removeFeature(this.resultFeature);
            }
            if(featureSet.features.length > 0){
                this.resultFeature = featureSet.features[0];
                this.spwViewer.get('spwMap').showFeature(this.resultFeature);
                this.spwViewer.get('spwMap').zoomToFeature(this.resultFeature);
            }
        },

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

            if(this.resultFeature){
                this.spwViewer.get('spwMap').removeFeature(this.resultFeature);
            }
            if(this.searchFilteringSelect && this.searchFilteringSelect.closeDropDown){
                this.searchFilteringSelect.closeDropDown();
            }
        },

        getJSON: function(url,success,error){
        	if(this.serviceType === "WMS"){
        		request({
                    url: url,
                    content: { request: 'GetFeature', version:'1.3.0', service:'WFS', outputFormat:'application/json', typeName: this.layer.layerId, srsName:"EPSG:"+this.spwViewer.get('spatialReference').wkid },
                    handleAs: "json",
                    timeout: 40000
                }).then(lang.hitch(this, function(data) {
                	var fc = {
            			features: array.map(data.features, lang.hitch(this, function(f){ 
            				var f = lang.mixin({attributes: lang.mixin({}, f.properties)}, {geometry: GeometryConverter.geoJSONToEsri(f.geometry)});
            				f.geometry.setSpatialReference(this.spwViewer.get('spatialReference'));
            				return f;
            			}))
                    };
                	this.linkQueryResultsToSelect(fc);
                }), error);
        	} else {
            	request({
                    url: url,
                    content: {f:'pjson'},
                    handleAs: "json",
                    timeout: 4000
                }).then(success, error);
        	}
        },

        getAllResults: function(){

            var query = new Query();
            query.where = '1=1';

            var queryTask = new QueryTask(this.queryServiceUrl);

            queryTask.executeForIds(query, lang.hitch(this, lang.hitch(this, function(result){
                    if(result) {
                        result = result.sort(function(a,b){
                            if (parseInt(a) == parseInt(b)) return 0;
                            if (parseInt(a) < parseInt(b)) return -1;
                            return 1;
                        });

                        var numberQueries = Math.ceil(result.length / this.maxRecordCountService);
                        var queriesInProgress = numberQueries;
                        var featureSet = null;

                        var alreadyPushed = [];

                        var queryFromIdsFunc = function(results) {
                            if (results) {
                                if (this.distinctValues === true) {
                                    if (featureSet == null) {
                                        featureSet = lang.mixin(lang.clone(results), {
                                            features: []
                                        });
                                    }

                                    array.forEach(results.features, lang.hitch(this, function(feature) {
                                        var value = feature.attributes[featureSet.displayFieldName];

                                        if (this.comboBoxServiceFields && this.comboBoxServiceFields.length > 0) {
                                            value = lang.replace('{' + this.comboBoxServiceFields.join('} {') + '}', feature.attributes);
                                        }

                                        if (value == null || alreadyPushed.indexOf(value) === -1) {
                                            alreadyPushed.push(value);
                                            featureSet.features.push(feature);
                                        }
                                    }));
                                }
                                else {
                                    if (featureSet == null) {
                                        featureSet = results;
                                    }
                                    else {
                                        featureSet.features = featureSet.features.concat(results.features);
                                    }
                                }
                            }

                            queriesInProgress--;

                            if (queriesInProgress < 1) {
                                this.linkQueryResultsToSelect(featureSet);
                            }
                        };

                        for(var i=0; i < numberQueries; i++) {

                            var firstIndex = i * this.maxRecordCountService;
                            var lastIndex = result[(((i + 1) * this.maxRecordCountService) - 1)] ?
                                                (((i + 1) * this.maxRecordCountService) - 1) : (result.length - 1);

                            this.queryFromIds(result[firstIndex], result[lastIndex], queryFromIdsFunc);
                        }
                    }
                    else {
                        this.hideLoading();
                        this.enableForm(false);
                    }
                })),
                    lang.hitch(this,function(error){
                        console.error(error);
                        this.hideLoading();
                        this.enableForm(false);
                    })
                );
        },

        enableForm: function(b) {
            if (!b) {
                var greyOverlay = domConstruct.create('div', {
                    style: "pointer-events:none;position:absolute;top:0px;left:0;bottom:0;right:0;background-color:black;opacity:0.2;filter: alpha(opacity = 20);"
                }, this.domNode);

                domStyle.set(this.loadingText, 'color', 'red');
                this.loadingText.innerHTML = 'Cet outil n\'est pas utilisable avec cette couche !';
            }

            domStyle.set(this.searchFilteringSelect.domNode, 'disabled', b ? '' : 'true');
            this.searchFilteringSelect.set('disabled', !b);

            this.goButton.set('disabled', !b);
        },

        queryFromIds: function(firstId, lastId, functionToExecute){

            var query = new Query();

            query.returnGeometry = false;
            query.outFields = this.comboBoxServiceFields;
            query.returnDistinctValues = this.distinctValues;
            query.where = this.esriOIDField + '>=' + firstId + ' AND ' + this.esriOIDField + '<=' + lastId;

            var queryTask = new QueryTask(this.queryServiceUrl);

            queryTask.execute(query, lang.hitch(this, functionToExecute),
                    lang.hitch(this,function(error){
                        console.error(error);
                        this.enableForm(false);
                    })
                );
        }
    });
});