UNPKG

geoportal-extensions-openlayers

Version:

![GitHub package.json version](https://img.shields.io/github/package-json/v/IGNF/geoportal-extensions?filename=build%2Fscripts%2Frelease%2Fpackage-openlayers.json)

1,316 lines (1,180 loc) 61.7 kB
// import CSS import "../CSS/Controls/Isochrone/GPisochronOpenLayers.css"; // import OpenLayers import Control from "ol/control/Control"; import { unByKey as olObservableUnByKey } from "ol/Observable"; import VectorLayer from "ol/layer/Vector"; import VectorSource from "ol/source/Vector"; // import GeoJSON from "ol/format/GeoJSON"; import { Fill, Stroke, Style } from "ol/style"; // import geoportal library access import Gp from "geoportal-access-lib"; // import local import Utils from "../../Common/Utils"; import Logger from "../../Common/Utils/LoggerByDefault"; import SelectorID from "../../Common/Utils/SelectorID"; import Markers from "./Utils/Markers"; import Draggable from "../../Common/Utils/Draggable"; import Interactions from "./Utils/Interactions"; // import local with ol dependencies import LayerSwitcher from "./LayerSwitcher"; import LocationSelector from "./LocationSelector"; import ButtonExport from "./Export"; import GeoJSONExtended from "../Formats/GeoJSON"; // DOM import IsoDOM from "../../Common/Controls/IsoDOM"; var logger = Logger.getLogger("isocurve"); /** * @classdesc * * Isocurve Control. * * @constructor * @alias ol.control.Isocurve * @type {ol.control.Isocurve} * @extends {ol.control.Control} * @param {Object} options - Isocurve control options * @param {String} [options.apiKey] - API key for services call (isocurve and autocomplete services). The key "calcul" is used by default. * @param {Boolean} [options.ssl = true] - use of ssl or not (default true, service requested using https protocol) * @param {Boolean} [options.collapsed = true] - Specify if widget has to be collapsed (true) or not (false) on map loading. Default is true. * @param {Boolean} [options.draggable = false] - Specify if widget is draggable * @param {Boolean|Object} [options.export = false] - Specify if button "Export" is displayed. For the use of the options of the "Export" control, see {@link ol.control.Export} * @param {Object} [options.exclusions = {"toll" : false, "tunnel" : false, "bridge" : false}] - list of exclusions with status (true = checked). By default : no exclusions checked. * @param {Array} [options.graphs = ["Voiture", "Pieton"]] - list of graph resources to be used for isocurve calculation, by default : ["Voiture", "Pieton"]. Possible values are "Voiture" and "Pieton". The first element is selected. * @param {Array} [options.methods = ["time", "distance"]] - list of methods, by default : ["time", "distance"]. Possible values are "time" and "distance". The first element is selected by default. * @param {Array} [options.directions = ["departure", "arrival"]] - list of directions to be displayed, by default : ["departure", "arrival"]. The first element is selected by default. Possible values are "departure" and "arrival". * Directions enable to specify if input location point will be used as a departure point ("departure") or as an arrival point ("arrival") * @param {Object} [options.isocurveOptions = {}] - isocurve service options. see {@link http://ignf.github.io/geoportal-access-lib/latest/jsdoc/module-Services.html#~isoCurve Gp.Services.isoCurve()} to know all isocurve options. * @param {Object} [options.autocompleteOptions = {}] - autocomplete service options. see {@link http://ignf.github.io/geoportal-access-lib/latest/jsdoc/module-Services.html#~autoComplete Gp.Services.autoComplete()} to know all autocomplete options * @param {Object} [options.markerOpts] - options to use your own marker. Default is a lightOrange marker. * @param {String} [options.markerOpts.url] - marker base64 encoded url (ex "data:image/png;base64,...""). Mandatory for a custom marker * @param {Array} [options.markerOpts.offset] - Offsets in pixels used when positioning the overlay. The first element in the array is the horizontal offset. A positive value shifts the overlay right. The second element in the array is the vertical offset. A positive value shifts the overlay down. Default is [0, 0]. (see http://openlayers.org/en/latest/apidoc/ol.Overlay.html) * @param {Object} [options.layerDescription = {}] - Layer informations to be displayed in LayerSwitcher widget (only if a LayerSwitcher is also added to the map) * @param {String} [options.layerDescription.title = "Isochrone/Isodistance"] - Layer title to be displayed in LayerSwitcher * @param {String} [options.layerDescription.description = "isochrone/isodistance basé sur un graphe"] - Layer description to be displayed in LayerSwitcher * @fires isocurve:drawstart * @fires isocurve:drawend * @fires isocurve:compute * @fires export:compute * @example * var iso = ol.control.Isocurve({ * "collapsed" : false, * "draggable" : true, * "export" : false, * "methods" : ["time", "distance"], * "exclusions" : { * "toll" : true, * "bridge" : false, * "tunnel" : true * }, * "graphs" : ["Pieton", "Voiture"], * "markerOpts" : { * "url" : "...", * "offset" : [0,0] * } * "isocurveOptions" : {}, * "autocompleteOptions" : {} * }); * * // if you want to pluggued the control Export with options : * var iso = new ol.control.Isocurve({ * export : { * name : "export", * format : "geojson", * title : "Exporter", * menu : false * } * }); */ var Isocurve = (function (Control) { /** * See {@link ol.control.Isocurve} * @module Isocurve * @alias module:~Controls/Isocurve * @param {*} options - options * @example * import Isocurve from "src/OpenLayers/Controls/Isocurve" */ function Isocurve (options) { options = options || {}; if (!(this instanceof Isocurve)) { throw new TypeError("ERROR CLASS_CONSTRUCTOR"); } // initialisation du composant this.initialize(options); // // Widget main DOM container this._container = this._createMainContainerElement(); // info: le container sera complété lors de l'ajout à la carte (setMap), car certains composants nécessitent d'être liés à la map. this._containerElement = null; // on peut éventuellement encapsuler le composant dans une div passée par l'utilisateur if (options.element && options.element.appendChild) { // dans ce cas on stocke les deux container options.element.appendChild(this._container); this._containerElement = options.element; } // call ol.control.Control constructor Control.call(this, { element : this._containerElement || this._container, target : options.target, render : options.render }); }; // Inherits from ol.control.Control if (Control) Isocurve.__proto__ = Control; /** * @lends module:Isocurve */ Isocurve.prototype = Object.create(Control.prototype, {}); // on récupère les méthodes de la classe commune IsoDOM Utils.assign(Isocurve.prototype, IsoDOM); /** * Constructor (alias) * * @private */ Isocurve.prototype.constructor = Isocurve; /** * Overwrite OpenLayers setMap method * * @param {ol.Map} map - Map. */ Isocurve.prototype.setMap = function (map) { if (map) { // enrichissement du DOM du container lors de l'ajout à la carte this._container = this._initContainer(map); // ajout d'un bouton d'export if (this.options.export) { var opts = Utils.assign({ control : this }, this.options.export); this.export = new ButtonExport(opts); this.export.render(); var self = this; this.export.on("export:compute", (e) => { self.dispatchEvent({ type : "export:compute", content : e.content }); }); } // mode "draggable" if (this.draggable) { Draggable.dragElement( this._IsoPanelContainer, this._IsoPanelHeaderContainer, map.getTargetElement() ); } } // on appelle la méthode setMap originale d'OpenLayers Control.prototype.setMap.call(this, map); }; // ################################################################### // // ##################### public methods ############################## // // ################################################################### // /** * Returns true if widget is collapsed (minimized), false otherwise * * @returns {Boolean} collapsed - true if widget is collapsed */ Isocurve.prototype.getCollapsed = function () { return this.collapsed; }; /** * Collapse or display widget main container * * @param {Boolean} collapsed - True to collapse widget, False to display it */ Isocurve.prototype.setCollapsed = function (collapsed) { if (collapsed === undefined) { logger.log("[ERROR] Isocurve:setCollapsed - missing collapsed parameter"); return; } if ((collapsed && this.collapsed) || (!collapsed && !this.collapsed)) { return; } if (collapsed) { document.getElementById("GPisochronPanelClose-" + this._uid).click(); } else { document.getElementById("GPshowIsochronPicto-" + this._uid).click(); } this.collapsed = collapsed; }; /** * Get vector layer where Isocurve geometry is drawn * * @returns {Object} layer - ol.layer.Vector isocurve layer */ Isocurve.prototype.getLayer = function () { return this._geojsonLayer; }; /** * Set vector layer where Isocurve geometry is drawn * * @param {Object} layer - ol.layer.Vector isocurve layer */ Isocurve.prototype.setLayer = function (layer) { if (!layer) { this._geojsonLayer = null; return; } if (!(layer instanceof VectorLayer)) { logger.log("no valid layer given for hosting drawn features."); return; } // application des styles layer.setStyle(this._defaultFeatureStyle); // sauvegarde this._geojsonLayer = layer; }; /** * Get vector layer * * @returns {String} geojson - GeoJSON format layer */ Isocurve.prototype.getGeoJSON = function () { return JSON.stringify(this._geojsonObject); }; /** * Set vector layer * * @param {String} geojson - GeoJSON format layer */ Isocurve.prototype.setGeoJSON = function (geojson) { try { this._geojsonObject = JSON.parse(geojson); } catch (e) { logger.log("no valid geojson given :" + e.message); } }; /** * Get isocurve data * * @returns {Object} data - process results */ Isocurve.prototype.getData = function () { var data = { type : "isocurve", transport : this._currentTransport, computation : this._currentComputation, exclusions : this._currentExclusions, direction : this._currentDirection, point : this._originPoint.getCoordinate(), // lon/lat wgs84 results : {} }; Utils.assign(data.results, this._currentIsoResults); return data; }; /** * Set isocurve data * * @param {Object} data - control informations * @param {String} data.transport - transport type * @param {String} data.computation - computation type * @param {Array} data.exclusions - list of exclusions * @param {String} data.direction - direction type * @param {Array} data.point - [lon, lat] * @param {Object} data.results - service response */ Isocurve.prototype.setData = function (data) { this._currentTransport = data.transport; this._currentComputation = data.computation; this._currentExclusions = data.exclusions; this._currentDirection = data.direction; // INFO // > this._originPoint.clear(); // l'utilisation de cette méthode declenche des evenements qui retirent la couche en cours ! // (cf. _createIsoPanelFormPointElement), var inputPointer = document.getElementById("GPlocationOriginPointer_" + 1 + "-" + this._uid); inputPointer.checked = true; var inputCoords = document.getElementById("GPlocationOriginCoords_" + 1 + "-" + this._uid); inputCoords.value = ""; this._originPoint.setCoordinate(data.point, "EPSG:4326"); this._currentIsoResults = data.results; }; /** * Get container * * @returns {DOMElement} container */ Isocurve.prototype.getContainer = function () { return this._container; }; /** * Get default style * * @returns {ol.style} style */ Isocurve.prototype.getStyle = function () { return this._defaultFeatureStyle; }; /** * This method is public. * It allows to control the execution of a traitment. * * @param {Array} position - position in the projection map [ x, y ] * @param {Object} value - distance in km or hours-minutes * @param {Object} options - options = {...} */ Isocurve.prototype.compute = function (position, value, options) { this._clear(); if (!this._showIsoContainer.checked) { this._pictoIsoContainer.click(); } var map = this.getMap(); if (!map) { return; } // Les options par defauts var settings = { direction : "departure", method : "time", transport : "Voiture", exclusions : [] }; // On recupere les options Utils.assign(settings, options); this._originPoint.setCoordinate(position); var coordinate = this._originPoint.getCoordinate(); var input = document.getElementById("GPlocationOrigin_" + 1 + "-" + this._uid); input.value = coordinate[0].toFixed(4) + " / " + coordinate[1].toFixed(4); this._currentTransport = settings.transport; if (settings.transport === "Voiture") { document.getElementById("GPisochronTransportCar-" + this._uid).checked = true; } else { document.getElementById("GPisochronTransportPedestrian-" + this._uid).checked = true; } this._currentExclusions = settings.exclusions; this._currentComputation = settings.method; if (settings.method === "time") { var time = value.split("."); this._currentTimeHour = time[0] || 0; document.getElementById("GPisochronValueChronInput1-" + this._uid).value = this._currentTimeHour; this._currentTimeMinute = time[1] || 0; document.getElementById("GPisochronValueChronInput2-" + this._uid).value = this._currentTimeMinute; document.getElementById("GPisochronChoiceAltChron-" + this._uid).click(); } else { this._currentDistance = value; document.getElementById("GPisochronValueDistInput-" + this._uid).value = this._currentDistance; document.getElementById("GPisochronChoiceAltDist-" + this._uid).click(); } this._currentDirection = settings.direction; (settings.direction === "departure") ? document.getElementById("GPisochronDirectionSelect-" + this._uid).selectedIndex = 0 : document.getElementById("GPisochronDirectionSelect-" + this._uid).selectedIndex = 1; this.onIsoComputationSubmit(); }; /** * This method is public. * It allows to init the control. */ Isocurve.prototype.init = function () { // point var coordinate = this._originPoint.getCoordinate(); var input = document.getElementById("GPlocationOrigin_" + 1 + "-" + this._uid); input.value = coordinate[1].toFixed(4) + " / " + coordinate[0].toFixed(4); // transport if (this._currentTransport === "Voiture") { document.getElementById("GPisochronTransportCar-" + this._uid).checked = true; } else { document.getElementById("GPisochronTransportPedestrian-" + this._uid).checked = true; } // method if (this._currentComputation === "time") { var minutes = this._currentIsoResults.time / 60; this._currentTimeHour = Math.floor(minutes / 60); document.getElementById("GPisochronValueChronInput1-" + this._uid).value = this._currentTimeHour; this._currentTimeMinute = Math.round(((minutes / 60) - this._currentTimeHour) * 60); document.getElementById("GPisochronValueChronInput2-" + this._uid).value = this._currentTimeMinute; document.getElementById("GPisochronChoiceAltChron-" + this._uid).click(); } else { this._currentDistance = this._currentIsoResults.distance / 1000; document.getElementById("GPisochronValueDistInput-" + this._uid).value = this._currentDistance; document.getElementById("GPisochronChoiceAltDist-" + this._uid).click(); } // direction (this._currentDirection === "departure") ? document.getElementById("GPisochronDirectionSelect-" + this._uid).selectedIndex = 0 : document.getElementById("GPisochronDirectionSelect-" + this._uid).selectedIndex = 1; }; /** * Clean UI : reinit control */ Isocurve.prototype.clean = function () { this._clearIsoInputs(); // INFO // le comportement est surchargé, ceci supprime la couche !? // cf. _createIsoPanelFormPointElement() this._originPoint.clearResults(); document.getElementById("GPlocationPoint_1-" + this._uid).style.cssText = ""; document.getElementById("GPlocationOriginCoords_1-" + this._uid).value = ""; document.getElementById("GPlocationOrigin_1-" + this._uid).value = ""; document.getElementById("GPlocationPoint_1-" + this._uid).style.cssText = ""; document.getElementById("GPlocationOriginPointer_1-" + this._uid).checked = false; document.getElementById("GPlocationOrigin_1-" + this._uid).className = "GPlocationOriginVisible"; document.getElementById("GPlocationOriginCoords_1-" + this._uid).className = "GPlocationOriginHidden"; this._currentIsoResults = null; this.setLayer(); }; // ################################################################### // // ##################### init component ############################## // // ################################################################### // /** * Initialize Isocurve control (called by Isocurve constructor) * * @param {Object} options - constructor options * @private */ Isocurve.prototype.initialize = function (options) { this._checkInputOptions(options); // set default options this.options = { collapsed : true, draggable : false, export : false, methods : ["time", "distance"], graphs : ["Voiture", "Pieton"], exclusions : { toll : false, tunnel : false, bridge : false }, directions : ["departure", "arrival"], markerOpts : { url : Markers["lightOrange"], offset : Markers.defaultOffset }, isocurveOptions : {}, autocompleteOptions : {}, layerDescription : { title : "Isochrone/Isodistance", description : "isochrone/isodistance basé sur un graphe" } }; // merge with user options Utils.assign(this.options, options); /** {Boolean} specify if isocurve control is collapsed (true) or not (false) */ this.collapsed = this.options.collapsed; /** {Boolean} specify if isocurve control is draggable (true) or not (false) */ this.draggable = this.options.draggable; // identifiant du contrôle : utile pour suffixer les identifiants CSS (pour gérer le cas où il y en a plusieurs dans la même page) this._uid = SelectorID.generate(); // Options du service paramétrables via l'interface (graph, method, exclusions) // Mode de transport selectionné : 'Voiture' ou 'Pieton' this._currentTransport = null; this._initTransport(); // Mode de calcul selectionné : 'time' (isochron) ou 'distance' (isodistance) this._currentComputation = null; this._initComputation(); // Exclusions selectionnées : Tunnel, Toll et Bridge this._currentExclusions = []; this._initExclusions(); // sens de parcours : "departure" ou "arrival" this._currentDirection = null; this._initDirection(); // point de saisie this._originPoint = null; // // containers principaux this._showIsoContainer = null; this._pictoIsoContainer = null; this._waitingContainer = null; this._formContainer = null; this._IsoPanelContainer = null; this._IsoPanelHeaderContainer = null; // les résultats du calcul this._currentIsoResults = null; // la géométrie this._geojsonLayer = null; this._geojsonObject = null; // bouton export this.export = null; // si un calcul est en cours ou non this._waiting = false; // timer pour cacher la patience après un certain temps this._timer = null; // styles pour les sélections des features this._defaultFeatureStyle = new Style({ fill : new Fill({ color : "rgba(0, 183, 152, 0.7)" }), stroke : new Stroke({ color : "rgba(0, 183, 152, 0)", width : 1 }) }); // liste des ressources avec droits par service // Ex. { // "Isocurve" : { // key : "ger4g456re45er456t4er5ge5", // resources : ["Pieton", "Voiture"] // } // } this._resources = {}; // listener key for event click on map this.listenerKey = null; }; /** * this method is called by this.initialize() * * @param {Object} options - options * * @private */ Isocurve.prototype._checkInputOptions = function (options) { // vérification des options // on ne permet pas de n'afficher aucun mode de calcul ou aucun mode de transport ? var i; // modes de calcul if (options.methods) { if (Array.isArray(options.methods)) { // on ne permet pas de passer un tableau vide : on spécifie au moins une méthode if (options.methods.length === 0) { options.methods = null; } else { for (i = 0; i < options.methods.length; i++) { if (typeof options.methods[i] !== "string") { logger.log("[ol.control.Isocurve] ERROR : parameter 'methods' elements should be of type 'string'"); } } } } else { logger.warn("'methods' parameter should be an array"); options.methods = null; } } // mode de transport if (options.graphs) { if (Array.isArray(options.graphs)) { // on ne permet pas de passer un tableau vide : on spécifie au moins un graph if (options.graphs.length === 0) { options.graphs = null; } else { for (i = 0; i < options.graphs.length; i++) { if (typeof options.graphs[i] !== "string") { logger.log("[ol.control.Isocurve] ERROR : parameter 'graphs' elements should be of type 'string'"); } else { if (options.graphs[i].toLowerCase() === "pieton") { options.graphs[i] = "Pieton"; } if (options.graphs[i].toLowerCase() === "voiture") { options.graphs[i] = "Voiture"; } } } } } else { logger.warn("'graphs' parameter should be an array"); options.graphs = null; } } // sens du parcours if (options.directions) { if (Array.isArray(options.directions)) { // on ne permet pas de passer un tableau vide : on spécifie au moins une direction if (options.directions.length === 0) { options.directions = null; } else { for (i = 0; i < options.directions.length; i++) { if (typeof options.directions[i] !== "string") { logger.log("[ol.control.Isocurve] ERROR : parameter 'directions' elements should be of type 'string'"); } } } } else { logger.warn("'directions' parameter should be an array"); options.directions = null; } } // collapsed if (options.collapsed === "true") { options.collapsed = true; } if (options.collapsed === "false") { options.collapsed = false; } }; /** * this method is called by this.initialize() and initialize transport mode * ("Voiture" ou "Pieton") * * @private */ Isocurve.prototype._initTransport = function () { // Mode de transport selectionné this._currentTransport = "Voiture"; // par defaut // par defaut var transports = this.options.graphs; if (!transports || transports.length === 0) { this.options.graphs = ["Voiture", "Pieton"]; } // option if (Array.isArray(transports) && transports.length) { // FIXME pb si le 1er graphe n'est pas une ressource connue ! if (transports[0] === "Voiture" || transports[0] === "Pieton") { this._currentTransport = transports[0]; } } // si l'utilisateur a spécifié un graph dans le service, on surcharge les options du widget var serviceOptions = this.options.isocurveOptions; if (serviceOptions.graph) { this._currentTransport = serviceOptions.graph; } }; /** * this method is called by this.initialize() and initialize computation mode * (time or distance) * * @private */ Isocurve.prototype._initComputation = function () { // Mode de calcul selectionné this._currentComputation = "time"; // par defaut // par defaut var methods = this.options.methods; if (!methods || methods.length === 0) { this.options.methods = ["time", "distance"]; } // option if (Array.isArray(methods) && methods.length) { // FIXME pb si le 1er graphe n'est pas une ressource connue ! if (methods[0] === "time" || methods[0] === "distance") { this._currentComputation = methods[0]; } } // si l'utilisateur a spécifié une méthode dans le service, on surcharge les options du widget var serviceOptions = this.options.isocurveOptions; if (serviceOptions.method) { this._currentComputation = serviceOptions.method; } if (serviceOptions.time) { this._currentComputation = "time"; } if (serviceOptions.distance) { this._currentComputation = "distance"; } }; /** * this method is called by this.initialize() and initialize direction mode * (departure or arrival) * * @private */ Isocurve.prototype._initDirection = function () { // Mode de calcul selectionné this._currentDirection = "departure"; // par defaut // par defaut var directions = this.options.directions; if (!directions || directions.length === 0) { this.options.directions = ["departure", "arrival"]; } // option if (Array.isArray(directions) && directions.length) { // FIXME pb si le 1er graphe n'est pas une ressource connue ! if (directions[0] === "departure" || directions[0] === "arrival") { this._currentDirection = directions[0]; } } // si l'utilisateur a spécifié une méthode dans le service, on surcharge les options du widget var serviceOptions = this.options.isocurveOptions; if (!serviceOptions.reverse) { this._currentDirection = "departure"; } if (serviceOptions.reverse === true) { this._currentDirection = "arrival"; this.options.directions = ["arrival", "departure"]; } }; /** * this method is called by this.initialize() and initialize exclusions * * @private */ Isocurve.prototype._initExclusions = function () { // Exclusions selectionnées : Tunnel, Toll et Bridge this._currentExclusions = []; // par defaut // par defaut var exclusion = this.options.exclusions; if (!exclusion || (typeof exclusion === "object" && Object.keys(exclusion).length === 0)) { this.options.exclusions = { toll : false, tunnel : false, bridge : false }; } // option if (exclusion && typeof exclusion === "object" && Object.keys(exclusion).length) { for (var k in exclusion) { if (exclusion.hasOwnProperty(k)) { if (exclusion.k) { this._currentExclusions.push(k); } } } } // si l'utilisateur a spécifié des exclusions dans le service, on surcharge les options du widget var serviceOptions = this.options.isocurveOptions; if (Array.isArray(serviceOptions.exclusions)) { this._currentExclusions = serviceOptions.exclusions; } }; // ################################################################### // // ######################## DOM initialize ########################### // // ################################################################### // /** * initialize component container (DOM) * * @param {Object} map - the map * * @returns {DOMElement} DOM element * * @private */ Isocurve.prototype._initContainer = function (map) { // get main container var container = this._container; var inputShow = this._showIsoContainer = this._createShowIsoElement(); container.appendChild(inputShow); // mode "collapsed" if (!this.collapsed) { inputShow.checked = true; } var picto = this._pictoIsoContainer = this._createShowIsoPictoElement(); container.appendChild(picto); // panneau var panel = this._IsoPanelContainer = this._createIsoPanelElement(); // header var header = this._IsoPanelHeaderContainer = this._createIsoPanelHeaderElement(); panel.appendChild(header); // form var form = this._formContainer = this._createIsoPanelFormElement(); // form: input de saisie de la localisation (fonction de Isocurve, voir ci-dessous) var point = this._createIsoPanelFormPointElement(map); form.appendChild(point); var isoChronChecked = false; var isoDistChecked = false; var typeChoice = this._createIsoPanelFormTypeChoiceElement(); for (var i = 0; i < this.options.methods.length; i++) { if (this.options.methods[i] === "time") { isoChronChecked = (i === 0); typeChoice.appendChild(this._createIsoPanelFormTypeChoiceChronElement(isoChronChecked)); } if (this.options.methods[i] === "distance") { isoDistChecked = (i === 0); typeChoice.appendChild(this._createIsoPanelFormTypeChoiceDistElement(isoDistChecked)); } } form.appendChild(typeChoice); // form: menu du choix des valeurs form.appendChild(this._createIsoPanelFormValueIsochronElement(isoChronChecked)); form.appendChild(this._createIsoPanelFormValueIsodistanceElement(isoDistChecked)); // form: menu du choix du transport et du sens du parcours var modeChoice = this._createIsoPanelFormModeChoiceElement(); modeChoice.appendChild(this._createIsoPanelFormModeChoiceTransportElement(this.options.graphs)); // FIXME : doit on passer le paramètre defaultDirection ? modeChoice.appendChild(this._createIsoPanelFormModeChoiceDirectionElement(this.options.directions)); form.appendChild(modeChoice); // form: menu des exclusions if (this.options.exclusions && (typeof this.options.exclusions === "object") && (Object.keys(this.options.exclusions).length !== 0)) { form.appendChild(this._createShowIsoExclusionsElement()); form.appendChild(this._createShowIsoExclusionsPictoElement()); var exclusion = this._createIsoPanelFormExclusionsElement(); exclusion.appendChild(this._createIsoPanelFormExclusionOptionsElement(this.options.exclusions)); form.appendChild(exclusion); } var divReset = this._createIsoFormResetElement(); form.appendChild(divReset); // form: bouton du calcul var submit = this._submitContainer = this._createIsoSubmitFormElement(); form.appendChild(submit); panel.appendChild(form); // waiting var waiting = this._waitingContainer = this._createIsoWaitingElement(); panel.appendChild(waiting); container.appendChild(panel); // hide autocomplete suggested locations on container click if (container.addEventListener) { container.addEventListener("click", (e) => this._hideIsoSuggestedLocations(e)); } return container; }; /** * Create start point * * @param {Object} map - the map * * @returns {Object} DOM element * @private */ Isocurve.prototype._createIsoPanelFormPointElement = function (map) { this._originPoint = new LocationSelector({ apiKey : this.options.apiKey || null, tag : { id : 1, groupId : this._uid, markerOpts : this.options.markerOpts, label : "Départ", display : true }, autocompleteOptions : this.options.autocompleteOptions || null }); this._originPoint.setMap(map); // a la sélection d'un nouveau point, on réinitialise aussi le tracé var self = this; // click sur le pointer document.getElementById("GPlocationOriginPointerImg_1-" + this._uid).onclick = function () { self._clearGeojsonLayer(); var map = self.getMap(); if (self._originPoint._inputShowPointerContainer.checked) { // au click sur l'input pour pointer sur la carte: on minimise le formulaire self._formContainer.className = "GPisochronFormMini"; // et au clic sur la carte, on réaffichera le formulaire "normal" this.listenerKey = map.on( "click", () => { self._formContainer.className = ""; self.dispatchEvent("isocurve:drawend"); } ); } else { // si on déselectionne le pointer, on rétablit le formulaire en mode normal self._formContainer.className = ""; // et on enlève l'écouteur d'évènement sur la carte // map.un("click", () => { self._formContainer.className = ""; }); olObservableUnByKey(this.listenerKey); } /** * event triggered at the start of drawing input * * @event isocurve:drawstart */ self.dispatchEvent("isocurve:drawstart"); }; // click sur le label document.getElementById("GPlocationOriginLabel_1-" + this._uid).onclick = function () { self._clearGeojsonLayer(); self._formContainer.className = ""; // on désactive l'écouteur d'événements sur la carte (pour ne pas placer un marker au clic) map.un( "click", () => { self._formContainer.className = ""; } ); self.dispatchEvent("isocurve:drawend"); }; // click sur la zone de saisie document.getElementById("GPlocationOrigin_1-" + this._uid).onclick = function () { self._clearGeojsonLayer(); /** * event triggered at the end of drawing input * * @event isocurve:drawend */ self.dispatchEvent("isocurve:drawend"); }; return this._originPoint._container; }; // ################################################################### // // ####################### handlers events to dom #################### // // ################################################################### // /** * this method is called by event 'submit' on 'GPisochronForm' tag form * (cf. this._createIsoPanelFormElement), * and call isocurve service to display results * * @private */ Isocurve.prototype.onIsoComputationSubmit = function () { // si on n'a pas de valeur récupérée pour notre point origine, on ne fait rien if (!this._originPoint || !this._originPoint.getCoordinate || !this._originPoint.getCoordinate()) { logger.log("[Isocurve] Missing position parameter to submit isocurve request"); return; } // récupération de l'origine var positionCoordinates = this._originPoint.getCoordinate(); var position = { x : positionCoordinates[0], y : positionCoordinates[1] }; logger.log("origin : ", position); // récupération du temps ou de la distance var time; var distance; if (this._currentComputation.toLowerCase() === "time") { var timeHourInput = document.getElementById("GPisochronValueChronInput1-" + this._uid); var hours = parseInt(timeHourInput.value, 10); if (isNaN && isNaN(hours)) { hours = 0; } var timeMinutesInput = document.getElementById("GPisochronValueChronInput2-" + this._uid); var minutes = parseInt(timeMinutesInput.value, 10); if (isNaN && isNaN(minutes)) { minutes = 0; } // durée exprimée en secondes time = hours * 3600 + minutes * 60; logger.log("time : " + time); } if (this._currentComputation.toLowerCase() === "distance") { var distInput = document.getElementById("GPisochronValueDistInput-" + this._uid); // distance exprimée en mètres distance = parseFloat(distInput.value) * 1000; logger.log("distance : " + distance); } // si on n'a pas de valeur de calcul renseignée, on ne lance pas la requête. if (!time && !distance) { logger.log("[Isocurve] Missing time or distance parameter to submit isocurve request"); return; } // on recupere les éventuelles options du service passées par l'utilisateur var options = this.options.isocurveOptions || {}; // gestion du protocole et du timeout // le timeout est indispensable sur le protocole JSONP. var _protocol = options.protocol || "XHR"; var _timeout = options.timeOut || 0; if (_protocol === "JSONP" && _timeout === 0) { // FIXME le timeout est obligatoire pour ce type de protocole... _timeout = 15000; } // gestion des callback var bOnFailure = !!(options.onFailure !== null && typeof options.onFailure === "function"); // cast variable to boolean var bOnSuccess = !!(options.onSuccess !== null && typeof options.onSuccess === "function"); // on met en place l'affichage des resultats dans la fenetre de resultats. var context = this; var isoRequestOptions = { position : position, graph : options.graph || this._currentTransport, exclusions : options.exclusions || this._currentExclusions, method : options.method || this._currentComputation, smoothing : options.smoothing || true, timeOut : _timeout, protocol : _protocol, resource : options.resource, // callback onSuccess onSuccess : function (results) { logger.log(results); if (results) { context._drawIsoResults(results); } if (bOnSuccess) { options.onSuccess.call(context, results); } }, // callback onFailure onFailure : function (error) { // FIXME mise à jour du controle mais le service ne repond pas en 200 !? context._hideWaitingContainer(); logger.log(error.message); if (bOnFailure) { options.onFailure.call(context, error); } } }; if ((this._currentDirection.toLowerCase() === "arrival") || (options.reverse)) { isoRequestOptions.reverse = true; } if (time) { isoRequestOptions.time = time; } if (distance) { isoRequestOptions.distance = distance; } this._requestIsoCurve(isoRequestOptions); }; /** * this method is called by event 'click' on 'GPshowIsochronPicto' picto * (cf. this._createShowIsoPictoElement), * and clear inputs and previous isocurve drawings * * @private */ Isocurve.prototype.onShowIsoPanelClick = function () { var map = this.getMap(); // on supprime toutes les interactions Interactions.unset(map); this.collapsed = this._showIsoContainer.checked; // on génère nous même l'evenement OpenLayers de changement de propriété // (utiliser ol.control.Isocurve.on("change:collapsed", function ) pour s'abonner à cet évènement) this.dispatchEvent("change:collapsed"); }; /** * this method is called by event 'change' on 'GPisochronChoiceAltDist' or 'GPisochronChoiceAltChron' * input (cf. this._createIsoPanelFormTypeChoiceElement), * and updates current computation mode * * @param {Object} e - HTMLElement * @private */ Isocurve.prototype.onIsoTypeChoiceChange = function (e) { var value = e.target.value; if (!value) { return; } if (value === "isodistance") { this._currentComputation = "distance"; } if (value === "isochron") { this._currentComputation = "time"; } }; /** * this method is called by event 'click' on 'GPisochronTransportPedestrian' or 'GPisochronTransportCar' * input (cf. this._createIsoPanelFormModeChoiceTransportElement), * and updates current transport mode * * @param {Object} e - HTMLElement * @private */ Isocurve.prototype.onIsoModeTransportChange = function (e) { var value = e.target.value; if (!value) { return; } this._currentTransport = value; }; /** * this method is called by event 'change' on 'GPisochronDirectionSelect' select * (cf. this._createIsoPanelFormModeChoiceDirectionElement), * and updates current direction mode * * @param {Object} e - HTMLElement * @private */ Isocurve.prototype.onIsoModeDirectionChange = function (e) { var value = e.target.value; if (!value) { return; } if (value.toLowerCase() === "arrival") { this._originPoint._inputLabelContainer.innerHTML = "Arrivée"; } else { this._originPoint._inputLabelContainer.innerHTML = "Départ"; } this._currentDirection = value; }; /** * this method is called by event 'change' on 'GPIsoExclusionsToll' * or 'GPIsoeExclusionsTunnel' or 'GPIsoExclusionsBridge' tag input * (cf. this._createIsoPanelFormExclusionOptionsElement). * this value is saved as a parameter for the service isocurve. * * @param {Object} e - HTMLElement * @private */ Isocurve.prototype.onIsoExclusionsChange = function (e) { var value = e.target.value; var checked = e.target.checked; if (!value) { return; } var bFound = false; var iFound = null; for (var i = 0; i < this._currentExclusions.length; i++) { if (deepEqual(this._currentExclusions[i], value.toLowerCase())) { iFound = i; bFound = true; } } // on l'ajoute si la valeur n'existe pas et est selectionnée if (!bFound && !checked) { this._currentExclusions.push(value.toLowerCase()); } // on la retire si la valeur existe et est deselectionnée if (bFound && checked) { this._currentExclusions[iFound] = null; } }; /** * this method is called by event 'click' on 'GPisoReset' * tag label (cf. this._createIsoFormResetElement), * and it cleans all isochron input options and results. * * @private */ Isocurve.prototype.onIsoResetClick = function () { // clear this._clear(); }; // ################################################################### // // ######################## isocurve calculation ##################### // // ################################################################### // /** * this method is called by this.onIsoComputationSubmit * and executes a request to the service. * * @param {Object} options - isocurve service request options * @private */ Isocurve.prototype._requestIsoCurve = function (options) { // on ne fait pas de requête si on n'a pas renseigné de parametres ! if (!options || ((typeof options === "object") && (Object.keys(options).length === 0))) { return; } // on ne fait pas de requête si on n'a pas de point d'origine if (!options.position) { return; } // si l'utilisateur a spécifié le paramètre ssl au niveau du control, on s'en sert // true par défaut (https) if (typeof options.ssl !== "boolean") { if (typeof this.options.ssl === "boolean") { options.ssl = this.options.ssl; } else { options.ssl = true; } } logger.log(options); // on efface une éventuelle précédente couche this._clearGeojsonLayer(); // mise en place de la patience this._displayWaitingContainer(); // appel du service de calcul d'isochrones Gp.Services.isoCurve(options); }; /** * this method is called by this.onIsoComputationSubmit (in case of success) * and draw isocurve results geometry on map * * @param {Object} results - isocurve response results * @private */ Isocurve.prototype._drawIsoResults = function (results) { // sauvegarde de l'etat des resultats this._currentIsoResults = results; // cache la patience this._hideWaitingContainer(); if (!results.geometry) { return; } var map = this.getMap(); // 1. création de l'objet geoJSON this._geojsonObject = { type : "FeatureCollection", crs : { type : "name", properties : { name : "EPSG:4326" } }, features : [ { type : "Feature", crs : { type : "name", properties : { name : "EPSG:4326" } }, geometry : results.geometry } ] }; this._geojsonObject.features.push({ type : "Feature", geometry : { type : "Point", coordinates : this._originPoint.getCoordinate() }, properties : { description : "Point d'origine", "marker-symbol" : this.options.markerOp