+ var container = document.createElement("div");
+ container.className = "GPlayerAdvancedToolsRelief";
+
+ var array = this._createAdvancedToolReliefElement(brOptions.scale, brOptions.defaultBoost);
+ for (var j = 0; j < array.length; j++) {
+ container.appendChild(array[j]);
+ }
+
+ return container;
+ },
+ /**
+ * Creation de l'icone de gestion du relief du layer (DOM)
+ *
+ * @param {Object} scale - définition de l'echelle que le slider utilise (min,max,step)
+ *
+ * @returns {DOMElement[]} array of two containers
+ */
+ _createAdvancedToolReliefElement : function (scale, defaultBoost) {
+ // exemple :
+ //
+ // Layer1
+ //
+ //
+ //
+ //
+ //
+ //
+ // 100
+ // %
+ //
+
+ var list = [];
+
+ // curseur pour changer l'exageration du relief
+ var divB = document.createElement("div");
+ divB.className = "GPlayerRelief";
+ divB.title = "Relief";
+
+ // le relief est à un facteur 1 par défaut
+ var relief = 1;
+
+ var input = document.createElement("input");
+ input.id = this._addUID("GPreliefValueDiv");
+ input.type = "range";
+
+ // echelle de 1 à 50 par defaut
+ if (!scale) {
+ scale = {
+ min : 1,
+ max : 50,
+ step : 1
+ };
+ };
+
+ input.min = scale.min || 1;
+ input.max = scale.max || 50;
+ input.step = scale.step || 1;
+
+
+ // le relief est à un facteur 1 par défaut
+ var defaultBoostValue = 1;
+ if (defaultBoost) {
+ defaultBoostValue = defaultBoost;
+ }
+
+ // the reliefValue given must me in the slider range
+ if (defaultBoostValue > input.max) {
+ defaultBoostValue = input.max;
+ }
+
+ if (defaultBoostValue < input.min) {
+ defaultBoostValue = input.min;
+ }
+
+ // mise à jour des couches et du slider une fois le controle ajouté
+ input.value = defaultBoostValue;
+
+ // add event for relief change
+ var context = this;
+ if (input.addEventListener) {
+ input.addEventListener(
+ "change",
+ function (e) {
+ context._onChangeLayerRelief(e);
+ }
+ );
+ } else if (input.attachEvent) {
+ // internet explorer
+ input.attachEvent(
+ "onchange",
+ function (e) {
+ context._onChangeLayerRelief(e);
+ }
+ );
+ }
+
+ if (input.addEventListener) {
+ input.addEventListener(
+ "input",
+ function (e) {
+ context._onChangeLayerRelief(e);
+ }
+ );
+ } else if (input.attachEvent) {
+ // internet explorer
+ input.attachEvent(
+ "oninput",
+ function (e) {
+ context._onChangeLayerRelief(e);
+ }
+ );
+ }
+
+ divB.appendChild(input);
+
+ // Valeur d'echelle du relief
+ var divC = document.createElement("div");
+ divC.id = this._addUID("GPreliefValueDiv");
+ divC.className = "GPlayerReliefValue";
+
+ var span = document.createElement("span");
+ span.id = this._addUID("GPreliefValue");
+ span.innerHTML = "x" + relief;
+
+ divC.appendChild(span);
+
+ list.push(divB);
+ list.push(divC);
+
+ return list;
+ },
+
+ /**
+ * Création du conteneur principal des couches MNT boostRelief (DOM)
+ *
+ * @returns {DOMElement} div DOM
+ */
+ _createMainBoostReliefListContainer : function () {
+ var div = document.createElement("div");
+ div.id = this._addUID("GPBoostReliefListContainer");
+ div.className = "GPpanel";
+
+ return div;
+ },
+
+ /**
+ * Show boostRelief control
+ * @param {Boolean} isDesktop - specifies if the support is desktop or tactile
+ *
+ * @returns {DOMElement} DOM element
+ */
+
+ _createMainPictoElement : function () {
+ var self = this;
+ var label = document.createElement("label");
+
+ label.id = this._addUID("GPshowBoostReliefListPicto");
+ label.className = "GPshowAdvancedToolPicto";
+ label.htmlFor = this._addUID("GPshowBoostReliefList");
+ label.title = "Afficher/Masquer le control d'exageration du relief";
+
+ var spanOpenClose = document.createElement("span");
+ spanOpenClose.id = this._addUID("GPshowBoostReliefOpenClose");
+ spanOpenClose.className = "GPshowAdvancedToolOpen";
+
+ /** Evenement de type 'click' sur le picto du controle */
+ label.addEventListener("click", function () {
+ if (document.getElementById(self._addUID("GPshowBoostReliefList")).checked) {
+ document.getElementById(self._addUID("GPBoostReliefListContainer")).style.display = "none";
+ } else {
+ document.getElementById(self._addUID("GPBoostReliefListContainer")).style.display = "block";
+ }
+ });
+
+ label.appendChild(spanOpenClose);
+
+ return label;
+ }
+};
+
+export default BoostReliefDOM;
diff --git a/src/Common-review/Controls/DrawingDOM.js b/src/Common-review/Controls/DrawingDOM.js
new file mode 100644
index 000000000..0db76f948
--- /dev/null
+++ b/src/Common-review/Controls/DrawingDOM.js
@@ -0,0 +1,671 @@
+import Logger from "../../Common/Utils/LoggerByDefault";
+
+var logger = Logger.getLogger("DrawingDOM");
+
+var DrawingDOM = {
+
+ /**
+ * Add uuid to the tag ID
+ * @param {String} id - id selector
+ * @returns {String} uid - id selector with an unique id
+ */
+ _addUID : function (id) {
+ var uid = (this._uid) ? id + "-" + this._uid : id;
+ return uid;
+ },
+
+ /**
+ * Main container (DOM)
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createMainContainerElement : function () {
+ var container = document.createElement("div");
+ container.id = this._addUID("GPdrawing");
+ container.className = "GPwidget";
+ return container;
+ },
+
+ // ################################################################### //
+ // ################### Methods of main container ##################### //
+ // ################################################################### //
+
+ /**
+ * Hidden checkbox for minimizing/maximizing
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createShowDrawingElement : function () {
+ var input = document.createElement("input");
+ input.id = this._addUID("GPshowDrawing");
+ input.className = "GPshowDrawing";
+ input.type = "checkbox";
+ return input;
+ },
+
+ /**
+ * Show mouse position control
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createShowDrawingPictoElement : function () {
+ var self = this;
+
+ var label = document.createElement("label");
+ label.id = this._addUID("GPshowDrawingPicto");
+ label.className = "GPshowAdvancedToolPicto";
+ label.htmlFor = this._addUID("GPshowDrawing");
+ label.title = this.options.labels.control;
+
+ // gestionnaire d'evenement :
+ // on ouvre le menu de saisie de saisie
+ // L'ouverture/Fermeture permet de faire le menage
+ // (reinitialisation)
+ if (label.addEventListener) {
+ label.addEventListener("click", function (e) {
+ self.onShowDrawingClick(e);
+ });
+ } else if (label.attachEvent) {
+ label.attachEvent("onclick", function (e) {
+ self.onShowDrawingClick(e);
+ });
+ }
+
+ var spanOpen = document.createElement("span");
+ spanOpen.id = this._addUID("GPshowDrawingOpen");
+ spanOpen.className = "GPshowAdvancedToolOpen";
+ label.appendChild(spanOpen);
+
+ return label;
+ },
+
+ /**
+ * Drawing panel
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createDrawingPanelElement : function () {
+ var div = document.createElement("div");
+ div.id = this._addUID("GPdrawingPanel");
+ div.className = "GPpanel";
+
+ return div;
+ },
+
+ // ################################################################### //
+ // ####################### Panel container ########################### //
+ // ################################################################### //
+
+ /**
+ * Creates drawing Panel header DOM structure
+ * @returns {DOMElement} DOM element
+ */
+ _createDrawingPanelHeaderElement : function () {
+ /*
+ *
+ *
Annoter la carte
+ *
+ *
+ */
+
+ var container = document.createElement("div");
+ container.className = "GPpanelHeader";
+
+ var divTitle = document.createElement("div");
+ divTitle.className = "GPpanelTitle";
+ divTitle.innerHTML = this.options.controlLabel || "Annoter la carte";
+ container.appendChild(divTitle);
+
+ var divClose = document.createElement("div");
+ divClose.id = this._addUID("GPdrawingPanelClose");
+ divClose.className = "GPpanelClose";
+ divClose.title = "Fermer le panneau";
+
+ // Link panel close / visibility checkbox
+ var dtObj = this;
+ if (divClose.addEventListener) {
+ divClose.addEventListener("click", function () {
+ document.getElementById(dtObj._addUID("GPshowDrawingPicto")).click();
+ }, false);
+ } else if (divClose.attachEvent) {
+ divClose.attachEvent("onclick", function () {
+ document.getElementById(dtObj._addUID("GPshowDrawingPicto")).click();
+ });
+ }
+
+ container.appendChild(divClose);
+
+ return container;
+ },
+
+ /**
+ * Creates drawing tools section.
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createDrawingToolsSections : function () {
+ var tools = [];
+
+ this.dtOptions = {};
+ if (this.options.tools.points) {
+ this.dtOptions.points = {
+ label : this.options.labels.points,
+ active : false,
+ panel : "draw",
+ id : "point"
+ };
+ }
+ if (this.options.tools.lines) {
+ this.dtOptions.lines = {
+ label : this.options.labels.lines,
+ active : false,
+ panel : "draw",
+ id : "line"
+ };
+ }
+ if (this.options.tools.polygons) {
+ this.dtOptions.polygons = {
+ label : this.options.labels.polygons,
+ active : false,
+ panel : "draw",
+ id : "polygon"
+ };
+ }
+ if (this.options.tools.holes) {
+ this.dtOptions.holes = {
+ label : this.options.labels.holes,
+ active : false,
+ panel : "draw",
+ id : "holes"
+ };
+ }
+ if (this.options.tools.text) {
+ this.dtOptions.text = {
+ label : this.options.labels.text,
+ active : false,
+ panel : "draw",
+ id : "text"
+ };
+ }
+ if (this.options.tools.edit) {
+ this.dtOptions.edit = {
+ label : this.options.labels.edit,
+ active : false,
+ panel : "edit",
+ id : "edit"
+ };
+ }
+ if (this.options.tools.display) {
+ this.dtOptions.display = {
+ label : this.options.labels.display,
+ active : false,
+ panel : "edit",
+ id : "display"
+ };
+ }
+ if (this.options.tools.tooltip) {
+ this.dtOptions.tooltip = {
+ label : this.options.labels.tooltip,
+ active : false,
+ panel : "edit",
+ id : "tooltip"
+ };
+ }
+ if (this.options.tools.remove) {
+ this.dtOptions.remove = {
+ label : this.options.labels.remove,
+ active : false,
+ panel : "edit",
+ id : "remove"
+ };
+ }
+ // ajout drawing tools
+ if (this.dtOptions.points ||
+ this.dtOptions.lines ||
+ this.dtOptions.polygons ||
+ this.dtOptions.text) {
+ tools.push(this._createDrawingToolSection(this.options.labels.creatingTools, "draw"));
+ }
+ // ajout editing tools
+ if (this.dtOptions.edit ||
+ this.dtOptions.display ||
+ this.dtOptions.tooltip ||
+ this.dtOptions.remove) {
+ tools.push(this._createDrawingToolSection(this.options.labels.editingTools, "edit"));
+ }
+ // ajout export tools
+ if (this.options.tools.export) {
+ tools.push(this._createSavingSection(
+ this.options.labels.export,
+ this.options.labels.exportTitle
+ ));
+ }
+
+ return tools;
+ },
+
+ /**
+ * Creates drawing tool section DOM structure.
+ *
+ * @param {String} sectionLabel - section title
+ * @param {String} panelType - Drawing ("draw") or editing ("edit") tools panel
+ * @returns {DOMElement} DOM element
+ */
+ _createDrawingToolSection : function (sectionLabel, panelType) {
+ /*
+ * Exemple panelType == "draw"
+ *
+ *
+ *
Outils de création
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ */
+ var container = document.createElement("div");
+ container.className = "drawing-tool-section";
+
+ var p = document.createElement("p");
+ p.className = "drawing-tool-section-title";
+ p.innerHTML = sectionLabel;
+ container.appendChild(p);
+
+ var ul = document.createElement("ul");
+ ul.className = "drawing-tools-flex-display";
+ var context = this;
+ // li click handler function
+ function liClickHandler (e) {
+ /* jshint validthis: true */
+ // this == elem clicked
+ context._handleDOMToolClick(e, this.id, context);
+ context._handleToolClick(e, this.id, context);
+ }
+ for (var type in this.dtOptions) {
+ if (this.dtOptions[type].panel !== panelType) {
+ continue;
+ }
+ var li = document.createElement("li");
+ li.className = "drawing-tool";
+ li.id = this._addUID("drawing-tool-" + this.dtOptions[type].id);
+ li.title = this.dtOptions[type].label;
+ li.addEventListener("click", liClickHandler);
+ ul.appendChild(li);
+ }
+ container.appendChild(ul);
+
+ return container;
+ },
+
+ /**
+ * Creates drawing tool section DOM structure.
+ *
+ * @param {String} buttonLabel - Button label
+ * @param {String} buttonTitle - Button title
+ * @returns {DOMElement} DOM element
+ */
+ _createSavingSection : function (buttonLabel, buttonTitle) {
+ /*
+ *
+ *
+ *
+ */
+ var container = document.createElement("div");
+ container.className = "drawing-tool-section drawing-tools-flex-display";
+
+ var button = document.createElement("button");
+ button.title = buttonTitle;
+ button.className = "tool-form-submit drawing-button";
+ button.id = this._addUID("drawing-export");
+ button.type = "button";
+ button.textContent = buttonLabel;
+ var context = this;
+ /** export function */
+ button.onclick = function () {
+ context.onExportFeatureClick();
+ };
+ container.appendChild(button);
+
+ return container;
+ },
+
+ /**
+ * Creates input for color choosing
+ *
+ * @param {Object} options - options
+ * @param {String} options.defaultValue - defaultValue
+ * @param {String} options.className - input className
+ * @returns {DOMElement} - created li element
+ */
+ _createMarkersChooser : function (options) {
+ var li = document.createElement("li");
+ li.className = options.className;
+ for (var i = 0; i < this.options.markersList.length; i++) {
+ // radio bouton pour la selection
+ var inputElem = document.createElement("input");
+ inputElem.type = "radio";
+ inputElem.name = "marker";
+ inputElem.id = this._addUID("marker-" + i);
+ inputElem.value = this.options.markersList[i].src;
+ inputElem.className = "marker-input-radio";
+ if (options.defaultValue === inputElem.value) {
+ inputElem.checked = true;
+ }
+ li.appendChild(inputElem);
+ // label pour l'affichage du marker
+ var labelElem = document.createElement("label");
+ labelElem.className = "marker-label"; // utile ?
+ labelElem.setAttribute("for", inputElem.id);
+ var imgElem = document.createElement("img");
+ imgElem.src = inputElem.value;
+ labelElem.appendChild(imgElem);
+ li.appendChild(labelElem);
+ }
+ return li;
+ },
+
+ /**
+ * Creates input for color choosing
+ *
+ * @param {Object} options - options
+ * @param {String} options.label - label
+ * @param {String} options.type - input type for element ("color")
+ * @param {String} options.defaultValue - defaultValue
+ * @param {String} options.id - input id
+ * @param {String} options.title - input title
+ * @param {String} options.className - input className
+ * @returns {DOMElement} - created li element
+ */
+ _createStylingElement : function (options) {
+ var li = document.createElement("li");
+ li.className = options.className;
+ var textNode = document.createTextNode(options.label);
+ li.appendChild(textNode);
+ var inputElem = document.createElement("input");
+ try {
+ inputElem.type = options.type;
+ } catch (e) {
+ // ie 11 input type== color ne marche pas...
+ inputElem.type = "text";
+ }
+ inputElem.id = options.id;
+ inputElem.value = options.defaultValue;
+ if (options.title) {
+ inputElem.title = options.title;
+ }
+ // si options.type == "range"
+ if (options.min !== undefined) {
+ inputElem.min = options.min;
+ }
+ if (options.max !== undefined) {
+ inputElem.max = options.max;
+ }
+ if (options.step !== undefined) {
+ inputElem.step = options.step;
+ }
+ li.appendChild(inputElem);
+ return li;
+ },
+
+ /**
+ * Creates Styling div to include in popup.
+ *
+ * @param {Object} options - toolId selected
+ * @param {String} options.geomType - gemeotryType selected ("Point", "Line" or "Polygon")
+ * @param {Object} options.initValues - values to init fields
+ * @param {String} options.initValues.markerSrc - marker URL for Points
+ * @param {Function} options.applyFunc - function called when apply is selected
+ * @returns {DOMElement} DOM element created
+ */
+ _createStylingDiv : function (options) {
+ var div = document.createElement("div");
+ div.className = "gp-styling-div";
+ var ul = document.createElement("ul");
+ var li = null;
+ /*
+ * TODO : finir de remplir la div pour tous les styles éditables.
+ */
+ switch (options.geomType.toLowerCase()) {
+ case "point":
+ li = this._createMarkersChooser({
+ className : "gp-styling-option",
+ // defaultValue : this.options.markersList[0].src
+ defaultValue : options.initValues.markerSrc
+ });
+ ul.appendChild(li);
+ break;
+ case "text":
+ li = this._createStylingElement({
+ type : "color",
+ className : "gp-styling-option",
+ label : this.options.labels.fillColor,
+ id : this._addUID("fillColor"),
+ defaultValue : options.initValues.fillColor
+ });
+ ul.appendChild(li);
+ li = this._createStylingElement({
+ type : "color",
+ className : "gp-styling-option",
+ label : this.options.labels.strokeColor,
+ id : this._addUID("strokeColor"),
+ defaultValue : options.initValues.strokeColor
+ });
+ ul.appendChild(li);
+ break;
+ case "line":
+ li = this._createStylingElement({
+ type : "color",
+ className : "gp-styling-option",
+ label : this.options.labels.strokeColor,
+ id : this._addUID("strokeColor"),
+ defaultValue : options.initValues.strokeColor
+ });
+ ul.appendChild(li);
+ li = this._createStylingElement({
+ type : "range",
+ className : "gp-styling-option",
+ label : this.options.labels.strokeWidth,
+ title : "1 à 10 pixels",
+ id : this._addUID("strokeWidth"),
+ min : 1,
+ max : 10,
+ step : 1,
+ defaultValue : options.initValues.strokeWidth
+ });
+ ul.appendChild(li);
+ break;
+ case "polygon":
+ li = this._createStylingElement({
+ type : "color",
+ className : "gp-styling-option",
+ label : this.options.labels.strokeColor,
+ id : this._addUID("strokeColor"),
+ defaultValue : options.initValues.strokeColor
+ });
+ ul.appendChild(li);
+ li = this._createStylingElement({
+ type : "range",
+ className : "gp-styling-option",
+ label : this.options.labels.strokeWidth,
+ title : "1 à 10 pixels",
+ id : this._addUID("strokeWidth"),
+ min : 1,
+ max : 10,
+ step : 1,
+ defaultValue : options.initValues.strokeWidth
+ });
+ ul.appendChild(li);
+ li = this._createStylingElement({
+ type : "color",
+ className : "gp-styling-option",
+ label : this.options.labels.fillColor,
+ id : this._addUID("fillColor"),
+ defaultValue : options.initValues.fillColor
+ });
+ ul.appendChild(li);
+ li = this._createStylingElement({
+ type : "range",
+ className : "gp-styling-option",
+ label : this.options.labels.fillOpacity,
+ title : "0 (transparent) à 100% (opaque)",
+ id : this._addUID("fillOpacity"),
+ min : 0,
+ max : 10,
+ step : 1,
+ defaultValue : options.initValues.fillOpacity * 10
+ });
+ ul.appendChild(li);
+ break;
+ default:
+ logger.log("Unhandled geometry type for styling.");
+ }
+ div.appendChild(ul);
+ // apply button
+ var applyButton = document.createElement("input");
+ applyButton.type = "button";
+ applyButton.className = "gp-styling-button";
+ applyButton.value = this.options.labels.applyToObject;
+ /** click sur applyButton */
+ applyButton.onclick = function () {
+ options.applyFunc.call(this, "apply");
+ };
+ div.appendChild(applyButton);
+ // set default button
+ var setDefaultButton = document.createElement("input");
+ setDefaultButton.type = "button";
+ setDefaultButton.value = this.options.labels.setAsDefault;
+ setDefaultButton.className = "gp-styling-button";
+ /** click sur set Default Button */
+ setDefaultButton.onclick = function () {
+ options.applyFunc.call(this, "default");
+ };
+ div.appendChild(setDefaultButton);
+ // cancel Button
+ var cancelButton = document.createElement("input");
+ cancelButton.type = "button";
+ // cancelButton.value = "X" ;
+ cancelButton.className = "gp-styling-button closer";
+ /** click sur cancel Button */
+ cancelButton.onclick = function () {
+ options.applyFunc.call(this, "cancel");
+ };
+ div.appendChild(cancelButton);
+ return div;
+ },
+
+ /**
+ * Creates Text editing div to include in popup.
+ *
+ * @param {Object} options - options for popup
+ * @param {String} options.geomType - gemeotryType selected ("Point", "Line" or "Polygon")
+ * @param {String} options.text - text to fill input.
+ * @param {String} options.measure - measure to fill input.
+ * @param {String} options.placeholder - placeholder for text input.
+ * @param {String} options.inputId - text input id.
+ * @param {Function} options.applyFunc - function called when text is to be saved.
+ * @returns {DOMElement} DOM element created
+ * @private
+ */
+ _createLabelDiv : function (options) {
+ var popup = document.createElement("div");
+ popup.className = "gp-label-div";
+ var inputLabel = null;
+ if (options.geomType === "Text") {
+ inputLabel = document.createElement("input");
+ inputLabel.type = "text";
+ inputLabel.className = "gp-input-label-style";
+ } else {
+ inputLabel = document.createElement("textArea");
+ inputLabel.rows = 2;
+ inputLabel.cols = 40;
+ inputLabel.className = "gp-textarea-att-label-style";
+ }
+
+ if (options.text) {
+ inputLabel.value = options.text;
+ }
+
+ inputLabel.autocomplete = "off";
+ inputLabel.placeholder = options.placeholder;
+ inputLabel.id = options.inputId;
+ popup.appendChild(inputLabel);
+ // blur
+ inputLabel.onblur = function () {
+ options.applyFunc.call(this, inputLabel.value, true);
+ };
+ // keyup
+ inputLabel.onkeyup = function (evtk) {
+ if (options.geomType === "Text" && evtk.keyCode === 13) {
+ options.applyFunc.call(this, inputLabel.value, true);
+ }
+ if (evtk.keyCode === 27) {
+ options.applyFunc.call(this, inputLabel.value, false);
+ }
+ };
+
+ if (options.measure && options.geomType !== "Text") {
+ var inputMeasure = document.createElement("input");
+ inputMeasure.type = "text";
+ inputMeasure.readonly = true;
+ inputMeasure.className = "gp-input-measure-style";
+ inputMeasure.value = options.measure;
+ popup.appendChild(inputMeasure);
+ }
+
+ if (options.geomType !== "Text") {
+ // apply button
+ var applyButton = document.createElement("input");
+ applyButton.type = "button";
+ applyButton.className = "gp-styling-button";
+ applyButton.value = this.options.labels.saveDescription;
+ /** click sur applyButton */
+ applyButton.onclick = function () {
+ options.applyFunc.call(this, inputLabel.value, true);
+ };
+ popup.appendChild(applyButton);
+ // cancel Button
+ var cancelButton = document.createElement("input");
+ cancelButton.type = "button";
+ cancelButton.className = "gp-styling-button closer";
+ /** click sur cancel Button */
+ cancelButton.onclick = function () {
+ options.applyFunc.call(this, inputLabel.value, false);
+ };
+ popup.appendChild(cancelButton);
+ }
+
+ return popup;
+ },
+
+ /**
+ * Handles drawing tool selection from a DOM point of view.
+ *
+ * @param {Event} e - DOM Event
+ * @param {String} toolId - toolId selected
+ * @param {DrawingDOM} context - Drawing control instance
+ */
+ _handleDOMToolClick : function (e, toolId, context) {
+ for (var availType in context.dtOptions) {
+ var availToolId = context._addUID("drawing-tool-" + context.dtOptions[availType].id);
+ var li = document.getElementById(availToolId);
+ // ce n'est pas l'outil selectionne : on le desactive (s'il ne l'était pas déjà).
+ if (availToolId !== toolId) {
+ li.className = "drawing-tool";
+ context.dtOptions[availType].active = false;
+ continue;
+ }
+ // ici, c'est le l'outil selectionne
+ if (context.dtOptions[availType].active) {
+ li.className = "drawing-tool";
+ } else {
+ li.className = "drawing-tool drawing-tool-active";
+ }
+ context.dtOptions[availType].active = !context.dtOptions[availType].active;
+ }
+ }
+
+};
+
+export default DrawingDOM;
diff --git a/src/Common-review/Controls/Editor/.gitkeep b/src/Common-review/Controls/Editor/.gitkeep
new file mode 100644
index 000000000..e69de29bb
diff --git a/src/Common-review/Controls/Editor/EditorDOM.js b/src/Common-review/Controls/Editor/EditorDOM.js
new file mode 100644
index 000000000..3facbf4ba
--- /dev/null
+++ b/src/Common-review/Controls/Editor/EditorDOM.js
@@ -0,0 +1,14 @@
+var EditorDOM = {
+
+ /**
+ * Add uuid to the tag ID
+ * @param {String} id - id selector
+ * @returns {String} uid - id selector with an unique id
+ */
+ _addUID : function (id) {
+ var uid = (this._uid) ? id + "-" + this._uid : id;
+ return uid;
+ }
+};
+
+export default EditorDOM;
diff --git a/src/Common-review/Controls/ElevationPathDOM.js b/src/Common-review/Controls/ElevationPathDOM.js
new file mode 100644
index 000000000..af28b935f
--- /dev/null
+++ b/src/Common-review/Controls/ElevationPathDOM.js
@@ -0,0 +1,254 @@
+var ElevationPathDOM = {
+
+ /**
+ * Add uuid to the tag ID
+ * @param {String} id - id selector
+ * @returns {String} uid - id selector with an unique id
+ */
+ _addUID : function (id) {
+ var uid = (this._uid) ? id + "-" + this._uid : id;
+ return uid;
+ },
+
+ /**
+ * Main container (DOM)
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createMainContainerElement : function () {
+ var container = document.createElement("div");
+ container.id = this._addUID("GPelevationPath");
+ container.className = "GPwidget";
+ return container;
+ },
+
+ // ################################################################### //
+ // ################# Methods to display Main Panel ################### //
+ // ################################################################### //
+
+ /**
+ * Hidden checkbox for minimizing/maximizing panel
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createShowElevationPathElement : function () {
+ var input = document.createElement("input");
+ input.id = this._addUID("GPshowElevationPath");
+ input.type = "checkbox";
+ return input;
+ },
+
+ /**
+ * Show control
+ * see event !
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createShowElevationPathPictoElement : function () {
+ // contexte d'execution
+ var context = this;
+
+ var label = document.createElement("label");
+ label.id = this._addUID("GPshowElevationPathPicto");
+ label.className = "GPshowAdvancedToolPicto";
+ label.htmlFor = this._addUID("GPshowElevationPath");
+ label.title = "Calculer un profil";
+
+ // gestionnaire d'evenement :
+ // on ouvre le menu de saisie de saisie
+ // L'ouverture/Fermeture permet de faire le menage
+ // (reinitialisation)
+ if (label.addEventListener) {
+ label.addEventListener("click", function (e) {
+ context.onShowElevationPathClick(e);
+ });
+ } else if (label.attachEvent) {
+ label.attachEvent("onclick", function (e) {
+ context.onShowElevationPathClick(e);
+ });
+ }
+
+ var spanOpen = document.createElement("span");
+ spanOpen.id = this._addUID("GPshowElevationPathOpen");
+ spanOpen.className = "GPshowAdvancedToolOpen";
+ label.appendChild(spanOpen);
+
+ return label;
+ },
+
+ // ################################################################### //
+ // ######################### Methods to Panel ######################## //
+ // ################################################################### //
+
+ /**
+ * Create Container Panel
+ *
+ * FIXME
+ * don't call this._createElevationPathPanelHeaderElement
+ * don't call this._createElevationPathPanelProfilElement
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createElevationPathPanelElement : function () {
+ var div = document.createElement("div");
+ div.id = this._addUID("GPelevationPathPanel");
+ div.className = "GPpanel";
+
+ // div.appendChild(this._createElevationPathPanelHeaderElement());
+ // div.appendChild(this._createElevationPathPanelProfilElement());
+
+ return div;
+ },
+
+ /**
+ * Create Header Panel
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createElevationPathPanelHeaderElement : function () {
+ var self = this;
+
+ var container = document.createElement("div");
+ container.className = "GPpanelHeader";
+
+ var divInfo = document.createElement("div");
+ divInfo.id = this._addUID("GPelevationPathPanelInfo");
+ divInfo.className = "GPpanelInfo";
+ divInfo.title = "Informations";
+ // add event on click
+ if (divInfo.addEventListener) {
+ divInfo.addEventListener(
+ "click",
+ function () {
+ self.onOpenElevationPathInfoClick();
+ }
+ );
+ } else if (divInfo.attachEvent) {
+ // internet explorer
+ divInfo.attachEvent(
+ "onclick",
+ function () {
+ self.onOpenElevationPathInfoClick();
+ }
+ );
+ }
+ container.appendChild(divInfo);
+
+ var divTitle = document.createElement("div");
+ divTitle.className = "GPpanelTitle";
+ divTitle.innerHTML = "Profil Altimétrique";
+ container.appendChild(divTitle);
+
+ var divReduce = document.createElement("div");
+ divReduce.id = this._addUID("GPelevationPathPanelReduce");
+ divReduce.className = "GPpanelReduce";
+ divReduce.title = "Masquer le panneau";
+
+ if (divReduce.addEventListener) {
+ divReduce.addEventListener("click", function () {
+ if (typeof self.onReduceElevationPathPanelClick === "function") {
+ document.getElementById(self._addUID("GPshowElevationPath")).checked = false;
+ self.onReduceElevationPathPanelClick();
+ }
+ }, false);
+ } else if (divReduce.attachEvent) {
+ divReduce.attachEvent("onclick", function () {
+ if (typeof self.onReduceElevationPathPanelClick === "function") {
+ document.getElementById(self._addUID("GPshowElevationPath")).checked = false;
+ self.onReduceElevationPathPanelClick();
+ }
+ });
+ }
+ container.appendChild(divReduce);
+
+ var divClose = document.createElement("div");
+ divClose.id = this._addUID("GPelevationPathPanelClose");
+ divClose.className = "GPpanelClose";
+ divClose.title = "Fermer le panneau";
+
+ // Link panel close / visibility checkbox
+ if (divClose.addEventListener) {
+ divClose.addEventListener("click", function () {
+ document.getElementById(self._addUID("GPshowElevationPathPicto")).click();
+ }, false);
+ } else if (divClose.attachEvent) {
+ divClose.attachEvent("onclick", function () {
+ document.getElementById(self._addUID("GPshowElevationPathPicto")).click();
+ });
+ }
+ container.appendChild(divClose);
+
+ return container;
+ },
+
+ /**
+ * Create Form
+ * see evenement !
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createElevationPathPanelProfilElement : function () {
+ var div = document.createElement("div");
+ div.id = "GPelevationPathProfil";
+
+ return div;
+ },
+
+ /**
+ * Create Waiting Panel
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createElevationPathWaitingElement : function () {
+ var div = document.createElement("div");
+ div.id = this._addUID("GPelevationPathCalcWaitingContainer");
+ div.className = "GPelevationPathCalcWaitingContainerHidden";
+
+ var p = document.createElement("p");
+ p.className = "GPelevationPathCalcWaiting";
+ p.innerHTML = "Calcul en cours...";
+
+ div.appendChild(p);
+
+ return div;
+ },
+
+ /**
+ * Create information Panel
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createElevationPathInformationsElement : function () {
+ var div = document.createElement("div");
+ div.id = this._addUID("GPelevationPathInformationsContainer");
+ div.className = "GPelevationPathInformationsContainerHidden";
+
+ var p = document.createElement("p");
+ p.className = "GPelevationPathInformations";
+ p.innerHTML = "Aucune information...";
+ div.appendChild(p);
+
+ return div;
+ },
+
+ /**
+ * Add a information into Panel
+ *
+ * @param {String} value - value of item
+ * @returns {DOMElement} DOM element
+ */
+ _addElevationPathInformationsItem : function (value) {
+ var div = document.getElementById(this._addUID("GPelevationPathInformationsContainer"));
+
+ if (div) {
+ var p = document.createElement("p");
+ p.className = "GPelevationPathInformations";
+ p.innerHTML = value;
+ div.appendChild(p);
+ }
+
+ return div;
+ }
+};
+
+export default ElevationPathDOM;
diff --git a/src/Common-review/Controls/GetFeatureInfoDOM.js b/src/Common-review/Controls/GetFeatureInfoDOM.js
new file mode 100644
index 000000000..73aac2546
--- /dev/null
+++ b/src/Common-review/Controls/GetFeatureInfoDOM.js
@@ -0,0 +1,77 @@
+var GetFeatureInfoDOM = {
+
+ /**
+ * Add uuid to the tag ID
+ * @param {String} id - id selector
+ * @returns {String} uid - id selector with an unique id
+ */
+ _addUID : function (id) {
+ var uid = (this._uid) ? id + "-" + this._uid : id;
+ return uid;
+ },
+
+ /**
+ * Main container (DOM)
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createMainContainerElement : function () {
+ var container = document.createElement("div");
+ container.id = this._addUID("GPgetFeatureInfo");
+ container.className = "GPwidget";
+ return container;
+ },
+
+ // ################################################################### //
+ // ################# Methods to display Main Panel ################### //
+ // ################################################################### //
+
+ /**
+ * Hidden checkbox for activating getFeatureInfo
+ * @param {Boolean} activate - specify if the control is active or inactive
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createActivateGetFeatureInfoElement : function (activate) {
+ // contexte d'execution
+ var context = this;
+
+ var input = document.createElement("input");
+ input.id = this._addUID("GPactivateGetFeatureInfo");
+ input.type = "checkbox";
+ input.checked = activate;
+
+ input.addEventListener("change", function (e) {
+ context.onActivateGetFeatureInfoElementChange(e);
+ });
+
+ return input;
+ },
+
+ /**
+ * Creation du container du picto du controle (DOM)
+ * @returns {DOMElement} DOM element
+ */
+ _createMainPictoElement : function () {
+ var self = this;
+
+ var label = document.createElement("label");
+ label.id = this._addUID("GPgetFeatureInfoPicto");
+ label.className = "GPshowAdvancedToolPicto";
+ label.htmlFor = this._addUID("GPactivateGetFeatureInfo");
+ label.title = "activer/desactiver l'interrogation des couches";
+
+ var spanOpen = document.createElement("span");
+ spanOpen.id = this._addUID("GPgetFeatureInfoActivate");
+ spanOpen.className = "GPshowAdvancedToolOpen";
+ label.appendChild(spanOpen);
+
+ var spanClose = document.createElement("span");
+ spanClose.id = self._addUID("GPgetFeatureInfoDeactivate");
+ label.appendChild(spanClose);
+
+ return label;
+ }
+};
+
+export default GetFeatureInfoDOM;
diff --git a/src/Common-review/Controls/IsoDOM.js b/src/Common-review/Controls/IsoDOM.js
new file mode 100644
index 000000000..6deb3982b
--- /dev/null
+++ b/src/Common-review/Controls/IsoDOM.js
@@ -0,0 +1,835 @@
+var IsoDOM = {
+
+ /**
+ * Add uuid to the tag ID
+ * @param {String} id - id selector
+ * @returns {String} uid - id selector with an unique id
+ */
+ _addUID : function (id) {
+ var uid = (this._uid) ? id + "-" + this._uid : id;
+ return uid;
+ },
+
+ /**
+ * Main container (DOM)
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createMainContainerElement : function () {
+ var container = document.createElement("div");
+ container.id = this._addUID("GPisochron");
+ container.className = "GPwidget";
+ return container;
+ },
+
+ // ################################################################### //
+ // ################# Methods to display Main Panel ################### //
+ // ################################################################### //
+
+ /**
+ * Hidden checkbox for minimizing/maximizing panel
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createShowIsoElement : function () {
+ var input = document.createElement("input");
+ input.id = this._addUID("GPshowIsochron");
+ input.type = "checkbox";
+ return input;
+ },
+
+ /**
+ * Show iso control
+ * see event !
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createShowIsoPictoElement : function () {
+ // contexte d'execution
+ var context = this;
+
+ var label = document.createElement("label");
+ label.id = this._addUID("GPshowIsochronPicto");
+ label.className = "GPshowAdvancedToolPicto";
+ label.htmlFor = this._addUID("GPshowIsochron");
+ label.title = "Calculer une isochrone";
+
+ // gestionnaire d'evenement :
+ // on ouvre le menu de saisie du calcul d'isochrone
+ // L'ouverture/Fermeture permet de faire le menage
+ // (reinitialisation)
+ if (label.addEventListener) {
+ label.addEventListener("click", function (e) {
+ context.onShowIsoPanelClick(e);
+ });
+ } else if (label.attachEvent) {
+ label.attachEvent("onclick", function (e) {
+ context.onShowIsoPanelClick(e);
+ });
+ }
+
+ var spanOpen = document.createElement("span");
+ spanOpen.id = this._addUID("GPshowIsochronOpen");
+ spanOpen.className = "GPshowAdvancedToolOpen";
+ label.appendChild(spanOpen);
+
+ return label;
+ },
+
+ // ################################################################### //
+ // ################## Methods to display Inputs Panel ################ //
+ // ################################################################### //
+
+ /**
+ * Create Container Panel
+ *
+ * FIXME
+ * don't call this._createIsoPanelHeaderElement
+ * don't call this._createIsoPanelFormElement
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createIsoPanelElement : function () {
+ var div = document.createElement("div");
+ div.id = this._addUID("GPisochronPanel");
+ div.className = "GPpanel";
+
+ // div.appendChild(this._createIsoPanelHeaderElement());
+ // div.appendChild(this._createIsoPanelFormElement());
+
+ return div;
+ },
+
+ /**
+ * Create Header Panel
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createIsoPanelHeaderElement : function () {
+ var self = this;
+
+ var container = document.createElement("div");
+ container.className = "GPpanelHeader";
+
+ var div = document.createElement("div");
+ div.className = "GPpanelTitle";
+ div.innerHTML = "Calcul d'isochrone";
+ container.appendChild(div);
+
+ // on desactive l'impl. reduction de la fenetre
+ // var divReduce = document.createElement("div");
+ // divReduce.id = this._addUID("GPisochronPanelReduce");
+ // divReduce.className = "GPpanelReduce";
+ // divReduce.title = "Masquer le panneau";
+ //
+ // if (divReduce.addEventListener) {
+ // divReduce.addEventListener("click", function () {
+ // if ( typeof self.onReduceIsoPanelClick === "function") {
+ // document.getElementById(self._addUID("GPshowIsochron")).checked = false;
+ // self.onReduceIsoPanelClick();
+ // }
+ // }, false);
+ // } else if (divReduce.attachEvent) {
+ // divReduce.attachEvent("onclick", function () {
+ // if ( typeof self.onReduceIsoPanelClick === "function") {
+ // document.getElementById(self._addUID("GPshowIsochron")).checked = false;
+ // self.onReduceIsoPanelClick();
+ // }
+ // });
+ // }
+ // container.appendChild(divReduce);
+
+ var divClose = document.createElement("div");
+ divClose.id = this._addUID("GPisochronPanelClose");
+ divClose.className = "GPpanelClose";
+ divClose.title = "Fermer le panneau";
+
+ // Link panel close / visibility checkbox
+ if (divClose.addEventListener) {
+ divClose.addEventListener("click", function () {
+ document.getElementById(self._addUID("GPshowIsochronPicto")).click();
+ }, false);
+ } else if (divClose.attachEvent) {
+ divClose.attachEvent("onclick", function () {
+ document.getElementById(self._addUID("GPshowIsochronPicto")).click();
+ });
+ }
+ container.appendChild(divClose);
+
+ return container;
+ },
+
+ /**
+ * Create Form
+ * see evenement !
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createIsoPanelFormElement : function () {
+ // contexte d'execution
+ var self = this;
+
+ var form = document.createElement("form");
+ form.id = this._addUID("GPisochronForm");
+
+ form.addEventListener("submit", function (e) {
+ e.preventDefault();
+ self.onIsoComputationSubmit(e);
+ return false;
+ });
+
+ return form;
+ },
+
+ /**
+ * Create Waiting Panel
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createIsoWaitingElement : function () {
+ var div = document.createElement("div");
+ div.id = this._addUID("GPisochronCalcWaitingContainer");
+ div.className = "GPisochronCalcWaitingContainerHidden";
+
+ var p = document.createElement("p");
+ p.className = "GPisochronCalcWaiting";
+ p.innerHTML = "Calcul en cours...";
+
+ div.appendChild(p);
+
+ return div;
+ },
+
+ // ################################################################### //
+ // ############# Methods to the type choice into form ################ //
+ // ################################################################### //
+
+ /**
+ * Create Container to type choice
+ *
+ * FIXME
+ * don't call this._createIsoPanelFormTypeChoiceChronElement
+ * don't call this._createIsoPanelFormTypeChoiceDistElement
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createIsoPanelFormTypeChoiceElement : function () {
+ var div = document.createElement("div");
+ div.id = this._addUID("GPisochronChoice");
+
+ // div.appendChild(this._createIsoPanelFormTypeChoiceChronElement());
+ // div.appendChild(this._createIsoPanelFormTypeChoiceDistElement());
+
+ return div;
+ },
+
+ /**
+ * Create Type choice Chron
+ * see event !
+ * FIXME event not useful
+ * @param {Boolean} checked - checked
+ * @returns {DOMElement} DOM element
+ */
+ _createIsoPanelFormTypeChoiceChronElement : function (checked) {
+ var self = this;
+
+ var div = document.createElement("div");
+ div.className = "GPisochronChoiceAlt";
+
+ var input = document.createElement("input");
+ input.id = this._addUID("GPisochronChoiceAltChron");
+ input.name = "GPisochronChoiceMode";
+ input.type = "radio";
+ input.checked = !!(checked);
+ if (input.addEventListener) {
+ input.addEventListener("change", function (e) {
+ document.getElementById(self._addUID("GPisochronValueChron")).className = "GPflexInput";
+ document.getElementById(self._addUID("GPisochronValueDist")).className = "GPisochronValueHidden";
+ self.onIsoTypeChoiceChange(e);
+ }, false);
+ } else if (input.attachEvent) {
+ input.attachEvent("onchange", function () {
+ document.getElementById(self._addUID("GPisochronValueChron")).className = "GPflexInput";
+ document.getElementById(self._addUID("GPisochronValueDist")).className = "GPisochronValueHidden";
+ self.onIsoTypeChoiceChange();
+ });
+ }
+ // info: Internet explorer support
+ input.value = "isochron";
+ div.appendChild(input);
+
+ var label = document.createElement("label");
+ label.className = "GPisochronChoiceAltImg";
+ label.htmlFor = this._addUID("GPisochronChoiceAltChron");
+ div.appendChild(label);
+
+ var span = document.createElement("span");
+ span.id = this._addUID("GPisochronChoiceAltChronTxt");
+ span.innerHTML = "isochrone";
+ if (span.addEventListener) {
+ span.addEventListener("click", function () {
+ document.getElementById(self._addUID("GPisochronChoiceAltChron")).click();
+ }, false);
+ } else if (span.attachEvent) {
+ span.attachEvent("onclick", function () {
+ document.getElementById(self._addUID("GPisochronChoiceAltChron")).click();
+ });
+ }
+ div.appendChild(span);
+
+ return div;
+ },
+
+ /**
+ * Create Type choice Dist
+ * see event !
+ * FIXME event not useful
+ * @param {Boolean} checked - checked
+ * @returns {DOMElement} DOM element
+ */
+ _createIsoPanelFormTypeChoiceDistElement : function (checked) {
+ var self = this;
+
+ var div = document.createElement("div");
+ div.className = "GPisochronChoiceAlt";
+
+ var input = document.createElement("input");
+ input.id = this._addUID("GPisochronChoiceAltDist");
+ input.name = "GPisochronChoiceMode";
+ input.type = "radio";
+ input.checked = !!(checked);
+ if (input.addEventListener) {
+ input.addEventListener("change", function (e) {
+ document.getElementById(self._addUID("GPisochronValueDist")).className = "GPflexInput";
+ document.getElementById(self._addUID("GPisochronValueChron")).className = "GPisochronValueHidden";
+ self.onIsoTypeChoiceChange(e);
+ }, false);
+ } else if (input.attachEvent) {
+ input.attachEvent("onchange", function () {
+ document.getElementById(self._addUID("GPisochronValueDist")).className = "GPflexInput";
+ document.getElementById(self._addUID("GPisochronValueChron")).className = "GPisochronValueHidden";
+ self.onIsoTypeChoiceChange();
+ });
+ }
+ // info: Internet explorer support
+ input.value = "isodistance";
+ div.appendChild(input);
+
+ var label = document.createElement("label");
+ label.className = "GPisochronChoiceAltImg";
+ label.htmlFor = this._addUID("GPisochronChoiceAltDist");
+ div.appendChild(label);
+
+ var span = document.createElement("span");
+ span.id = this._addUID("GPisochronChoiceAltDistTxt");
+ span.innerHTML = "isodistance";
+ if (span.addEventListener) {
+ span.addEventListener("click", function () {
+ document.getElementById(self._addUID("GPisochronChoiceAltDist")).click();
+ }, false);
+ } else if (span.attachEvent) {
+ span.attachEvent("onclick", function () {
+ document.getElementById(self._addUID("GPisochronChoiceAltDist")).click();
+ });
+ }
+ div.appendChild(span);
+
+ return div;
+ },
+
+ // ################################################################### //
+ // ############### Methods to the value iso into form ################ //
+ // ################################################################### //
+
+ /**
+ * Create isochron inputs values
+ * see event !
+ * @param {Boolean} checked - checked
+ * @returns {DOMElement} DOM element
+ */
+ _createIsoPanelFormValueIsochronElement : function (checked) {
+ // contexte
+ var context = this;
+
+ var div = document.createElement("div");
+ div.id = this._addUID("GPisochronValueChron");
+ div.className = (checked) ? "GPflexInput" : "GPisochronValueHidden";
+
+ var label = document.createElement("label");
+ label.id = this._addUID("GPisochronValueChronLabel");
+ label.htmlFor = this._addUID("GPisochronValueChronInput");
+ label.innerHTML = "Temps";
+ div.appendChild(label);
+
+ var input1 = document.createElement("input");
+ input1.id = this._addUID("GPisochronValueChronInput1");
+ input1.min = "0";
+ input1.step = "1";
+ input1.value = "0";
+ input1.type = "number";
+ if (input1.addEventListener) {
+ input1.addEventListener("change", function (e) {
+ if (typeof context.onIsoValueChronTimeMinuteChange === "function") {
+ context.onIsoValueChronTimeHourChange(e);
+ }
+ });
+ } else if (input1.attachEvent) {
+ input1.attachEvent("onchange", function (e) {
+ if (typeof context.onIsoValueChronTimeMinuteChange === "function") {
+ context.onIsoValueChronTimeHourChange(e);
+ }
+ });
+ }
+ div.appendChild(input1);
+
+ var label1 = document.createElement("label");
+ label1.innerHTML = "h";
+ div.appendChild(label1);
+
+ var input2 = document.createElement("input");
+ input2.id = this._addUID("GPisochronValueChronInput2");
+ input2.min = "0";
+ input2.max = "59";
+ input2.step = "1";
+ input2.value = "0";
+ input2.type = "number";
+ if (input2.addEventListener) {
+ input2.addEventListener("change", function (e) {
+ if (typeof context.onIsoValueChronTimeMinuteChange === "function") {
+ context.onIsoValueChronTimeMinuteChange(e);
+ }
+ });
+ } else if (input2.attachEvent) {
+ input2.attachEvent("onchange", function (e) {
+ if (typeof context.onIsoValueChronTimeMinuteChange === "function") {
+ context.onIsoValueChronTimeMinuteChange(e);
+ }
+ });
+ }
+ div.appendChild(input2);
+
+ var label2 = document.createElement("label");
+ label2.innerHTML = "min";
+ div.appendChild(label2);
+
+ return div;
+ },
+
+ /**
+ * Create isodistance inputs values
+ * see event !
+ * @param {Boolean} checked - checked
+ * @returns {DOMElement} DOM element
+ */
+ _createIsoPanelFormValueIsodistanceElement : function (checked) {
+ // contexte
+ var context = this;
+
+ var div = document.createElement("div");
+ div.id = this._addUID("GPisochronValueDist");
+ div.className = (checked) ? "GPflexInput" : "GPisochronValueHidden";
+
+ var label = document.createElement("label");
+ label.id = this._addUID("GPisochronValueDistLabel");
+ label.htmlFor = this._addUID("GPisochronValueDistInput");
+ label.innerHTML = "Distance";
+ div.appendChild(label);
+
+ var input1 = document.createElement("input");
+ input1.id = this._addUID("GPisochronValueDistInput");
+ input1.min = "0";
+ input1.step = "any";
+ input1.value = "0";
+ input1.type = "number";
+ if (input1.addEventListener) {
+ input1.addEventListener("change", function (e) {
+ if (typeof context.onIsoValueDistChange === "function") {
+ context.onIsoValueDistChange(e);
+ }
+ });
+ } else if (input1.attachEvent) {
+ input1.attachEvent("onchange", function (e) {
+ if (typeof context.onIsoValueDistChange === "function") {
+ context.onIsoValueDistChange(e);
+ }
+ });
+ }
+ div.appendChild(input1);
+
+ var label1 = document.createElement("label");
+ label1.innerHTML = "km";
+ div.appendChild(label1);
+
+ return div;
+ },
+
+ // ################################################################### //
+ // ############ Methods to the mode choice into form ################# //
+ // ################################################################### //
+
+ /**
+ * Create Container to Mode choice
+ *
+ * FIXME
+ * don't call this._createIsoPanelFormModeChoiceTransportElement
+ * don't call this._createIsoPanelFormModeChoiceDirectionElement
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createIsoPanelFormModeChoiceElement : function () {
+ var div = document.createElement("div");
+ div.id = this._addUID("GPisochronModeChoice");
+
+ // div.appendChild(this._createIsoPanelFormModeChoiceTransportElement());
+ // div.appendChild(this._createIsoPanelFormModeChoiceDirectionElement());
+
+ return div;
+ },
+
+ /**
+ * Create Mode choice transport
+ * see event !
+ * FIXME event not useful
+ * @param {Array} transports - transports in a list
+ * @returns {DOMElement} DOM element
+ */
+ _createIsoPanelFormModeChoiceTransportElement : function (transports) {
+ // contexte d'execution
+ var context = this;
+
+ var div = document.createElement("div");
+ div.id = this._addUID("GPisochronTransportChoice");
+
+ var span = document.createElement("span");
+ span.className = "GPisochronModeLabel";
+ span.innerHTML = "Mode de transport";
+ div.appendChild(span);
+
+ /* jshint -W083 */
+ for (var i = 0; i < transports.length; i++) {
+ var transport = transports[i];
+
+ if (transport === "Voiture") {
+ var inputCar = document.createElement("input");
+ inputCar.id = this._addUID("GPisochronTransportCar");
+ inputCar.type = "radio";
+ inputCar.name = "GPisochronTransport";
+ if (i === 0) {
+ inputCar.checked = true;
+ }
+ // gestionnaire d'evenement :
+ // on stocke le mode de transport,
+ // utilisation pour la requête sur le service de calcul d'itiniraire
+ if (inputCar.addEventListener) {
+ inputCar.addEventListener("change", function (e) {
+ context.onIsoModeTransportChange(e);
+ });
+ } else if (inputCar.attachEvent) {
+ inputCar.attachEvent("onchange", function (e) {
+ context.onIsoModeTransportChange(e);
+ });
+ }
+ // info : internet explorer support
+ inputCar.value = "Voiture";
+ div.appendChild(inputCar);
+
+ var labelCar = document.createElement("label");
+ labelCar.className = "GPisochronTransportImg";
+ labelCar.htmlFor = this._addUID("GPisochronTransportCar");
+ labelCar.title = "Voiture";
+ div.appendChild(labelCar);
+ }
+
+ if (transport === "Pieton") {
+ var inputPedestrian = document.createElement("input");
+ inputPedestrian.id = this._addUID("GPisochronTransportPedestrian");
+ inputPedestrian.type = "radio";
+ inputPedestrian.name = "GPisochronTransport";
+ if (i === 0) {
+ inputPedestrian.checked = true;
+ }
+ // gestionnaire d'evenement :
+ // on stocke le mode de transport,
+ // utilisation pour la requête sur le service de calcul d'itiniraire
+ if (inputPedestrian.addEventListener) {
+ inputPedestrian.addEventListener("change", function (e) {
+ context.onIsoModeTransportChange(e);
+ });
+ } else if (inputPedestrian.attachEvent) {
+ inputPedestrian.attachEvent("onchange", function (e) {
+ context.onIsoModeTransportChange(e);
+ });
+ }
+ // info : internet explorer support
+ inputPedestrian.value = "Pieton";
+ div.appendChild(inputPedestrian);
+
+ var labelPedestrian = document.createElement("label");
+ labelPedestrian.className = "GPisochronTransportImg";
+ labelPedestrian.htmlFor = this._addUID("GPisochronTransportPedestrian");
+ labelPedestrian.title = "Piéton";
+ div.appendChild(labelPedestrian);
+ }
+ }
+
+ return div;
+ },
+
+ /**
+ * Create Mode choice direction
+ * see event!
+ *
+ * @param {Array} directions - directions to display in list ("Departure", "Arrival"). First element will be selected by default
+ * @returns {DOMElement} DOM element
+ */
+ _createIsoPanelFormModeChoiceDirectionElement : function (directions) {
+ // contexte d'execution
+ var self = this;
+
+ var div = document.createElement("div");
+ div.id = this._addUID("GPisochronDirectionChoice");
+
+ var span = document.createElement("span");
+ span.className = "GPisochronModeLabel";
+ span.innerHTML = "Sens de parcours";
+ div.appendChild(span);
+
+ var select = document.createElement("select");
+ select.id = this._addUID("GPisochronDirectionSelect");
+ select.className = "GPinputSelect";
+ // gestionnaire d'evenement :
+ // on stocke la valeur du mode de calcul,
+ // utilisation pour la requête sur le service de calcul d'iso
+ select.addEventListener("change", function (e) {
+ self.onIsoModeDirectionChange(e);
+ });
+
+ for (var i = 0; i < directions.length; i++) {
+ var direction = directions[i];
+ if (direction.toLowerCase() === "departure") {
+ var departureOption = document.createElement("option");
+ if (i === 0) {
+ departureOption.selected = "selected";
+ }
+ departureOption.value = "departure";
+ departureOption.text = "Départ";
+ select.appendChild(departureOption);
+ }
+ if (direction.toLowerCase() === "arrival") {
+ var arrivalOption = document.createElement("option");
+ if (i === 0) {
+ arrivalOption.selected = "selected";
+ }
+ arrivalOption.value = "arrival";
+ arrivalOption.text = "Arrivée";
+ select.appendChild(arrivalOption);
+ }
+ }
+ div.appendChild(select);
+
+ return div;
+ },
+
+ // ################################################################### //
+ // ################# Methods to the choice exclusions ################ //
+ // ################################################################### //
+
+ /**
+ * Hidden checkbox for minimizing/maximizing Exclusions Options
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createShowIsoExclusionsElement : function () {
+ var input = document.createElement("input");
+ input.id = this._addUID("GPshowIsoExclusions");
+ input.type = "checkbox";
+ return input;
+ },
+
+ /**
+ * Label to Exclusions Options
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createShowIsoExclusionsPictoElement : function () {
+ var label = document.createElement("label");
+ label.id = this._addUID("GPshowIsoExclusionsPicto");
+ label.className = "GPshowMoreOptionsImage GPshowMoreOptions GPshowIsoExclusionsPicto";
+ label.htmlFor = this._addUID("GPshowIsoExclusions");
+ label.title = "Exclusions";
+ label.style.top = "240px";
+
+ return label;
+ },
+
+ /**
+ * Create Container to Exclusions
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createIsoPanelFormExclusionsElement : function () {
+ var div = document.createElement("div");
+ div.id = this._addUID("GPisoExclusions");
+
+ var span = document.createElement("span");
+ span.className = "GPisoExclusionsLabel";
+ span.innerHTML = "Passages autorisés";
+ div.appendChild(span);
+
+ // div.appendChild(this._createIsoPanelFormExclusionOptionsElement());
+
+ return div;
+ },
+
+ /**
+ * Create Exclusions Options
+ * see event !
+ * FIXME event not useful
+ * @param {Array} exclusions - exclusions to display in list
+ * @returns {DOMElement} DOM element
+ */
+ _createIsoPanelFormExclusionOptionsElement : function (exclusions) {
+ // contexte d'execution
+ var context = this;
+
+ var div = document.createElement("div");
+ div.className = "GPisoExclusionsOptions";
+
+ /* jshint -W083 */
+ for (var value in exclusions) {
+ if (exclusions.hasOwnProperty(value)) {
+ var status = exclusions[value];
+ switch (value) {
+ case "toll":
+ var inputToll = document.createElement("input");
+ inputToll.id = this._addUID("GPisoExclusionsToll");
+ inputToll.type = "checkbox";
+ inputToll.checked = !status;
+ // gestionnaire d'evenement :
+ // on stocke l'exclusion,
+ // utilisation pour la requête sur le service de calcul d'itiniraire
+ if (inputToll.addEventListener) {
+ inputToll.addEventListener("change", function (e) {
+ context.onIsoExclusionsChange(e);
+ });
+ } else if (inputToll.attachEvent) {
+ inputToll.attachEvent("onchange", function (e) {
+ context.onIsoExclusionsChange(e);
+ });
+ }
+ // info : internet explorer support
+ inputToll.value = "Toll";
+ div.appendChild(inputToll);
+
+ var labelToll = document.createElement("label");
+ labelToll.className = "GPisoExclusionsOption";
+ labelToll.htmlFor = this._addUID("GPisoExclusionsToll");
+ labelToll.innerHTML = "Péages";
+ div.appendChild(labelToll);
+ break;
+
+ case "tunnel":
+ var inputTunnel = document.createElement("input");
+ inputTunnel.id = this._addUID("GPisoExclusionsTunnel");
+ inputTunnel.type = "checkbox";
+ inputTunnel.checked = !status;
+ // gestionnaire d'evenement :
+ // on stocke l'exclusion,
+ // utilisation pour la requête sur le service de calcul d'itiniraire
+ if (inputTunnel.addEventListener) {
+ inputTunnel.addEventListener("change", function (e) {
+ context.onIsoExclusionsChange(e);
+ });
+ } else if (inputTunnel.attachEvent) {
+ inputTunnel.attachEvent("onchange", function (e) {
+ context.onIsoExclusionsChange(e);
+ });
+ }
+ // info : internet explorer support
+ inputTunnel.value = "Tunnel";
+ div.appendChild(inputTunnel);
+
+ var labelTunnel = document.createElement("label");
+ labelTunnel.className = "GPisoExclusionsOption";
+ labelTunnel.htmlFor = this._addUID("GPisoExclusionsTunnel");
+ labelTunnel.innerHTML = "Tunnels";
+ div.appendChild(labelTunnel);
+ break;
+
+ case "bridge":
+ var inputBridge = document.createElement("input");
+ inputBridge.id = this._addUID("GPisoExclusionsBridge");
+ inputBridge.type = "checkbox";
+ inputBridge.checked = !status;
+ // gestionnaire d'evenement :
+ // on stocke l'exclusion,
+ // utilisation pour la requête sur le service de calcul d'itiniraire
+ if (inputBridge.addEventListener) {
+ inputBridge.addEventListener("change", function (e) {
+ context.onIsoExclusionsChange(e);
+ });
+ } else if (inputBridge.attachEvent) {
+ inputBridge.attachEvent("onchange", function (e) {
+ context.onIsoExclusionsChange(e);
+ });
+ }
+ // info : internet explorer support
+ inputBridge.value = "Bridge";
+ div.appendChild(inputBridge);
+
+ var labelBridge = document.createElement("label");
+ labelBridge.className = "GPisoExclusionsOption";
+ labelBridge.htmlFor = this._addUID("GPisoExclusionsBridge");
+ labelBridge.innerHTML = "Ponts";
+ div.appendChild(labelBridge);
+ break;
+ }
+ }
+ }
+
+ return div;
+ },
+
+ // ################################################################### //
+ // ############################### Submit Form ####################### //
+ // ################################################################### //
+
+ /**
+ * Create Submit Form Element
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createIsoSubmitFormElement : function () {
+ var input = document.createElement("input");
+ input.id = this._addUID("GPisochronSubmit");
+ input.className = "GPinputSubmit";
+ input.type = "submit";
+ input.value = "Calculer";
+
+ return input;
+ },
+
+ // ################################################################### //
+ // ############################### Reset picto ####################### //
+ // ################################################################### //
+
+ /**
+ * Create Reset Picto Element
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createIsoFormResetElement : function () {
+ var self = this;
+
+ var divReset = document.createElement("div");
+ divReset.id = this._addUID("GPisochronReset");
+ divReset.title = "Réinitialiser les paramètres";
+ divReset.addEventListener("click", function (e) {
+ self.onIsoResetClick(e);
+ });
+
+ return divReset;
+ }
+};
+
+export default IsoDOM;
diff --git a/src/Common-review/Controls/LayerImportDOM.js b/src/Common-review/Controls/LayerImportDOM.js
new file mode 100644
index 000000000..b48f46b13
--- /dev/null
+++ b/src/Common-review/Controls/LayerImportDOM.js
@@ -0,0 +1,1064 @@
+import SelectorID from "../Utils/SelectorID";
+
+var LayerImportDOM = {
+
+ /**
+ * Add uuid to the tag ID
+ * @param {String} id - id selector
+ * @returns {String} uid - id selector with an unique id
+ */
+ _addUID : function (id) {
+ var uid = (this._uid) ? id + "-" + this._uid : id;
+ return uid;
+ },
+
+ /**
+ * Map loading
+ *
+ * @returns {DOMElement} container
+ */
+ _createLoadingElement : function () {
+ var div = document.createElement("div");
+ div.id = "GPmapLoading";
+ div.className = "";
+ return div;
+ },
+
+ /**
+ * Main container (DOM)
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createMainContainerElement : function () {
+ var container = document.createElement("div");
+ container.id = this._addUID("GPimport");
+ container.className = "GPwidget";
+ return container;
+ },
+
+ // ################################################################### //
+ // ######################### show widget ############################# //
+ // ################################################################### //
+
+ /**
+ * Hidden checkbox for minimizing/maximizing
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createShowImportElement : function () {
+ var input = document.createElement("input");
+ input.id = this._addUID("GPshowImport");
+ input.type = "checkbox";
+ return input;
+ },
+
+ /**
+ * Show Import
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createShowImportPictoElement : function () {
+ // contexte d'execution
+ var self = this;
+
+ var label = document.createElement("label");
+ label.id = this._addUID("GPshowImportPicto");
+ label.className = "GPshowAdvancedToolPicto";
+ label.htmlFor = this._addUID("GPshowImport");
+ label.title = "Ouvrir l'import de couches";
+
+ // Close all results and panels when minimizing the widget
+ if (label.addEventListener) {
+ label.addEventListener("click", function () {
+ self._onShowImportClick();
+ });
+ } else if (label.attachEvent) {
+ label.attachEvent("onclick", function () {
+ self._onShowImportClick();
+ });
+ }
+
+ var spanOpen = document.createElement("span");
+ spanOpen.id = this._addUID("GPshowImportOpen");
+ spanOpen.className = "GPshowAdvancedToolOpen";
+ label.appendChild(spanOpen);
+
+ return label;
+ },
+
+ // ################################################################### //
+ // ######################### Header panel ############################ //
+ // ################################################################### //
+
+ /**
+ * Create Container Panel
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createImportPanelElement : function () {
+ var div = document.createElement("div");
+ div.id = this._addUID("GPimportPanel");
+ div.className = "GPpanel";
+
+ return div;
+ },
+
+ /**
+ * Create Header Panel
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createImportPanelHeaderElement : function () {
+ var container = document.createElement("div");
+ container.className = "GPpanelHeader";
+
+ // panel title
+ var panelTitle = this._createImportPanelTitleElement();
+ container.appendChild(panelTitle);
+ // close picto
+ var closeDiv = this._createImportPanelCloseElement();
+ container.appendChild(closeDiv);
+
+ return container;
+ },
+
+ /**
+ * Create Header Title Panel
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createImportPanelTitleElement : function () {
+ var div = document.createElement("div");
+ div.className = "GPpanelTitle";
+ div.innerHTML = "Import de données";
+ return div;
+ },
+
+ /**
+ * Create Header close div
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createImportPanelCloseElement : function () {
+ // contexte
+ var self = this;
+
+ var divClose = document.createElement("div");
+ divClose.id = this._addUID("GPimportPanelClose");
+ divClose.className = "GPpanelClose";
+ divClose.title = "Fermer le panneau";
+
+ // Link panel close / visibility checkbox
+ if (divClose.addEventListener) {
+ divClose.addEventListener("click", function () {
+ document.getElementById(self._addUID("GPshowImportPicto")).click();
+ }, false);
+ } else if (divClose.attachEvent) {
+ divClose.attachEvent("onclick", function () {
+ document.getElementById(self._addUID("GPshowImportPicto")).click();
+ });
+ }
+
+ return divClose;
+ },
+
+ // ################################################################### //
+ // ########################### Form panel ############################ //
+ // ################################################################### //
+
+ /**
+ * Create Form
+ * see event !
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createImportPanelFormElement : function () {
+ // contexte d'execution
+ var self = this;
+
+ var form = document.createElement("form");
+ form.id = this._addUID("GPimportForm");
+ form.className = "map-tool-box";
+
+ // TODO ?
+ if (form.addEventListener) {
+ form.addEventListener("submit", function (e) {
+ e.preventDefault();
+ self._onImportSubmit();
+ });
+ } else if (form.attachEvent) {
+ form.attachEvent("onsubmit", function (e) {
+ e.preventDefault();
+ self._onImportSubmit();
+ });
+ }
+
+ return form;
+ },
+
+ /**
+ * Create Container for import type choice
+ *
+ * @param {Array} importTypes - import types to be displayed (and used)
+ * @returns {DOMElement} DOM element
+ */
+ _createImportTypeLineElement : function (importTypes) {
+ // contexte d'execution
+ var context = this;
+
+ var div = document.createElement("div");
+ div.id = this._addUID("GPimportTypeLine");
+ div.className = "GPimportInputLine";
+
+ var label = document.createElement("label");
+ label.htmlFor = this._addUID("GPimportType");
+ label.className = "GPimportLabel";
+ label.innerHTML = "Type de donnée";
+ label.title = "Type de donnée";
+ div.appendChild(label);
+
+ var select = document.createElement("select");
+ select.className = "GPimportSelect";
+ // gestionnaire d'evenement : on stocke la valeur du type d'import
+ if (select.addEventListener) {
+ select.addEventListener("change", function (e) {
+ if (this.value === "KML" || this.value === "GPX" || this.value === "GeoJSON" || this.value === "MAPBOX") {
+ // static import
+ document.getElementById(context._addUID("GPimportStaticParams")).className = "GPimportVisibleParams";
+ document.getElementById(context._addUID("GPimportServiceParams")).className = "GPimportHiddenParams";
+ } else if (this.value === "WMS" || this.value === "WMTS" || this.value === "WFS") {
+ // service import
+ document.getElementById(context._addUID("GPimportServiceParams")).className = "GPimportVisibleParams";
+ document.getElementById(context._addUID("GPimportStaticParams")).className = "GPimportHiddenParams";
+ }
+ context._onImportTypeChange(e);
+ });
+ } else if (select.attachEvent) {
+ select.attachEvent("onchange", function () {
+ if (this.value === "KML" || this.value === "GPX" || this.value === "GeoJSON" || this.value === "MAPBOX") {
+ // static import
+ document.getElementById(context._addUID("GPimportStaticParams")).className = "GPimportVisibleParams";
+ document.getElementById(context._addUID("GPimportServiceParams")).className = "GPimportHiddenParams";
+ } else if (this.value === "WMS" || this.value === "WMTS" || this.value === "WFS") {
+ // service import
+ document.getElementById(context._addUID("GPimportServiceParams")).className = "GPimportVisibleParams";
+ document.getElementById(context._addUID("GPimportStaticParams")).className = "GPimportHiddenParams";
+ }
+ context._onImportTypeChange();
+ });
+ }
+ select.id = this._addUID("GPimportType");
+
+ // on prend soit les valeurs passées par l'utilisateur, soit des valeurs par défaut
+ if (!importTypes || !Array.isArray(importTypes)) {
+ importTypes = [
+ "KML",
+ "GPX",
+ "GeoJSON",
+ "MAPBOX",
+ "WMS",
+ "WMTS",
+ "WFS"
+ ];
+ }
+ var option;
+ for (var i = 0; i < importTypes.length; i++) {
+ option = document.createElement("option");
+ option.value = importTypes[i];
+ option.text = (importTypes[i] === "MAPBOX") ? "Vecteur tuilé" : importTypes[i];
+ select.appendChild(option);
+ }
+
+ div.appendChild(select);
+
+ return div;
+ },
+
+ /**
+ * Create Waiting Panel
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createImportWaitingElement : function () {
+ var div = document.createElement("div");
+ div.id = this._addUID("GPimportWaitingContainer");
+ div.className = "GPimportWaitingContainerHidden";
+
+ var p = document.createElement("p");
+ p.className = "GPimportWaiting";
+ p.innerHTML = "Recherche en cours...";
+
+ div.appendChild(p);
+
+ return div;
+ },
+
+ // ################################################################### //
+ // ##### Params for static import (KML / GPX / GeoJSON) ############## //
+ // ################################################################### //
+
+ /**
+ * Create container for KML/GPX/GeoJSON parameters
+ * @param {String} currentType - GeoJSON, GPX or KML value
+ * @returns {DOMElement} DOM element
+ */
+ _createImportStaticParamsContainer : function (currentType) {
+ var div = document.createElement("div");
+ div.id = this._addUID("GPimportStaticParams");
+ if (currentType === "KML" || currentType === "GPX" || currentType === "GeoJSON" || currentType === "MAPBOX") {
+ div.className = "GPimportVisibleParams";
+ } else {
+ div.className = "GPimportHiddenParams";
+ }
+
+ return div;
+ },
+
+ /**
+ * Create name label for KML/GPX/GeoJSON parameters
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createStaticNameLabel : function () {
+ var div = document.createElement("div");
+ div.className = "GPimportInputLine";
+
+ var label = document.createElement("label");
+ label.className = "GPimportLabel";
+ label.htmlFor = this._addUID("GPimportName");
+ label.innerHTML = "Nom";
+ label.title = "Nom";
+ div.appendChild(label);
+
+ var input = document.createElement("input");
+ input.type = "text";
+ input.id = this._addUID("GPimportName");
+ input.className = "GPimportInput";
+ div.appendChild(input);
+
+ return div;
+ },
+
+ /**
+ * Create import choice for KML/GPX/GeoJSON parameters (local or url)
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createStaticModeChoiceDiv : function () {
+ var div = document.createElement("div");
+ div.id = this._addUID("GPimportChoice");
+ return div;
+ },
+
+ /**
+ * Create local import choice for KML/GPX/GeoJSON parameters
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createStaticLocalChoiceDiv : function () {
+ var context = this;
+
+ var div = document.createElement("div");
+ div.className = "GPimportChoiceAlt";
+
+ var input = document.createElement("input");
+ input.type = "radio";
+ if (input.addEventListener) {
+ input.addEventListener("change", function (e) {
+ document.getElementById(context._addUID("GPimportValueLocal")).className = "GPimportInputLine";
+ document.getElementById(context._addUID("GPimportValueUrl")).className = "GPimportValueHidden";
+ context._onStaticImportTypeChange(e);
+ });
+ } else if (input.appendChild) {
+ input.appendChild("onchange", function () {
+ document.getElementById(context._addUID("GPimportValueLocal")).className = "GPimportInputLine";
+ document.getElementById(context._addUID("GPimportValueUrl")).className = "GPimportValueHidden";
+ context._onStaticImportTypeChange();
+ });
+ }
+ input.name = "GPimportChoiceMode";
+ input.value = "local";
+ input.checked = true;
+ input.id = this._addUID("GPimportChoiceAltLocal");
+ div.appendChild(input);
+
+ var label = document.createElement("label");
+ label.className = "GPimportChoiceAltTxt";
+ label.htmlFor = this._addUID("GPimportChoiceAltLocal");
+ label.innerHTML = "par fichier local";
+ label.title = "par fichier local";
+ div.appendChild(label);
+
+ return div;
+ },
+
+ /**
+ * Create url import choice for KML/GPX/GeoJSON parameters
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createStaticUrlChoiceDiv : function () {
+ var context = this;
+
+ var div = document.createElement("div");
+ div.className = "GPimportChoiceAlt";
+
+ var input = document.createElement("input");
+ input.type = "radio";
+ if (input.addEventListener) {
+ input.addEventListener("change", function (e) {
+ document.getElementById(context._addUID("GPimportValueUrl")).className = "GPimportInputLine";
+ document.getElementById(context._addUID("GPimportValueLocal")).className = "GPimportValueHidden";
+ context._onStaticImportTypeChange(e);
+ });
+ } else if (input.appendChild) {
+ input.appendChild("onchange", function () {
+ document.getElementById(context._addUID("GPimportValueUrl")).className = "GPimportInputLine";
+ document.getElementById(context._addUID("GPimportValueLocal")).className = "GPimportValueHidden";
+ context._onStaticImportTypeChange();
+ });
+ }
+ input.id = this._addUID("GPimportChoiceAltUrl");
+ input.name = "GPimportChoiceMode";
+ input.value = "url";
+ input.checked = false;
+ div.appendChild(input);
+
+ var label = document.createElement("label");
+ label.className = "GPimportChoiceAltTxt";
+ label.htmlFor = this._addUID("GPimportChoiceAltUrl");
+ label.innerHTML = "par URL";
+ label.title = "par URL";
+ div.appendChild(label);
+
+ return div;
+ },
+
+ /**
+ * Create input div for KML/GPX/GeoJSON parameters local import
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createStaticLocalInputDiv : function () {
+ var div = document.createElement("div");
+ div.id = this._addUID("GPimportValueLocal");
+ div.className = "GPimportInputLine";
+ return div;
+ },
+
+ /**
+ * Create input label for KML/GPX/GeoJSON parameters local import
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createStaticLocalInputLabel : function () {
+ var label = document.createElement("label");
+ label.className = "GPimportLabel";
+ label.htmlFor = this._addUID("GPimportFile");
+ label.innerHTML = "Fichier local";
+ label.title = "Fichier local";
+ return label;
+ },
+
+ /**
+ * Create file input for KML/GPX/GeoJSON parameters local import
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createStaticLocalInput : function () {
+ var input = document.createElement("input");
+ input.type = "file";
+ input.id = this._addUID("GPimportFile");
+ input.className = "GPimportInputFile";
+ return input;
+ },
+
+ /**
+ * Create input div for KML/GPX/GeoJSON parameters url import
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createStaticUrlInputDiv : function () {
+ var div = document.createElement("div");
+ div.id = this._addUID("GPimportValueUrl");
+ div.className = "GPimportValueHidden";
+ return div;
+ },
+
+ /**
+ * Create input label for KML/GPX/GeoJSON parameters url import
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createStaticUrlInputLabel : function () {
+ var label = document.createElement("label");
+ label.className = "GPimportLabel";
+ label.htmlFor = this._addUID("GPimportUrl");
+ label.innerHTML = "URL";
+ label.title = "URL";
+ return label;
+ },
+
+ /**
+ * Create url input for KML/GPX/GeoJSON parameters url import
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createStaticUrlInput : function () {
+ var input = document.createElement("input");
+ input.type = "text";
+ input.id = this._addUID("GPimportUrl");
+ input.className = "GPimportInput";
+ return input;
+ },
+
+ // ################################################################### //
+ // ######## Params for service params import (WMS//WMTS/WFS) ######### //
+ // ################################################################### //
+
+ /**
+ * Create container for WMS/WMTS/WFS parameters
+ * @param {String} currentType - WMS, WMTS or WFS value
+ * @returns {DOMElement} DOM element
+ */
+ _createServiceParamsContainer : function (currentType) {
+ var div = document.createElement("div");
+ div.id = this._addUID("GPimportServiceParams");
+ if (currentType === "WMS" || currentType === "WMTS" || currentType === "WFS") {
+ div.className = "GPimportVisibleParams";
+ } else {
+ div.className = "GPimportHiddenParams";
+ }
+
+ return div;
+ },
+
+ /**
+ * Create div for WMS/WMTS/WFS url
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createServiceUrlDiv : function () {
+ var div = document.createElement("div");
+ div.className = "GPimportInputLine";
+ return div;
+ },
+
+ /**
+ * Create input label for WMS/WMTS/WFS url
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createServiceUrlInputLabel : function () {
+ var label = document.createElement("label");
+ label.className = "GPimportLabel";
+ label.htmlFor = this._addUID("GPimportServiceUrl");
+ label.innerHTML = "URL du service";
+ label.title = "URL du service";
+ return label;
+ },
+
+ /**
+ * Create input for WMS/WMTS/WFS parameters url
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createServiceUrlInput : function () {
+ var input = document.createElement("input");
+ input.type = "text";
+ input.id = this._addUID("GPimportServiceUrl");
+ input.className = "GPimportInput";
+ return input;
+ },
+
+ // ################################################################### //
+ // ########################### Submit Form ########################### //
+ // ################################################################### //
+
+ /**
+ * Create Submit Form Element
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createImportSubmitFormElement : function () {
+ var input = document.createElement("input");
+ input.id = this._addUID("GPimportSubmit");
+ input.className = "GPinputSubmit tool-form-submit";
+ input.type = "submit";
+ input.value = "Importer";
+
+ return input;
+ },
+
+ // ################################################################### //
+ // ########################### GetCap Panel ########################## //
+ // ################################################################### //
+
+ /**
+ * Create GetCap Panel Element
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createImportGetCapPanelElement : function () {
+ var div = document.createElement("div");
+ div.id = this._addUID("GPimportGetCapPanel");
+ div.className = "GPpanel";
+ return div;
+ },
+
+ /**
+ * Create GetCap Panel Header Element
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createImportGetCapPanelHeaderElement : function () {
+ // contexte
+ var context = this;
+
+ var container = document.createElement("div");
+ container.className = "GPpanelHeader";
+
+ // panel title
+ var panelTitle = document.createElement("div");
+ panelTitle.className = "GPpanelTitle";
+ panelTitle.innerHTML = "Couches accessibles";
+ panelTitle.title = "Couches accessibles";
+ container.appendChild(panelTitle);
+
+ // close picto
+ var closeDiv = document.createElement("div");
+ if (closeDiv.addEventListener) {
+ closeDiv.addEventListener("click", function () {
+ document.getElementById(context._addUID("GPimportGetCapPanel")).style.display = "none";
+ document.getElementById(context._addUID("GPimportPanel")).style.display = "";
+ context._onGetCapPanelClose();
+ });
+ } else if (closeDiv.attachEvent) {
+ closeDiv.attachEvent("click", function () {
+ document.getElementById(context._addUID("GPimportGetCapPanel")).style.display = "none";
+ document.getElementById(context._addUID("GPimportPanel")).style.display = "";
+ context._onGetCapPanelClose();
+ });
+ }
+ closeDiv.className = "GPpanelClose";
+ closeDiv.title = "Fermer le panneau";
+ closeDiv.id = this._addUID("GPimportGetCapPanelClose");
+ container.appendChild(closeDiv);
+
+ return container;
+ },
+
+ /**
+ * Create GetCap Results List Element
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createImportGetCapResultsContainer : function () {
+ var container = document.createElement("div");
+ container.className = "GPimportGetCapRoot";
+ container.id = this._addUID("GPimportGetCapResults");
+
+ return container;
+ },
+
+ _addImportGetCapResultListRubrique : function (title, container) {
+ var ul = document.createElement("ul");
+ ul.className = "GPimportGetCapListRubrique";
+ ul.title = title;
+
+ container.appendChild(ul);
+ return container;
+ },
+
+ _addImportGetCapResultRubrique : function (title, container) {
+ var li = document.createElement("li");
+ li.className = "GPimportGetCapRubrique";
+
+ // input
+ var input = document.createElement("input");
+ input.id = "GPimportGetCapRubrique-" + SelectorID.generate();
+ input.className = "GPimportGetCapRubrique";
+ input.type = "checkbox";
+ li.appendChild(input);
+
+ // label for
+ var label = document.createElement("label");
+ label.className = "GPimportGetCapRubriqueTitle";
+ label.htmlFor = input.id;
+ label.innerHTML = title;
+ label.title = title;
+ li.appendChild(label);
+
+ container.appendChild(li);
+ return container;
+ },
+
+ _addImportGetCapResultListLayer : function (container) {
+ var ul = document.createElement("ul");
+ ul.className = "GPimportGetCapListLayer";
+
+ container.appendChild(ul);
+ return container;
+ },
+
+ _addImportGetCapResultLayer : function (description, id, container) {
+ var li = document.createElement("li");
+ li.className = "GPimportGetCapProposal";
+ li.innerHTML = description.content;
+ li.title = description.title;
+ li.id = "GPimportGetCapProposal_" + id;
+
+ var context = this;
+ if (li.addEventListener) {
+ li.addEventListener("click", function (e) {
+ context._onGetCapResponseLayerClick(e);
+ });
+ } else if (li.attachEvent) {
+ li.attachEvent("onclick", function () {
+ context._onGetCapResponseLayerClick();
+ });
+ }
+
+ container.appendChild(li);
+ return container;
+ },
+
+ // ################################################################### //
+ // ########################### MapBox Panel ########################## //
+ // ################################################################### //
+
+ /**
+ * Create MapBox Panel Element
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createImportMapBoxPanelElement : function () {
+ var div = document.createElement("div");
+ div.id = this._addUID("GPimportMapBoxPanel");
+ div.className = "GPpanel";
+ return div;
+ },
+
+ /**
+ * Create MapBox Panel Header Element
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createImportMapBoxPanelHeaderElement : function () {
+ // contexte
+ var context = this;
+
+ var container = document.createElement("div");
+ container.className = "GPpanelHeader";
+
+ // return picto
+ var returnDiv = document.createElement("div");
+ returnDiv.id = this._addUID("GPimportMapBoxPanelReturnPicto");
+ returnDiv.title = "Masquer le panneau";
+ returnDiv.className = "";
+ if (returnDiv.addEventListener) {
+ returnDiv.addEventListener("click", function (e) {
+ // document.getElementById(context._addUID("GPimportMapBoxPanel")).style.display = "none";
+ // document.getElementById(context._addUID("GPimportPanel")).style.display = "none";
+ context._onMapBoxReturnPictoClick(e);
+ });
+ } else if (returnDiv.attachEvent) {
+ returnDiv.attachEvent("onclick", function (e) {
+ // document.getElementById(context._addUID("GPimportMapBoxPanel")).style.display = "none";
+ // document.getElementById(context._addUID("GPimportPanel")).style.display = "none";
+ context._onMapBoxReturnPictoClick(e);
+ });
+ }
+ container.appendChild(returnDiv);
+
+ // panel title
+ var panelTitle = document.createElement("div");
+ panelTitle.className = "GPpanelTitle";
+ panelTitle.innerHTML = "Edition des styles";
+ panelTitle.title = "Edition des styles";
+ container.appendChild(panelTitle);
+
+ // close picto
+ var closeDiv = document.createElement("div");
+ if (closeDiv.addEventListener) {
+ closeDiv.addEventListener("click", function () {
+ document.getElementById(context._addUID("GPimportMapBoxPanel")).style.display = "none";
+ document.getElementById(context._addUID("GPimportPanel")).style.display = "";
+ context._onMapBoxPanelClose();
+ });
+ } else if (closeDiv.attachEvent) {
+ closeDiv.attachEvent("click", function () {
+ document.getElementById(context._addUID("GPimportMapBoxPanel")).style.display = "none";
+ document.getElementById(context._addUID("GPimportPanel")).style.display = "";
+ context._onMapBoxPanelClose();
+ });
+ }
+ closeDiv.className = "GPpanelClose";
+ closeDiv.title = "Fermer le panneau";
+ closeDiv.id = this._addUID("GPimportMapBoxPanelClose");
+ container.appendChild(closeDiv);
+
+ return container;
+ },
+
+ /**
+ * Create MapBox Results List Element
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createImportMapBoxResultsContainer : function () {
+ var container = document.createElement("div");
+ container.className = "GPimportMapBoxpRoot";
+ container.id = this._addUID("GPimportMapBoxResults");
+ return container;
+ }
+
+ // _addImportMapBoxResultListSource : function (id, source, container) {
+ // var ul = document.createElement("ul");
+ // ul.className = "GPimportMapBoxListSource";
+ // ul.title = id;
+ //
+ // var label = document.createElement("label");
+ // label.className = "GPimportMapBoxListSourceTitle";
+ // label.innerHTML = "Listes des couches pour la source '" + id + "' :";
+ // label.title = source.attribution || id;
+ // ul.appendChild(label);
+ //
+ // container.appendChild(ul);
+ // return container;
+ // },
+ //
+ // _addImportMapBoxResultSource : function (layer, container) {
+ // var li = document.createElement("li");
+ // li.className = "GPimportMapBoxSource";
+ //
+ // // input
+ // var input = document.createElement("input");
+ // input.id = "GPimportMapBoxSource-" + SelectorID.generate();
+ // input.className = "GPimportMapBoxSource";
+ // input.type = "checkbox";
+ // li.appendChild(input);
+ //
+ // // label for
+ // var name = layer["source-layer"] || layer.id || layer.source;
+ // var label = document.createElement("label");
+ // label.className = "GPimportMapBoxSourceTitle";
+ // label.htmlFor = input.id;
+ // label.innerHTML = name;
+ // label.title = JSON.stringify(layer.metadata) || name;
+ // li.appendChild(label);
+ //
+ // container.appendChild(li);
+ // return container;
+ // },
+ //
+ // _addImportMapBoxStyleSource : function (layer, container) {
+ // // contexte
+ // var self = this;
+ //
+ // var _style = false;
+ // var _obj = {};
+ // var _layer = JSON.parse(JSON.stringify(layer)); // on utilise une copie !
+ // if (_layer.paint && Object.keys(_layer.paint).length) {
+ // _style = true;
+ // _obj.paint = _layer.paint;
+ // }
+ //
+ // // pas de style dans paint, on teste dans layout !
+ // if (_layer.layout && Object.keys(_layer.layout).length) {
+ // _style = true;
+ // _obj.layout = _layer.layout;
+ // // on supprime visibility à l'affichage uniquement
+ // // cf. _addImportMapBoxVisibilitySource !
+ // if (_layer.layout.visibility) {
+ // delete _obj.visibility;
+ // }
+ // }
+ //
+ // function syntaxHighlight (json) {
+ // json = json.replace(/&/g, "&").replace(//g, ">");
+ // return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+-]?\d+)?)/g, function (match) {
+ // var cls = "gp-json-number";
+ // if (/^"/.test(match)) {
+ // if (/:$/.test(match)) {
+ // cls = "gp-json-key";
+ // } else {
+ // cls = "gp-json-string";
+ // }
+ // } else if (/true|false/.test(match)) {
+ // cls = "gp-json-boolean";
+ // } else if (/null/.test(match)) {
+ // cls = "gp-json-null";
+ // }
+ // return "" + match + "";
+ // });
+ // }
+ //
+ // var div = document.createElement("div");
+ // div.className = "GPimportMapBoxSourceStyle";
+ //
+ // if (_style) {
+ // var strJson = JSON.stringify(_obj, null, 4);
+ //
+ // var label = document.createElement("label");
+ // label.innerHTML = "JSON Styles :";
+ // div.appendChild(label);
+ // var pre = document.createElement("pre");
+ // pre.className = "GPimportMapBoxJsonEdit";
+ // pre.innerHTML = syntaxHighlight(strJson);
+ // if (pre.addEventListener) {
+ // pre.addEventListener("click", function (e) {
+ // self._onSwitchStyleEditSourceMapBox(e);
+ // });
+ // } else if (pre.appendChild) {
+ // pre.appendChild("onclick", function (e) {
+ // self._onSwitchStyleEditSourceMapBox(e);
+ // });
+ // }
+ // div.appendChild(pre);
+ // }
+ //
+ // container.appendChild(div);
+ // return container;
+ // },
+ //
+ // _addImportMapBoxFilterSource : function (layer, container) {
+ // // contexte
+ // var self = this;
+ //
+ // var _filter = false;
+ // // FIXME tag filter est obselete !
+ // // on doit utiliser les expressions dans "paint" ou "layout" !
+ // if (layer.filter && layer.filter.length) {
+ // _filter = true;
+ // }
+ //
+ // var div = document.createElement("div");
+ // div.className = "GPimportMapBoxSourceFilter";
+ //
+ // if (_filter) {
+ // var label = document.createElement("label");
+ // label.innerHTML = "JSON Filtres :";
+ // div.appendChild(label);
+ // var pre = document.createElement("pre");
+ // pre.className = "GPimportMapBoxJsonEdit";
+ // pre.innerHTML = JSON.stringify(layer.filter, null, 4);
+ // if (pre.addEventListener) {
+ // pre.addEventListener("click", function (e) {
+ // self._onSwitchFilterEditSourceMapBox(e);
+ // });
+ // } else if (pre.appendChild) {
+ // pre.appendChild("onclick", function (e) {
+ // self._onSwitchFilterEditSourceMapBox(e);
+ // });
+ // }
+ // div.appendChild(pre);
+ // }
+ //
+ // container.appendChild(div);
+ // return container;
+ // },
+ //
+ // _addImportMapBoxScaleSource : function (layer, container) {
+ // // contexte
+ // var self = this;
+ //
+ // var _scaleMin = layer.minzoom || 0;
+ // var _scaleMax = layer.maxzoom || 21;
+ //
+ // var div = document.createElement("div");
+ // div.className = "GPimportMapBoxSourceScale";
+ //
+ // var labelMin = document.createElement("label");
+ // labelMin.className = "GPimportMapBoxSourceScaleLabel";
+ // labelMin.innerHTML = "minZoom :";
+ // div.appendChild(labelMin);
+ //
+ // var inputMin = document.createElement("input");
+ // inputMin.className = "GPimportMapBoxSourceScaleInput";
+ // inputMin.type = "range";
+ // inputMin.value = _scaleMin;
+ // inputMin.title = _scaleMin;
+ // inputMin.disabled = false;
+ // inputMin.min = 0;
+ // inputMin.max = 21;
+ // if (inputMin.addEventListener) {
+ // inputMin.addEventListener("change", function (e) {
+ // self._onChangeScaleMinSourceMapBox(e, layer);
+ // });
+ // } else if (inputMin.appendChild) {
+ // inputMin.appendChild("onchange", function (e) {
+ // self._onChangeScaleMinSourceMapBox(e, layer);
+ // });
+ // }
+ // div.appendChild(inputMin);
+ //
+ // div.appendChild(document.createElement("br"));
+ //
+ // var labelMax = document.createElement("label");
+ // labelMax.className = "GPimportMapBoxSourceScaleLabel";
+ // labelMax.innerHTML = "maxZoom :";
+ // div.appendChild(labelMax);
+ //
+ // var inputMax = document.createElement("input");
+ // inputMax.className = "GPimportMapBoxSourceScaleInput";
+ // inputMax.type = "range";
+ // inputMax.value = _scaleMax;
+ // inputMax.title = _scaleMax;
+ // inputMax.disabled = false;
+ // inputMax.min = 0;
+ // inputMax.max = 21;
+ // if (inputMax.addEventListener) {
+ // inputMax.addEventListener("change", function (e) {
+ // self._onChangeScaleMaxSourceMapBox(e, layer);
+ // });
+ // } else if (inputMax.appendChild) {
+ // inputMax.appendChild("onchange", function (e) {
+ // self._onChangeScaleMaxSourceMapBox(e, layer);
+ // });
+ // }
+ // div.appendChild(inputMax);
+ //
+ // container.appendChild(div);
+ // return container;
+ // },
+ //
+ // _addImportMapBoxVisibilitySource : function (layer, container) {
+ // // contexte
+ // var self = this;
+ //
+ // var _visibility = true;
+ // if (layer.layout && layer.layout.visibility && layer.layout.visibility === "none") {
+ // _visibility = false;
+ // }
+ //
+ // var div = document.createElement("div");
+ // div.className = "GPimportMapBoxSourceVisibility";
+ //
+ // var label = document.createElement("label");
+ // label.className = "GPimportMapBoxSourceVisibilityLabel";
+ // label.innerHTML = "Visibilité :";
+ // div.appendChild(label);
+ //
+ // var input = document.createElement("input");
+ // input.className = "GPimportMapBoxSourceVisibilityInput";
+ // input.type = "checkbox";
+ // input.checked = _visibility;
+ // input.disabled = false;
+ // if (input.addEventListener) {
+ // input.addEventListener("change", function (e) {
+ // self._onChangeVisibilitySourceMapBox(e, layer);
+ // });
+ // } else if (input.appendChild) {
+ // input.appendChild("onchange", function (e) {
+ // self._onChangeVisibilitySourceMapBox(e, layer);
+ // });
+ // }
+ // div.appendChild(input);
+ //
+ // container.appendChild(div);
+ // return container;
+ // }
+};
+
+export default LayerImportDOM;
diff --git a/src/Common-review/Controls/LayerSwitcherDOM.js b/src/Common-review/Controls/LayerSwitcherDOM.js
new file mode 100644
index 000000000..7ccd92fe2
--- /dev/null
+++ b/src/Common-review/Controls/LayerSwitcherDOM.js
@@ -0,0 +1,676 @@
+import Sortable from "sortablejs";
+
+var LayerSwitcherDOM = {
+
+ /**
+ * Creation du drag and drop
+ *
+ * @param {Object} elementDraggable - Element HTML (DOM) Container
+ * @param {Object} context - this
+ */
+ _createDraggableElement : function (elementDraggable, context) {
+ Sortable.create(elementDraggable, {
+ handle : ".GPlayerName",
+ draggable : ".draggable-layer",
+ ghostClass : "GPghostLayer",
+ animation : 200,
+ // Call event function on drag and drop
+ onEnd : function (e) {
+ // FIXME pas terrrible, mais il faut bien passer ce contexte...
+ context._onDragAndDropLayerClick(e);
+ }
+ });
+ },
+
+ // ################################################################### //
+ // ######################### Main container ########################## //
+ // ################################################################### //
+
+ /**
+ * Add uuid to the tag ID
+ * @param {String} id - id selector
+ * @returns {String} uid - id selector with an unique id
+ */
+ _addUID : function (id) {
+ var uid = (this._uid) ? id + "-" + this._uid : id;
+ return uid;
+ },
+
+ /**
+ * Creation du container principal (DOM)
+ *
+ * @returns {DOMElement} container - layer switcher DOM element
+ */
+ _createMainContainerElement : function () {
+ var container = document.createElement("div");
+ container.id = this._addUID("GPlayerSwitcher");
+ container.className = "GPwidget";
+ return container;
+ },
+
+ /**
+ * Creation du container principal d"affichage des layers (DOM)
+ *
+ * @returns {DOMElement} input - element for minimizing/maximizing the layer switcher
+ */
+ _createMainLayersShowElement : function () {
+ //
+ var input = document.createElement("input");
+ input.id = this._addUID("GPshowLayersList");
+ input.type = "checkbox";
+ return input;
+ },
+
+ /**
+ * Creation du container principal des layers (DOM)
+ *
+ * @returns {DOMElement} container - layers list container
+ */
+ _createMainLayersElement : function () {
+ // ajout de la liste des layers dans le container principal
+ //
+ // (...)
+ //
+ var div = document.createElement("div");
+ div.id = this._addUID("GPlayersList");
+ div.className = "GPpanel";
+ return div;
+ },
+
+ /**
+ * Creation du container du picto du controle (DOM)
+ *
+ * @returns {DOMElement} label
+ */
+ _createMainPictoElement : function () {
+ var self = this;
+
+ // exemple :
+ //
+ //
+
+ var label = document.createElement("label");
+ label.id = this._addUID("GPshowLayersListPicto");
+ label.className = "GPshowAdvancedToolPicto";
+ label.htmlFor = this._addUID("GPshowLayersList");
+ label.title = "Afficher/masquer le gestionnaire de couches";
+
+ var spanOpen = document.createElement("span");
+ spanOpen.id = this._addUID("GPshowLayersListOpen");
+ spanOpen.className = "GPshowAdvancedToolOpen";
+ spanOpen.addEventListener("click", function () {
+ if (document.getElementById(self._addUID("GPshowLayersList")).checked) {
+ var layers = document.getElementsByClassName("GPlayerInfoOpened");
+ for (var i = 0; i < layers.length; i++) {
+ layers[i].className = "GPlayerInfo";
+ }
+ document.getElementById(self._addUID("GPlayerInfoPanel")).className = "GPlayerInfoPanelClosed";
+ }
+ });
+
+ label.appendChild(spanOpen);
+
+ var spanClose = document.createElement("span");
+ spanClose.addEventListener("click", function () {
+ if (document.getElementById(self._addUID("GPshowLayersList")).checked) {
+ var layers = document.getElementsByClassName("GPlayerInfoOpened");
+ for (var i = 0; i < layers.length; i++) {
+ layers[i].className = "GPlayerInfo";
+ }
+ document.getElementById(self._addUID("GPlayerInfoPanel")).className = "GPlayerInfoPanelClosed";
+ }
+ });
+ spanClose.id = self._addUID("GPshowLayersListClose");
+
+ label.appendChild(spanClose);
+
+ return label;
+ },
+
+ /**
+ * Creation du container du panneau d"information (DOM)
+ *
+ * @returns {DOMElement} container
+ */
+ _createMainInfoElement : function () {
+ // gestion du panneau d"information dans le container principal
+ //
...
+ var div = document.createElement("div");
+ div.id = this._addUID("GPlayerInfoPanel");
+ div.className = "GPpanel GPlayerInfoPanelClosed";
+ return div;
+ },
+
+ // ################################################################### //
+ // ######################### Layer container ######################### //
+ // ################################################################### //
+
+ /**
+ * Creation du container du layer (DOM)
+ *
+ * @param {Object} obj - options de la couche à ajouter dans le layer switcher
+ * @param {Object} obj.layer - couche (ol ou leaflet)
+ * @param {String} obj.id - identifiant de la couche (pour ol ou leaflet)
+ * @param {String} obj.title - nom de la couche à afficher dans le controle
+ * @param {String} obj.description - description de la couche à afficher
+ * @param {Boolean} obj.visibility - visibilité de la couche dans la carte (true or false)
+ * @param {Float} obj.opacity - opacité de la couche
+ *
+ * @returns {DOMElement} container
+ */
+ _createContainerLayerElement : function (obj) {
+ // exemple :
+ //
+ //
+ //
+ //
+ //
+
+ //
+ //
+ var container = document.createElement("div");
+ container.id = this._addUID("GPlayerSwitcher_ID_" + obj.id);
+ container.className = "GPlayerSwitcher_layer draggable-layer";
+
+ // ajout des outils basiques (visibility / layer name)
+ container.appendChild(this._createBasicToolElement(obj));
+
+ // liste des outils avancés (layer info / opacity slider / opacity value / removal)
+ var array = this._createAdvancedToolShowElement(obj);
+ for (var i = 0; i < array.length; i++) {
+ container.appendChild(array[i]);
+ }
+
+ // ajout des outils avancés
+ container.appendChild(this._createAdvancedToolElement(obj));
+
+ return container;
+ },
+
+ // ################################################################### //
+ // ############################ Layer tool ########################### //
+ // ################################################################### //
+
+ /**
+ * Creation du container des outils basiques du layer (DOM)
+ *
+ * @param {Object} obj - options de la couche à ajouter dans le layer switcher
+ *
+ * @returns {DOMElement} container
+ */
+ _createBasicToolElement : function (obj) {
+ // exemple :
+ //
+ //
+ //
+ //
+
+ var div = document.createElement("div");
+ div.id = this._addUID("GPbasicTools_ID_" + obj.id);
+ div.className = "GPlayerBasicTools";
+
+ div.appendChild(this._createBasicToolNameElement(obj));
+
+ var array = this._createBasicToolVisibilityElement(obj);
+ for (var i = 0; i < array.length; i++) {
+ div.appendChild(array[i]);
+ }
+
+ return div;
+ },
+
+ /**
+ * Creation du nom du layer (DOM)
+ *
+ * @param {Object} obj - options de la couche à ajouter dans le layer switcher
+ *
+ * @returns {DOMElement} container
+ */
+ _createBasicToolNameElement : function (obj) {
+ // exemple :
+ // Quartiers prioritaires de la ville
+ var span = document.createElement("span");
+ span.id = this._addUID("GPname_ID_" + obj.id);
+ span.className = "GPlayerName";
+ span.title = obj.description || obj.title;
+ span.innerHTML = obj.title;
+
+ return span;
+ },
+
+ /**
+ * Creation de l'icone de visibilité du layer (DOM)
+ *
+ * @param {Object} obj - options de la couche à ajouter dans le layer switcher
+
+ * @returns {DOMElement[]} array containing input and label elements
+ */
+ _createBasicToolVisibilityElement : function (obj) {
+ // exemple :
+ //
+ //
+
+ var list = [];
+
+ var checked = (typeof obj.visibility !== "undefined") ? obj.visibility : true;
+ var id = this._addUID("GPvisibility_ID_" + obj.id);
+
+ var input = document.createElement("input");
+ input.id = id;
+ input.type = "checkbox";
+ input.checked = checked;
+
+ var label = document.createElement("label");
+ label.htmlFor = id;
+ label.id = this._addUID("GPvisibilityPicto_ID_" + obj.id);
+ label.className = "GPlayerVisibility";
+ label.title = "Afficher/masquer la couche";
+
+ // add event for visibility change
+ var context = this;
+ if (input.addEventListener) {
+ input.addEventListener(
+ "click",
+ function (e) {
+ context._onVisibilityLayerClick(e);
+ }
+ );
+ } else if (input.attachEvent) {
+ // internet explorer
+ input.attachEvent(
+ "onclick",
+ function (e) {
+ context._onVisibilityLayerClick(e);
+ }
+ );
+ }
+
+ list.push(input);
+ list.push(label);
+
+ return list;
+ },
+
+ /**
+ * Creation de l'affichage du menu des outils avancés du layer (DOM)
+ *
+ * @param {Object} obj - options de la couche à ajouter dans le layer switcher
+ *
+ * @returns {DOMElement[]} array containing input and label elements
+ */
+ _createAdvancedToolShowElement : function (obj) {
+ //
+ //
+
+ var list = [];
+
+ var label = document.createElement("label");
+ label.id = this._addUID("GPshowAdvancedToolsPicto_ID_" + obj.id);
+ label.htmlFor = this._addUID("GPshowAdvancedTools_ID_" + obj.id);
+ label.title = "Plus d'outils";
+ label.className = "GPshowMoreOptions GPshowLayerAdvancedTools";
+
+ var input = document.createElement("input");
+ input.type = "checkbox";
+ input.id = this._addUID("GPshowAdvancedTools_ID_" + obj.id);
+
+ list.push(input);
+ list.push(label);
+
+ return list;
+ },
+
+ /**
+ * Creation du container des outils avancés du layer (DOM)
+ *
+ * @param {Object} obj - options de la couche à ajouter dans le layer switcher
+ *
+ * @returns {DOMElement} container
+ */
+ _createAdvancedToolElement : function (obj) {
+ // exemple :
+ //
+ //
+ //
+ //
+ //
+
+ var container = document.createElement("div");
+ container.id = this._addUID("GPadvancedTools_ID_" + obj.id);
+ container.className = "GPlayerAdvancedTools";
+
+ container.appendChild(this._createAdvancedToolDeleteElement(obj));
+
+ // si on n'a de l'informations à afficher, on met en place ce composant
+ if (obj.title && obj.description) {
+ container.appendChild(this._createAdvancedToolInformationElement(obj));
+ }
+ if (obj.type !== "feature") {
+ var array = this._createAdvancedToolOpacityElement(obj);
+ for (var i = 0; i < array.length; i++) {
+ container.appendChild(array[i]);
+ }
+ }
+
+ return container;
+ },
+
+ /**
+ * Creation de l'icone de suppression du layer (DOM)
+ *
+ * @param {Object} obj - options de la couche à ajouter dans le layer switcher
+ *
+ * @returns {DOMElement} container
+ */
+ _createAdvancedToolDeleteElement : function (obj) {
+ // exemple :
+ //
+
+ var div = document.createElement("div");
+ div.id = this._addUID("GPremove_ID_" + obj.id);
+ div.className = "GPlayerRemove";
+ div.title = "Supprimer la couche";
+ div.layerId = obj.id;
+
+ var context = this;
+ if (div.addEventListener) {
+ div.addEventListener(
+ "click",
+ function (e) {
+ context._onDropLayerClick(e);
+ }
+ );
+ } else if (div.attachEvent) {
+ // internet explorer
+ div.attachEvent(
+ "onclick",
+ function (e) {
+ context._onDropLayerClick(e);
+ }
+ );
+ }
+
+ return div;
+ },
+
+ /**
+ * Creation de l'icone d'information du layer (DOM)
+ *
+ * @param {Object} obj - options de la couche à ajouter dans le layer switcher
+ *
+ * @returns {DOMElement} container
+ */
+ _createAdvancedToolInformationElement : function (obj) {
+ // exemple :
+ //
+
+ var div = document.createElement("div");
+ div.id = this._addUID("GPinfo_ID_" + obj.id);
+ div.className = "GPlayerInfo";
+ div.title = "Informations/légende";
+ div.layerId = obj.id;
+ // add event on click
+ var context = this;
+ if (div.addEventListener) {
+ div.addEventListener(
+ "click",
+ function (e) {
+ context._onOpenLayerInfoClick(e);
+ }
+ );
+ } else if (div.attachEvent) {
+ // internet explorer
+ div.attachEvent(
+ "onclick",
+ function (e) {
+ context._onOpenLayerInfoClick(e);
+ }
+ );
+ }
+
+ return div;
+ },
+
+ /**
+ * Creation de l'icone de gestion de l'opacité du layer (DOM)
+ *
+ * @param {Object} obj - options de la couche à ajouter dans le layer switcher
+ *
+ * @returns {DOMElement[]} array of two containers
+ */
+ _createAdvancedToolOpacityElement : function (obj) {
+ // exemple :
+ //
+ //
+ //
+ //
+ // 100
+ // %
+ //
+
+ var list = [];
+
+ // curseur pour changer l'opacité
+ var divO = document.createElement("div");
+ divO.id = this._addUID("GPopacity_ID_" + obj.id);
+ divO.className = "GPlayerOpacity";
+ divO.title = "Opacité";
+
+ var opacity = (typeof obj.opacity !== "undefined") ? obj.opacity : 1;
+ opacity = Math.round(opacity * 100);
+
+ var input = document.createElement("input");
+ input.id = this._addUID("GPopacityValueDiv_ID_" + obj.id);
+ input.type = "range";
+ input.value = opacity;
+
+ // add event for opacity change
+ var context = this;
+ if (input.addEventListener) {
+ input.addEventListener(
+ "change",
+ function (e) {
+ context._onChangeLayerOpacity(e);
+ }
+ );
+ } else if (input.attachEvent) {
+ // internet explorer
+ input.attachEvent(
+ "onchange",
+ function (e) {
+ context._onChangeLayerOpacity(e);
+ }
+ );
+ }
+
+ if (input.addEventListener) {
+ input.addEventListener(
+ "input",
+ function (e) {
+ context._onChangeLayerOpacity(e);
+ }
+ );
+ } else if (input.attachEvent) {
+ // internet explorer
+ input.attachEvent(
+ "oninput",
+ function (e) {
+ context._onChangeLayerOpacity(e);
+ }
+ );
+ }
+
+ divO.appendChild(input);
+
+ // Valeur d'opacité
+ var divC = document.createElement("div");
+ divC.id = this._addUID("GPopacityValueDiv_ID_" + obj.id);
+ divC.className = "GPlayerOpacityValue";
+
+ var span = document.createElement("span");
+ span.id = this._addUID("GPopacityValue_ID_" + obj.id);
+ span.innerHTML = opacity + "%";
+
+ divC.appendChild(span);
+
+ list.push(divO);
+ list.push(divC);
+
+ return list;
+ },
+
+ // ################################################################### //
+ // ############################ Layer info ########################### //
+ // ################################################################### //
+
+ /**
+ * Creation du container du layer info (DOM)
+ *
+ * TODO GPlayerInfoPopup : ???
+ * TODO GPlayerInfoLink : mettre en forme les échelles !
+ *
+ * @param {Object} obj - options de la couche à ajouter dans le layer switcher
+ *
+ * @returns {DOMElement} container
+ */
+ _createContainerLayerInfoElement : function (obj) {
+ var container = document.createElement("div");
+ container.id = this._addUID("GPlayerInfoContent");
+
+ var title = document.createElement("div");
+ title.id = this._addUID("GPlayerInfoTitle");
+ title.innerHTML = obj.title;
+ container.appendChild(title);
+
+ if (obj.quicklookUrl) {
+ var quick = document.createElement("div");
+ quick.id = this._addUID("GPlayerInfoQuicklook");
+ quick.title = "Afficher un aperçu de la couche";
+ var refquick = document.createElement("a");
+ refquick.href = obj.quicklookUrl;
+ refquick.appendChild(quick);
+ container.appendChild(refquick);
+ }
+
+ var close = document.createElement("div");
+ close.id = this._addUID("GPlayerInfoClose");
+ close.title = "Fermer la fenêtre";
+
+ var self = this;
+ /** Call event function on close click */
+ var onCloseClick = function () {
+ document.getElementById(self._addUID("GPlayerInfoPanel")).className = "GPlayerInfoPanelClosed";
+ var layers = document.getElementsByClassName("GPlayerInfoOpened");
+ for (var i = 0; i < layers.length; i++) {
+ layers[i].className = "GPlayerInfo";
+ }
+ };
+ if (close.addEventListener) {
+ close.addEventListener("click", onCloseClick);
+ } else if (close.attachEvent) {
+ // internet explorer
+ close.attachEvent("onclick", onCloseClick);
+ }
+ container.appendChild(close);
+
+ var desc = document.createElement("div");
+ desc.id = this._addUID("GPlayerInfoDescription");
+ desc.innerHTML = obj.description;
+ container.appendChild(desc);
+
+ if (obj.metadata) {
+ var mtd = document.createElement("div");
+ mtd.id = this._addUID("GPlayerInfoMetadata");
+
+ var mtdtitle = document.createElement("div");
+ mtdtitle.className = "GPlayerInfoSubtitle";
+ mtdtitle.innerHTML = "Métadonnées";
+ mtd.appendChild(mtdtitle);
+
+ for (var i = 0; i < obj.metadata.length; i++) {
+ var urlmtd = obj.metadata[i].url;
+
+ var mtdlink = document.createElement("div");
+ mtdlink.className = "GPlayerInfoLink";
+
+ var refmtd = document.createElement("a");
+ refmtd.href = urlmtd;
+ refmtd.innerHTML = urlmtd;
+ mtdlink.appendChild(refmtd);
+ mtd.appendChild(mtdlink);
+ }
+
+ if (obj.metadata.length !== 0) {
+ container.appendChild(mtd);
+ }
+ }
+
+ if (obj.legends) {
+ var lgd = document.createElement("div");
+ lgd.id = this._addUID("GPlayerInfoLegend");
+
+ var lgdtitle = document.createElement("div");
+ lgdtitle.className = "GPlayerInfoSubtitle";
+ lgdtitle.innerHTML = "Légende";
+ lgd.appendChild(lgdtitle);
+
+ var legends = {};
+ var maxScale = obj.maxScaleDenominator || 560000000;
+
+ // on crée un tableau temporaire pour ordonner les légendes selon le dénominateur d'échelle
+ for (var k = 0; k < obj.legends.length; k++) {
+ var minScale = obj.legends[k].minScaleDenominator;
+ if (minScale) {
+ var s = minScale.toString();
+ minScale = Math.round(parseInt(s.substring(0, 3), 10) / 10) * Math.pow(10, s.length - 2);
+ } else {
+ minScale = 270;
+ }
+ legends[minScale] = obj.legends[k];
+ }
+
+ for (var scale in legends) {
+ if (legends.hasOwnProperty(scale)) {
+ var urllgd = legends[scale].url;
+ // on n'affiche pas les légendes pointant vers "nolegend.jpg"
+ if (typeof urllgd === "string" && urllgd.toLowerCase().indexOf("nolegend.jpg") === -1) {
+ // TODO GPlayerInfoPopup
+ var lgdlink = document.createElement("div");
+ lgdlink.className = "GPlayerInfoLink";
+
+ maxScale = legends[scale].maxScaleDenominator || maxScale;
+
+ var reflgd = document.createElement("a");
+ reflgd.href = urllgd;
+ reflgd.innerHTML = "Du 1/" + scale + " au 1/" + maxScale;
+ lgdlink.appendChild(reflgd);
+ lgd.appendChild(lgdlink);
+ } else {
+ delete legends[scale];
+ }
+ }
+ }
+
+ if (Object.keys(legends).length !== 0) {
+ container.appendChild(lgd);
+ }
+ }
+
+ return container;
+ }
+};
+
+export default LayerSwitcherDOM;
diff --git a/src/Common-review/Controls/LocationSelectorDOM.js b/src/Common-review/Controls/LocationSelectorDOM.js
new file mode 100644
index 000000000..ea03d8edb
--- /dev/null
+++ b/src/Common-review/Controls/LocationSelectorDOM.js
@@ -0,0 +1,484 @@
+import ID from "../Utils/SelectorID";
+import Logger from "../../Common/Utils/LoggerByDefault";
+
+var logger = Logger.getLogger("LocationSelectorDOM");
+
+var LocationSelectorDOM = {
+
+ /**
+ * Add uuid to the tag ID
+ * @param {String} id - id selector
+ * @returns {String} uid - id selector with an unique id
+ */
+ _addUID : function (id) {
+ var uid = (this._uid) ? id + "-" + this._uid : id;
+ return uid;
+ },
+
+ /**
+ * Main container (DOM)
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createMainContainerElement : function () {
+ var container = document.createElement("div");
+ container.className = this._addUID("GPlocationPoint"); // ceci permet de gerer les groupes de points !
+ container.className += " GPwidget";
+ return container;
+ },
+
+ /**
+ * Create Container Point
+ * see event !
+ *
+ * @param {Number} id - tag ID
+ * @param {Number} display - display
+ * @returns {DOMElement} DOM element
+ */
+ _createLocationPointElement : function (id, display) {
+ var div = document.createElement("div");
+ div.id = this._addUID("GPlocationPoint_" + id);
+ div.className = (display) ? "GPflexInput GPlocationStageFlexInput" : "GPflexInput GPlocationStageFlexInputHidden";
+ div.style.cssText = "";
+
+ return div;
+ },
+
+ /**
+ * Create Container Point
+ * see event !
+ *
+ * @param {Number} id - tag ID
+ * @param {String} text - label
+ * @returns {DOMElement} DOM element
+ */
+ _createLocationPointLabelElement : function (id, text) {
+ // contexte d'execution
+ var self = this;
+
+ var labelOrigin = document.createElement("label");
+ labelOrigin.id = this._addUID("GPlocationOriginLabel_" + id);
+ labelOrigin.htmlFor = "GPlocationOrigin_" + id;
+ labelOrigin.innerHTML = text;
+ labelOrigin.addEventListener("click", function (e) {
+ var i = ID.index(this.id);
+ var points = document.getElementsByClassName(self._addUID("GPlocationPoint"));
+ for (var j = 0; j < points.length; j++) {
+ var tag = points[j].childNodes[0].id;
+ var id = ID.index(tag);
+ document.getElementById(self._addUID("GPlocationPoint_" + id)).style.cssText = "";
+ }
+ document.getElementById(self._addUID("GPlocationOriginCoords_" + i)).value = "";
+ document.getElementById(self._addUID("GPlocationOrigin_" + i)).value = "";
+ document.getElementById(self._addUID("GPlocationPoint_" + i)).style.cssText = "";
+ document.getElementById(self._addUID("GPlocationOriginPointer_" + i)).checked = false;
+ document.getElementById(self._addUID("GPlocationOrigin_" + i)).className = "GPlocationOriginVisible";
+ document.getElementById(self._addUID("GPlocationOriginCoords_" + i)).className = "GPlocationOriginHidden";
+ if (document.getElementById(self._addUID("GPlocationStageRemove_" + i))) {
+ document.getElementById(self._addUID("GPlocationStageRemove_" + i)).className = "GPlocationStageRemove";
+ }
+ if (document.getElementById(self._addUID("GPlocationStageAdd"))) {
+ document.getElementById(self._addUID("GPlocationStageAdd")).className = "";
+ }
+ // document.getElementById(self._addUID("GPlocationOriginCoords_" + i)).disabled = true;
+ self.onLocationClearPointClick(e);
+ });
+
+ return labelOrigin;
+ },
+
+ /**
+ * Create Input AutoComplete Point tag
+ *
+ * @param {Number} id - tag ID
+ * @returns {DOMElement} DOM element
+ */
+ _createLocationAutoCompleteteInputElement : function (id) {
+ // contexte d'execution
+ var self = this;
+
+ var inputOrigin = document.createElement("input");
+ inputOrigin.id = this._addUID("GPlocationOrigin_" + id);
+ inputOrigin.className = "GPlocationOriginVisible";
+ inputOrigin.type = "text";
+ inputOrigin.placeholder = "Saisir une adresse";
+ inputOrigin.autocomplete = "off";
+ inputOrigin.addEventListener("keyup", function (e) {
+ var charCode = e.which || e.keyCode;
+ if (charCode === 13 || charCode === 10 || charCode === 38 || charCode === 40) {
+ return;
+ }
+
+ var i = ID.index(this.id);
+ if (document.getElementById(self._addUID("GPlocationOrigin_" + i)).value.length > 2) {
+ document.getElementById(self._addUID("GPlocationAutoCompleteList_" + i)).style.display = "block";
+ } else {
+ document.getElementById(self._addUID("GPlocationAutoCompleteList_" + i)).style.display = "none";
+ }
+ // gestionnaire d'evenement :
+ // on récupère la valeur de saisie pour une requête sur le service d'autocompletion.
+ // le resultat de la requête nous permet de recuperer les coordonnées du point...
+ self.onAutoCompleteSearchText(e);
+ });
+
+ inputOrigin.addEventListener("keydown", function (e) {
+ var charCode = e.which || e.keyCode;
+
+ var container = document.getElementById(self._addUID("GPlocationAutoCompleteList_" + id));
+
+ // si aucun container !?
+ if (!container) {
+ return;
+ }
+
+ var curr = container.getElementsByClassName("GPautoCompleteProposal current");
+ var list = container.getElementsByClassName("GPautoCompleteProposal");
+
+ // si aucune suggestion, on ne va pas plus loin !
+ var length = list.length;
+ if (!length) {
+ return;
+ }
+
+ var current = null;
+
+ // si aucun item courant, on prend le 1er !
+ if (!curr.length) {
+ current = list[0];
+ current.className = "GPautoCompleteProposal current";
+ current.style.color = "#000000";
+ current.style["background-color"] = "#CEDBEF";
+ return;
+ } else {
+ current = curr[0];
+ }
+
+ var index = parseInt(ID.index(current.id), 10);
+ var next = (index === length - 1) ? list[0] : list[index + 1];
+ var prev = (index === 0) ? list[length - 1] : list[index - 1];
+
+ current.style["background-color"] = "";
+ current.style.color = "";
+ prev.style["background-color"] = "";
+ prev.style.color = "";
+ next.style["background-color"] = "";
+ next.style.color = "";
+
+ switch (charCode) {
+ case 38: // arrow up
+ logger.log("arrow up");
+ current.className = "GPautoCompleteProposal";
+ prev.className = "GPautoCompleteProposal current";
+ prev.style.color = "#000000";
+ prev.style["background-color"] = "#CEDBEF";
+ break;
+ case 40: // arrow down
+ logger.log("arrow down");
+ current.className = "GPautoCompleteProposal";
+ next.className = "GPautoCompleteProposal current";
+ next.style.color = "#000000";
+ next.style["background-color"] = "#CEDBEF";
+ break;
+ case 13: // enter
+ logger.log("enter");
+ current.click(e);
+ break;
+ }
+
+ current.focus();
+ });
+
+ return inputOrigin;
+ },
+
+ /**
+ * Create Input Coordinate Point tag
+ *
+ * @param {Number} id - tag ID
+ * @returns {DOMElement} DOM element
+ */
+ _createLocationCoordinateInputElement : function (id) {
+ // contexte d'execution
+ var self = this;
+
+ var inputOriginCoord = document.createElement("input");
+ inputOriginCoord.id = this._addUID("GPlocationOriginCoords_" + id);
+ inputOriginCoord.className = "GPlocationOriginHidden";
+ inputOriginCoord.type = "text";
+ inputOriginCoord.disabled = false;
+ inputOriginCoord.addEventListener("click", function () {
+ var i = ID.index(this.id);
+ document.getElementById(self._addUID("GPlocationOriginLabel_" + i)).click();
+ });
+ return inputOriginCoord;
+ },
+
+ /**
+ * Create Show Pointer tag
+ *
+ * @param {Number} id - tag ID
+ * @returns {DOMElement} DOM element
+ */
+ _createLocationPointerShowInputElement : function (id) {
+ var inputOriginPointer = document.createElement("input");
+ inputOriginPointer.id = this._addUID("GPlocationOriginPointer_" + id);
+ inputOriginPointer.type = "checkbox";
+ return inputOriginPointer;
+ },
+
+ /**
+ * Create Input Pointer tag
+ *
+ * @param {Number} id - tag ID
+ * @returns {DOMElement} DOM element
+ */
+ _createLocationPointerInputElement : function (id) {
+ // contexte d'execution
+ var self = this;
+
+ var labelOriginPointer = document.createElement("label");
+ labelOriginPointer.id = this._addUID("GPlocationOriginPointerImg_" + id);
+ labelOriginPointer.htmlFor = "GPlocationOriginPointer_" + id;
+ labelOriginPointer.className = "GPlocationOriginPointerImg";
+ labelOriginPointer.title = "Pointer un lieu sur la carte";
+ labelOriginPointer.addEventListener("click", function (e) {
+ e.preventDefault();
+ e.stopPropagation();
+ var i = ID.index(this.id);
+ var points = document.getElementsByClassName(self._addUID("GPlocationPoint"));
+ var j;
+ var tag;
+ var id;
+ for (j = 0; j < points.length; j++) {
+ tag = points[j].childNodes[0].id;
+ id = ID.index(tag);
+ if (i !== id) {
+ document.getElementById(self._addUID("GPlocationOriginPointer_" + id)).checked = false;
+ if (document.getElementById(self._addUID("GPlocationOriginCoords_" + id)).value === "Pointer un lieu sur la carte") {
+ document.getElementById(self._addUID("GPlocationOriginCoords_" + id)).value = "";
+ document.getElementById(self._addUID("GPlocationOrigin_" + id)).className = "GPlocationOriginVisible";
+ document.getElementById(self._addUID("GPlocationOriginCoords_" + id)).className = "GPlocationOriginHidden";
+ }
+ }
+ }
+ if (document.getElementById(self._addUID("GPlocationOriginPointer_" + i)).checked) {
+ document.getElementById(self._addUID("GPlocationOriginCoords_" + i)).value = "";
+ for (j = 0; j < points.length; j++) {
+ tag = points[j].childNodes[0].id;
+ id = ID.index(tag);
+ document.getElementById(self._addUID("GPlocationPoint_" + id)).style.cssText = "";
+ }
+ if (document.getElementById(self._addUID("GPlocationStageRemove_" + i))) {
+ document.getElementById(self._addUID("GPlocationStageRemove_" + i)).className = "GPlocationStageRemove";
+ }
+ if (document.getElementById(self._addUID("GPlocationStageAdd"))) {
+ document.getElementById(self._addUID("GPlocationStageAdd")).className = "";
+ }
+ document.getElementById(self._addUID("GPlocationOriginPointer_" + i)).checked = false;
+ document.getElementById(self._addUID("GPlocationOrigin_" + i)).className = "GPlocationOriginVisible";
+ document.getElementById(self._addUID("GPlocationOriginCoords_" + i)).className = "GPlocationOriginHidden";
+ } else {
+ document.getElementById(self._addUID("GPlocationOriginCoords_" + i)).value = "Pointer un lieu sur la carte";
+ for (j = 0; j < points.length; j++) {
+ tag = points[j].childNodes[0].id;
+ id = ID.index(tag);
+ if (i === id) {
+ document.getElementById(self._addUID("GPlocationPoint_" + id)).style.cssText = "";
+ } else {
+ document.getElementById(self._addUID("GPlocationPoint_" + id)).style.display = "none";
+ }
+ }
+ if (document.getElementById(self._addUID("GPlocationStageRemove_" + i))) {
+ document.getElementById(self._addUID("GPlocationStageRemove_" + i)).className = "GPlocationOriginHidden";
+ }
+ if (document.getElementById(self._addUID("GPlocationStageAdd"))) {
+ document.getElementById(self._addUID("GPlocationStageAdd")).className = "GPlocationOriginHidden";
+ }
+ document.getElementById(self._addUID("GPlocationOriginPointer_" + i)).checked = true;
+ document.getElementById(self._addUID("GPlocationOrigin_" + i)).className = "GPlocationOriginHidden";
+ document.getElementById(self._addUID("GPlocationOriginCoords_" + i)).className = "GPlocationOriginVisible";
+ document.getElementById(self._addUID("GPlocationOriginCoords_" + i)).disabled = true;
+ }
+ // gestionnaire d'evenement :
+ // on stocke la valeur du point, utilisée pour la requête sur le service de calcul d'itiniraire
+ self.onActivateMapPointClick(e);
+ });
+
+ return labelOriginPointer;
+ },
+
+ /**
+ * Create Remove Point tag
+ * see event !
+ *
+ * @param {Number} id - tag ID
+ * @returns {DOMElement} DOM element
+ */
+ _createLocationRemovePointElement : function (id) {
+ // contexte d'execution
+ var self = this;
+
+ var divRm = document.createElement("div");
+ divRm.id = this._addUID("GPlocationStageRemove_" + id);
+ divRm.className = "GPlocationStageRemove";
+ divRm.title = "Supprimer l'étape";
+ divRm.addEventListener("click", function (e) {
+ var points = document.getElementsByClassName(self._addUID("GPlocationPoint"));
+ var last = points.length - 1;
+ var start = points[0].childNodes[0].id;
+ var end = points[last].childNodes[0].id;
+
+ var startID = ID.index(start);
+ var endID = ID.index(end);
+
+ if (id !== startID && id !== endID) {
+ var i = ID.index(this.id);
+ document.getElementById(self._addUID("GPlocationPoint_" + i)).className = "GPflexInput GPlocationStageFlexInputHidden";
+ document.getElementById(self._addUID("GPlocationOrigin_" + i)).value = "";
+ document.getElementById(self._addUID("GPlocationOrigin_" + i)).className = "GPlocationOriginVisible";
+ document.getElementById(self._addUID("GPlocationOriginCoords_" + i)).value = "";
+ document.getElementById(self._addUID("GPlocationOriginCoords_" + i)).className = "GPlocationOriginHidden";
+ document.getElementById(self._addUID("GPlocationStageAdd")).style.display = "";
+ // Moving up exclusions picto
+ // var exclusionsPictoTop = document.getElementById(self._addUID("GPshowLocationExclusionsPicto")).style.top;
+ // document.getElementById(self._addUID("GPshowLocationExclusionsPicto")).style.top = (parseInt(exclusionsPictoTop) - 33).toString() + "px";
+
+ // gestionnaire d'evenement :
+ // on supprime le point, utilisé pour la requête sur le service d'itiniraire
+ self.onLocationRemovePointClick(e);
+ }
+ });
+
+ return divRm;
+ },
+
+ /**
+ * Create Add Point tag
+ * see event !
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createLocationAddPointElement : function () {
+ // contexte d'execution
+ var self = this;
+
+ var divAdd = document.createElement("div");
+ divAdd.id = this._addUID("GPlocationStageAdd");
+ divAdd.title = "Ajouter une étape";
+ divAdd.addEventListener("click", function (e) {
+ var lastStage = 1;
+ var nbStages = 0;
+ var points = document.getElementsByClassName(self._addUID("GPlocationPoint"));
+ for (var i = 1; i < points.length - 1; i++) {
+ var tag = points[i].childNodes[0].id;
+ var id = ID.index(tag);
+ if (document.getElementById(self._addUID("GPlocationPoint_" + id))) {
+ if (document.getElementById(self._addUID("GPlocationPoint_" + id)).className === "GPflexInput GPlocationStageFlexInputHidden") {
+ if (lastStage === 1) {
+ lastStage = id;
+ }
+ } else {
+ nbStages++;
+ }
+ }
+ }
+ // FIXME algo à revoir : lastStage = id hors si id = 300 sur 3 points !?
+ if (lastStage < points.length) {
+ document.getElementById(self._addUID("GPlocationPoint_" + lastStage)).className = "GPflexInput GPlocationStageFlexInput";
+ // Moving down exclusions picto
+ // var exclusionsPictoTop = document.getElementById(self._addUID("GPshowLocationExclusionsPicto")).style.top;
+ // document.getElementById(self._addUID("GPshowLocationExclusionsPicto")).style.top = (parseInt(exclusionsPictoTop) + 33).toString() + "px";
+ }
+ if (nbStages === 4) {
+ document.getElementById(self._addUID("GPlocationStageAdd")).style.display = "none";
+ }
+ // gestionnaire d'evenement :
+ // on ajoute le point, utilisé pour la requête sur le service d'itiniraire
+ self.onLocationAddPointClick(e);
+ });
+
+ return divAdd;
+ },
+
+ /**
+ * Create Results autocompletion to the point
+ * see event!
+ *
+ * @param {Number} id - tag ID
+ * @returns {DOMElement} DOM element
+ */
+ _createLocationAutoCompleteResultElement : function (id) {
+ // contexte d'execution
+ var self = this;
+
+ var div = document.createElement("div");
+ div.id = this._addUID("GPlocationAutoCompleteList_" + id);
+ div.className = "GPadvancedAutoCompleteList";
+
+ if (div.addEventListener) {
+ div.addEventListener("click", function (e) {
+ self.onAutoCompletedResultsItemClick(e);
+ document.getElementById(self._addUID("GPlocationAutoCompleteList_" + id)).style.display = "none";
+ }, false);
+ } else if (div.attachEvent) {
+ div.attachEvent("onclick", function (e) {
+ self.onAutoCompletedResultsItemClick(e);
+ document.getElementById(self._addUID("GPlocationAutoCompleteList_" + id)).style.display = "none";
+ });
+ }
+
+ return div;
+ },
+
+ /**
+ * Autocompletion result to a point.
+ * Proposals are dynamically filled in Javascript by autocomplete service
+ *
+ * TODO formaliser le contenu des reponse
+ *
+ * @param {Number} id - tag ID
+ * @param {Object} location - suggested location result
+ * @param {Number} n - number of the point
+ */
+ _createLocationAutoCompletedLocationElement : function (id, location, n) {
+ var container = document.getElementById(this._addUID("GPlocationAutoCompleteList_" + id));
+
+ var div = document.createElement("div");
+ div.id = this._addUID("AutoCompletedLocation_" + n);
+ div.className = "GPautoCompleteProposal";
+ div.innerHTML = location.fullText;
+
+ container.appendChild(div);
+ },
+
+ /**
+ * Display Coordinate
+ * @param {String} value - a Coordinate
+ */
+ GPdisplayCoordinate : function (value) {
+ var points = document.getElementsByClassName(this._addUID("GPlocationPoint"));
+ for (var i = 0; i < points.length; i++) {
+ var tag = points[i].childNodes[0].id;
+ var id1 = ID.index(tag);
+ if (document.getElementById(this._addUID("GPlocationOriginPointer_" + id1)).checked) {
+ document.getElementById(this._addUID("GPlocationOriginCoords_" + id1)).value = value;
+ document.getElementById(this._addUID("GPlocationOriginCoords_" + id1)).disabled = false;
+ for (var j = 0; j < points.length; j++) {
+ tag = points[j].childNodes[0].id;
+ var id2 = ID.index(tag);
+ document.getElementById(this._addUID("GPlocationPoint_" + id2)).style.cssText = "";
+ if (document.getElementById(this._addUID("GPlocationStageRemove_" + id2))) {
+ document.getElementById(this._addUID("GPlocationStageRemove_" + id2)).className = "GPlocationStageRemove";
+ }
+ }
+ document.getElementById(this._addUID("GPlocationOriginPointer_" + id1)).checked = false;
+ if (document.getElementById(this._addUID("GPlocationStageAdd"))) {
+ document.getElementById(this._addUID("GPlocationStageAdd")).className = "";
+ }
+ return;
+ }
+ }
+ }
+};
+
+export default LocationSelectorDOM;
diff --git a/src/Common-review/Controls/MeasureAreaDOM.js b/src/Common-review/Controls/MeasureAreaDOM.js
new file mode 100644
index 000000000..900a882f7
--- /dev/null
+++ b/src/Common-review/Controls/MeasureAreaDOM.js
@@ -0,0 +1,80 @@
+var MeasureAreaDOM = {
+
+ /**
+ * Add uuid to the tag ID
+ * @param {String} id - id selector
+ * @returns {String} uid - id selector with an unique id
+ */
+ _addUID : function (id) {
+ var uid = (this._uid) ? id + "-" + this._uid : id;
+ return uid;
+ },
+
+ /**
+ * Main container (DOM)
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createMainContainerElement : function () {
+ var container = document.createElement("div");
+ container.id = this._addUID("GPmeasureArea");
+ container.className = "GPwidget";
+ return container;
+ },
+
+ // ################################################################### //
+ // ################### Methods of main container ##################### //
+ // ################################################################### //
+
+ /**
+ * Hidden checkbox for minimizing/maximizing
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createShowMeasureAreaElement : function () {
+ var input = document.createElement("input");
+ input.id = this._addUID("GPshowMeasureArea");
+ input.type = "checkbox";
+ return input;
+ },
+
+ /**
+ * Show control
+ * see event !
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createShowMeasureAreaPictoElement : function () {
+ // contexte d'execution
+ var context = this;
+
+ var label = document.createElement("label");
+ label.id = this._addUID("GPshowMeasureAreaPicto");
+ label.className = "GPshowAdvancedToolPicto";
+ label.htmlFor = this._addUID("GPshowMeasureArea");
+ label.title = "Mesurer une surface";
+
+ // gestionnaire d'evenement :
+ // on ouvre le menu de saisie...
+ // L'ouverture/Fermeture permet de faire le menage
+ // (reinitialisation)
+ if (label.addEventListener) {
+ label.addEventListener("click", function (e) {
+ context.onShowMeasureAreaClick(e);
+ });
+ } else if (label.attachEvent) {
+ label.attachEvent("onclick", function (e) {
+ context.onShowMeasureAreaClick(e);
+ });
+ }
+
+ var spanOpen = document.createElement("span");
+ spanOpen.id = this._addUID("GPshowMeasureAreaOpen");
+ spanOpen.className = "GPshowAdvancedToolOpen";
+ label.appendChild(spanOpen);
+
+ return label;
+ }
+};
+
+export default MeasureAreaDOM;
diff --git a/src/Common-review/Controls/MeasureAzimuthDOM.js b/src/Common-review/Controls/MeasureAzimuthDOM.js
new file mode 100644
index 000000000..84f003e83
--- /dev/null
+++ b/src/Common-review/Controls/MeasureAzimuthDOM.js
@@ -0,0 +1,80 @@
+var MeasureAzimuthDOM = {
+
+ /**
+ * Add uuid to the tag ID
+ * @param {String} id - id selector
+ * @returns {String} uid - id selector with an unique id
+ */
+ _addUID : function (id) {
+ var uid = (this._uid) ? id + "-" + this._uid : id;
+ return uid;
+ },
+
+ /**
+ * Main container (DOM)
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createMainContainerElement : function () {
+ var container = document.createElement("div");
+ container.id = this._addUID("GPmeasureAzimuth");
+ container.className = "GPwidget";
+ return container;
+ },
+
+ // ################################################################### //
+ // ################### Methods of main container ##################### //
+ // ################################################################### //
+
+ /**
+ * Hidden checkbox for minimizing/maximizing
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createShowMeasureAzimuthElement : function () {
+ var input = document.createElement("input");
+ input.id = this._addUID("GPshowMeasureAzimuth");
+ input.type = "checkbox";
+ return input;
+ },
+
+ /**
+ * Show control
+ * see event !
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createShowMeasureAzimuthPictoElement : function () {
+ // contexte d'execution
+ var context = this;
+
+ var label = document.createElement("label");
+ label.id = this._addUID("GPshowMeasureAzimuthPicto");
+ label.className = "GPshowAdvancedToolPicto";
+ label.htmlFor = this._addUID("GPshowMeasureAzimuth");
+ label.title = "Mesurer un azimut";
+
+ // gestionnaire d'evenement :
+ // on ouvre le menu de saisie...
+ // L'ouverture/Fermeture permet de faire le menage
+ // (reinitialisation)
+ if (label.addEventListener) {
+ label.addEventListener("click", function (e) {
+ context.onShowMeasureAzimuthClick(e);
+ });
+ } else if (label.attachEvent) {
+ label.attachEvent("onclick", function (e) {
+ context.onShowMeasureAzimuthClick(e);
+ });
+ }
+
+ var spanOpen = document.createElement("span");
+ spanOpen.id = this._addUID("GPshowMeasureAzimuthOpen");
+ spanOpen.className = "GPshowAdvancedToolOpen";
+ label.appendChild(spanOpen);
+
+ return label;
+ }
+};
+
+export default MeasureAzimuthDOM;
diff --git a/src/Common-review/Controls/MeasureLengthDOM.js b/src/Common-review/Controls/MeasureLengthDOM.js
new file mode 100644
index 000000000..7be6593cf
--- /dev/null
+++ b/src/Common-review/Controls/MeasureLengthDOM.js
@@ -0,0 +1,80 @@
+var MeasureLengthDOM = {
+
+ /**
+ * Add uuid to the tag ID
+ * @param {String} id - id selector
+ * @returns {String} uid - id selector with an unique id
+ */
+ _addUID : function (id) {
+ var uid = (this._uid) ? id + "-" + this._uid : id;
+ return uid;
+ },
+
+ /**
+ * Main container (DOM)
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createMainContainerElement : function () {
+ var container = document.createElement("div");
+ container.id = this._addUID("GPmeasureLength");
+ container.className = "GPwidget";
+ return container;
+ },
+
+ // ################################################################### //
+ // ################### Methods of main container ##################### //
+ // ################################################################### //
+
+ /**
+ * Hidden checkbox for minimizing/maximizing
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createShowMeasureLengthElement : function () {
+ var input = document.createElement("input");
+ input.id = this._addUID("GPshowMeasureLength");
+ input.type = "checkbox";
+ return input;
+ },
+
+ /**
+ * Show control
+ * see event !
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createShowMeasureLengthPictoElement : function () {
+ // contexte d'execution
+ var context = this;
+
+ var label = document.createElement("label");
+ label.id = this._addUID("GPshowMeasureLengthPicto");
+ label.className = "GPshowAdvancedToolPicto";
+ label.htmlFor = this._addUID("GPshowMeasureLength");
+ label.title = "Mesurer une distance";
+
+ // gestionnaire d'evenement :
+ // on ouvre le menu de saisie...
+ // L'ouverture/Fermeture permet de faire le menage
+ // (reinitialisation)
+ if (label.addEventListener) {
+ label.addEventListener("click", function (e) {
+ context.onShowMeasureLengthClick(e);
+ });
+ } else if (label.attachEvent) {
+ label.attachEvent("onclick", function (e) {
+ context.onShowMeasureLengthClick(e);
+ });
+ }
+
+ var spanOpen = document.createElement("span");
+ spanOpen.id = this._addUID("GPshowMeasureLengthOpen");
+ spanOpen.className = "GPshowAdvancedToolOpen";
+ label.appendChild(spanOpen);
+
+ return label;
+ }
+};
+
+export default MeasureLengthDOM;
diff --git a/src/Common-review/Controls/MeasureToolBoxDOM.js b/src/Common-review/Controls/MeasureToolBoxDOM.js
new file mode 100644
index 000000000..ed1949e0c
--- /dev/null
+++ b/src/Common-review/Controls/MeasureToolBoxDOM.js
@@ -0,0 +1,102 @@
+var MeasureToolBoxDOM = {
+
+ _toolboxId : "GPtoolbox-measure-main",
+ _buttonId : "GPtoolbox-measure-button",
+ _widgetId : "GPtoolbox-measure-widget",
+
+ /**
+ * get toolBox ID
+ * @param {Number} uid - uid
+ * @returns {String} id selector unique
+ */
+ getToolBoxID : function (uid) {
+ return (uid) ? this._toolboxId + "-" + uid : this._toolboxId;
+ },
+
+ /**
+ * get button ID
+ * @param {Number} uid - uid
+ * @returns {String} id selector unique
+ */
+ getButtonID : function (uid) {
+ return (uid) ? this._buttonId + "-" + uid : this._buttonId;
+ },
+
+ /**
+ * get toolBox Container for widget
+ * @param {Number} uid - uid
+ * @returns {String} id selector unique
+ */
+ getWidgetID : function (uid) {
+ return (uid) ? this._widgetId + "-" + uid : this._widgetId;
+ },
+
+ /**
+ * Main container (DOM)
+ * @param {Number} uid - uid
+ * @returns {DOMElement} DOM element
+ */
+ _createToolBoxContainerElement : function (uid) {
+ //
+ //
+ //
+ //
+ //
+ //
+ var container = document.createElement("div");
+ container.id = this.getToolBoxID(uid);
+ container.className = "GPshowAdvancedToolPicto";
+
+ var button = document.createElement("button");
+ button.id = this.getButtonID(uid);
+ var self = this;
+ button.addEventListener("click", function () {
+ this.blur(); // permet de perdre le focus !
+ var widget = document.getElementById(self.getWidgetID(uid));
+ if (widget.style.display === "block") {
+ widget.style.display = "none";
+ } else {
+ widget.style.display = "block";
+ }
+ });
+ container.appendChild(button);
+
+ var widget = document.createElement("div");
+ widget.id = this.getWidgetID(uid);
+ widget.addEventListener("click", function () {
+
+ /*
+ e.preventDefault();
+
+ // FIXME desactiver tous les outils sur
+ // l'ouverture/fermeture de la toolbox ?
+
+ var current = e.target.parentNode.getAttribute("for");
+ var widgets = this.querySelectorAll("div > input");
+ for (var i = 0; i < widgets.length; i++) {
+ var id = widgets[i].id;
+
+ if (document.getElementById(id) &&
+ document.getElementById(id).checked &&
+ document.querySelector("#" + id + " + label")) {
+ document.querySelector("#" + id + " + label").click();
+ // document.getElementById(id).checked = true;
+ }
+
+ if (current === id && widgets[i].checked) {
+ widgets[i].checked = false;
+ } else if (current === id && !widgets[i].checked) {
+ widgets[i].checked = true;
+ }
+ }
+ */
+
+ }, false);
+
+ container.appendChild(widget);
+
+ return container;
+ }
+};
+
+export default MeasureToolBoxDOM;
diff --git a/src/Common-review/Controls/MiniGlobeDOM.js b/src/Common-review/Controls/MiniGlobeDOM.js
new file mode 100644
index 000000000..f03985d4e
--- /dev/null
+++ b/src/Common-review/Controls/MiniGlobeDOM.js
@@ -0,0 +1,28 @@
+var MiniGlobeDOM = {
+
+ /**
+ * Add uuid to the tag ID
+ * @param {String} id - id selector
+ * @returns {String} uid - id selector with an unique id
+ */
+ _addUID : function (id) {
+ var uid = (this._uid) ? id + "-" + this._uid : id;
+ return uid;
+ },
+
+ /**
+ * Main container (DOM)
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createMainContainerElement : function () {
+ var container = document.createElement("div");
+ container.id = this._addUID("GPminiglobeContainer");
+ container.className = "GPwidget";
+ container.style.width = "100px";
+ container.style.height = "100px";
+ return container;
+ }
+};
+
+export default MiniGlobeDOM;
diff --git a/src/Common-review/Controls/MousePositionDOM.js b/src/Common-review/Controls/MousePositionDOM.js
new file mode 100644
index 000000000..e24ce7352
--- /dev/null
+++ b/src/Common-review/Controls/MousePositionDOM.js
@@ -0,0 +1,940 @@
+var MousePositionDOM = {
+
+ /**
+ * Add uuid to the tag ID
+ * @param {String} id - id selector
+ * @returns {String} uid - id selector with an unique id
+ */
+ _addUID : function (id) {
+ var uid = (this._uid) ? id + "-" + this._uid : id;
+ return uid;
+ },
+
+ /**
+ * Main container (DOM)
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createMainContainerElement : function () {
+ var container = document.createElement("div");
+ container.id = this._addUID("GPmousePosition");
+ container.className = "GPwidget";
+ return container;
+ },
+
+ // ################################################################### //
+ // ################### Methods of main container ##################### //
+ // ################################################################### //
+
+ /**
+ * Hidden checkbox for minimizing/maximizing
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createShowMousePositionElement : function () {
+ var input = document.createElement("input");
+ input.id = this._addUID("GPshowMousePosition");
+ input.type = "checkbox";
+ return input;
+ },
+
+ /**
+ * Show mouse position control
+ * @param {Boolean} isDesktop - specifies if the support is desktop or tactile
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createShowMousePositionPictoElement : function (isDesktop) {
+ // contexte d'execution
+ var self = this;
+
+ var label = document.createElement("label");
+ label.id = this._addUID("GPshowMousePositionPicto");
+ label.className = "GPshowAdvancedToolPicto";
+ label.htmlFor = this._addUID("GPshowMousePosition");
+ label.title = "Afficher les coordonnées du curseur";
+
+ // FIXME detection disponible dans le JS !
+ // Detection : test for desktop or tactile
+ // var isDesktop = true;
+ // var userAgent = window.navigator.userAgent.toLowerCase();
+ // if (userAgent.indexOf("iphone") !== -1 ||
+ // userAgent.indexOf("ipod") !== -1 ||
+ // userAgent.indexOf("ipad") !== -1 ||
+ // userAgent.indexOf("android") !== -1 ||
+ // userAgent.indexOf("mobile") !== -1 ||
+ // userAgent.indexOf("blackberry") !== -1 ||
+ // userAgent.indexOf("tablet") !== -1 ||
+ // userAgent.indexOf("phone") !== -1 ||
+ // userAgent.indexOf("touch") !== -1 ) {
+ // isDesktop = false;
+ // }
+ // if (userAgent.indexOf("msie") !== -1 ||
+ // userAgent.indexOf("trident") !== -1) {
+ // isDesktop = true;
+ // }
+
+ // Show map center localisation if panel opened and tactile support
+ label.addEventListener("click", function (e) {
+ var mapCenterClass = "";
+ if (!document.getElementById(self._addUID("GPshowMousePosition")).checked && !isDesktop) {
+ mapCenterClass = "GPmapCenterVisible";
+ }
+ document.getElementById("GPmapCenter").className = mapCenterClass;
+ self.onShowMousePositionClick(e);
+ });
+
+ var spanOpen = document.createElement("span");
+ spanOpen.id = this._addUID("GPshowMousePositionOpen");
+ spanOpen.className = "GPshowAdvancedToolOpen";
+ label.appendChild(spanOpen);
+
+ return label;
+ },
+
+ /**
+ * mouse position panel
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createMousePositionPanelElement : function () {
+ var panel = document.createElement("div");
+ panel.id = this._addUID("GPmousePositionPanel");
+ panel.className = "GPpanel";
+
+ // FIXME on decompose la fonction pour les besoins du controle,
+ // on ajoutera ces childs à la main...
+ // div.appendChild(this._createMousePositionPanelHeaderElement());
+ // div.appendChild(this._createMousePositionPanelBasicElement());
+ // div.appendChild(this._createShowMousePositionSettingsElement());
+ // div.appendChild(this._createMousePositionSettingsElement());
+
+ return panel;
+ },
+
+ /**
+ * Map center localisation (tactile use)
+ *
+ * @returns {DOMElement} container
+ */
+ _createMapCenter : function () {
+ var div = document.createElement("div");
+ div.id = "GPmapCenter";
+ div.className = "";
+ return div;
+ },
+
+ // ################################################################### //
+ // ####################### Panel container ########################### //
+ // ################################################################### //
+
+ /**
+ * @returns {DOMElement} container
+ */
+ _createMousePositionPanelHeaderElement : function () {
+ var container = document.createElement("div");
+ container.className = "GPpanelHeader";
+
+ var divTitle = document.createElement("div");
+ divTitle.className = "GPpanelTitle";
+ divTitle.innerHTML = "Coordonnées";
+ container.appendChild(divTitle);
+
+ var divClose = document.createElement("div");
+ divClose.id = "GPmousePositionPanelClose";
+ divClose.className = "GPpanelClose";
+ divClose.title = "Fermer le panneau";
+
+ // Link panel close / visibility checkbox
+ var self = this;
+ if (divClose.addEventListener) {
+ divClose.addEventListener("click", function () {
+ document.getElementById(self._addUID("GPshowMousePositionPicto")).click();
+ }, false);
+ } else if (divClose.attachEvent) {
+ divClose.attachEvent("onclick", function () {
+ document.getElementById(self._addUID("GPshowMousePositionPicto")).click();
+ });
+ }
+
+ container.appendChild(divClose);
+
+ return container;
+ },
+
+ /**
+ * coordinate panel
+ * @param {Boolean} [displayAltitude] - specifies if the altitude panel must be displayed
+ * @param {Boolean} [displayCoordinates] - specifies if the coordinates panel must be displayed
+ * @param {Boolean} [editCoordinates] - specifies if the coordinates edition is allowed
+ * @param {Boolean} [currentProjectionUnits] - specifies if the current projection units
+ *
+ * FIXME
+ * call this._createMousePositionPanelBasicCoordinateElement
+ * call this._createMousePositionPanelBasicAltitudeElement
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createMousePositionPanelBasicElement : function (displayAltitude, displayCoordinates, editCoordinates, currentProjectionUnits) {
+ // default Values
+ displayAltitude = (typeof displayAltitude === "undefined") ? true : displayAltitude;
+ displayCoordinates = (typeof displayCoordinates === "undefined") ? true : displayCoordinates;
+ editCoordinates = (typeof editCoordinates === "undefined") ? false : editCoordinates;
+
+ var container = document.createElement("div");
+ container.id = this._addUID("GPmousePositionBasicPanel");
+
+ // FIXME on devrait decomposer la fonction pour les besoins du controle,
+ // on ajoutera ces childs à la main...
+ container.appendChild(this._createMousePositionPanelBasicCoordinateElement(displayCoordinates, editCoordinates, currentProjectionUnits));
+ container.appendChild(this._createMousePositionPanelEditToolsElement(editCoordinates));
+ container.appendChild(this._createMousePositionPanelBasicAltitudeElement(displayAltitude));
+
+ return container;
+ },
+
+ /**
+ * create coordinate elements
+ *
+ * @param {String} coordType - ("Lon" ou "Lat")
+ * @param {Boolean} [editCoordinates=false] - specifies if the coordinates edition is allowed
+ *
+ * @returns {Array} list of DOM elements
+ */
+ _createCoordinateElement : function (coordType, editCoordinates) {
+ var context = this;
+
+ if (["Lon", "Lat"].indexOf(coordType) === -1) {
+ return [];
+ }
+
+ var list = [];
+ var input = document.createElement("input");
+ input.id = this._addUID("GPmousePosition" + coordType);
+ input.title = editCoordinates === true ? "Cliquer pour saisir des coordonnées" : "";
+ input.readOnly = true;
+
+ if (editCoordinates) {
+ input.addEventListener("click", function () {
+ context.onMousePositionEditModeClick(true);
+ });
+ input.addEventListener("change", function (e) {
+ this.classList.remove("error");
+ var valid = context.validateExtentCoordinate(coordType, this.value, e);
+ valid ? this.classList.remove("error") : this.classList.add("error");
+ });
+ }
+ list.push(input);
+
+ var span = document.createElement("span");
+ span.className = "GPmousePositionUnits";
+ list.push(span);
+
+ return list;
+ },
+
+ /**
+ *
+ * @param {String} coordType - ("Lon" ou "Lat")
+ * @param {Boolean} [editCoordinates=false] - specifies if the coordinates edition is allowed
+ *
+ * @returns {Array} list of DOM elements
+ */
+ _createDMSCoordinateElement : function (coordType, editCoordinates) {
+ if (["Lon", "Lat"].indexOf(coordType) === -1) {
+ return [];
+ }
+
+ var context = this;
+
+ var list = [];
+
+ var input = document.createElement("input");
+ input.id = this._addUID("GPmousePosition" + coordType + "Degrees");
+ input.className = "GPSexagesimal";
+ input.setAttribute("name", "degrees");
+ input.title = editCoordinates === true ? "Cliquer pour saisir des coordonnées" : "";
+ input.readOnly = true;
+ input.dataset.min = 0;
+ input.dataset.max = (coordType === "Lon") ? 180 : 90;
+ if (editCoordinates) {
+ input.addEventListener("click", function () {
+ context.onMousePositionEditModeClick(true);
+ });
+ input.addEventListener("change", function () {
+ this.classList.remove("error");
+ var valid = context._checkDMSDegrees(coordType, this);
+ valid ? this.classList.remove("error") : this.classList.add("error");
+ });
+ }
+ list.push(input);
+
+ var span = document.createElement("span");
+ span.className = "GPmousePositionSexagesimalLabel";
+ span.innerHTML = "°";
+ list.push(span);
+
+ var input1 = document.createElement("input");
+ input1.id = this._addUID("GPmousePosition" + coordType + "Minutes");
+ input1.className = "GPSexagesimal";
+ input1.setAttribute("name", "minutes");
+ input1.title = editCoordinates === true ? "Cliquer pour saisir des coordonnées" : "";
+ input1.readOnly = true;
+ input1.dataset.min = 0;
+ input1.dataset.max = 59;
+ if (editCoordinates) {
+ input1.addEventListener("click", function () {
+ context.onMousePositionEditModeClick(true);
+ });
+ input1.addEventListener("change", function () {
+ this.classList.remove("error");
+ var valid = context._checkDMSElement(this);
+ valid ? this.classList.remove("error") : this.classList.add("error");
+ });
+ }
+ list.push(input1);
+
+ var span1 = document.createElement("span");
+ span1.className = "GPmousePositionSexagesimalLabel";
+ span1.innerHTML = "'";
+ list.push(span1);
+
+ var input2 = document.createElement("input");
+ input2.id = this._addUID("GPmousePosition" + coordType + "Seconds");
+ input2.className = "GPSexagesimalsec";
+ input2.setAttribute("name", "seconds");
+ input2.title = editCoordinates === true ? "Cliquer pour saisir des coordonnées" : "";
+ input2.readOnly = true;
+ input2.dataset.min = 0;
+ input2.dataset.max = 59;
+ if (editCoordinates) {
+ input2.addEventListener("click", function () {
+ context.onMousePositionEditModeClick(true);
+ });
+ input2.addEventListener("change", function () {
+ this.classList.remove("error");
+ var valid = context._checkDMSElement(this, true);
+ valid ? this.classList.remove("error") : this.classList.add("error");
+ });
+ }
+ list.push(input2);
+
+ var span2 = document.createElement("span");
+ span2.className = "GPmousePositionSexagesimalLabel";
+ span2.innerHTML = "''";
+ list.push(span2);
+
+ var select = document.createElement("select");
+ select.id = this._addUID("GPmousePosition" + coordType + "Direction");
+ select.className = "GPmousePositionDirection";
+ select.setAttribute("name", "direction");
+ select.disabled = true;
+
+ var option = document.createElement("option");
+ option.value = (coordType === "Lon") ? "E" : "N";
+ option.innerHTML = (coordType === "Lon") ? "E" : "N";
+ select.appendChild(option);
+
+ var option1 = document.createElement("option");
+ option1.value = (coordType === "Lon") ? "O" : "S";
+ option1.innerHTML = (coordType === "Lon") ? "O" : "S";
+ select.appendChild(option1);
+ list.push(select);
+
+ return list;
+ },
+
+ /**
+ * @param {Boolean} [display=false] - specifies if the coordinates panel must be displayed
+ * @param {Boolean} [editCoordinates] - specifies if the coordinates edition is allowed
+ * @param {Boolean} [currentProjectionUnits] - specifies if the current projection units
+ *
+ * @returns {DOMElement} container
+ */
+ _createMousePositionPanelBasicCoordinateElement : function (display, editCoordinates, currentProjectionUnits) {
+ var div = document.createElement("div");
+ div.id = this._addUID("GPmousePositionCoordinate");
+ div.style.display = display ? "block" : "none";
+
+ // latitude
+ var divLat = document.createElement("div");
+
+ var spanLat = document.createElement("span");
+ spanLat.className = "GPmousePositionLabel";
+ spanLat.id = this._addUID("GPmousePositionLatLabel");
+ spanLat.innerHTML = "Latitude : ";
+ divLat.appendChild(spanLat);
+
+ var span = document.createElement("span");
+ span.id = this._addUID("GPmousePositionLatCoordinate");
+
+ var arrayCoords;
+ if (currentProjectionUnits === "DMS") {
+ arrayCoords = this._createDMSCoordinateElement("Lat", editCoordinates);
+ } else {
+ arrayCoords = this._createCoordinateElement("Lat", editCoordinates);
+ }
+ for (var i = 0; i < arrayCoords.length; i++) {
+ span.appendChild(arrayCoords[i]);
+ }
+ divLat.appendChild(span);
+ div.appendChild(divLat);
+
+ // longitude
+ var divLon = document.createElement("div");
+
+ var spanLon = document.createElement("span");
+ spanLon.className = "GPmousePositionLabel";
+ spanLon.id = this._addUID("GPmousePositionLonLabel");
+ spanLon.innerHTML = "Longitude : ";
+ divLon.appendChild(spanLon);
+
+ var span1 = document.createElement("span");
+ span1.id = this._addUID("GPmousePositionLonCoordinate");
+
+ var arrayCoords1;
+ if (currentProjectionUnits === "DMS") {
+ arrayCoords1 = this._createDMSCoordinateElement("Lon", editCoordinates);
+ } else {
+ arrayCoords1 = this._createCoordinateElement("Lon", editCoordinates);
+ }
+ for (var j = 0; j < arrayCoords1.length; j++) {
+ span1.appendChild(arrayCoords1[j]);
+ }
+ divLon.appendChild(span1);
+ div.appendChild(divLon);
+
+ return div;
+ },
+
+ /**
+ * @param {Boolean} [display=false] - specifies if the altitude panel must be displayed
+ *
+ * @returns {DOMElement} container
+ */
+ _createMousePositionPanelBasicAltitudeElement : function (display) {
+ var div = document.createElement("div");
+ div.id = this._addUID("GPmousePositionAltitude");
+ div.style.display = display ? "block" : "none";
+
+ var spanLabel = document.createElement("span");
+ spanLabel.className = "GPmousePositionLabel";
+ spanLabel.innerHTML = "Altitude : ";
+ div.appendChild(spanLabel);
+
+ var spanAlt = document.createElement("span");
+ spanAlt.className = "GPmousePositionCoords";
+ spanAlt.id = this._addUID("GPmousePositionAlt");
+ spanAlt.innerHTML = "...";
+ div.appendChild(spanAlt);
+
+ var spanUnits = document.createElement("span");
+ spanUnits.className = "GPmousePositionAltitudeUnits";
+ spanUnits.innerHTML = "m";
+ div.appendChild(spanUnits);
+
+ return div;
+ },
+
+ /**
+ * @param {Boolean} [editCoordinates=false] - specifies if the coordinates edition is allowed
+ *
+ * @returns {DOMElement} container
+ */
+ _createMousePositionPanelEditToolsElement : function (editCoordinates) {
+ var context = this;
+
+ var div = document.createElement("div");
+ div.className = "GPmousePositionPanelEditTools";
+ div.id = this._addUID("GPmousePositionPanelEditTools");
+ if (!editCoordinates) {
+ div.style.display = "none";
+ }
+
+ var span1 = document.createElement("span");
+ span1.className = "GPmousePositionEditTool";
+ span1.id = this._addUID("GPmousePositionLocate");
+ span1.title = editCoordinates === true ? "Cliquer pour saisir des coordonnées" : "";
+ if (editCoordinates) {
+ span1.addEventListener("click", function () {
+ context.onMousePositionEditModeLocateClick();
+ });
+ }
+ div.appendChild(span1);
+
+ var span2 = document.createElement("span");
+ span2.className = "GPmousePositionEditTool";
+ span2.id = this._addUID("GPmousePositionCloseEdit");
+ span2.title = "Quitter la saisie des coordonnées";
+ span2.style.display = "none";
+ if (editCoordinates) {
+ span2.addEventListener("click", function () {
+ context.onMousePositionEditModeClick(false);
+ });
+ }
+ div.appendChild(span2);
+
+ return div;
+ },
+
+ // ################################################################### //
+ // #################### Settings container ########################### //
+ // ################################################################### //
+
+ /**
+ * @param {Boolean} [display=false] - specifies if the settings panel must be displayed
+ *
+ * @returns {DOMElement[]} array containing input and label elements
+ */
+ _createShowMousePositionSettingsElement : function (display) {
+ var list = [];
+
+ var context = this;
+
+ var input = document.createElement("input");
+ input.type = "checkbox";
+ input.id = this._addUID("GPshowMousePositionSettings");
+
+ var label = document.createElement("label");
+ label.id = this._addUID("GPshowMousePositionSettingsPicto");
+ label.htmlFor = this._addUID("GPshowMousePositionSettings");
+ label.title = "Réglages";
+ label.className = "GPshowMoreOptionsImage GPshowMoreOptions GPshowMousePositionSettingsPicto"; // FIXME classname and id ?
+ label.style.display = display ? "block" : "none";
+ if (label.addEventListener) {
+ label.addEventListener("click", function (e) {
+ if (typeof context.onShowMousePositionSettingsClick === "function") {
+ context.onShowMousePositionSettingsClick(e);
+ }
+ }, false);
+ } else if (label.attachEvent) {
+ label.attachEvent("onclick", function (e) {
+ if (typeof context.onShowMousePositionSettingsClick === "function") {
+ context.onShowMousePositionSettingsClick(e);
+ }
+ });
+ }
+
+ list.push(input);
+ list.push(label);
+
+ return list;
+ },
+
+ /**
+ * settings panel
+ * @param {Boolean} [display=true] - specifies if the settings panel must be displayed
+ *
+ * FIXME
+ * don't call this._createMousePositionSettingsSystemsElement
+ * don't call this._createMousePositionSettingsUnitsElement
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createMousePositionSettingsElement : function (display) {
+ var container = document.createElement("div");
+ container.id = this._addUID("GPmousePositionSettings");
+ container.style.display = (display === undefined || display) ? "block" : "none";
+
+ var span = document.createElement("span");
+ span.className = "GPmousePositionSettingsLabel";
+ span.innerHTML = "Système de référence";
+ container.appendChild(span);
+
+ // FIXME on decompose la fonction pour les besoins du controle,
+ // on ajoutera ces childs à la main...
+ // FIXME tableau statique !
+ // var systems = [
+ // {
+ // code : "GEOGRAPHIC",
+ // label : "Géographique"
+ // },
+ // {
+ // code : "MERCATOR",
+ // label : "Mercator"
+ // },
+ // {
+ // code : "LAMB93",
+ // label : "Lambert 93"
+ // },
+ // {
+ // code : "LAMB2E",
+ // label : "Lambert II étendu"
+ // }
+ // ];
+ //
+ // var selectSystem = this._createMousePositionSettingsSystemsElement(systems);
+ //
+ // container.appendChild(selectSystem);
+
+ // FIXME on decompose la fonction pour les besoins du controle,
+ // on ajoutera ces childs à la main...
+ // FIXME tableau statique !
+ // var units = [
+ // {
+ // code : "DEC",
+ // label : "degrés décimaux",
+ // },
+ // {
+ // code : "DMS",
+ // label : "degrés sexagésimaux",
+ // },
+ // {
+ // code : "RAD",
+ // label : "radians",
+ // },
+ // {
+ // code : "GON",
+ // label : "grades"
+ // }
+ // ];
+ //
+ // var selectUnits = this._createMousePositionSettingsUnitsElement(units);
+ //
+ // container.appendChild(selectUnits);
+
+ return container;
+ },
+
+ /**
+ * @param {Object[]} systems - list of systems
+ *
+ * @returns {DOMElement} DOM element select
+ */
+ _createMousePositionSettingsSystemsElement : function (systems) {
+ // contexte d'execution
+ var context = this;
+
+ var selectSystem = document.createElement("select");
+ selectSystem.id = this._addUID("GPmousePositionProjectionSystem");
+ selectSystem.className = "GPinputSelect GPmousePositionSettingsSelect";
+ selectSystem.addEventListener("change", function (e) {
+ context.onMousePositionProjectionSystemChange(e);
+ });
+ selectSystem.addEventListener("mouseover", function (e) {
+ // FIXME mettre une condition si target === option
+ if (e.target.nodeName !== "OPTION") {
+ context.onMousePositionProjectionSystemMouseOver(e);
+ }
+ });
+
+ for (var i = 0; i < systems.length; i++) {
+ var obj = systems[i];
+ var option = document.createElement("option");
+ option.value = obj.code;
+ option.text = obj.label || i;
+ // option.label = obj.label;
+ selectSystem.appendChild(option);
+ }
+
+ return selectSystem;
+ },
+
+ /**
+ * @param {Object[]} units - list of units
+ *
+ * @returns {DOMElement} DOM element select
+ */
+ _createMousePositionSettingsUnitsElement : function (units) {
+ // contexte d'execution
+ var context = this;
+
+ var selectUnits = document.createElement("select");
+ selectUnits.id = this._addUID("GPmousePositionProjectionUnits");
+ selectUnits.className = "GPinputSelect GPmousePositionSettingsSelect";
+ selectUnits.addEventListener("change", function (e) {
+ context.onMousePositionProjectionUnitsChange(e);
+ });
+
+ for (var j = 0; j < units.length; j++) {
+ var obj = units[j];
+ var option = document.createElement("option");
+ option.value = (obj.code) ? obj.code : j;
+ option.text = obj.label || j;
+ // option.label = obj.label;
+ selectUnits.appendChild(option);
+ }
+
+ return selectUnits;
+ },
+
+ /**
+ * @param {String} [currentProjectionType="Metric"] - "Geographical" or "Metric"
+ */
+ _resetLabelElements : function (currentProjectionType) {
+ // Changement des labels dans le formulaire de saisie
+ var spanLat = document.getElementById(this._addUID("GPmousePositionLatLabel"));
+ spanLat.innerHTML = currentProjectionType === "Geographical" ? "Latitude :" : "X :";
+
+ var spanLon = document.getElementById(this._addUID("GPmousePositionLonLabel"));
+ spanLon.innerHTML = currentProjectionType === "Geographical" ? "Longitude :" : "Y :";
+ },
+
+ /**
+ * @param {String} currentProjectionUnits - projection units
+ */
+ _resetUnitElements : function (currentProjectionUnits) {
+ var value = "";
+ if (currentProjectionUnits === "M" || currentProjectionUnits === "KM") {
+ value = currentProjectionUnits.toLowerCase();
+ }
+
+ var elts = document.getElementsByClassName("GPmousePositionUnits");
+ for (var e = 0; e < elts.length; e++) {
+ elts[e].innerHTML = value;
+ }
+ },
+
+ /**
+ * @method _resetCoordinateElements
+ * @param {Boolean} editCoordinates - edit coordinates option
+ * @param {String} currentProjectionType - current projection type
+ * @param {String} currentProjectionUnits - current projection unit
+ */
+ _resetCoordinateElements : function (editCoordinates, currentProjectionType, currentProjectionUnits) {
+ // Suppression de tous les enfants de GPmousePositionLatCoordinate
+ var latElt = document.getElementById(this._addUID("GPmousePositionLatCoordinate"));
+ while (latElt.firstChild) {
+ latElt.removeChild(latElt.firstChild);
+ }
+
+ var arrayCoords;
+ if (currentProjectionUnits === "DMS") {
+ arrayCoords = this._createDMSCoordinateElement("Lat", editCoordinates);
+ } else {
+ arrayCoords = this._createCoordinateElement("Lat", editCoordinates);
+ }
+ for (var i = 0; i < arrayCoords.length; i++) {
+ latElt.appendChild(arrayCoords[i]);
+ }
+
+ // Suppression de tous les enfants de GPmousePositionLonCoordinate
+ var lonElt = document.getElementById(this._addUID("GPmousePositionLonCoordinate"));
+ while (lonElt.firstChild) {
+ lonElt.removeChild(lonElt.firstChild);
+ }
+
+ var arrayCoords1;
+ if (currentProjectionUnits === "DMS") {
+ arrayCoords1 = this._createDMSCoordinateElement("Lon", editCoordinates);
+ } else {
+ arrayCoords1 = this._createCoordinateElement("Lon", editCoordinates);
+ }
+ for (var j = 0; j < arrayCoords1.length; j++) {
+ lonElt.appendChild(arrayCoords1[j]);
+ }
+
+ // FIXME on simule un deplacement ?
+ // this.onMapMove();
+ },
+
+ /**
+ * Set/unset editing mode
+ *
+ * @method _setEditMode
+ * @param {Boolean} editing - active edit coordinates mode
+ */
+ _setEditMode : function (editing) {
+ var locateElt = document.getElementById(this._addUID("GPmousePositionLocate"));
+ locateElt.title = editing ? "Aller à la position ..." : "Cliquer pour saisir des coordonnées";
+
+ var closeEditElt = document.getElementById(this._addUID("GPmousePositionCloseEdit"));
+ closeEditElt.style.display = editing ? "inline-block" : "none";
+
+ var selector = "div[id^=" + this._addUID("GPmousePositionCoordinate") + "]";
+ var inputs = document.querySelectorAll(selector + " input");
+ for (var i = 0; i < inputs.length; i++) {
+ inputs[i].readOnly = !editing;
+ if (editing) {
+ inputs[i].value = "";
+ inputs[i].classList.remove("error");
+ }
+ }
+ var selects = document.querySelectorAll(selector + " select");
+ for (var j = 0; j < selects.length; j++) {
+ selects[j].disabled = !editing;
+ }
+ },
+
+ /**
+ *
+ * @param {DOMElement} input - input element
+ * @param {Boolean} isFloat - check for float value
+ *
+ * @returns {Boolean} true if input value is within bounds
+ */
+ _checkDMSElement : function (input, isFloat) {
+ var b = isFloat !== undefined;
+
+ var value = input.value;
+ if (b) {
+ value = value.replace(",", ".");
+ }
+ if (isNaN(value)) {
+ return false;
+ }
+
+ var v = parseFloat(value);
+ if (!b && (v | 0) !== v) { // is it an integer
+ return false;
+ }
+
+ var min = Number(input.dataset.min);
+ var max = Number(input.dataset.max);
+ return (v >= min && v <= max);
+ },
+
+ /**
+ * @param {String} coordType - "Lon" or "Lat"
+ * @param {DOMElement} input - input element
+ *
+ * @returns {Boolean} true if input value is within bounds
+ */
+ _checkDMSDegrees : function (coordType, input) {
+ if (isNaN(input.value)) {
+ return false;
+ }
+
+ var v = parseFloat(input.value);
+ if ((v | 0) !== v) { // is it an integer
+ return false;
+ }
+
+ var min = Number(input.dataset.min);
+ var max = Number(input.dataset.max);
+ if (v < min || v > max) {
+ return false;
+ }
+
+ var inputMinutes = document.getElementById(this._addUID("GPmousePosition" + coordType + "Minutes"));
+ var inputSeconds = document.getElementById(this._addUID("GPmousePosition" + coordType + "Seconds"));
+
+ if (v >= max) {
+ inputMinutes.dataset.max = 0;
+ inputSeconds.dataset.max = 0;
+ } else {
+ inputMinutes.dataset.max = 59;
+ inputSeconds.dataset.max = 59.9999;
+ }
+
+ return true;
+ },
+
+ // ################################################################### //
+ // ####################### handlers Event ############################ //
+ // ################################################################### //
+
+ /**
+ * Function displaying coordinates from cursor position (desktop)
+ * or map center (tactile)
+ * @param {Object} coordinate - coordinates
+ */
+ GPdisplayCoords : function (coordinate) {
+ // Compute coords in case of cursor position (desktop)
+ if (coordinate && coordinate != null) {
+ var labelLon = document.getElementById(this._addUID("GPmousePositionLonLabel"));
+ var labelLat = document.getElementById(this._addUID("GPmousePositionLatLabel"));
+
+ if (coordinate.x || coordinate.y) {
+ labelLat.innerHTML = "X : ";
+ labelLon.innerHTML = "Y : ";
+ } else if (coordinate.e || coordinate.n) {
+ labelLat.innerHTML = "E : ";
+ labelLon.innerHTML = "N : ";
+ } else {
+ labelLat.innerHTML = "Latitude : ";
+ labelLon.innerHTML = "Longitude : ";
+ }
+
+ if (typeof coordinate.lat === "object" && typeof coordinate.lng === "object") {
+ var parts = {
+ lng : "Lon",
+ lat : "Lat"
+ };
+ var units = ["Degrees", "Minutes", "Seconds"];
+ for (var p in parts) {
+ for (var u = 0; u < units.length; ++u) {
+ var selector = "GPmousePosition" + parts[p] + units[u];
+ var elt = document.getElementById(this._addUID(selector));
+ var key = units[u].charAt(0).toLowerCase();
+ elt.value = coordinate[p][key];
+ }
+ }
+ // directions
+ document.getElementById(this._addUID("GPmousePositionLonDirection")).value = coordinate.lng.direction;
+ document.getElementById(this._addUID("GPmousePositionLatDirection")).value = coordinate.lat.direction;
+ } else {
+ var elLat = document.getElementById(this._addUID("GPmousePositionLat"));
+ var elLon = document.getElementById(this._addUID("GPmousePositionLon"));
+
+ elLat.value = coordinate.x || coordinate.lat || coordinate.e || "0";
+ elLon.value = coordinate.y || coordinate.lng || coordinate.lon || coordinate.n || "0";
+
+ // les unites
+ var unit = (coordinate.unit === undefined) ? "" : coordinate.unit;
+ var elements = document.getElementsByClassName("GPmousePositionUnits");
+ for (var n = 0; n < elements.length; ++n) {
+ elements[n].innerHTML = unit;
+ }
+ }
+ }
+ },
+
+ /**
+ * Function displaying altitude from cursor position (desktop)
+ * or map center (tactile)
+ * @param {Object} coordinate - coordinates
+ * @param {Number} altitudeTimeoutDelay - when the mouse stop moving, delay before the altitude request is launched
+ * @param {Number} noDataValue - the no data value
+ * @param {Number} noDataValueTolerance - the no data value tolerance
+ */
+ GPdisplayElevation : function (coordinate, altitudeTimeoutDelay, noDataValue, noDataValueTolerance) {
+ // contexte d'execution
+ var self = this;
+
+ // Latency for altitude request
+ var altitudeTimeout;
+ if (!altitudeTimeoutDelay) {
+ altitudeTimeoutDelay = 500;
+ }
+
+ clearTimeout(altitudeTimeout);
+ document.getElementById(this._addUID("GPmousePositionAlt")).innerHTML = "...";
+
+ if (noDataValue == null) {
+ noDataValue = -99999;
+ }
+ if (noDataValueTolerance == null) {
+ noDataValueTolerance = 99980;
+ }
+ var maxThreshold = noDataValue + noDataValueTolerance;
+ var minThreshold = noDataValue - noDataValueTolerance;
+
+ // Compute coords in case of cursor position (desktop)
+ if (coordinate && coordinate != null) {
+ // If no altitude panel, don't call altitude request
+ if (document.getElementById(this._addUID("GPmousePositionAltitude"))) {
+ altitudeTimeout = setTimeout(function () {
+ self.onRequestAltitude(coordinate, function (z) {
+ if (minThreshold < z && z < maxThreshold) {
+ self.GPresetElevation();
+ } else {
+ document.getElementById(self._addUID("GPmousePositionAlt")).innerHTML = z;
+ }
+ });
+ }, altitudeTimeoutDelay);
+ }
+ }
+ },
+
+ /**
+ * Function reseting altitude value
+ */
+ GPresetElevation : function () {
+ if (document.getElementById(this._addUID("GPmousePositionAltitude"))) {
+ document.getElementById(this._addUID("GPmousePositionAlt")).innerHTML = "---";
+ }
+ }
+};
+
+export default MousePositionDOM;
diff --git a/src/Common-review/Controls/ProfileElevationPathDOM.js b/src/Common-review/Controls/ProfileElevationPathDOM.js
new file mode 100644
index 000000000..910c408f9
--- /dev/null
+++ b/src/Common-review/Controls/ProfileElevationPathDOM.js
@@ -0,0 +1,524 @@
+/* globals AmCharts, d3 */
+var ProfileElevationPathDOM = {
+
+ /**
+ * Display Profile function used by default : no additonal framework needed.
+ * @param {Object} data - elevations values for profile
+ * @param {HTMLElement} container - html container where to display profile
+ * @param {Object} context - this control object
+ * @param {Object} className - calling class (ie ElevationPath)
+ * @returns {DOMElement} profil container
+ */
+ displayProfileByDefault : function (data, container, context, className) {
+ var self = context;
+
+ // on nettoie toujours...
+ if (container) {
+ while (container.firstChild) {
+ container.removeChild(container.firstChild);
+ }
+ }
+
+ if (!data) {
+ return;
+ }
+
+ var _displayProfileOptions = self.options.displayProfileOptions;
+
+ var _points = data.points;
+
+ var sortedElev = JSON.parse(JSON.stringify(_points));
+ sortedElev.sort(function (e1, e2) {
+ return e1.z - e2.z;
+ });
+
+ var minZ = sortedElev[0].z;
+ var maxZ = sortedElev[sortedElev.length - 1].z;
+ var diff = maxZ - minZ;
+ var dist = data.distance;
+ var unit = data.unit;
+ // var distMin = 0;
+ var barwidth = 100 / _points.length;
+
+ var div = document.createElement("div");
+ div.id = "profileElevationByDefault";
+ container.appendChild(div);
+
+ var divBox = document.createElement("div");
+ divBox.className = "profile-box";
+
+ var divZ = document.createElement("div");
+ divZ.className = "profile-z-vertical";
+ var ulZ = document.createElement("ul");
+ var liZmin = document.createElement("li");
+ liZmin.setAttribute("class", "profile-min-z");
+ liZmin.innerHTML = minZ + " m";
+ var liZmax = document.createElement("li");
+ liZmax.setAttribute("class", "profile-max-z");
+ liZmax.innerHTML = maxZ + " m";
+
+ // var divUnit = document.createElement("div");
+ // divUnit.className = "profile-unit";
+ // divUnit.innerHTML = "m";
+
+ ulZ.appendChild(liZmax);
+ ulZ.appendChild(liZmin);
+ divZ.appendChild(ulZ);
+ // divZ.appendChild(divUnit);
+ divBox.appendChild(divZ);
+
+ var divData = document.createElement("div");
+ divData.className = "profile-content";
+ divData.addEventListener("mouseover", function (e) {
+ var _lon = parseFloat(e.target.dataset["lon"]);
+ var _lat = parseFloat(e.target.dataset["lat"]);
+
+ if (_lon && _lat) {
+ className.__createProfileMarker(self, {
+ lat : _lat,
+ lon : _lon
+ });
+ }
+ });
+ divData.addEventListener("mousemove", function (e) {
+ var _lon = parseFloat(e.target.dataset["lon"]);
+ var _lat = parseFloat(e.target.dataset["lat"]);
+
+ if (_lon && _lat) {
+ className.__updateProfileMarker(self, {
+ lat : _lat,
+ lon : _lon
+ });
+ }
+ });
+ divData.addEventListener("mouseout", function () {
+ className.__removeProfileMarker(self);
+ });
+
+ var ulData = document.createElement("ul");
+ ulData.id = "profile-data";
+ ulData.className = "profile-z-axis profile-x-axis";
+ divData.appendChild(ulData);
+
+ for (var i = 0; i < _points.length; i++) {
+ var d = _points[i];
+ var li = document.createElement("li");
+ li.setAttribute("data-z", d.z);
+ li.setAttribute("data-lon", d.lon);
+ li.setAttribute("data-lat", d.lat);
+ li.setAttribute("data-dist", d.dist);
+
+ var pct = Math.floor((d.z - minZ) * 100 / diff);
+ li.setAttribute("class", "percent v" + pct);
+ li.title = "Altitude : " + d.z + "m";
+ if (_displayProfileOptions.currentSlope) {
+ li.title += " - Pente : " + d.slope + "%";
+ }
+ li.title += " (Lat : " + d.lat + " / Lon : " + d.lon + ")";
+
+ li.setAttribute("style", "width: " + barwidth + "%");
+ ulData.appendChild(li);
+ }
+
+ divBox.appendChild(divData);
+ div.appendChild(divBox);
+
+ var divX = document.createElement("div");
+ divX.className = "profile-x-horizontal";
+ var ulX = document.createElement("ul");
+ var liXmin = document.createElement("li");
+ liXmin.setAttribute("class", "profile-min-x");
+ liXmin.innerHTML = "";
+ var liXmax = document.createElement("li");
+ liXmax.setAttribute("class", "profile-max-x");
+ liXmax.innerHTML = dist + " " + unit;
+ ulX.appendChild(liXmin);
+ ulX.appendChild(liXmax);
+ divX.appendChild(ulX);
+ div.appendChild(divX);
+
+ return container;
+ },
+
+ /**
+ * Display Profile without graphical rendering (raw service response)
+ * @param {Object} data - elevations values for profile
+ * @param {HTMLElement} container - html container where to display profile
+ * @param {Object} context - this control object
+ * @param {Object} className - calling class (ie ElevationPath)
+ * @returns {DOMElement} profil container
+ */
+ displayProfileRaw : function (data, container, context, className) {
+ // on nettoie toujours...
+ if (container) {
+ while (container.firstChild) {
+ container.removeChild(container.firstChild);
+ }
+ }
+
+ var _points = data.points;
+
+ var div = document.createElement("textarea");
+ div.id = "profilElevationResults";
+ div.rows = 10;
+ div.cols = 50;
+ div.style.width = "100%";
+ div.innerHTML = JSON.stringify(_points, undefined, 4);
+ div.addEventListener("mouseover", function (e) {
+ className.__customRawProfileMouseOverEvent(context, e);
+ });
+
+ // TODO
+ // for (var i = 0; i < _points.length; i++) {
+ // var point = _points[i];
+ // var divC = document.createElement("code");
+ // divC.id = "point_" + i;
+ // divC.innerHTML = JSON.stringify(point, undefined, 4);
+ // div.appendChild(divC);
+ // divC.addEventListener("mouseover", function (e) {
+ // className.__customRawProfileMouseOverEvent(context, e);
+ // });
+ // }
+
+ container.appendChild(div);
+
+ return container;
+ },
+
+ /**
+ * Display Profile using D3 javascript framework. This method needs D3 libraries to be loaded.
+ * @param {Object} data - elevations values for profile
+ * @param {HTMLElement} container - html container where to display profile
+ * @param {Object} context - this control object
+ * @param {Object} className - calling class (ie ElevationPath)
+ * @returns {DOMElement} profil container
+ */
+ displayProfileLibD3 : function (data, container, context, className) {
+ var self = context;
+
+ // on nettoie toujours...
+ if (container) {
+ while (container.firstChild) {
+ container.removeChild(container.firstChild);
+ }
+ }
+
+ var _points = data.points;
+
+ var _displayProfileOptions = self.options.displayProfileOptions;
+
+ var margin = {
+ top : 20,
+ right : 20,
+ bottom : 30,
+ left : 40
+ };
+
+ var width = container.clientWidth - margin.left - margin.right;
+ var height = container.clientHeight - margin.top - margin.bottom;
+
+ var x = d3.scale.linear()
+ .range([0, width]);
+
+ var y = d3.scale.linear()
+ .range([height, 0]);
+
+ var xAxis = d3.svg.axis()
+ .scale(x)
+ .orient("bottom")
+ .ticks(5);
+
+ var yAxis = d3.svg.axis()
+ .scale(y)
+ .orient("left")
+ .ticks(5);
+
+ var line = d3.svg.line()
+ .interpolate("basis")
+ .x(function (d) {
+ return x(d.dist);
+ })
+ .y(function (d) {
+ return y(d.z);
+ });
+
+ var area = d3.svg.area()
+ .interpolate("basis")
+ .x(function (d) {
+ return x(d.dist);
+ })
+ .y0(height)
+ .y1(function (d) {
+ return y(d.z);
+ });
+
+ var svg = d3.select(container)
+ .append("svg")
+ .attr("width", width + margin.left + margin.right)
+ .attr("height", height + margin.top + margin.bottom)
+ .append("g")
+ .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
+
+ var xDomain = d3.extent(_points, function (d) {
+ return d.dist;
+ });
+ x.domain(xDomain);
+
+ var yDomain = [
+ 0,
+ d3.max(_points, function (d) {
+ return d.z;
+ })
+ ];
+ y.domain(yDomain);
+
+ svg.append("path")
+ .datum(_points)
+ .attr("class", "area-d3")
+ .attr("d", area);
+
+ svg.append("g")
+ .attr("class", "x axis-d3")
+ .attr("transform", "translate(0," + height + ")")
+ .call(xAxis)
+ .append("text")
+ .attr("y", -15)
+ .attr("dy", ".71em")
+ .attr("x", width)
+ .text("Distance (" + data.unit + ")");
+
+ svg.append("g")
+ .attr("class", "y axis-d3")
+ .call(yAxis)
+ .append("text")
+ .attr("transform", "rotate(-90)")
+ .attr("y", 6)
+ .attr("dy", ".71em")
+ .text("Altitude (m)");
+
+ svg.append("g")
+ .attr("class", "grid-d3 vertical")
+ .attr("transform", "translate(0," + height + ")")
+ .call(xAxis
+ .orient("bottom")
+ .tickSize(-height, 0, 0)
+ .tickFormat("")
+ );
+
+ svg.append("g")
+ .attr("class", "grid-d3 horizontal")
+ .call(yAxis
+ .orient("left")
+ .tickSize(-width, 0, 0)
+ .tickFormat("")
+ );
+
+ svg.append("path")
+ .datum(_points)
+ .attr("class", "line-d3")
+ .attr("d", line);
+
+ svg.selectAll("circle")
+ .data(_points)
+ .enter()
+ .append("circle")
+ .attr("cx", function (d) {
+ return x(d.dist);
+ })
+ .attr("cy", function (d) {
+ return y(d.z);
+ })
+ .attr("r", 0)
+ .attr("class", "circle-d3");
+
+ var focus = svg.append("g").style("display", "none");
+
+ focus.append("line")
+ .attr("id", "focusLineX")
+ .attr("class", "focusLine-d3");
+ focus.append("line")
+ .attr("id", "focusLineY")
+ .attr("class", "focusLine-d3");
+ focus.append("circle")
+ .attr("id", "focusCircle")
+ .attr("r", 4)
+ .attr("class", "circle-d3 focusCircle-d3");
+
+ var div = d3.select(container).append("div")
+ .attr("class", "tooltip-d3")
+ .style("opacity", 0);
+
+ var bisectDist = d3.bisector(function (d) {
+ return d.dist;
+ }).left;
+
+ svg.append("rect")
+ .attr("class", "overlay-d3")
+ .attr("width", width)
+ .attr("height", height)
+ .on("mouseover", function () {
+ focus.style("display", null);
+ className.__createProfileMarker(self, _points[0]);
+ })
+ .on("mouseout", function () {
+ focus.style("display", "none");
+ className.__removeProfileMarker(self);
+
+ // tooltips
+ div.transition()
+ .duration(500)
+ .style("opacity", 0);
+ })
+ .on("mousemove", function () {
+ var m = d3.mouse(this);
+ var distance = x.invert(m[0]);
+ var i = bisectDist(_points, distance);
+
+ var d0 = _points[i - 1];
+ var d1 = _points[i];
+ var d = distance - d0[0] > d1[0] - distance ? d1 : d0;
+
+ var xc = x(d.dist);
+ var yc = y(d.z);
+
+ focus.select("#focusCircle")
+ .attr("cx", xc)
+ .attr("cy", yc);
+ focus.select("#focusLineX")
+ .attr("x1", xc).attr("y1", y(yDomain[0]))
+ .attr("x2", xc).attr("y2", y(yDomain[1]));
+ focus.select("#focusLineY")
+ .attr("x1", x(xDomain[0])).attr("y1", yc)
+ .attr("x2", x(xDomain[1])).attr("y2", yc);
+
+ className.__updateProfileMarker(self, d);
+
+ // tooltips
+ div.transition()
+ .duration(200)
+ .style("opacity", 0.9);
+
+ var _message = "";
+ _message += " Altitude : " + d.z + " m";
+ if (_displayProfileOptions.currentSlope) {
+ _message += " Pente : " + d.slope + " %";
+ }
+ _message += " (Lat : " + d.lat + "/ Lon : " + d.lon + ")";
+
+ div.html(_message)
+ .style("left", (d3.event.pageX) + "px")
+ .style("top", (d3.event.pageY - 28) + "px");
+ });
+
+ // return d3.selectAll("rect.overlay")[0][0];
+ return svg;
+ },
+
+ /**
+ * Display Profile using Amcharts framework. This method needs AmCharts libraries to be loaded.
+ * @param {Object} data - elevations values for profile
+ * @param {HTMLElement} container - html container where to display profile
+ * @param {Object} context - this control object
+ * @param {Object} className - calling class (ie ElevationPath)
+ * @returns {DOMElement} profil container
+ */
+ displayProfileLibAmCharts : function (data, container, context, className) {
+ var self = context;
+
+ var _points = data.points;
+
+ var ballonText = "[[title]] : [[value]]m ";
+ var currentSlope = self.options.displayProfileOptions.currentSlope;
+ if (currentSlope) {
+ ballonText += "Pente : [[slope]] % ";
+ }
+ ballonText += "(Lat: [[lat]] / Lon:[[lon]])";
+
+ AmCharts.addInitHandler(function () {});
+
+ var settings = {
+ type : "serial",
+ pathToImages : "http://cdn.amcharts.com/lib/3/images/",
+ categoryField : "dist",
+ autoMarginOffset : 0,
+ marginRight : 10,
+ marginTop : 10,
+ startDuration : 0,
+ color : "#5E5E5E",
+ fontSize : 8,
+ theme : "light",
+ thousandsSeparator : "",
+ numberFormatter : {
+ precision : -1,
+ decimalSeparator : ",",
+ thousandsSeparato : " "
+ },
+ categoryAxis : {
+ color : "#5E5E5E",
+ gridPosition : "start",
+ minHorizontalGap : 40,
+ tickPosition : "start",
+ title : "Distance (" + data.unit + ")",
+ titleColor : "#5E5E5E",
+ labelOffset : 0,
+ startOnAxis : true
+ },
+ chartCursor : {
+ animationDuration : 0,
+ bulletsEnabled : true,
+ bulletSize : 10,
+ categoryBalloonEnabled : false,
+ cursorColor : "#F90",
+ graphBulletAlpha : 1,
+ graphBulletSize : 1,
+ zoomable : false
+ },
+ trendLines : [],
+ graphs : [{
+ balloonColor : "#CCCCCC",
+ balloonText : ballonText,
+ bullet : "round",
+ bulletAlpha : 0,
+ bulletBorderColor : "#FFF",
+ bulletBorderThickness : 2,
+ bulletColor : "#F90",
+ bulletSize : 6,
+ hidden : false,
+ id : "AmGraph-1",
+ fillAlphas : 0.4,
+ fillColors : "#C77A04",
+ lineAlpha : 1,
+ lineColor : "#C77A04",
+ lineThickness : 1,
+ title : "Altitude",
+ valueField : "z"
+ }],
+ guides : [],
+ valueAxes : [{
+ id : "ValueAxis-1",
+ minVerticalGap : 20,
+ title : "Altitude (m)"
+ }],
+ balloon : {
+ borderColor : "#CCCCCC",
+ borderThickness : 1,
+ fillColor : "#FFFFFF",
+ showBullet : true
+ },
+ titles : [],
+ allLabels : [],
+ dataProvider : _points
+ };
+
+ var _containerProfile = AmCharts.makeChart(container, settings);
+
+ _containerProfile.addListener("changed", function (e) {
+ var obj = e.chart.dataProvider[e.index];
+ className.__updateProfileMarker(self, obj);
+ });
+
+ return _containerProfile;
+ }
+};
+
+export default ProfileElevationPathDOM;
diff --git a/src/Common-review/Controls/ReverseGeocodingDOM.js b/src/Common-review/Controls/ReverseGeocodingDOM.js
new file mode 100644
index 000000000..e2e59e29b
--- /dev/null
+++ b/src/Common-review/Controls/ReverseGeocodingDOM.js
@@ -0,0 +1,463 @@
+var ReverseGeocodingDOM = {
+
+ /**
+ * Add uuid to the tag ID
+ * @param {String} id - id selector
+ * @returns {String} uid - id selector with an unique id
+ */
+ _addUID : function (id) {
+ var uid = (this._uid) ? id + "-" + this._uid : id;
+ return uid;
+ },
+
+ /**
+ * Main container (DOM)
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createMainContainerElement : function () {
+ var container = document.createElement("div");
+ container.id = this._addUID("GPreverseGeocoding");
+ container.className = "GPwidget";
+ return container;
+ },
+
+ // ################################################################### //
+ // ################### Methods of main container ##################### //
+ // ################################################################### //
+
+ /**
+ * Hidden checkbox for minimizing/maximizing
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createShowReverseGeocodingElement : function () {
+ var input = document.createElement("input");
+ input.id = this._addUID("GPshowReverseGeocoding");
+ input.type = "checkbox";
+ return input;
+ },
+
+ /**
+ * Show ReverseGeocoding
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createShowReverseGeocodingPictoElement : function () {
+ // contexte d'execution
+ var self = this;
+
+ var label = document.createElement("label");
+ label.id = this._addUID("GPshowReverseGeocodingPicto");
+ label.className = "GPshowAdvancedToolPicto";
+ label.htmlFor = this._addUID("GPshowReverseGeocoding");
+ label.title = "Ouvrir la recherche inverse";
+
+ // Close all results and panels when minimizing the widget
+ if (label.addEventListener) {
+ label.addEventListener("click", function () {
+ self.onShowReverseGeocodingClick();
+ });
+ } else if (label.attachEvent) {
+ label.attachEvent("onclick", function () {
+ self.onShowReverseGeocodingClick();
+ });
+ }
+
+ var spanOpen = document.createElement("span");
+ spanOpen.id = this._addUID("GPshowReverseGeocodingOpen");
+ spanOpen.className = "GPshowAdvancedToolOpen";
+ label.appendChild(spanOpen);
+
+ return label;
+ },
+
+ /**
+ * Create Waiting Panel
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createReverseGeocodingWaitingElement : function () {
+ var div = document.createElement("div");
+ div.id = this._addUID("GPreverseGeocodingCalcWaitingContainer");
+ div.className = "GPreverseGeocodingCalcWaitingContainerHidden";
+
+ var p = document.createElement("p");
+ p.className = "GPreverseGeocodingCalcWaiting";
+ p.innerHTML = "Recherche en cours...";
+
+ div.appendChild(p);
+
+ return div;
+ },
+
+ /**
+ * Reverse geocoding results panel element.
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createReverseGeocodingResultsPanelElement : function () {
+ var resultsPanelDiv = document.createElement("div");
+ resultsPanelDiv.id = this._addUID("GPreverseGeocodingResultsPanel");
+ resultsPanelDiv.className = "GPpanel GPreverseGeocodingComponentHidden";
+ return resultsPanelDiv;
+ },
+
+ /**
+ * Reverse geocoding results list.
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createReverseGeocodingResultsListElement : function () {
+ var container = document.createElement("div");
+ container.id = this._addUID("GPreverseGeocodingResultsList");
+ // Results are dynamically filled in Javascript by reverse geocoding service
+ return container;
+ },
+
+ /**
+ * Add Result
+ * (results dynamically generate !)
+ *
+ * @param {String} locationDescription - reverse geocoded location results
+ * @param {Number} id - ID
+ */
+ _createReverseGeocodingResultElement : function (locationDescription, id) {
+ // contexte
+ var context = this;
+
+ var container = document.getElementById(this._addUID("GPreverseGeocodingResultsList"));
+
+ var div = document.createElement("div");
+ div.id = this._addUID("ReverseGeocodedLocation_" + id);
+ div.className = "GPautoCompleteProposal";
+ div.innerHTML = locationDescription;
+ div.title = locationDescription;
+
+ if (div.addEventListener) {
+ div.addEventListener("mouseover", function (e) {
+ context.onReverseGeocodingResultMouseOver(e);
+ });
+ div.addEventListener("mouseout", function (e) {
+ context.onReverseGeocodingResultMouseOut(e);
+ });
+ div.addEventListener("click", function (e) {
+ if (typeof context.onReverseGeocodingResultClick === "function") {
+ context.onReverseGeocodingResultClick(e);
+ }
+ });
+ } else if (div.attachEvent) {
+ div.attachEvent("onmouseover", function (e) {
+ context.onReverseGeocodingResultMouseOver(e);
+ });
+ div.attachEvent("onmouseout", function (e) {
+ context.onReverseGeocodingResultMouseOut(e);
+ });
+ div.attachEvent("onclick", function (e) {
+ if (typeof context.onReverseGeocodingResultClick === "function") {
+ context.onReverseGeocodingResultClick(e);
+ }
+ });
+ }
+
+ container.appendChild(div);
+ },
+
+ // ################################################################### //
+ // ######################### Inputs panel ############################ //
+ // ################################################################### //
+
+ /**
+ * Create Container Panel
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createReverseGeocodingPanelElement : function () {
+ var div = document.createElement("div");
+ div.id = this._addUID("GPreverseGeocodingPanel");
+ div.className = "GPpanel";
+
+ return div;
+ },
+
+ /**
+ * Create Header Panel
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createReverseGeocodingPanelHeaderElement : function () {
+ var container = document.createElement("div");
+ container.className = "GPpanelHeader";
+ // info: on sépare les appels pour la création du picto de retour,
+ // du titre et de la croix de fermeture pour les récupérer dans le composant
+ return container;
+ },
+
+ /**
+ * Create return picto in panel header
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createReverseGeocodingPanelReturnPictoElement : function () {
+ // contexte
+ var self = this;
+
+ var divNew = document.createElement("div");
+ divNew.id = this._addUID("GPreverseGeocodingReturnPicto");
+ divNew.title = "Nouvelle recherche";
+ divNew.className = "GPreverseGeocodingReturnPictoHidden";
+ if (divNew.addEventListener) {
+ divNew.addEventListener("click", function (e) {
+ document.getElementById(self._addUID("GPreverseGeocodingResultsPanel")).className = "GProuteComponentHidden";
+ document.getElementById(self._addUID("GPreverseGeocodingForm")).className = "";
+ document.getElementById(self._addUID("GPreverseGeocodingHeaderTitle")).innerHTML = "Recherche inverse";
+ document.getElementById(self._addUID("GPreverseGeocodingReturnPicto")).className = "GPreverseGeocodingReturnPictoHidden";
+ self.onGPreverseGeocodingReturnPictoClick(e);
+ });
+ } else if (divNew.attachEvent) {
+ divNew.attachEvent("onclick", function (e) {
+ document.getElementById(self._addUID("GPreverseGeocodingResultsPanel")).className = "GProuteComponentHidden";
+ document.getElementById(self._addUID("GPreverseGeocodingForm")).className = "";
+ document.getElementById(self._addUID("GPreverseGeocodingHeaderTitle")).innerHTML = "Recherche inverse";
+ document.getElementById(self._addUID("GPreverseGeocodingReturnPicto")).className = "GPreverseGeocodingReturnPictoHidden";
+ self.onGPreverseGeocodingReturnPictoClick(e);
+ });
+ }
+ return divNew;
+ },
+
+ /**
+ * Create Header Title Panel
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createReverseGeocodingPanelTitleElement : function () {
+ var div = document.createElement("div");
+ div.className = "GPpanelTitle";
+ div.id = this._addUID("GPreverseGeocodingHeaderTitle");
+ div.innerHTML = "Recherche inverse";
+ return div;
+ },
+
+ /**
+ * Create Header close div
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createReverseGeocodingPanelCloseElement : function () {
+ // contexte
+ var self = this;
+
+ var divClose = document.createElement("div");
+ divClose.id = this._addUID("GPreverseGeocodingPanelClose");
+ divClose.className = "GPpanelClose";
+ divClose.title = "Fermer le panneau";
+
+ // Link panel close / visibility checkbox
+ if (divClose.addEventListener) {
+ divClose.addEventListener("click", function () {
+ document.getElementById(self._addUID("GPshowReverseGeocodingPicto")).click();
+ }, false);
+ } else if (divClose.attachEvent) {
+ divClose.attachEvent("onclick", function () {
+ document.getElementById(self._addUID("GPshowReverseGeocodingPicto")).click();
+ });
+ }
+
+ return divClose;
+ },
+
+ /**
+ * Create Form
+ * see event !
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createReverseGeocodingPanelFormElement : function () {
+ // contexte d'execution
+ var self = this;
+
+ var form = document.createElement("form");
+ form.id = this._addUID("GPreverseGeocodingForm");
+
+ if (form.addEventListener) {
+ form.addEventListener("submit", function (e) {
+ e.preventDefault();
+ self.onReverseGeocodingSubmit();
+ });
+ } else if (form.attachEvent) {
+ form.attachEvent("onsubmit", function (e) {
+ e.preventDefault();
+ self.onReverseGeocodingSubmit();
+ });
+ }
+
+ return form;
+ },
+
+ // ################################################################### //
+ // ####################### Choice mode into form ##################### //
+ // ################################################################### //
+
+ /**
+ * Create Container to Mode choice geocoding type
+ *
+ * @param {Array} resources - geocoding resources to be displayed (and used)
+ * @returns {DOMElement} DOM element
+ */
+ _createReverseGeocodingFormModeChoiceGeocodingTypeElement : function (resources) {
+ // contexte d'execution
+ var context = this;
+
+ var div = document.createElement("div");
+ div.className = "GPflexInput";
+
+ var label = document.createElement("label");
+ label.className = "GPreverseGeocodingCodeLabel";
+ label.innerHTML = "Recherche par";
+ label.title = "Recherche par";
+ div.appendChild(label);
+
+ var select = document.createElement("select");
+ select.className = "GPreverseGeocodingCode";
+ // gestionnaire d'evenement : on stocke la valeur du type de geocodage,
+ // utilisé dans la requête de géocodage inverse
+ if (select.addEventListener) {
+ select.addEventListener("change", function (e) {
+ context.onReverseGeocodingTypeChange(e);
+ });
+ } else if (select.attachEvent) {
+ select.attachEvent("onchange", function (e) {
+ context.onReverseGeocodingTypeChange(e);
+ });
+ }
+
+ // on prend soit les valeurs passées par l'utilisateur, soit des valeurs par défaut
+ if (!resources || !Array.isArray(resources)) {
+ resources = ["StreetAddress", "PositionOfInterest", "CadastralParcel"];
+ }
+ for (var i = 0; i < resources.length; i++) {
+ switch (resources[i]) {
+ case "PositionOfInterest":
+ var POIOption = document.createElement("option");
+ POIOption.value = "PositionOfInterest";
+ POIOption.text = "Lieux/toponymes";
+ select.appendChild(POIOption);
+ break;
+ case "StreetAddress":
+ var SAOption = document.createElement("option");
+ SAOption.value = "StreetAddress";
+ SAOption.text = "Adresses";
+ select.appendChild(SAOption);
+ break;
+ case "CadastralParcel":
+ var CPOption = document.createElement("option");
+ CPOption.value = "CadastralParcel";
+ CPOption.text = "Parcelles cadastrales";
+ select.appendChild(CPOption);
+ break;
+ case "Administratif":
+ var adminOption = document.createElement("option");
+ adminOption.value = "Administratif";
+ adminOption.text = "Unités administratives";
+ select.appendChild(adminOption);
+ break;
+ default:
+ break;
+ }
+ }
+
+ div.appendChild(select);
+
+ return div;
+ },
+
+ /**
+ * Create Container to Mode choice geocoding delimitation
+ *
+ * @param {Array} delimitations - geocoding delimitations to be displayed (and used)
+ * @returns {DOMElement} DOM element
+ */
+ _createReverseGeocodingFormModeChoiceGeocodingDelimitationElement : function (delimitations) {
+ // contexte d'execution
+ var context = this;
+
+ var div = document.createElement("div");
+ div.className = "GPflexInput";
+
+ var label = document.createElement("label");
+ label.className = "GPreverseGeocodingCodeLabel";
+ label.innerHTML = "Délimitation";
+ label.title = "Délimitation";
+ div.appendChild(label);
+
+ var select = document.createElement("select");
+ select.className = "GPreverseGeocodingCode";
+ // gestionnaire d'evenement : on stocke la valeur du type de délimitation,
+ // et on modifie l'événement de pointage sur la carte en fonction
+ if (select.addEventListener) {
+ select.addEventListener("change", function (e) {
+ context.onReverseGeocodingDelimitationChange(e);
+ });
+ } else if (select.attachEvent) {
+ select.attachEvent("onchange", function (e) {
+ context.onReverseGeocodingDelimitationChange(e);
+ });
+ }
+
+ // on prend soit les valeurs passées par l'utilisateur, soit des valeurs par défaut
+ if (!delimitations || !Array.isArray(delimitations)) {
+ delimitations = ["Point", "Circle", "Extent"];
+ }
+ for (var i = 0; i < delimitations.length; i++) {
+ switch (delimitations[i].toLowerCase()) {
+ case "point":
+ var pointOption = document.createElement("option");
+ pointOption.value = "point";
+ pointOption.text = "Pointer un lieu";
+ select.appendChild(pointOption);
+ break;
+ case "circle":
+ var circleOption = document.createElement("option");
+ circleOption.value = "circle";
+ circleOption.text = "Dessiner un cercle";
+ select.appendChild(circleOption);
+ break;
+ case "extent":
+ var extentOption = document.createElement("option");
+ extentOption.value = "extent";
+ extentOption.text = "Dessiner une emprise";
+ select.appendChild(extentOption);
+ break;
+ default:
+ break;
+ }
+ }
+
+ div.appendChild(select);
+
+ return div;
+ },
+
+ // ################################################################### //
+ // ########################### Submit Form ########################### //
+ // ################################################################### //
+
+ /**
+ * Create Submit Form Element
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createReverseGeocodingSubmitFormElement : function () {
+ var input = document.createElement("input");
+ input.id = this._addUID("GPreverseGeocodingSubmit");
+ input.className = "GPinputSubmit";
+ input.type = "submit";
+ input.value = "Rechercher";
+
+ return input;
+ }
+
+};
+
+export default ReverseGeocodingDOM;
diff --git a/src/Common-review/Controls/RouteDOM.js b/src/Common-review/Controls/RouteDOM.js
new file mode 100644
index 000000000..bede85b74
--- /dev/null
+++ b/src/Common-review/Controls/RouteDOM.js
@@ -0,0 +1,1200 @@
+import ID from "../Utils/SelectorID";
+import Logger from "../../Common/Utils/LoggerByDefault";
+
+var logger = Logger.getLogger("RouteDOM");
+
+var RouteDOM = {
+
+ /**
+ * Add uuid to the tag ID
+ * @param {String} id - id selector
+ * @returns {String} uid - id selector with an unique id
+ */
+ _addUID : function (id) {
+ var uid = (this._uid) ? id + "-" + this._uid : id;
+ return uid;
+ },
+
+ /**
+ * Main container (DOM)
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createMainContainerElement : function () {
+ var container = document.createElement("div");
+ container.id = this._addUID("GProute");
+ container.className = "GPwidget";
+ return container;
+ },
+
+ // ################################################################### //
+ // ################# Methods to display Main Panel ################### //
+ // ################################################################### //
+
+ /**
+ * Hidden checkbox for minimizing/maximizing panel
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createShowRouteElement : function () {
+ var input = document.createElement("input");
+ input.id = this._addUID("GPshowRoute");
+ input.type = "checkbox";
+ return input;
+ },
+
+ /**
+ * Show route control
+ * see event !
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createShowRoutePictoElement : function () {
+ // contexte d'execution
+ var context = this;
+
+ var label = document.createElement("label");
+ label.id = this._addUID("GPshowRoutePicto");
+ label.className = "GPshowAdvancedToolPicto";
+ label.htmlFor = this._addUID("GPshowRoute");
+ label.title = "Ouvrir le calcul d'itinéraire";
+
+ // gestionnaire d'evenement :
+ // on ouvre le menu de saisie du calcul d'itiniraire
+ // L'ouverture/Fermeture permet de faire le menage
+ // (reinitialisation)
+ if (label.addEventListener) {
+ label.addEventListener("click", function (e) {
+ context.onShowRoutePanelClick(e);
+ });
+ } else if (label.attachEvent) {
+ label.attachEvent("onclick", function (e) {
+ context.onShowRoutePanelClick(e);
+ });
+ }
+
+ var spanOpen = document.createElement("span");
+ spanOpen.id = this._addUID("GPshowRouteOpen");
+ spanOpen.className = "GPshowAdvancedToolOpen";
+ label.appendChild(spanOpen);
+
+ return label;
+ },
+
+ // ################################################################### //
+ // ################## Methods to display Inputs Panel ################ //
+ // ################################################################### //
+
+ /**
+ * Create Container Panel
+ *
+ * FIXME
+ * don't call this._createRoutePanelHeaderElement
+ * don't call this._createRoutePanelFormElement
+ * don't call this._createRoutePanelResultsElement
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createRoutePanelElement : function () {
+ var div = document.createElement("div");
+ div.id = this._addUID("GProutePanel");
+ div.className = "GPpanel";
+
+ // div.appendChild(this._createRoutePanelHeaderElement());
+ // div.appendChild(this._createRoutePanelFormElement());
+ // div.appendChild(this._createRoutePanelResultsElement());
+
+ return div;
+ },
+
+ /**
+ * Create Header Panel
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createRoutePanelHeaderElement : function () {
+ // contexte d'execution
+ var self = this;
+
+ var container = document.createElement("div");
+ container.className = "GPpanelHeader";
+
+ var div = document.createElement("div");
+ div.className = "GPpanelTitle";
+ div.innerHTML = "Calcul d'itinéraire";
+ container.appendChild(div);
+
+ var divClose = document.createElement("div");
+ divClose.id = this._addUID("GProutePanelClose");
+ divClose.className = "GPpanelClose";
+ divClose.title = "Masquer le panneau";
+
+ // Link panel close / visibility checkbox
+ if (divClose.addEventListener) {
+ divClose.addEventListener("click", function () {
+ document.getElementById(self._addUID("GPshowRoutePicto")).click();
+ }, false);
+ } else if (divClose.attachEvent) {
+ divClose.attachEvent("onclick", function () {
+ document.getElementById(self._addUID("GPshowRoutePicto")).click();
+ });
+ }
+ container.appendChild(divClose);
+
+ return container;
+ },
+
+ /**
+ * Create Form
+ * see evenement !
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createRoutePanelFormElement : function () {
+ // contexte d'execution
+ var self = this;
+
+ var form = document.createElement("form");
+ form.id = this._addUID("GProuteForm");
+ form.setAttribute("onkeypress", "return event.keyCode != 13;"); // FIXME hack pour desactiver l'execution via 'enter' au clavier !
+
+ form.addEventListener("submit", function (e) {
+ logger.log(e);
+ e.preventDefault();
+
+ // points
+ var points = document.getElementsByClassName(self._addUID("GPlocationPoint"));
+
+ // Must have at least two origin points
+ var start = points[0].childNodes[0].id;
+ var end = points[points.length - 1].childNodes[0].id;
+ var startID = ID.index(start);
+ var endID = ID.index(end);
+
+ if ((document.getElementById(self._addUID("GPlocationOrigin_" + startID)).value === "" &&
+ document.getElementById(self._addUID("GPlocationOriginCoords_" + startID)).value === "") ||
+ (document.getElementById(self._addUID("GPlocationOrigin_" + endID)).value === "" &&
+ document.getElementById(self._addUID("GPlocationOriginCoords_" + endID)).value === "")) {
+ return false;
+ }
+
+ // Send stages to results panel
+ var id;
+ document.getElementById(self._addUID("GProuteResultsStages")).innerHTML = "";
+ for (var i = 0; i < points.length; i++) {
+ var tag = points[i].childNodes[0].id;
+ id = ID.index(tag);
+ if (document.getElementById(self._addUID("GPlocationPoint_" + id)).className === "GPflexInput GPlocationStageFlexInput") {
+ var resultStage = document.createElement("div");
+ resultStage.className = "GProuteResultsStages";
+ var resultStageLabel = document.createElement("div");
+ resultStageLabel.className = "GProuteResultStageLabel";
+ resultStageLabel.innerHTML = document.getElementById(self._addUID("GPlocationOriginLabel_" + id)).innerHTML + " :";
+ resultStage.appendChild(resultStageLabel);
+ var resultStageValue = document.createElement("div");
+ resultStageValue.className = "GProuteResultStageValue";
+ var elementCoords = document.getElementById(self._addUID("GPlocationOriginCoords_" + id));
+ var stageCoords = elementCoords.value;
+ var visible = (elementCoords.className === "GPlocationOriginVisible");
+ if (stageCoords !== null && stageCoords !== "" && visible) {
+ resultStageValue.innerHTML = stageCoords;
+ } else {
+ resultStageValue.innerHTML = document.getElementById(self._addUID("GPlocationOrigin_" + id)).value;
+ }
+ resultStage.appendChild(resultStageValue);
+ if (resultStageValue.innerHTML !== "") {
+ document.getElementById(self._addUID("GProuteResultsStages")).appendChild(resultStage);
+ }
+ }
+ }
+
+ // on peut récuperer les valeurs utiles pour les transmettre au service d'iti...
+ // - le mode de calcul
+ // - le mode de transport
+ // - les exclusions
+ // Les points sont déjà stockés dans l'application.
+
+ // computation mode params
+ var modeComputation = null;
+ if (document.getElementById(self._addUID("GProuteComputationSelect"))) {
+ var select = document.getElementById(self._addUID("GProuteResultsComputationSelect"));
+ select.selectedIndex = document.getElementById(self._addUID("GProuteComputationSelect")).selectedIndex;
+ modeComputation = select.options[select.selectedIndex].value;
+ }
+
+ // transport mode params
+ var modeTransport = null;
+ // voiture ?
+ if (document.getElementById(self._addUID("GProuteTransportCar"))) {
+ if (document.getElementById(self._addUID("GProuteTransportCar")).checked) {
+ modeTransport = document.getElementById(self._addUID("GProuteTransportCar")).value;
+ }
+ }
+ // pieton ?
+ if (document.getElementById(self._addUID("GProuteTransportPedestrian"))) {
+ if (document.getElementById(self._addUID("GProuteTransportPedestrian")).checked) {
+ modeTransport = document.getElementById(self._addUID("GProuteTransportPedestrian")).value;
+ }
+ }
+
+ // exclusions params
+ var exclusions = [];
+ var exclusionsElement = document.getElementsByClassName("GProuteExclusionsOption");
+ for (var j = 0; j < exclusionsElement.length; j++) {
+ id = exclusionsElement[j].htmlFor;
+ var el = document.getElementById(id);
+ if (!el.checked) {
+ exclusions.push(el.value);
+ }
+ }
+
+ self.onRouteComputationSubmit({
+ computation : modeComputation,
+ transport : modeTransport,
+ exclusions : exclusions
+ });
+
+ // FIXME mise à jour du controle dans le composant JS !
+ // document.getElementById(self._addUID("GProuteForm")).className = "GProuteComponentHidden";
+ // document.getElementById(self._addUID("GProuteResultsPanel")).className = "";
+
+ return false;
+ });
+
+ return form;
+ },
+
+ /**
+ * Create Results Panel
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createRoutePanelResultsElement : function () {
+ var container = document.createElement("div");
+ container.id = this._addUID("GProuteResultsPanel");
+ container.className = "GProuteComponentHidden";
+
+ container.appendChild(this._createRouteResultsStagesElement());
+ container.appendChild(this._createRouteResultsElement());
+
+ var divBorderUp = document.createElement("div");
+ divBorderUp.className = "GPfakeBorder GPfakeBorderLeft";
+ container.appendChild(divBorderUp);
+
+ container.appendChild(this._createRouteShowResultsDetailsElement());
+
+ var labelShow = document.createElement("label");
+ labelShow.htmlFor = this._addUID("GProuteResultsShowDetails");
+ labelShow.innerHTML = "Afficher le détail";
+ container.appendChild(labelShow);
+
+ var labelHide = document.createElement("label");
+ labelHide.htmlFor = this._addUID("GProuteResultsShowDetails");
+ labelHide.innerHTML = "Masquer le détail";
+ container.appendChild(labelHide);
+
+ var divBorderDown = document.createElement("div");
+ divBorderDown.className = "GPfakeBorder";
+ container.appendChild(divBorderDown);
+
+ container.appendChild(this._createRouteResultsDetailsElement());
+
+ return container;
+ },
+
+ /**
+ * Create Waiting Panel
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createRouteWaitingElement : function () {
+ var div = document.createElement("div");
+ div.id = this._addUID("GProuteCalcWaitingContainer");
+ div.className = "GProuteCalcWaitingContainerHidden";
+
+ var p = document.createElement("p");
+ p.className = "GProuteCalcWaiting";
+ p.innerHTML = "Calcul en cours...";
+
+ div.appendChild(p);
+
+ return div;
+ },
+ // ################################################################### //
+ // ############### Methods to the window results ##################### //
+ // ################################################################### //
+
+ /**
+ * Create Results Stages
+ * (results dynamically generate !)
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createRouteResultsStagesElement : function () {
+ var div = document.createElement("div");
+ div.id = this._addUID("GProuteResultsStages");
+ return div;
+ },
+
+ /**
+ * Create Show Results
+ * see event!
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createRouteResultsElement : function () {
+ // contexte
+ var self = this;
+
+ var container = document.createElement("div");
+ container.id = this._addUID("GProuteResults");
+
+ // FIXME Route results are dynamically filled in Javascript by route service
+ var divValue = document.createElement("div");
+ divValue.id = this._addUID("GProuteResultsValues");
+ container.appendChild(divValue);
+
+ var divMode = document.createElement("div");
+ divMode.id = this._addUID("GProuteResultsMode");
+
+ var select = document.createElement("select");
+ select.id = this._addUID("GProuteResultsComputationSelect");
+ select.className = "GPinputSelect";
+ // gestionnaire d'evenement :
+ // on stocke la valeur du mode de calcul, et on relance le calcul d'itiniraire
+ select.addEventListener("change", function (e) {
+ self.onRouteModeComputationChangeAndRun(e);
+ });
+
+ var computes = [{
+ code : "fastest",
+ label : "Plus rapide"
+ }, {
+ code : "shortest",
+ label : "Plus court"
+ }];
+
+ for (var i = 0; i < computes.length; i++) {
+ var option = document.createElement("option");
+ option.value = computes[i].code;
+ option.text = computes[i].label;
+ select.appendChild(option);
+ }
+ divMode.appendChild(select);
+ container.appendChild(divMode);
+
+ var divNew = document.createElement("div");
+ divNew.id = this._addUID("GProuteResultsNew");
+ divNew.title = "Modifier le calcul";
+ divNew.addEventListener("click", function (e) {
+ document.getElementById(self._addUID("GProuteResultsPanel")).className = "GProuteComponentHidden";
+ document.getElementById(self._addUID("GProuteForm")).className = "";
+ self.onShowRouteResultsNewClick(e);
+ });
+ container.appendChild(divNew);
+
+ return container;
+ },
+
+ /**
+ * Add Results Duration and Distance
+ * (results dynamically generate !)
+ * see event!
+ * @param {Number} distance - distance
+ * @param {Number} duration - duration
+ * @param {Function} fconvert - fconvert
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _addRouteResultsValuesElement : function (distance, duration, fconvert) {
+ var div = document.getElementById(this._addUID("GProuteResultsValues"));
+
+ // clean !
+ if (div.childElementCount) {
+ while (div.firstChild) {
+ div.removeChild(div.firstChild);
+ }
+ }
+
+ var containerDistance = document.createElement("div");
+ containerDistance.className = "GProuteResultsValue";
+
+ var labelDistance = document.createElement("label");
+ labelDistance.className = "GProuteResultsValueLabel";
+ labelDistance.innerHTML = "Distance :";
+ containerDistance.appendChild(labelDistance);
+
+ var distanceLabel = 0;
+ var isKm = parseInt(distance / 1000, 10);
+
+ if (!isKm) {
+ distanceLabel = Math.round(distance) + " m";
+ } else {
+ var distanceArrondi = Math.round(distance);
+ distanceArrondi = distanceArrondi / 1000;
+ distanceLabel = distanceArrondi + " km";
+ }
+
+ var divDistance = document.createElement("div");
+ divDistance.id = this._addUID("GProuteResultsValueDist");
+ divDistance.innerHTML = distanceLabel;
+ containerDistance.appendChild(divDistance);
+
+ div.appendChild(containerDistance);
+
+ var containerDuration = document.createElement("div");
+ containerDuration.className = "GProuteResultsValue";
+
+ var labelDuration = document.createElement("label");
+ labelDuration.className = "GProuteResultsValueLabel";
+ labelDuration.innerHTML = "Durée :";
+ containerDuration.appendChild(labelDuration);
+
+ var divDuration = document.createElement("div");
+ divDuration.id = this._addUID("GProuteResultsValueDist");
+ divDuration.innerHTML = fconvert(duration);
+ containerDuration.appendChild(divDuration);
+
+ div.appendChild(containerDuration);
+
+ return div;
+ },
+
+ /**
+ * Create Show Results Details
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createRouteShowResultsDetailsElement : function () {
+ var input = document.createElement("input");
+ input.id = this._addUID("GProuteResultsShowDetails");
+ input.type = "checkbox";
+ return input;
+ },
+
+ /**
+ * Create Results Details
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createRouteResultsDetailsElement : function () {
+ //
+ var div = document.createElement("div");
+ div.id = this._addUID("GProuteResultsDetails");
+ return div;
+ },
+
+ /**
+ * Add Results Details
+ * (results dynamically generate !)
+ * @param {Object[]} instructions - instructions
+ * @param {Function} fconvert - fconvert
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _addRouteResultsDetailsElement : function (instructions, fconvert) {
+ // contexte
+ var context = this;
+
+ var div = document.getElementById(this._addUID("GProuteResultsDetails"));
+
+ // clean !
+ if (div.childElementCount) {
+ while (div.firstChild) {
+ div.removeChild(div.firstChild);
+ }
+ }
+
+ // calcul des valeurs cumulé !
+ var distanceCumul = 0;
+ var durationCumul = 0;
+
+ /* jshint -W083 */
+ for (var i = 0; i < instructions.length; i++) {
+ var id = i + 1;
+
+ var o = instructions[i];
+
+ var divNum = document.createElement("div");
+ divNum.className = "GProuteResultsDetailsNumber";
+ divNum.innerHTML = id + ".";
+ div.appendChild(divNum);
+
+ durationCumul += parseFloat(o.duration);
+ distanceCumul += parseFloat(o.distance);
+
+ var distance = 0;
+ var isCumulKm = parseInt(distanceCumul / 1000, 10);
+ if (!isCumulKm) {
+ distance = Math.round(distanceCumul) + " m";
+ } else {
+ var distanceArrondi = Math.round(distanceCumul);
+ distanceArrondi = distanceArrondi / 1000;
+ distance = distanceArrondi + " km";
+ }
+
+ var divIns = document.createElement("div");
+ divIns.className = "GProuteResultsDetailsInstruction";
+ divIns.id = this._addUID("GProuteResultsDetailsInstruction_" + id);
+ divIns.title = "distance : " + distance + " / " + "temps : " + fconvert(durationCumul);
+ divIns.innerHTML = o.instruction;
+
+ divIns.addEventListener("mouseover", function (e) {
+ context.onRouteResultsDetailsMouseOver(e);
+ });
+ divIns.addEventListener("mouseout", function (e) {
+ context.onRouteResultsDetailsMouseOut(e);
+ });
+ divIns.addEventListener("click", function (e) {
+ // mode mobile !
+ if (typeof context.onRouteResultsDetailsClick === "function") {
+ context.onRouteResultsDetailsClick(e);
+ }
+ });
+ div.appendChild(divIns);
+ }
+
+ return div;
+ },
+
+ // ################################################################### //
+ // ################### Methods to the form points #################### //
+ // ################# OVERWRITTEN BY LOCATIONSELECTOR ! ################# //
+
+ /**
+ * Create Point
+ * see event !
+ * OVERWRITTEN BY LOCATIONSELECTOR !
+ * (version initial without LOCATIONSELECTOR PLUGIN)
+ * @param {Integer} n - n
+ * @param {String} text - text
+ * @param {Boolean} visibility - visibility
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createRoutePanelFormPointElement : function (n, text, visibility) {
+ // contexte d'execution
+ var context = this;
+
+ var div = document.createElement("div");
+ div.id = "GProutePoint" + n;
+ div.className = (visibility) ? "GPflexInput GProuteStageFlexInput" : "GPflexInput GProuteStageFlexInputHidden";
+
+ var labelOrigin = document.createElement("label");
+ labelOrigin.id = "GProuteOriginLabel" + n;
+ labelOrigin.htmlFor = "GProuteOrigin" + n;
+ labelOrigin.innerHTML = text;
+ labelOrigin.addEventListener("click", function () {
+ var i = this.id.charAt(this.id.length - 1);
+ document.getElementById("GProuteOriginCoords" + i).value = "";
+ for (var j = 1; j < 8; j++) {
+ document.getElementById("GProutePoint" + j).style.display = "flex";
+ }
+ document.getElementById("GProuteForm").className = "";
+ document.getElementById("GProuteOriginPointer" + i).checked = false;
+ document.getElementById("GProuteOrigin" + i).className = "GProuteOriginVisible";
+ document.getElementById("GProuteOriginCoords" + i).className = "GProuteOriginHidden";
+ });
+ div.appendChild(labelOrigin);
+
+ var inputOrigin = document.createElement("input");
+ inputOrigin.id = "GProuteOrigin" + n;
+ inputOrigin.className = "GProuteOriginVisible";
+ inputOrigin.type = "text";
+ inputOrigin.placeholder = "Saisir une adresse";
+ inputOrigin.addEventListener("keyup", function (e) {
+ var charCode = e.which || e.keyCode;
+ if (charCode === 13 || charCode === 10) {
+ return;
+ }
+ var i = this.id.charAt(this.id.length - 1);
+ if (document.getElementById("GProuteOrigin" + i).value.length > 2) {
+ document.getElementById("GProuteAutoCompleteList" + i).style.display = "block";
+ } else {
+ document.getElementById("GProuteAutoCompleteList" + i).style.display = "none";
+ }
+ // gestionnaire d'evenement :
+ // on récupère la valeur de saisie pour une requête sur le service d'autocompletion.
+ // le resultat de la requête nous permet de recuperer les coordonnées du point...
+ context.onAutoCompleteSearchText(e);
+ });
+ inputOrigin.addEventListener("blur", function () {
+ var i = this.id.charAt(this.id.length - 1);
+ document.getElementById("GProuteAutoCompleteList" + i).style.display = "none";
+ });
+ div.appendChild(inputOrigin);
+
+ var inputOriginCoord = document.createElement("input");
+ inputOriginCoord.id = "GProuteOriginCoords" + n;
+ inputOriginCoord.className = "GProuteOriginHidden";
+ inputOriginCoord.type = "text";
+ inputOriginCoord.disabled = true;
+ div.appendChild(inputOriginCoord);
+
+ var inputOriginPointer = document.createElement("input");
+ inputOriginPointer.id = "GProuteOriginPointer" + n;
+ inputOriginPointer.type = "checkbox";
+ div.appendChild(inputOriginPointer);
+
+ var labelOriginPointer = document.createElement("label");
+ labelOriginPointer.id = "GProuteOriginPointerImg" + n;
+ labelOriginPointer.htmlFor = "GProuteOriginPointer" + n;
+ labelOriginPointer.className = "GProuteOriginPointerImg";
+ labelOriginPointer.title = "Pointer un lieu sur la carte";
+ labelOriginPointer.addEventListener("click", function (evt) {
+ evt.preventDefault();
+ evt.stopPropagation();
+ var i = this.id.charAt(this.id.length - 1);
+ var j;
+ for (j = 1; j < 8; j++) {
+ if (i !== j) {
+ document.getElementById("GProuteOriginPointer" + j).checked = false;
+ if (document.getElementById("GProuteOriginCoords" + j).value === "Pointer un lieu sur la carte") {
+ document.getElementById("GProuteOriginCoords" + j).value = "";
+ document.getElementById("GProuteOrigin" + j).className = "GProuteOriginVisible";
+ document.getElementById("GProuteOriginCoords" + j).className = "GProuteOriginHidden";
+ }
+ }
+ }
+ if (document.getElementById("GProuteOriginPointer" + i).checked) {
+ document.getElementById("GProuteOriginCoords" + i).value = "";
+ for (j = 1; j < 8; j++) {
+ document.getElementById("GProutePoint" + j).style.display = "flex";
+ }
+ document.getElementById("GProuteForm").className = "";
+ document.getElementById("GProuteOriginPointer" + i).checked = false;
+ document.getElementById("GProuteOrigin" + i).className = "GProuteOriginVisible";
+ document.getElementById("GProuteOriginCoords" + i).className = "GProuteOriginHidden";
+ } else {
+ document.getElementById("GProuteOriginCoords" + i).value = "Pointer un lieu sur la carte";
+ for (j = 1; j < 8; j++) {
+ if (i === j) {
+ document.getElementById("GProutePoint" + j).style.display = "flex";
+ } else {
+ document.getElementById("GProutePoint" + j).style.display = "none";
+ }
+ }
+ document.getElementById("GProuteForm").className = "GProuteFormMini";
+ document.getElementById("GProuteOriginPointer" + i).checked = true;
+ document.getElementById("GProuteOrigin" + i).className = "GProuteOriginHidden";
+ document.getElementById("GProuteOriginCoords" + i).className = "GProuteOriginVisible";
+ }
+ // gestionnaire d'evenement :
+ // on stocke la valeur du point, utilisée pour la requête sur le service de calcul d'itiniraire
+ context.onRouteMapPointClick(evt);
+ });
+ div.appendChild(labelOriginPointer);
+
+ return div;
+ },
+
+ /**
+ * Create Remove Point tag
+ * see event !
+ * OVERWRITTEN BY LOCATIONSELECTOR !
+ * (version initial without LOCATIONSELECTOR PLUGIN)
+ * @param {Integer} n - n
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createRoutePanelFormRemoveStageElement : function (n) {
+ // contexte d'execution
+ var context = this;
+
+ var divRm = document.createElement("div");
+ divRm.id = "GProuteStageRemove" + n;
+ divRm.className = "GProuteStageRemove";
+ divRm.title = "Supprimer l'étape";
+ if (n !== 1 && n !== 7) {
+ divRm.addEventListener("click", function (e) {
+ var i = this.id.charAt(this.id.length - 1);
+ document.getElementById("GProutePoint" + i).className = "GPflexInput GProuteStageFlexInputHidden";
+ document.getElementById("GProuteOrigin" + i).value = "";
+ document.getElementById("GProuteOrigin" + i).className = "GProuteOriginVisible";
+ document.getElementById("GProuteOriginCoords" + i).value = "";
+ document.getElementById("GProuteOriginCoords" + i).className = "GProuteOriginHidden";
+ document.getElementById("GProuteStageAdd").style.display = "";
+ // Moving up exclusions picto
+ // var exclusionsPictoTop = document.getElementById("GPshowRouteExclusionsPicto").style.top;
+ // document.getElementById("GPshowRouteExclusionsPicto").style.top = (parseInt(exclusionsPictoTop, 10) - 33).toString() + "px";
+ // gestionnaire d'evenement :
+ // on supprime le point, utilisé pour la requête sur le service d'itiniraire
+ context.onRouteRemovePointClick(e);
+ });
+ }
+ return divRm;
+ },
+
+ /**
+ * Create Add Point tag
+ * see event !
+ * OVERWRITTEN BY LOCATIONSELECTOR !
+ * (version initial without LOCATIONSELECTOR PLUGIN)
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createRoutePanelFormAddStageElement : function () {
+ // contexte d'execution
+ var context = this;
+
+ var divAdd = document.createElement("div");
+ divAdd.id = "GProuteStageAdd";
+ divAdd.title = "Ajouter une étape";
+ divAdd.addEventListener("click", function (e) {
+ var lastStage = 1;
+ var nbStages = 0;
+ for (var i = 2; i < 7; i++) {
+ if (document.getElementById("GProutePoint" + i).className === "GPflexInput GProuteStageFlexInputHidden") {
+ if (lastStage === 1) {
+ lastStage = i;
+ }
+ } else {
+ nbStages++;
+ }
+ }
+ if (lastStage < 7) {
+ document.getElementById("GProutePoint" + lastStage).className = "GPflexInput GProuteStageFlexInput";
+ // Moving down exclusions picto
+ // var exclusionsPictoTop = document.getElementById("GPshowRouteExclusionsPicto").style.top;
+ // document.getElementById("GPshowRouteExclusionsPicto").style.top = (parseInt(exclusionsPictoTop, 10) + 33).toString() + "px";
+ }
+ if (nbStages === 4) {
+ document.getElementById("GProuteStageAdd").style.display = "none";
+ }
+ // gestionnaire d'evenement :
+ // on ajoute le point, utilisé pour la requête sur le service d'itiniraire
+ context.onRouteAddPointClick(e);
+ });
+
+ return divAdd;
+ },
+
+ /**
+ * Create Results autocompletion to the point
+ * see event!
+ * OVERWRITTEN BY LOCATIONSELECTOR !
+ * (version initial without LOCATIONSELECTOR PLUGIN)
+ * @param {Integer} n - n
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createRoutePanelFormAutoCompleteListElement : function (n) {
+ // contexte d'execution
+ var context = this;
+
+ var div = document.createElement("div");
+ div.id = "GProuteAutoCompleteList" + n;
+ div.className = "GPadvancedAutoCompleteList";
+
+ if (div.addEventListener) {
+ div.addEventListener("click", function (e) {
+ context.onAutoCompletedResultsItemClick(e);
+ document.getElementById("GProuteAutoCompleteList" + n).style.display = "none";
+ }, false);
+ } else if (div.attachEvent) {
+ div.attachEvent("onclick", function (e) {
+ context.onAutoCompletedResultsItemClick(e);
+ document.getElementById("GProuteAutoCompleteList" + n).style.display = "none";
+ });
+ }
+
+ // Proposals are dynamically filled in Javascript by autocomplete service
+ //
...
+
+ return div;
+ },
+
+ /**
+ * Autocompletion result to a point.
+ * Proposals are dynamically filled in Javascript by autocomplete service
+ * OVERWRITTEN BY LOCATIONSELECTOR !
+ * (version initial without LOCATIONSELECTOR PLUGIN)
+ *
+ *
+ * @param {Object} location - suggested location results
+ * @param {Number} n - number of the point
+ * @param {Number} id - ID
+ */
+ _createRouteAutoCompletedLocationElement : function (location, n, id) {
+ var container = document.getElementById("GProuteAutoCompleteList" + n);
+
+ var div = document.createElement("div");
+ div.id = "AutoCompletedLocation" + id;
+ div.className = "GPautoCompleteProposal";
+ div.innerHTML = location.fullText;
+
+ container.appendChild(div);
+ },
+
+ // ################################################################### //
+ // ############## Methods to the choice mode into form ############### //
+ // ################################################################### //
+
+ /**
+ * Create Container to Mode choice transport
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createRoutePanelFormModeChoiceElement : function () {
+ var div = document.createElement("div");
+ div.id = this._addUID("GProuteModeChoice");
+
+ // div.appendChild(this._createRoutePanelFormModeChoiceTransportElement());
+ // div.appendChild(this._createRoutePanelFormModeChoiceComputeElement());
+
+ return div;
+ },
+
+ /**
+ * Create Mode choice transport
+ * see event !
+ * FIXME event not useful
+ * @param {String[]} transports - transports
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createRoutePanelFormModeChoiceTransportElement : function (transports) {
+ // contexte d'execution
+ var context = this;
+
+ var div = document.createElement("div");
+ div.id = this._addUID("GProuteTransportChoice");
+
+ var span = document.createElement("span");
+ span.className = "GProuteModeLabel";
+ span.innerHTML = "Mode de transport";
+ div.appendChild(span);
+
+ /* jshint -W083 */
+ for (var i = 0; i < transports.length; i++) {
+ var transport = transports[i];
+
+ if (transport === "Voiture") {
+ var inputCar = document.createElement("input");
+ inputCar.id = this._addUID("GProuteTransportCar");
+ inputCar.type = "radio";
+ inputCar.name = "GProuteTransport";
+ inputCar.value = "Voiture";
+ if (i === 0) {
+ inputCar.checked = true;
+ }
+ // gestionnaire d'evenement :
+ // on stocke le mode de transport,
+ // utilisation pour la requête sur le service de calcul d'itiniraire
+ if (inputCar.addEventListener) {
+ inputCar.addEventListener("change", function (e) {
+ context.onRouteModeTransportChange(e);
+ });
+ } else if (inputCar.attachEvent) {
+ inputCar.attachEvent("onchange", function (e) {
+ context.onRouteModeTransportChange(e);
+ });
+ }
+ div.appendChild(inputCar);
+
+ var labelCar = document.createElement("label");
+ labelCar.className = "GProuteTransportImg";
+ labelCar.htmlFor = this._addUID("GProuteTransportCar");
+ labelCar.title = "Voiture";
+ div.appendChild(labelCar);
+ }
+
+ if (transport === "Pieton") {
+ var inputPedestrian = document.createElement("input");
+ inputPedestrian.id = this._addUID("GProuteTransportPedestrian");
+ inputPedestrian.type = "radio";
+ inputPedestrian.name = "GProuteTransport";
+ inputPedestrian.value = "Pieton";
+ if (i === 0) {
+ inputPedestrian.checked = true;
+ }
+ // gestionnaire d'evenement :
+ // on stocke le mode de transport,
+ // utilisation pour la requête sur le service de calcul d'itiniraire
+ if (inputPedestrian.addEventListener) {
+ inputPedestrian.addEventListener("change", function (e) {
+ context.onRouteModeTransportChange(e);
+ });
+ } else if (inputPedestrian.attachEvent) {
+ inputPedestrian.attachEvent("onchange", function (e) {
+ context.onRouteModeTransportChange(e);
+ });
+ }
+ div.appendChild(inputPedestrian);
+
+ var labelPedestrian = document.createElement("label");
+ labelPedestrian.className = "GProuteTransportImg";
+ labelPedestrian.htmlFor = this._addUID("GProuteTransportPedestrian");
+ labelPedestrian.title = "Piéton";
+ div.appendChild(labelPedestrian);
+ }
+ }
+
+ return div;
+ },
+
+ /**
+ * Create Mode choice computation
+ * see event!
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createRoutePanelFormModeChoiceComputeElement : function () {
+ // contexte d'execution
+ var context = this;
+
+ var div = document.createElement("div");
+ div.id = this._addUID("GProuteComputationChoice");
+
+ var span = document.createElement("span");
+ span.className = "GProuteModeLabel";
+ span.innerHTML = "Mode de calcul";
+ div.appendChild(span);
+
+ var select = document.createElement("select");
+ select.id = this._addUID("GProuteComputationSelect");
+ select.className = "GPinputSelect";
+ // gestionnaire d'evenement :
+ // on stocke la valeur du mode de calcul,
+ // utilisation pour la requête sur le service de calcul d'itiniraire
+ select.addEventListener("change", function (e) {
+ context.onRouteModeComputationChange(e);
+ });
+
+ var computes = [{
+ code : "fastest",
+ label : "Plus rapide"
+ }, {
+ code : "shortest",
+ label : "Plus court"
+ }];
+
+ for (var i = 0; i < computes.length; i++) {
+ var option = document.createElement("option");
+ option.value = computes[i].code;
+ option.text = computes[i].label;
+ select.appendChild(option);
+ }
+ div.appendChild(select);
+
+ return div;
+ },
+
+ // ################################################################### //
+ // ################# Methods to the choice exclusions ################ //
+ // ################################################################### //
+
+ /**
+ * Hidden checkbox for minimizing/maximizing Exclusions Options
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createShowRouteExclusionsElement : function () {
+ var input = document.createElement("input");
+ input.id = this._addUID("GPshowRouteExclusions");
+ input.type = "checkbox";
+ return input;
+ },
+
+ /**
+ * Label to Exclusions Options
+ * see event !
+ * FIXME event not useful
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createShowRouteExclusionsPictoElement : function () {
+ // contexte d'execution
+ var context = this;
+
+ var label = document.createElement("label");
+ label.id = this._addUID("GPshowRouteExclusionsPicto");
+ label.className = "GPshowMoreOptionsImage GPshowMoreOptions GPshowRouteExclusionsPicto";
+ label.htmlFor = this._addUID("GPshowRouteExclusions");
+ label.title = "Exclusions";
+ // label.style.top = "185px";
+
+ // gestionnaire d'evenement :
+ // on ouvre le menu des options des exclusions
+ if (label.addEventListener) {
+ label.addEventListener("click", function (e) {
+ context.onShowRouteExclusionsClick(e);
+ });
+ } else if (label.attachEvent) {
+ label.attachEvent("onclick", function (e) {
+ context.onShowRouteExclusionsClick(e);
+ });
+ }
+
+ return label;
+ },
+
+ /**
+ * Create Container to Exclusions
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createRoutePanelFormExclusionsElement : function () {
+ var div = document.createElement("div");
+ div.id = this._addUID("GProuteExclusions");
+
+ var span = document.createElement("span");
+ span.className = "GProuteExclusionsLabel";
+ span.innerHTML = "Passages autorisés";
+ div.appendChild(span);
+
+ // div.appendChild(this._createRoutePanelFormExclusionOptionsElement());
+
+ return div;
+ },
+
+ /**
+ * Create Exclusions Options
+ * see event !
+ * FIXME event not useful
+ * @param {Object[]} exclusions - exclusions
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createRoutePanelFormExclusionOptionsElement : function (exclusions) {
+ // contexte d'execution
+ var context = this;
+
+ var div = document.createElement("div");
+ div.className = "GProuteExclusionsOptions";
+
+ /* jshint -W083 */
+ for (var value in exclusions) {
+ if (exclusions.hasOwnProperty(value)) {
+ var status = exclusions[value];
+ switch (value) {
+ case "toll":
+ var inputToll = document.createElement("input");
+ inputToll.id = this._addUID("GProuteExclusionsToll");
+ inputToll.type = "checkbox";
+ inputToll.value = "Toll";
+ inputToll.checked = !status;
+ // gestionnaire d'evenement :
+ // on stocke l'exclusion,
+ // utilisation pour la requête sur le service de calcul d'itiniraire
+ if (inputToll.addEventListener) {
+ inputToll.addEventListener("change", function (e) {
+ context.onRouteExclusionsChange(e);
+ });
+ } else if (inputToll.attachEvent) {
+ inputToll.attachEvent("onchange", function (e) {
+ context.onRouteExclusionsChange(e);
+ });
+ }
+ div.appendChild(inputToll);
+
+ var labelToll = document.createElement("label");
+ labelToll.className = "GProuteExclusionsOption";
+ labelToll.htmlFor = this._addUID("GProuteExclusionsToll");
+ labelToll.innerHTML = "Péages";
+ div.appendChild(labelToll);
+ break;
+
+ case "tunnel":
+ var inputTunnel = document.createElement("input");
+ inputTunnel.id = this._addUID("GProuteExclusionsTunnel");
+ inputTunnel.type = "checkbox";
+ inputTunnel.value = "Tunnel";
+ inputTunnel.checked = !status;
+ // gestionnaire d'evenement :
+ // on stocke l'exclusion,
+ // utilisation pour la requête sur le service de calcul d'itiniraire
+ if (inputTunnel.addEventListener) {
+ inputTunnel.addEventListener("change", function (e) {
+ context.onRouteExclusionsChange(e);
+ });
+ } else if (inputTunnel.attachEvent) {
+ inputTunnel.attachEvent("onchange", function (e) {
+ context.onRouteExclusionsChange(e);
+ });
+ }
+ div.appendChild(inputTunnel);
+
+ var labelTunnel = document.createElement("label");
+ labelTunnel.className = "GProuteExclusionsOption";
+ labelTunnel.htmlFor = this._addUID("GProuteExclusionsTunnel");
+ labelTunnel.innerHTML = "Tunnels";
+ div.appendChild(labelTunnel);
+ break;
+
+ case "bridge":
+ var inputBridge = document.createElement("input");
+ inputBridge.id = this._addUID("GProuteExclusionsBridge");
+ inputBridge.type = "checkbox";
+ inputBridge.value = "Bridge";
+ inputBridge.checked = !status;
+ // gestionnaire d'evenement :
+ // on stocke l'exclusion,
+ // utilisation pour la requête sur le service de calcul d'itiniraire
+ if (inputBridge.addEventListener) {
+ inputBridge.addEventListener("change", function (e) {
+ context.onRouteExclusionsChange(e);
+ });
+ } else if (inputBridge.attachEvent) {
+ inputBridge.attachEvent("onchange", function (e) {
+ context.onRouteExclusionsChange(e);
+ });
+ }
+ div.appendChild(inputBridge);
+
+ var labelBridge = document.createElement("label");
+ labelBridge.className = "GProuteExclusionsOption";
+ labelBridge.htmlFor = this._addUID("GProuteExclusionsBridge");
+ labelBridge.innerHTML = "Ponts";
+ div.appendChild(labelBridge);
+ break;
+ }
+ }
+ }
+
+ return div;
+ },
+
+ // ################################################################### //
+ // ############################### Submit Form ####################### //
+ // ################################################################### //
+
+ /**
+ * Create Submit Form Element
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createRouteSubmitFormElement : function () {
+ var input = document.createElement("input");
+ input.id = this._addUID("GProuteSubmit");
+ input.className = "GPinputSubmit";
+ input.type = "submit";
+ input.value = "Calculer";
+
+ return input;
+ },
+
+ // ################################################################### //
+ // ############################### Reset picto ####################### //
+ // ################################################################### //
+
+ /**
+ * Create Reset Picto Element
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createRouteFormResetElement : function () {
+ var self = this;
+
+ var divReset = document.createElement("div");
+ divReset.id = this._addUID("GProuteReset");
+ divReset.title = "Réinitialiser les paramètres";
+ divReset.addEventListener("click", function (e) {
+ self.onRouteResetClick(e);
+ });
+
+ return divReset;
+ }
+};
+
+export default RouteDOM;
diff --git a/src/Common-review/Controls/ScaleDOM.js b/src/Common-review/Controls/ScaleDOM.js
new file mode 100644
index 000000000..826eb2a8f
--- /dev/null
+++ b/src/Common-review/Controls/ScaleDOM.js
@@ -0,0 +1,26 @@
+var ScaleDOM = {
+
+ /**
+ * Add uuid to the tag ID
+ * @param {String} id - id selector
+ * @returns {String} uid - id selector with an unique id
+ */
+ _addUID : function (id) {
+ var uid = (this._uid) ? id + "-" + this._uid : id;
+ return uid;
+ },
+
+ /**
+ * Main container (DOM)
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createMainContainerElement : function () {
+ var container = document.createElement("div");
+ container.id = this._addUID("GPscaleContainer");
+ container.className = "GPwidget";
+ return container;
+ }
+};
+
+export default ScaleDOM;
diff --git a/src/Common-review/Controls/SearchEngineDOM.js b/src/Common-review/Controls/SearchEngineDOM.js
new file mode 100644
index 000000000..c9dfbb5b7
--- /dev/null
+++ b/src/Common-review/Controls/SearchEngineDOM.js
@@ -0,0 +1,747 @@
+import ID from "../Utils/SelectorID";
+
+var SearchEngineDOM = {
+
+ /**
+ * Add uuid to the tag ID
+ * @param {String} id - id selector
+ * @returns {String} uid - id selector with an unique id
+ */
+ _addUID : function (id) {
+ var uid = (this._uid) ? id + "-" + this._uid : id;
+ return uid;
+ },
+
+ /**
+ * Main container (DOM)
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createMainContainerElement : function () {
+ var container = document.createElement("div");
+ container.id = this._addUID("GPsearchEngine");
+ container.className = "GPwidget";
+ return container;
+ },
+
+ // ################################################################### //
+ // ################### Methods of main container ##################### //
+ // ################################################################### //
+
+ /**
+ * Hidden checkbox for minimizing/maximizing
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createShowSearchEngineElement : function () {
+ var input = document.createElement("input");
+ input.id = this._addUID("GPshowSearchEngine");
+ input.type = "checkbox";
+ return input;
+ },
+
+ /**
+ * Show search engine
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createShowSearchEnginePictoElement : function () {
+ // contexte d'execution
+ var self = this;
+
+ var label = document.createElement("label");
+ label.id = this._addUID("GPshowSearchEnginePicto");
+ label.className = "GPshowAdvancedToolPicto";
+ label.htmlFor = this._addUID("GPshowSearchEngine");
+ label.title = "Afficher/masquer la recherche par lieux";
+
+ // Close all results and panels when minimizing the widget
+ label.addEventListener("click", function () {
+ document.getElementById(self._addUID("GPautoCompleteList")).style.display = "none";
+ document.getElementById(self._addUID("GPgeocodeResultsList")).style.display = "none";
+ var showAdvancedSearch = document.getElementById(self._addUID("GPshowAdvancedSearch"));
+ if (showAdvancedSearch) {
+ showAdvancedSearch.style.display = null;
+ document.getElementById(self._addUID("GPadvancedSearchPanel")).style.display = "none";
+ }
+ var id = "#GPsearchInput-" + self._uid;
+ document.querySelector(id + " input").disabled = false; // FIXME form[id^=GPsearchInput] = #GPsearchInput ?
+ self.onShowSearchEngineClick();
+ });
+
+ var spanOpen = document.createElement("span");
+ spanOpen.id = this._addUID("GPshowSearchEngineOpen");
+ spanOpen.className = "GPshowAdvancedToolOpen";
+ label.appendChild(spanOpen);
+
+ return label;
+ },
+
+ /**
+ * Simple search input
+ * @param {String} placeholder - placeholder
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createSearchInputElement : function (placeholder) {
+ // contexte d'execution
+ var self = this;
+
+ var form = document.createElement("form");
+ form.id = this._addUID("GPsearchInput");
+ // Open geocode results panel when submitting the input
+ form.addEventListener("submit", function (e) {
+ e.preventDefault();
+ document.getElementById(self._addUID("GPgeocodeResultsList")).style.display = "block";
+ document.getElementById(self._addUID("GPautoCompleteList")).style.display = "none";
+ // cf. FIXME
+ // document.querySelector("#GPsearchInput input").blur ();
+
+ // gestionnaire d'evenement :
+ // on récupère la valeur de saisie pour requête sur le service de geocodage
+ self.onGeocodingSearchSubmit(e);
+ return false;
+ });
+
+ var input = document.createElement("input");
+ input.id = this._addUID("GPsearchInputText");
+ input.type = "text";
+ input.placeholder = placeholder;
+ input.autocomplete = "off";
+ // Manage autocomplete list appearance when filling the address input
+ input.addEventListener("keyup", function (e) {
+ var charCode = e.which || e.keyCode;
+ if (charCode === 13 || charCode === 10 || charCode === 38 || charCode === 40) {
+ return;
+ }
+ document.getElementById(self._addUID("GPgeocodeResultsList")).style.display = "none";
+ if (input.value.length > 2) {
+ document.getElementById(self._addUID("GPautoCompleteList")).style.display = "block";
+ } else {
+ document.getElementById(self._addUID("GPautoCompleteList")).style.display = "none";
+ }
+ // gestionnaire d'evenement :
+ // on récupère la valeur de saisie pour requête sur le service d'autocompletion
+ self.onAutoCompleteSearchText(e);
+ });
+
+ // FIXME ce code interfere avec le click sur la liste des suggested locations !
+ // input.addEventListener("blur", function(e) {
+ // document.getElementById(self._addUID("GPautoCompleteList")).style.display = "none";
+ // });
+
+ input.addEventListener("keydown", function (e) {
+ // FIXME
+ // l'action clavier 'enter (13)' lance le submit de la form !
+ // Ce comportement n'est pas souhaité car le submit execute un geocodage !
+ // Il faut donc trouver le moyen d'eviter le submit sur un return venant
+ // seulement d'une selection de suggestion...
+
+ var charCode = e.which || e.keyCode;
+
+ var container = document.getElementById(self._addUID("GPautocompleteResults"));
+
+ // si aucun container !?
+ if (!container) {
+ return;
+ }
+
+ var curr = container.getElementsByClassName("GPautoCompleteProposal current");
+ var list = container.getElementsByClassName("GPautoCompleteProposal");
+
+ // si aucune suggestion, on ne va pas plus loin !
+ var length = list.length;
+ if (!length) {
+ return;
+ }
+
+ var current = null;
+
+ // si aucun item courant, on prend le 1er !
+ if (!curr.length) {
+ current = list[0];
+ current.className = "GPautoCompleteProposal current";
+ current.style.color = "#000000";
+ current.style["background-color"] = "#CEDBEF";
+ return;
+ } else {
+ current = curr[0];
+ }
+
+ var index = parseInt(ID.index(current.id), 10);
+ var next = (index === length - 1) ? list[0] : list[index + 1];
+ var prev = (index === 0) ? list[length - 1] : list[index - 1];
+
+ current.style["background-color"] = "";
+ current.style.color = "";
+ prev.style["background-color"] = "";
+ prev.style.color = "";
+ next.style["background-color"] = "";
+ next.style.color = "";
+
+ switch (charCode) {
+ case 38: // arrow up
+ current.className = "GPautoCompleteProposal";
+ prev.className = "GPautoCompleteProposal current";
+ prev.style.color = "#000000";
+ prev.style["background-color"] = "#CEDBEF";
+ break;
+ case 40: // arrow down
+ current.className = "GPautoCompleteProposal";
+ next.className = "GPautoCompleteProposal current";
+ next.style.color = "#000000";
+ next.style["background-color"] = "#CEDBEF";
+ break;
+ case 13: // enter
+ // cf. FIXME
+ e.preventDefault();
+ current.click(e);
+ break;
+ }
+
+ current.focus();
+ });
+
+ form.appendChild(input);
+
+ var div = document.createElement("div");
+ div.id = this._addUID("GPsearchInputReset");
+ // Reset input
+ div.addEventListener("click", function () {
+ document.getElementById(self._addUID("GPsearchInputText")).value = "";
+ document.getElementById(self._addUID("GPautoCompleteList")).style.display = "none";
+ document.getElementById(self._addUID("GPgeocodeResultsList")).style.display = "none";
+ self.onSearchResetClick();
+ });
+ form.appendChild(div);
+
+ return form;
+ },
+
+ /**
+ * Show advanced search panel
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createShowAdvancedSearchElement : function () {
+ // contexte d'execution
+ var self = this;
+
+ var div = document.createElement("div");
+ div.id = this._addUID("GPshowAdvancedSearch");
+ div.className = "GPshowAdvancedToolPicto";
+ div.title = "Ouvrir la recherche avancée";
+
+ // Open advanced search
+ div.addEventListener("click", function () {
+ var id = "#GPsearchInput-" + self._uid;
+ document.querySelector(id + " input").disabled = true;
+ document.getElementById(self._addUID("GPautoCompleteList")).style.display = "none";
+ document.getElementById(self._addUID("GPgeocodeResultsList")).style.display = "none";
+ document.getElementById(self._addUID("GPshowAdvancedSearch")).style.display = "none";
+ document.getElementById(self._addUID("GPadvancedSearchPanel")).style.display = "inline-block";
+ });
+
+ var span = document.createElement("span");
+ span.id = this._addUID("GPshowAdvancedSearchOpen");
+ span.className = "GPshowAdvancedToolOpen";
+ div.appendChild(span);
+
+ return div;
+ },
+
+ /**
+ * Advanced search panel
+ *
+ * FIXME
+ * don't call this._createAdvancedSearchPanelHeaderElement
+ * don't call this._createAdvancedSearchPanelFormElement
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createAdvancedSearchPanelElement : function () {
+ var div = document.createElement("div");
+ div.id = this._addUID("GPadvancedSearchPanel");
+ div.className = "GPpanel";
+ div.style.display = "none";
+
+ // FIXME on decompose la fonction pour les besoins du controle,
+ // on ajoutera ces childs à la main...
+ // div.appendChild(this._createAdvancedSearchPanelHeaderElement ());
+ // div.appendChild(this._createAdvancedSearchPanelFormElement ());
+
+ return div;
+ },
+
+ /**
+ * Geocoding results
+ *
+ * FIXME
+ * don't call this._createGeocodeResultsListElement
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createGeocodeResultsElement : function () {
+ var div = document.createElement("div");
+ div.id = this._addUID("GPgeocodeResultsList");
+ div.className = "GPpanel";
+ div.style.display = "none";
+
+ div.appendChild(this._createGeocodeResultsHeaderElement());
+
+ // FIXME on decompose la fonction pour les besoins du controle,
+ // on ajoutera ces childs à la main...
+ // div.appendChild(this._createGeocodeResultsListElement ());
+
+ return div;
+ },
+
+ /**
+ * Autocompletion results
+ *
+ * FIXME
+ * don't call this._createAutoCompleteListElement
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createAutoCompleteElement : function () {
+ var div = document.createElement("div");
+ div.id = this._addUID("GPautoCompleteList");
+ div.className = "GPautoCompleteList"; // GPpanel ?
+ div.style.display = "none";
+
+ // FIXME on decompose la fonction pour les besoins du controle,
+ // on ajoutera ces childs à la main...
+ // div.appendChild(this._createAutoCompleteListElement ());
+
+ return div;
+ },
+
+ // ################################################################### //
+ // ################### Autocompletion container ###################### //
+ // ################################################################### //
+
+ /**
+ * Autocompletion results list.
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createAutoCompleteListElement : function () {
+ // contexte d'execution
+ var self = this;
+
+ var container = document.createElement("div");
+ container.id = this._addUID("GPautocompleteResults");
+
+ if (container.addEventListener) {
+ container.addEventListener("click", function (e) {
+ self.onAutoCompletedResultsItemClick(e);
+ document.getElementById(self._addUID("GPautoCompleteList")).style.display = "none";
+ }, false);
+ } else if (container.attachEvent) {
+ container.attachEvent("onclick", function (e) {
+ self.onAutoCompletedResultsItemClick(e);
+ document.getElementById(self._addUID("GPautoCompleteList")).style.display = "none";
+ });
+ }
+
+ // Proposals are dynamically filled in Javascript by autocomplete service
+ //
...
+
+ return container;
+ },
+
+ /**
+ * Autocompletion result.
+ * Proposals are dynamically filled in Javascript by autocomplete service
+ *
+ * TODO formaliser le contenu des reponse
+ *
+ * @param {Object} location - suggested or geocoded location results
+ * @param {Number} id - ID
+ */
+ _createAutoCompletedLocationElement : function (location, id) {
+ var container = document.getElementById(this._addUID("GPautocompleteResults"));
+
+ var div = document.createElement("div");
+ div.id = this._addUID("AutoCompletedLocation_" + id);
+ div.className = "GPautoCompleteProposal";
+ div.innerHTML = location.fullText;
+ if (div.addEventListener) {
+ div.addEventListener("click", function (e) {
+ container.click(e);
+ }, false);
+ } else if (div.attachEvent) {
+ div.attachEvent("onclick", function (e) {
+ container.click(e);
+ });
+ }
+
+ container.appendChild(div);
+ },
+
+ // ################################################################### //
+ // ############### Geocoding with advanced container ################# //
+ // ################################################################### //
+
+ /**
+ * @returns {DOMElement} DOM element
+ */
+ _createAdvancedSearchPanelHeaderElement : function () {
+ // contexte d'execution
+ var self = this;
+
+ var container = document.createElement("div");
+ container.className = "GPpanelHeader";
+
+ var divTitle = document.createElement("div");
+ divTitle.className = "GPpanelTitle";
+ divTitle.innerHTML = "Recherche avancée";
+ container.appendChild(divTitle);
+
+ var divClose = document.createElement("div");
+ divClose.id = this._addUID("GPadvancedSearchClose");
+ divClose.className = "GPpanelClose";
+ divClose.title = "Fermer la recherche avancée";
+
+ if (divClose.addEventListener) {
+ divClose.addEventListener("click", function () {
+ var id = "#GPsearchInput-" + self._uid;
+ document.querySelector(id + " input").disabled = false;
+ document.getElementById(self._addUID("GPgeocodeResultsList")).style.display = "none";
+ document.getElementById(self._addUID("GPshowAdvancedSearch")).style.display = "inline-block";
+ document.getElementById(self._addUID("GPadvancedSearchPanel")).style.display = "none";
+ }, false);
+ } else if (divClose.attachEvent) {
+ divClose.attachEvent("onclick", function () {
+ var id = "#GPsearchInput-" + self._uid;
+ document.querySelector(id + " input").disabled = false;
+ document.getElementById(self._addUID("GPgeocodeResultsList")).style.display = "none";
+ document.getElementById(self._addUID("GPshowAdvancedSearch")).style.display = "inline-block";
+ document.getElementById(self._addUID("GPadvancedSearchPanel")).style.display = "none";
+ });
+ }
+
+ container.appendChild(divClose);
+
+ return container;
+ },
+
+ /**
+ * @param {Object[]} advancedSearchCodes - codes
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createAdvancedSearchPanelFormElement : function (advancedSearchCodes) {
+ // contexte d'execution
+ var self = this;
+
+ var form = document.createElement("form");
+ form.id = this._addUID("GPadvancedSearchForm");
+ form.addEventListener("submit", function (e) {
+ e.preventDefault();
+ // data
+ var data = [];
+ // liste des attributs de la ressource de geocodage
+ var id = "#GPadvancedSearchFilters-" + self._uid;
+ var matchesFilters = document.querySelectorAll(id + " > div > div > input");
+ for (var i = 0; i < matchesFilters.length; i++) {
+ var element = matchesFilters[i];
+ data.push({
+ key : element.name,
+ value : element.value
+ });
+ }
+
+ // gestionnaire d'evenement :
+ // on récupère les valeurs de saisies pour requête sur le service de geocodage
+ self.onGeocodingAdvancedSearchSubmit(e, data);
+ document.getElementById(self._addUID("GPgeocodeResultsList")).style.display = "block";
+
+ return false;
+ });
+
+ var div = document.createElement("div");
+ div.className = "GPflexInput";
+
+ var label = document.createElement("label");
+ label.className = "GPadvancedSearchCodeLabel";
+ label.innerHTML = "Recherche par";
+ div.appendChild(label);
+
+ var select = this._createAdvancedSearchFormCodeElement(advancedSearchCodes);
+ div.appendChild(select);
+
+ // FIXME on decompose la fonction pour les besoins du controle,
+ // on ajoutera ces childs à la main...
+
+ // var filters = this._createAdvancedSearchFormFiltersElement ();
+ // form.appendChild(filters);
+
+ // var input = this._createAdvancedSearchFormInputElement ();
+ // form.appendChild(input);
+
+ form.appendChild(div);
+
+ return form;
+ },
+
+ /**
+ * @param {Object[]} codes - codes
+ * @returns {DOMElement} DOM element
+ */
+ _createAdvancedSearchFormCodeElement : function (codes) {
+ // contexte d'execution
+ var self = this;
+
+ var select = document.createElement("select");
+ select.id = this._addUID("GPadvancedSearchCode");
+ select.className = "GPadvancedSearchCode";
+ select.addEventListener("change", function (e) {
+ // var idx = e.target.selectedIndex;
+ // var value = e.target.options[idx].value;
+ // gestionnaire d'evenement :
+ // permet de recuperer des informations diverses...
+ self.onGeocodingAdvancedSearchCodeChange(e);
+ }, false);
+
+ // liste statique au cas où des codes n'ont pas été passés en entrée
+ if (!codes) {
+ codes = [{
+ id : "PositionOfInterest",
+ title : "Lieux/toponymes"
+ }, {
+ id : "StreetAddress",
+ title : "Adresses"
+ }, {
+ id : "CadastralParcel",
+ title : "Parcelles cadastrales"
+ }, {
+ id : "Administratif",
+ title : "Administratif"
+ }];
+ }
+
+ for (var i = 0; i < codes.length; i++) {
+ var option = document.createElement("option");
+ option.value = codes[i].id;
+ option.text = codes[i].title;
+ select.appendChild(option);
+ }
+
+ return select;
+ },
+
+ /**
+ * @returns {DOMElement} DOM element
+ */
+ _createAdvancedSearchFormInputElement : function () {
+ var input = document.createElement("input");
+ input.type = "submit";
+ input.id = this._addUID("GPadvancedSearchSubmit");
+ input.className = "GPinputSubmit";
+ input.value = "Chercher";
+
+ return input;
+ },
+
+ /**
+ * Filters geocoding.
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createAdvancedSearchFormFiltersElement : function () {
+ var container = document.createElement("div");
+ container.id = this._addUID("GPadvancedSearchFilters");
+ return container;
+ },
+
+ /**
+ * Create filter container for resources :
+ * "PositionOfInterest", "StreetAddress", ...
+ *
+ * @param {String} code - code of geocoding resource
+ * @param {Boolean} display - display
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createAdvancedSearchFiltersTableElement : function (code, display) {
+ var container = document.createElement("div");
+ container.id = this._addUID(code);
+ if (!display) {
+ container.style.display = "none";
+ }
+
+ return container;
+ },
+
+ /**
+ * Create filter attribut for a resource :
+ * "PositionOfInterest", "StreetAddress", ...
+ * Research filters are filled in Javascript depending on developer choice
+ *
+ * @param {Object} filterAttributes - filter attributes :
+ * @param {String} filterAttributes.code - code of geocoding resource
+ * @param {String} filterAttributes.name - ID
+ * @param {String} filterAttributes.title - label
+ * @param {String} filterAttributes.description - description
+ * @param {String} filterAttributes.value - value
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createAdvancedSearchFiltersAttributElement : function (filterAttributes) {
+ // INFORMATION
+ // cette methode peut être appelée si le document n'existe pas, elle
+ // permet ainsi de creer une div sans insertion dans le container...
+
+ var container = null;
+ var name = filterAttributes.name;
+ var title = filterAttributes.title;
+ var description = filterAttributes.description;
+ var code = filterAttributes.code;
+ var value = filterAttributes.value;
+
+ var div = document.createElement("div");
+ div.className = "GPflexInput";
+
+ var label = document.createElement("label");
+ label.className = "GPadvancedSearchFilterLabel";
+ label.htmlFor = name;
+ label.title = description || title;
+ label.innerHTML = title;
+ div.appendChild(label);
+
+ var input = document.createElement("input");
+ input.id = name;
+ input.className = "GPadvancedSearchFilterInput";
+ input.type = "text";
+ input.name = name;
+ if (value) {
+ input.value = value;
+ }
+ div.appendChild(input);
+
+ container = document.getElementById(this._addUID(code));
+
+ if (container) {
+ container.appendChild(div);
+ } else {
+ // le container, c'est la div !
+ container = div;
+ }
+
+ return container;
+ },
+
+ // ################################################################### //
+ // ################## Geocoding results container #################### //
+ // ################################################################### //
+
+ /**
+ * @returns {DOMElement} DOM element
+ */
+ _createGeocodeResultsHeaderElement : function () {
+ var self = this;
+
+ var container = document.createElement("div");
+ container.className = "GPpanelHeader";
+
+ var divTitle = document.createElement("div");
+ divTitle.className = "GPpanelTitle";
+ divTitle.innerHTML = "Résultats de la recherche";
+ container.appendChild(divTitle);
+
+ var divClose = document.createElement("div");
+ divClose.id = this._addUID("GPgeocodeResultsClose");
+ divClose.className = "GPpanelClose";
+ divClose.title = "Fermer la fenêtre de résultats";
+
+ if (divClose.addEventListener) {
+ divClose.addEventListener("click", function () {
+ document.getElementById(self._addUID("GPgeocodeResultsList")).style.display = "none";
+ }, false);
+ } else if (divClose.attachEvent) {
+ divClose.attachEvent("onclick", function () {
+ document.getElementById(self._addUID("GPgeocodeResultsList")).style.display = "none";
+ });
+ }
+ container.appendChild(divClose);
+
+ return container;
+ },
+
+ /**
+ * Geocoding results list.
+ *
+ * @returns {DOMElement} DOM element
+ */
+ _createGeocodeResultsListElement : function () {
+ // contexte d'execution
+ var self = this;
+
+ var container = document.createElement("div");
+ container.id = this._addUID("GPgeocodeResults");
+
+ if (container.addEventListener) {
+ container.addEventListener("click", function (e) {
+ if (!e.ctrlKey) {
+ document.getElementById(self._addUID("GPgeocodeResultsList")).style.display = "none";
+ }
+ self.onGeocodedResultsItemClick(e);
+ }, false);
+ } else if (container.attachEvent) {
+ container.attachEvent("onclick", function (e) {
+ if (!e.ctrlKey) {
+ document.getElementById(self._addUID("GPgeocodeResultsList")).style.display = "none";
+ }
+ self.onGeocodedResultsItemClick(e);
+ });
+ }
+ // Results are dynamically filled in Javascript by geocoding service
+ //
...
+
+ return container;
+ },
+
+ /**
+ * Geocoding result.
+ * Results are dynamically filled in Javascript by geocoding service
+ *
+ * TODO formaliser le contenu des reponses
+ * FIXME formater la reponse en amont !
+ *
+ * @param {Object} location - suggested or geocoded location results
+ * @param {Number} id - ID
+ */
+ _createGeocodedLocationElement : function (location, id) {
+ var container = document.getElementById(this._addUID("GPgeocodeResults"));
+
+ var div = document.createElement("div");
+ div.id = this._addUID("GeocodedLocation_" + id);
+ div.className = "GPautoCompleteProposal";
+
+ if (typeof location === "string") {
+ div.innerHTML = location;
+ } else {
+ var places = location.placeAttributes;
+
+ if (places.freeform) {
+ // reponse en freeForm
+ div.innerHTML = places.freeform;
+ } else if (places.postalCode) {
+ // cas des StreetAddress, PositionOfInterest, Administratif
+ // on affiche uniquement ce qui est commun aux ressources ...
+ div.innerHTML = places.postalCode + " " + places.commune;
+ } else if (places.cadastralParcel) {
+ // cas des CadastralParcel
+ div.innerHTML = places.cadastralParcel;
+ } else {
+ div.innerHTML = "...";
+ }
+ }
+
+ container.appendChild(div);
+ }
+};
+
+export default SearchEngineDOM;
diff --git a/src/Common-review/Styles.js b/src/Common-review/Styles.js
new file mode 100644
index 000000000..ad280fa0f
--- /dev/null
+++ b/src/Common-review/Styles.js
@@ -0,0 +1,17 @@
+import "./CSS/GPboostRelief.css";
+import "./CSS/GPdrawing.css";
+import "./CSS/GPelevationPath.css";
+import "./CSS/GPgeneralWidget.css";
+import "./CSS/GPgetFeatureInfo.css";
+import "./CSS/GPisochron.css";
+import "./CSS/GPlayerSwitcher.css";
+import "./CSS/GPlocation.css";
+import "./CSS/GPmeasureArea.css";
+import "./CSS/GPmeasureAzimuth.css";
+import "./CSS/GPmeasureLength.css";
+import "./CSS/GPmeasureToolTip.css";
+import "./CSS/GPmousePosition.css";
+import "./CSS/GPreverseGeocoding.css";
+import "./CSS/GProute.css";
+import "./CSS/GPsearchEngine.css";
+import "./CSS/GPwaiting.css";
diff --git a/src/Common-review/Utils.js b/src/Common-review/Utils.js
new file mode 100644
index 000000000..a303fb92c
--- /dev/null
+++ b/src/Common-review/Utils.js
@@ -0,0 +1,98 @@
+/**
+* @module Utils
+* @alias Gp.olUtils
+* @description
+* ...
+*
+* @example
+* detectSupport();
+* assign();
+* mergeParams();
+*/
+var Utils = {
+
+ /**
+ * this method is called by the constructor.
+ * this information is useful to switch to touch mode.
+ * Detection : test for desktop or tactile
+ *
+ * @returns {Boolean} isDesktop - true for desktop userAgent, false for mobile
+ */
+ detectSupport : function () {
+ var isDesktop = true;
+ var userAgent = window.navigator.userAgent.toLowerCase();
+
+ if (userAgent.indexOf("iphone") !== -1 ||
+ userAgent.indexOf("ipod") !== -1 ||
+ userAgent.indexOf("ipad") !== -1 ||
+ userAgent.indexOf("android") !== -1 ||
+ userAgent.indexOf("mobile") !== -1 ||
+ userAgent.indexOf("blackberry") !== -1 ||
+ userAgent.indexOf("tablet") !== -1 ||
+ userAgent.indexOf("phone") !== -1 ||
+ userAgent.indexOf("touch") !== -1) {
+ isDesktop = false;
+ }
+
+ if (userAgent.indexOf("msie") !== -1 ||
+ userAgent.indexOf("trident") !== -1) {
+ isDesktop = true;
+ }
+
+ return isDesktop;
+ },
+
+ /**
+ * Copies all source object members to dest
+ *
+ * @param {Object} dest - destination object where properties and method will be copied
+ * @param {Object} source - source object from which properties and method will be copied
+ * @returns {Object} dest
+ */
+ assign : function (dest, source) {
+ dest = dest || {};
+ for (var prop in source) {
+ if (source.hasOwnProperty(prop)) {
+ dest[prop] = source[prop];
+ }
+ }
+ return dest;
+ },
+
+ /**
+ * Merge two objects parameters (deeper than assign)
+ *
+ * @param {Object} dest - destination object where properties and method will be merge
+ * @param {Object} source - source object from which properties and method will be merge
+ * @param {Boolean} replace - replace destination value by source if exists or not (true by default)
+ */
+ mergeParams : function (dest, source, replace) {
+ if (!dest || !source) {
+ return;
+ }
+ if (typeof replace === "undefined") {
+ replace = true;
+ }
+ for (var param in source) {
+ if (source.hasOwnProperty(param)) {
+ if (typeof source[param] === "object") {
+ if (dest.hasOwnProperty(param)) {
+ this.mergeParams(dest[param], source[param], replace);
+ } else {
+ dest[param] = source[param];
+ }
+ } else {
+ if (dest.hasOwnProperty(param)) {
+ if (replace) {
+ dest[param] = source[param];
+ }
+ } else {
+ dest[param] = source[param];
+ }
+ }
+ }
+ }
+ }
+};
+
+export default Utils;
diff --git a/src/Common-review/Utils/AutoLoadConfig.js b/src/Common-review/Utils/AutoLoadConfig.js
new file mode 100644
index 000000000..36122b19b
--- /dev/null
+++ b/src/Common-review/Utils/AutoLoadConfig.js
@@ -0,0 +1,58 @@
+import Gp from "geoportal-access-lib";
+
+(function () {
+ var scripts = document.getElementsByTagName("script");
+
+ var key = scripts[scripts.length - 1].getAttribute("data-key");
+ // in case of several keys
+ if (key) {
+ var splitKeys = key.split(/;|,|\|/);
+ if (key && splitKeys.length > 1) {
+ var keys = [];
+ for (var i = 0; i < splitKeys.length; i++) {
+ keys.push(splitKeys[i]);
+ }
+ key = keys;
+ }
+ }
+ var url = scripts[scripts.length - 1].getAttribute("data-url");
+ var timeout = scripts[scripts.length - 1].getAttribute("data-timeout");
+
+ // callback
+ var success = function () {
+ // Pas de messages en mode prod
+ // console.log("GetConfig success!");
+ };
+
+ // callback
+ var error = function (e) {
+ throw new Error("Configuration load failed : " + e.message);
+ };
+
+ if (!key && !url) {
+ // pas de message d'information !
+ // console.log("WARNING : parameters missing 'data-key' and 'data-url', the loading of configuration can not be done !");
+ return;
+ }
+
+ var options = {
+ apiKey : key,
+ onSuccess : success,
+ onFailure : error
+ };
+
+ if (url) {
+ options.serverUrl = url;
+ options.callbackSuffix = "";
+ }
+
+ if (timeout) {
+ options.timeOut = timeout;
+ }
+
+ // test d'existance de la varibale globale Gp.Config
+ if (!Gp.Config) {
+ // appel du service
+ Gp.Services.getConfig(options);
+ }
+})();
diff --git a/src/Common-review/Utils/CheckRightManagement.js b/src/Common-review/Utils/CheckRightManagement.js
new file mode 100644
index 000000000..e6c2a1b16
--- /dev/null
+++ b/src/Common-review/Utils/CheckRightManagement.js
@@ -0,0 +1,172 @@
+import Logger from "../../Common/Utils/LoggerByDefault";
+import Config from "./Config";
+
+export default {
+ /**
+ * Contrôle des droits sur les ressources.
+ *
+ * @param {Object} options - liste des options
+ * @param {String} options.key - clef API
+ * @param {Array} options.resources - liste des ressources
+ * @param {Array} options.services - liste des services
+ * @returns {Object} rightManagement - undefined ou {
+ * key : "",
+ * service-1 : [resource-1, resource-2],
+ * service-2 : [resource-1, resource-2]
+ * }
+ */
+ check : function (options) {
+ // logger
+
+ var logger = Logger.getLogger("checkrightmanagement");
+
+ // si aucune option n'est renseignée...
+ if (!options) {
+ // message orienté pour le developpeur !
+ logger.error("WARNING : " +
+ "no parameter specified !");
+ return;
+ }
+
+ // les options
+ var _key = options.key;
+ var _resources = options.resources || [];
+ var _services = options.services || [];
+
+ // si aucune information sur les ressources,
+ // il est impossible de controler quelquechose !!!
+ if (!_resources || _resources.length === 0) {
+ // message orienté pour le developpeur !
+ logger.error("WARNING : " +
+ "no parameter 'resources' specified !");
+ return;
+ }
+
+ // si aucune information sur les services,
+ // il est impossible de controler quelquechose !!!
+ if (!_services || _services.length === 0) {
+ // message orienté pour le developpeur !
+ logger.error("WARNING : " +
+ "no parameter 'services' specified !");
+ return;
+ }
+
+ // les ressources controlées :
+ // Ex.
+ // {
+ // "Itineraire" : ["Pieton", "Voiture"],
+ // "Geocode" : ["PositionOfInterest", "StreetAddress", "CadastralParcel", "Administratif"],
+ // "AutoCompletion" : ["PositionOfInterest", "StreetAddress", "CadastralParcel", "Administratif"],
+ // "Elevation" : ["SERVICE_CALCUL_ALTIMETRIQUE_RSC"]
+ // }
+ var _rightManagement = {};
+
+ // la clef API n'est pas renseignée
+ if (!_key) {
+ // on verifie si l'autoconfiguration est disponible
+
+ if (!Config.isConfigLoaded()) {
+ // si l'autoconfiguration n'est pas chargée,
+ // aucune vérification des droits est possible...
+
+ logger.warn("WARNING : " +
+ "The 'apiKey' parameter is missing, " +
+ "and the contract key configuration has not been loaded, " +
+ "so impossible to check yours rights !");
+
+ return;
+ } else {
+ // si l'autoconfiguration est chargée,
+ // on recupere la clef API, et on en profitera ensuite pour controler
+ // les droits sur les ressources.
+
+ // FIXME par defaut, on recupere toujours la première...
+ _key = Object.keys(Config.configuration.generalOptions.apiKeys)[0];
+ logger.log(_key);
+ }
+ }
+
+ // la clef API est renseignée ou recuperée de l'autoconfiguration
+ if (_key) {
+ // on verifie si l'autoconfiguration est disponible
+
+ if (!Config.isConfigLoaded()) {
+ // si l'autoconfiguration n'est pas chargée,
+ // il est toujours possible de requeter le service avec une clef API,
+ // mais les droits sur les ressources ne sont pas garantis, on risque
+ // d'obtenir des erreurs 403 forbidden...
+ // la responsabilité revient à l'utilisateur (message d'information)...
+
+ logger.warn("WARNING : " +
+ "the contract key configuration has not been loaded, " +
+ "so be carefull !");
+
+ // les ressouces non controlées
+ var _noRightManagement = {};
+
+ for (var i = 0; i < _services.length; i++) {
+ var service = _services[i];
+ _noRightManagement[service] = [];
+
+ for (var j = 0; j < _resources.length; j++) {
+ var resource = _resources[j];
+ _noRightManagement[service].push(resource);
+ }
+ }
+
+ // on ajoute la clef
+ _noRightManagement.key = _key;
+
+ logger.log("right management not checked", _noRightManagement);
+
+ return _noRightManagement;
+ } else {
+ // si l'autoconf est chargée,
+ // on verifie la correspondance entre la clef et l'autoconfiguration,
+ // on previent l'utilisateur (message d'information) s'il n'a
+ // pas de droits sur certaines ressources ...
+
+ // doit on ecarter les ressources sans droit ?
+ // oui, si possible avec un message d'information pour l'utilisateur...
+
+ for (var k = 0; k < _resources.length; k++) {
+ var _resource = _resources[k];
+
+ for (var l = 0; l < _services.length; l++) {
+ var _service = _services[l];
+
+ var params = Config.getServiceParams(_resource, _service, _key);
+ if (!params || Object.keys(params).length === 0) {
+ logger.warn("WARNING : " +
+ "The contract key configuration has no rights to load this geoportal " +
+ "resource (" + _resource + ") " +
+ "for this service (" + _service + ") ");
+ continue;
+ }
+
+ if (!_rightManagement[_service]) {
+ _rightManagement[_service] = [];
+ }
+
+ _rightManagement[_service].push(_resource);
+ }
+ }
+
+ if (!_rightManagement || Object.keys(_rightManagement).length === 0) {
+ logger.warn("WARNING : " +
+ "The contract key configuration has been loaded, " +
+ "and the 'apiKey' parameter has been set, " +
+ "but, there is a problem on the mapping between the contract and the key !");
+ return;
+ }
+
+ // on ajoute la clef
+ _rightManagement.key = _key;
+
+ logger.log("right management checked", _rightManagement);
+
+ return _rightManagement;
+ }
+ }
+ }
+};
diff --git a/src/Common-review/Utils/ColorUtils.js b/src/Common-review/Utils/ColorUtils.js
new file mode 100644
index 000000000..3b51b62c2
--- /dev/null
+++ b/src/Common-review/Utils/ColorUtils.js
@@ -0,0 +1,75 @@
+/**
+* @module ColorUtils
+* @alias Gp.ColorUtils
+* @description
+* ...
+*
+* @example
+* rgbaToHex();
+* hexToRgba();
+*/
+var ColorUtils = {
+ /**
+ * Converts rgba String to #RRGGBBAA
+ * (Code adapted from : https://gist.github.com/mstssk/afda4ce9e5c335fd79cd)
+ *
+ * @param {String} rgba - A color of RGB or RGBA format.
+ * @returns {Object} hex and opacity formated values
+ */
+ rgbaToHex : function (rgba) {
+ // number to hex conversion
+ function hex (number) {
+ if (number > 255) {
+ throw new Error("'" + number + "'' is greater than 255(0xff);");
+ }
+ var str = Number(number).toString(16);
+ return ("0" + str).slice(-2);
+ }
+ var regex = /rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(0?.?\d+)\s*)?\)/;
+ var parsed = regex.exec(rgba);
+ if (!parsed) {
+ throw new Error("Invalid format: " + rgba);
+ }
+ var red = parsed[1];
+ var green = parsed[2];
+ var blue = parsed[3];
+ var alpha = parsed[4];
+ var elems = [hex(red), hex(green), hex(blue)];
+ var result = {};
+ result.hex = "#" + elems.join("");
+ if (alpha) {
+ // elems.push(hex(alpha));
+ result.opacity = parseFloat(alpha);
+ }
+ return result;
+ },
+
+ /**
+ * Converts hex color and opacity value to rgba String.
+ * (Code adapted from : http://stackoverflow.com/a/5624139)
+ * @param {String} hex - A color value on RGB format (hexa).
+ * @param {Number} opacity - A opacity value.
+ * @returns {String} A color of RGB or RGBA format
+ */
+ hexToRgba : function (hex, opacity) {
+ // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
+ var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
+ if (!hex) {
+ throw new Error("Invalid format");
+ }
+ hex = hex.replace(shorthandRegex, function (m, r, g, b) {
+ return r + r + g + g + b + b;
+ });
+
+ var rgb = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
+ rgb = rgb ? {
+ r : parseInt(rgb[1], 16),
+ g : parseInt(rgb[2], 16),
+ b : parseInt(rgb[3], 16)
+ } : null;
+ var result = rgb ? "rgba(" + rgb.r + ", " + rgb.g + ", " + rgb.b + ", " + opacity + ")" : null;
+ return result;
+ }
+};
+
+export default ColorUtils;
diff --git a/src/Common-review/Utils/Config.js b/src/Common-review/Utils/Config.js
new file mode 100644
index 000000000..fc63876f4
--- /dev/null
+++ b/src/Common-review/Utils/Config.js
@@ -0,0 +1,265 @@
+import Logger from "../../Common/Utils/LoggerByDefault";
+
+var logger = Logger.getLogger("config");
+
+var Config = {
+
+ /** autoconf */
+ configuration : null,
+
+ /**
+ * Controle du chargement de l'autoconf
+ *
+ * @returns {Boolean} isConfigLoaded - True si l'autoconf a déjà été chargée, False sinon.
+ */
+ isConfigLoaded : function () {
+ var scope = typeof window !== "undefined" ? window : typeof self !== "undefined" ? self : typeof global !== "undefined" ? global : {};
+ if (scope.Gp && scope.Gp.Config && Object.keys(scope.Gp.Config).length !== 0) {
+ this.configuration = scope.Gp.Config;
+ return true;
+ }
+ return false;
+ },
+
+ /**
+ * Recuperation de l'identifiant d'une couche donnée
+ *
+ * @param {String} layerName - nom de la couche (par ex. "ORTHOIMAGERY.ORTHOPHOTOS")
+ * @param {String} service - nom du service (par ex. "WMS" ou "WMTS")
+ * @returns {String} layerId - identifiant de la couche (par ex. "ORTHOIMAGERY.ORTHOPHOTOS$GEOPORTAIL:OGC:WMTS")
+ */
+ getLayerId : function (layerName, service) {
+ var layerId = null;
+
+ // layer
+ // key : [layerName]$[contexte]:OGC:[service]
+ // ex : "ORTHOIMAGERY.ORTHOPHOTOS$GEOPORTAIL:OGC:WMTS"
+
+ // service
+ // key : [layerName]$[contexte];[service]
+ // ex : PositionOfInterest$OGC:OPENLS;ReverseGeocode
+
+ if (this.configuration) {
+ var layers = this.configuration["layers"];
+ for (var key in layers) {
+ if (layers.hasOwnProperty(key)) {
+ var parts = key.split("$");
+ if (layerName === parts[0]) {
+ if (parts[1]) {
+ var servicePartsLayer = parts[1].split(":");
+ var servicePartsService = parts[1].split(";");
+
+ if (servicePartsService[1] === service) {
+ layerId = key;
+ break;
+ }
+ if (servicePartsLayer[2] === service) {
+ layerId = key;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ if (!layerId) {
+ logger.error("ERROR layer id (layer name: " + layerName + " / service: " + service + ") was not found !?");
+ }
+
+ return layerId;
+ },
+
+ /**
+ * Récupération des paramètres nécessaires à l'affichage d'une couche WMS ou WMTS
+ *
+ * @param {String} layerName - nom de la couche (par ex. "ORTHOIMAGERY.ORTHOPHOTOS")
+ * @param {String} service - nom du service (par ex. "WMS" ou "WMTS")
+ * @param {String} [apiKey] - Clé de contrat API
+ * @returns {Object} params - paramètres du service (WMS ou WMTS) pour la couche donnée
+ * @returns {String} params.url - Url du service à requêter pour afficher la couche
+ * @returns {String} params.version - Version du service
+ * @returns {String} params.styles - Style par défaut de la couche
+ * @returns {String} params.format - Format par défaut de la couche
+ * @returns {String} params.projection - Projection par défaut de la couche
+ * @returns {Number} params.minScale - Dénominateur d'échelle minimum de la couche
+ * @returns {Number} params.maxScale - Dénominateur d'échelle maximum de la couche
+ * @returns {Gp.BBox} params.extent - Etendue de la couche, dans la projection de la couche
+ * @returns {Array} params.legends - Tableau des légendes associées à la couche
+ * @returns {Array} params.metadata - Tableau des métadonnées associées à la couche
+ * @returns {Array} params.originators - Tableau des originators associés à la couche
+ * @returns {Array} params.title - Nom de la resource, lisible par un humain.
+ * @returns {Array} params.description - Url de l'image d'aperçu rapide de la ressource.
+ * @returns {Array} params.quicklookUrl- Tableau des originators associés à la couche
+ * @returns {String} params.[TMSLink] - Identifiant de la pyramide (TMS), dans le cas d'une couche WMTS
+ * @returns {Gp.Point} params.[matrixOrigin] - Origine de la matrice (top left corner), dans le cas d'une couche WMTS
+ * @returns {Array} params.[nativeResolutions] - Tableau regroupant les résolutions de chaque niveau de la matrice, dans le cas d'une couche WMTS
+ * @returns {Array} params.[matrixIds] - Tableau regroupant les identifiants de chaque niveau de la matrice, dans le cas d'une couche WMTS
+ */
+ getLayerParams : function (layerName, service, apiKey) {
+ var params = {};
+
+ if (this.configuration) {
+ // récupération de l'identifiant complet de la couche.
+ var layerId = this.getLayerId(layerName, service);
+
+ if (layerId) {
+ // récupération de l'objet de configuration de la couche
+ var layerConf = this.configuration.layers[layerId];
+
+ // controle de la clef
+ var key = layerConf.apiKeys[0];
+ if (apiKey) {
+ if (apiKey !== key) {
+ logger.error("ERROR different keys (" + apiKey + " !== " + key + ") !?");
+ return;
+ }
+ }
+
+ apiKey = apiKey || key;
+ params.key = apiKey;
+ // récupération des paramètres du service
+ params.url = layerConf.getServerUrl(apiKey);
+ params.version = layerConf.getServiceParams().version;
+ params.styles = layerConf.getDefaultStyle();
+ params.format = layerConf.getDefaultFormat();
+ params.projection = layerConf.getDefaultProjection();
+
+ // récupération des infos de la couche
+ params.minScale = layerConf.getMinScaleDenominator();
+ params.maxScale = layerConf.getMaxScaleDenominator();
+ params.extent = layerConf.getBBOX();
+ params.legends = layerConf.getLegends();
+ params.metadata = layerConf.getMetadata();
+ params.originators = layerConf.getOriginators();
+ params.title = layerConf.getTitle();
+ params.description = layerConf.getDescription();
+ params.quicklookUrl = layerConf.getQuicklookUrl();
+
+ // WMTS : récupération des tileMatrixSetLimits
+ if (layerConf.wmtsOptions) {
+ params.tileMatrixSetLimits = layerConf.wmtsOptions.tileMatrixSetLimits;
+ }
+
+ // WMTS : récupération des paramètres de la pyramide (TMS)
+ var TMSLink = layerConf.getTMSID();
+ if (TMSLink) {
+ params.TMSLink = TMSLink;
+ var tmsConf = this.configuration.getTMSConf(TMSLink);
+ // Get matrix origin : Gp.Point = Object{x:Float, y:Float}
+ params.matrixOrigin = tmsConf.getTopLeftCorner();
+ params.nativeResolutions = tmsConf.nativeResolutions;
+ params.matrixIds = tmsConf.matrixIds;
+ params.tileMatrices = tmsConf.tileMatrices;
+ }
+ }
+ }
+
+ return params;
+ },
+
+ /**
+ * Recuperation des parametres d'un service
+ *
+ * @param {String} [resource] - "PositionOfInterest", "StreetAddress", "Voiture", "Pieton", ...
+ * @param {String} [service] - Geocode, Itineraire, ...
+ * @param {String} [apiKey] - Clé de contrat API
+ * @returns {Object} params - paramètres de la ressource
+ * @returns {String} params. -
+ * @returns {String} params. -
+ * @returns {String} params. -
+ */
+ getServiceParams : function (resource, service, apiKey) {
+ var params = {};
+
+ if (this.configuration) {
+ // récupération de l'identifiant complet de la couche.
+ var layerId = this.getLayerId(resource, service);
+
+ if (layerId) {
+ // récupération de l'objet de configuration de la couche
+ var layerConf = this.configuration.layers[layerId];
+
+ // controle de la clef
+ var key = layerConf.apiKeys[0];
+ if (apiKey) {
+ if (apiKey !== key) {
+ return;
+ }
+ }
+
+ apiKey = apiKey || key;
+ params.key = apiKey;
+ // récupération des paramètres du service
+ params.url = layerConf.getServerUrl(apiKey);
+ params.version = layerConf.getServiceParams().version;
+
+ // récupération des infos de la couche
+ params.extent = layerConf.getBBOX();
+ params.title = layerConf.getTitle();
+ params.description = layerConf.getDescription();
+ }
+ }
+
+ return params;
+ },
+
+ /**
+ * Resolution en geographique
+ *
+ * @returns {Array} resolutions
+ */
+ getResolutions : function () {
+ var resolutions = [];
+
+ if (this.configuration) {
+ resolutions = this.configuration["generalOptions"]["wgs84Resolutions"];
+ }
+
+ return resolutions;
+ },
+
+ /**
+ * Recuperation des parametres TMS de la configuration
+ * @param {String} tmsName - tile matrix set name
+ *
+ * @returns {Object} tile matrix set
+ */
+ getTileMatrix : function (tmsName) {
+ var tms = {};
+
+ if (this.configuration) {
+ if (tmsName) {
+ tms = this.configuration["tileMatrixSets"][tmsName.toUpperCase()];
+ }
+ }
+
+ return tms;
+ },
+
+ /**
+ * Récupération des contraintes générales d'une couche donnée : extent, minScale, maxScale, projection
+ *
+ * @param {String} layerId - identifiant de la couche
+ * @returns {Object} params - contraintes de la couche
+ * @returns {String} params.projection - Projection par défaut de la couche
+ * @returns {Number} params.minScale - Dénominateur d'échelle minimum de la couche
+ * @returns {Number} params.maxScale - Dénominateur d'échelle maximum de la couche
+ * @returns {Gp.BBox} params.extent - Etendue de la couche, dans la projection de la couche
+ */
+ getGlobalConstraints : function (layerId) {
+ var params = {};
+
+ if (layerId) {
+ // récupération de l'objet de configuration de la couche
+ var layerConf = this.configuration.layers[layerId];
+ params.projection = layerConf.getDefaultProjection();
+ params.minScale = layerConf.getMinScaleDenominator();
+ params.maxScale = layerConf.getMaxScaleDenominator();
+ params.extent = layerConf.getBBOX();
+ }
+
+ return params;
+ }
+};
+
+export default Config;
diff --git a/src/Common-review/Utils/Draggable.js b/src/Common-review/Utils/Draggable.js
new file mode 100644
index 000000000..61920f09e
--- /dev/null
+++ b/src/Common-review/Utils/Draggable.js
@@ -0,0 +1,120 @@
+import Logger from "./LoggerByDefault";
+
+var logger = Logger.getLogger("draggable");
+
+var Draggable = {
+ /**
+ * A draggable HTML element with JavaScript and CSS.
+ *
+ * @param {DOMElement} element - element
+ * @param {DOMElement} header - header (optional)
+ * @param {DOMElement} container - container (optional)
+ * @see https://www.w3schools.com/howto/howto_js_draggable.asp
+ * @see https://stackoverflow.com/questions/52231588/how-to-constrain-div-drag-space-no-jquery
+ * @example
+ * // CSS :
+ * // #element { position: absolute; }
+ * // HTML :
+ * //
+ * //
+ * //
+ * // ...
+ * //
+ * //
+ * //
+ * // JS :
+ * var element = document.getElementById("element");
+ * Draggable.dragElement(element, header, container);
+ */
+ dragElement : function (element, header, container) {
+ var offsetX, offsetY;
+
+ var isDragReady = false;
+
+ var dragoffset = {
+ x : 0,
+ y : 0
+ };
+
+ if (header) {
+ header.addEventListener("mousedown", dragMouseDown, true);
+ } else {
+ element.addEventListener("mousedown", dragMouseDown, true);
+ }
+
+ // TODO mettre en place les contraintes
+ // var constraints = {};
+ // if (container) {
+ // constraints = {
+ // width : container.clientWidth,
+ // height : container.clientHeight,
+ // top : container.offsetTop,
+ // left : container.offsetLeft
+ // };
+ // }
+
+ function dragMouseDown (e) {
+ e = e || window.event;
+ e.preventDefault();
+
+ isDragReady = true;
+
+ // get the mouse cursor position at startup
+ e._pageX = e._pageX || e.clientX + (document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft);
+ e._pageY = e._pageY || e.clientY + (document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop);
+ dragoffset.x = e._pageX - element.offsetLeft;
+ dragoffset.y = e._pageY - element.offsetTop;
+
+ document.addEventListener("mouseup", closeDragElement, true);
+ document.addEventListener("mousemove", elementDrag, true);
+ }
+
+ function closeDragElement () {
+ /* stop moving when mouse button is released: */
+ isDragReady = false;
+ document.removeEventListener("mouseup", closeDragElement, true);
+ document.removeEventListener("mousemove", elementDrag, true);
+ }
+
+ function elementDrag (e) {
+ e = e || window.event;
+ // e.preventDefault();
+
+ // cf. https://jsfiddle.net/nbbg08mg/2/
+ if (isDragReady) {
+ e._pageX = e._pageX || e.clientX + (document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft);
+ e._pageY = e._pageY || e.clientY + (document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop);
+
+ var parentLeft = element.parentElement.offsetLeft;
+ var parentTop = element.parentElement.offsetTop;
+ logger.trace("parent offset", parentLeft, parentTop);
+
+ // left/right constraint
+ if (e._pageX - dragoffset.x < 0 - parentLeft) {
+ offsetX = 0 - parentLeft;
+ } else if (e._pageX - dragoffset.x + element.clientWidth > document.body.clientWidth) {
+ offsetX = document.body.clientWidth - element.clientWidth;
+ } else {
+ offsetX = e._pageX - dragoffset.x;
+ }
+ logger.trace("left/right constraint", offsetX);
+
+ // top/bottom constraint
+ if (e._pageY - dragoffset.y < 0 - parentTop) {
+ offsetY = 0 - parentTop;
+ } else if (e._pageY - dragoffset.y + element.clientHeight > document.body.clientHeight) {
+ offsetY = document.body.clientHeight - element.clientHeight;
+ } else {
+ offsetY = e._pageY - dragoffset.y;
+ }
+ logger.trace("top/bottom constraint", offsetY);
+
+ // set the element's new position:
+ element.style.top = offsetY + "px";
+ element.style.left = offsetX + "px";
+ }
+ }
+ }
+};
+
+export default Draggable;
diff --git a/src/Common-review/Utils/LayerUtils.js b/src/Common-review/Utils/LayerUtils.js
new file mode 100644
index 000000000..477f76da9
--- /dev/null
+++ b/src/Common-review/Utils/LayerUtils.js
@@ -0,0 +1,312 @@
+/**
+* @module LayerUtils
+* @alias Gp.LayerUtils
+* @description
+* ...
+*
+* @example
+* getZoomLevelFromScaleDenominator();
+* getAttributions();
+* intersects();
+*/
+var LayerUtils = {
+
+ /**
+ * Obtenir le ZoomLevel à partir du ScaleDenominator
+ * @param {Number} scaleDenominator - the scale denominator
+ * @param {String} crs - the crs
+ *
+ * @returns {Integer} zoom level
+ */
+ getZoomLevelFromScaleDenominator : function (scaleDenominator, crs) {
+ // ------------------------------------------------- //
+ // Code issu de l'API Geoportal/Catalogue/Config.js //
+ // ------------------------------------------------- //
+ // var configuration = Gp.Config;
+ // var general = configuration.generalOptions;
+ // var layers = configuration.layersContext;
+ //
+ // for (var tms in general.tileMatrixSets) {
+ // var tileMatrixSet = general.tileMatrixSets[tms];
+ // // IGN's WMTS bug : epsg:nnnn instead of EPSG:nnnn
+ // var crs = tileMatrixSet.supportedCRS = tileMatrixSet.supportedCRS.replace(/epsg/,"EPSG");
+ //
+ // if (!Geoportal.Catalogue.CRSRESOLUTIONS.hasOwnProperty(crs)) {
+ // var p= new OpenLayers.Projection(crs);
+ // Geoportal.Catalogue.CRSRESOLUTIONS[crs]= [];
+ // var matrixIds= tileMatrixSet.matrixIds;
+ // for (var i= 0, li= matrixIds.length; i
} params.extent - map current geographical extent (EPSG:4326) : [top, left, bottom, right] = [maxy, minx, miny, maxx]
+ * @param {Number} params.zoom - map current zoom
+ * @param {String} params.crs - map current projection code (ex "EPSG:2154")
+ * @param {Boolean} params.visibility - layer visibility
+ * @param {Gp.Services.Config.Originator} params.originators - resource originators (from Gp.Config.layers[].originators)
+ * @returns {Object} attributions - associative array, mapping originators url (keys) with their properties : html attributions elements
+ */
+ getAttributions : function (params) {
+ var zoom = params.zoom;
+
+ var attributions = [];
+
+ if (params.originators != null && params.visibility) {
+ // drawLogo = boolean, true if attribution should be displayed (zoom, extent), false otherwise
+ var drawLogo;
+ for (var j = 0, jl = params.originators.length; j < jl; j++) {
+ drawLogo = true;
+ var originator = params.originators[j];
+
+ var constraints = params.originators[j].constraints || [];
+ for (var k = 0, kl = constraints.length; k < kl; k++) {
+ var constraint = constraints[k];
+ drawLogo = true;
+
+ var minZoomLevel = this.getZoomLevelFromScaleDenominator(constraint.maxScaleDenominator, params.crs);
+ var maxZoomLevel = this.getZoomLevelFromScaleDenominator(constraint.minScaleDenominator, params.crs) || 21;
+
+ // min zoom constraints
+ if (minZoomLevel && (minZoomLevel > zoom)) {
+ drawLogo = false;
+ }
+
+ // max zoom constraints
+ if (drawLogo && maxZoomLevel !== null && (maxZoomLevel < zoom)) {
+ drawLogo = false;
+ }
+
+ // bbox constraints
+ var bbox = constraint.bbox;
+ if (drawLogo && bbox) {
+ drawLogo = false;
+ var viewExtent = params.extent;
+ if (viewExtent) {
+ var bounds = [bbox.top, bbox.left, bbox.bottom, bbox.right];
+ if (this.intersects(viewExtent, bounds)) {
+ // at least one constraint matches the map ones
+ drawLogo = true;
+ break;
+ }
+ }
+ }
+ }
+
+ if (drawLogo) {
+ // on a un originator qui correspond au zoom et à l'étendue.
+
+ var logo = originator.logo;
+ var url = originator.url;
+ var name = originator.name ? originator.name : "";
+ var text = originator.attribution;
+
+ var container = document.createElement("div");
+ container.className = "gp-control-attribution";
+
+ // on crée un lien dans tous les cas (même s'il ne pointe pas vers une référence), pour avoir accès à la class CSS (pour surcharge)
+ var link = null;
+ link = document.createElement("a");
+ link.className = "gp-control-attribution-link";
+ link.target = "_blank";
+ container.appendChild(link);
+ if (url) {
+ link.href = url;
+ }
+
+ var bImage = !!(logo);
+ var image = null;
+ // si on a un logo, on l'affiche à l'interieur du lien
+ if (bImage) {
+ image = document.createElement("img");
+ if (link) {
+ image.className = "gp-control-attribution-image";
+ link.appendChild(image);
+ } else {
+ image.className = "";
+ container.appendChild(image);
+ }
+ image.src = logo; // FIXME : mixContent !
+ image.title = text || name;
+ image.style.height = "30px";
+ image.style.width = "30px";
+ } else {
+ // sinon, on affiche le nom de l'originator, ou sa description ou l'url.
+ if (name) {
+ link.textContent = name;
+ } else if (text) {
+ link.textContent = text;
+ } else if (url) {
+ link.textContent = url;
+ } else {
+ link.textContent = "";
+ }
+ }
+
+ attributions.push(container.innerHTML + " ");
+ }
+ }
+ }
+
+ return attributions;
+ },
+
+ /**
+ * Determines if one extent (extent1) intersects another (extent2)
+ *
+ * @param {Array.} extent1 - First extent : [top, left, bottom, right] = [maxy, minx, miny, maxx]
+ * @param {Array.} extent2 - Second extent : [top, left, bottom, right] = [maxy, minx, miny, maxx]
+ * @return {Boolean} intersects - True if the two extents intersect, false otherwise.
+ */
+ intersects : function (extent1, extent2) {
+ var intersectsX = (extent1[1] <= extent2[3]) && (extent2[1] <= extent1[3]);
+ var intersectsY = (extent1[2] <= extent2[0]) && (extent2[2] <= extent1[0]);
+ return intersectsX && intersectsY;
+ }
+};
+
+export default LayerUtils;
diff --git a/src/Common-review/Utils/LoggerByDefault.js b/src/Common-review/Utils/LoggerByDefault.js
new file mode 100644
index 000000000..d6c973443
--- /dev/null
+++ b/src/Common-review/Utils/LoggerByDefault.js
@@ -0,0 +1,21 @@
+import * as Log from "loglevel";
+
+var LoggerByDefault = {
+ /**
+ *logger statique
+ * @param {String} [name="default"] - the logger name
+ *
+ * @returns {Object} logger
+ */
+ getLogger : function (name) {
+ // Substitute global constants configured at compile time
+ // cf. webpack.config.js
+ // on masque cette constante afin d'eviter "referenceerror not defined"
+ ("__PRODUCTION__".match(/true/))
+ ? Log.disableAll() : Log.enableAll();
+ var logname = name || "default";
+ return Log.getLogger(logname);
+ }
+};
+
+export default LoggerByDefault;
diff --git a/src/Common-review/Utils/MathUtils.js b/src/Common-review/Utils/MathUtils.js
new file mode 100644
index 000000000..8b5f7b648
--- /dev/null
+++ b/src/Common-review/Utils/MathUtils.js
@@ -0,0 +1,111 @@
+/**
+* @module MathUtils
+* @alias Gp.MathUtils
+* @description
+* ...
+*
+* @example
+* modulo();
+* decimalToDMS();
+* toInteger();
+* isInteger();
+* toFloat();
+*/
+var MathUtils = {
+ /**
+ * Reste de la division euclidienne
+ * @param {Number} a - divisor
+ * @param {Number} b - quotient
+ * @returns {Number} Modulo
+ */
+ modulo : function (a, b) {
+ var r = a % b;
+ return r * b < 0 ? r + b : r;
+ },
+
+ /**
+ * Transform degrees, minutes, seconds form decimal degrees -
+ * Largely inspired by the private function degreesToStringHDMS from ol/coordinate.js
+ *
+ * @param {Number} degrees - decimal degrees
+ * @param {Array} hemispheres - "NS" ou "EO"
+ * @param {Number} numDigits - number of digits for seconds
+ * @returns {Object} DMS coordinate
+ */
+ decimalToDMS : function (degrees, hemispheres, numDigits) {
+ var normalizedDegrees = this.modulo(degrees + 180, 360) - 180;
+ var x = Math.abs(3600 * normalizedDegrees);
+ var dflPrecision = numDigits || 0;
+ var precision = Math.pow(10, dflPrecision);
+
+ var deg = Math.floor(x / 3600);
+ var min = Math.floor((x - deg * 3600) / 60);
+ var sec = x - (deg * 3600) - (min * 60);
+ sec = Math.ceil(sec * precision) / precision;
+
+ if (sec >= 60) {
+ sec = 0;
+ min += 1;
+ }
+
+ if (min >= 60) {
+ min = 0;
+ deg += 1;
+ }
+
+ var direction = hemispheres.charAt(normalizedDegrees < 0 ? 1 : 0);
+ return {
+ d : deg,
+ m : min,
+ s : sec,
+ direction : direction
+ };
+ },
+
+ /**
+ * Converts string to Integer
+ *
+ * @param {String} s - string number
+ * @param {Numeric} base - between 2 and 36
+ * @returns {null|Numeric} result
+ */
+ toInteger : function (s, base) {
+ var _base = base || 10;
+ var n = parseInt(s, _base);
+ if (!isNaN(n) && isFinite(n)) {
+ return n;
+ }
+ return null;
+ },
+
+ /**
+ * check if s represents an integer
+ *
+ * @param {String} s - string number
+ * @returns {Boolean} is integer
+ */
+ isInteger : function (s) {
+ if (isNaN(s)) {
+ return false;
+ }
+
+ var v = parseFloat(s);
+ return ((v | 0) === v);
+ },
+
+ /**
+ * Converts s to float
+ *
+ * @param {String} s - string number
+ * @returns {null|Numeric} result
+ */
+ toFloat : function (s) {
+ var n = parseFloat(s);
+ if (!isNaN(n) && isFinite(n)) {
+ return n;
+ }
+ return null;
+ }
+};
+
+export default MathUtils;
diff --git a/src/Common-review/Utils/ProxyUtils.js b/src/Common-review/Utils/ProxyUtils.js
new file mode 100644
index 000000000..ca9acda12
--- /dev/null
+++ b/src/Common-review/Utils/ProxyUtils.js
@@ -0,0 +1,50 @@
+import Logger from "../../Common/Utils/LoggerByDefault";
+
+/**
+* @module ProxyUtils
+* @alias Gp.ProxyUtils
+* @description
+* ...
+*
+* @example
+* proxifyUrl();
+*/
+var ProxyUtils = {
+ /**
+ * Ajoute un proxy aux url des couches vecteurs si besoin.
+ *
+ * @param {String} url - Url to proxify.
+ * @param {Object} [proxyOptions] - Object defining proxy options.
+ * @param {String} proxyOptions.proxyUrl - Proxy URL.
+ * @param {Array.} [proxyOptions.noProxyDomains] - Proxy will not be used for this list of domain names.
+ *
+ * @returns {String} proxy url
+ */
+ proxifyUrl : function (url, proxyOptions) {
+ // logger
+
+ var logger = Logger.getLogger("proxifyUrl");
+
+ if (!proxyOptions ||
+ !proxyOptions.hasOwnProperty("proxyUrl") ||
+ proxyOptions.proxyUrl === null ||
+ proxyOptions.proxyUrl.trim().length === 0) {
+ return url;
+ }
+ // on regarde si l'url nest pas dans les domaines sans proxy
+ if (proxyOptions.noProxyDomains &&
+ Array.isArray(proxyOptions.noProxyDomains) &&
+ proxyOptions.noProxyDomains.length > 0) {
+ for (var i in proxyOptions.noProxyDomains) {
+ logger.trace("[ProxyUtils] proxifyUrl : analyzing " + proxyOptions.noProxyDomains[i]);
+ if (url.indexOf(proxyOptions.noProxyDomains[i]) !== -1) {
+ logger.info("[ProxyUtils] proxifyUrl : " + url + " found in noProxyDomains list (" + proxyOptions.noProxyDomains[i] + ").");
+ return url;
+ }
+ }
+ }
+ return proxyOptions.proxyUrl + encodeURIComponent(url);
+ }
+};
+
+export default ProxyUtils;
diff --git a/src/Common-review/Utils/Register.js b/src/Common-review/Utils/Register.js
new file mode 100644
index 000000000..bd4e6f510
--- /dev/null
+++ b/src/Common-review/Utils/Register.js
@@ -0,0 +1,643 @@
+// FIXME
+// - exception lors du register IGNF des projections geocent ?
+// Ex. Transforming EPSG:4978 geocent projection fails?
+// cf. https://github.com/proj4js/proj4js/issues/195
+// - probleme de performance avec le chargement des projections (env. 4s),
+// et ceci bloque le rendu graphique...
+
+/**
+ * Register definition for IGNF, and EPSG CRS.
+ * @example
+ * Gp.Register.IGNF.AMST63
+ * // return : "+title=Amsterdam 1963 +proj=geocent +towgs84=109.753,-528.133,-362.244,0,0,0,0 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs"
+ * Gp.Register.get("IGNF:AMST63")
+ * // same as Gp.Register.IGNF.AMST63
+ */
+var Register = {
+
+ /**
+ * instance already loaded into proj4
+ */
+ isLoaded : false,
+
+ /**
+ * get the definition for a code
+ *
+ * @param {String} name - ie. EPSG:2154 (Lambert)
+ * @returns {Object} definition
+ * @example
+ * Register.get("EPSG:2154");
+ * // "+title=RGF93 / Lambert-93 +proj=lcc +lat_1=49 ..."
+ */
+ get : function (name) {
+ if (name === "" || name === null || typeof name === "undefined") {
+ return;
+ }
+
+ var s = name.split(":");
+ if (s.length !== 2) {
+ return;
+ }
+
+ var _register = s[0];
+ var _code = s[1];
+
+ if (!this.hasOwnProperty(_register)) {
+ return;
+ }
+
+ if (!this[_register].hasOwnProperty(_code)) {
+ return;
+ }
+
+ return this[_register][_code];
+ },
+
+ /**
+ * does projection code exist ?
+ *
+ * @param {String} name - ie. EPSG:2154 (Lambert)
+ * @returns {Boolean} true/false
+ * @example
+ * Register.exist("EPSG:2154"); // true
+ */
+ exist : function (name) {
+ if (name === "" || name === null || typeof name === "undefined") {
+ return false;
+ }
+
+ var s = name.split(":");
+ if (s.length !== 2) {
+ return false;
+ }
+
+ var _register = s[0];
+ var _code = s[1];
+
+ if (!this.hasOwnProperty(_register)) {
+ return false;
+ }
+
+ if (!this[_register].hasOwnProperty(_code)) {
+ return false;
+ }
+
+ return true;
+ },
+
+ /**
+ * load all defs to proj4
+ * @param {Object} Proj4 - proj4 instance
+ */
+ load : function (Proj4) {
+ // un flag pour savoir si le chargement est déjà realisé
+ // (car ceci peut être couteux !)
+ if (!this.isLoaded) {
+ var registers = [
+ "IGNF", // exception lors du register IGNF ?
+ "EPSG",
+ "CRS"
+ ];
+ for (var i = 0; i < registers.length; i++) {
+ var _register = registers[i];
+ var codes = this[_register];
+ for (var _code in codes) {
+ if (codes.hasOwnProperty(_code)) {
+ var name = _register + ":" + _code;
+ Proj4.defs(name, this.get(name));
+ // on enlève la dependance à OpenLayers...
+ // la fonction register est donc à appeller afin d'enregistrer
+ // les definitions dans OpenLayers :
+ // import { get } from "ol/proj";
+ // import proj4 from "proj4";
+ // import { register } from "ol/proj/proj4";
+ // Register.load();
+ // // Make projections defined in proj4 (with proj4.defs()) available in OpenLayers.
+ // // see ol/proj/proj4.register (https://openlayers.org/en/latest/apidoc/module-ol_proj_proj4.html)
+ // register(proj4);
+ // console.log(get("CRS:84").getCode()); // "CRS:84"
+ }
+ }
+ }
+ this.isLoaded = true;
+ }
+ },
+
+ /**
+ * load defs by default to proj4
+ *
+ * include into proj4 :
+ * - WGS84
+ * - ['EPSG:4326']
+ * - ['EPSG:3785'], ['EPSG:3857'], GOOGLE, ['EPSG:900913'], ['EPSG:102113']
+ * +
+ * - ["EPSG:2154"], ["EPSG:27571"], ["EPSG:27572"], ["EPSG:27573"], ["EPSG:2757"],
+ * - ["CRS:84"],
+ * - ["IGNF:LAMB93"],
+ * - ["IGNF:LAMBE"], ["IGNF:LAMB1"], ["IGNF:LAMB2"], ["IGNF:LAMB3"], ["IGNF:LAMB4"],
+ * - ["IGNF:RGF93G"],
+ * - ["IGNF:WGS84G"]
+ *
+ * @param {Object} Proj4 - proj4 instance
+ */
+ loadByDefault : function (Proj4) {
+ // FIXME definir la liste de projections par defaut...
+ var registers = {
+ EPSG : {
+ 2154 : Register["EPSG"]["2154"],
+ 27571 : Register["EPSG"]["27571"],
+ 27572 : Register["EPSG"]["27572"],
+ 27573 : Register["EPSG"]["27573"],
+ 27574 : Register["EPSG"]["27574"]
+ },
+ CRS : {
+ 84 : Register["CRS"]["84"]
+ },
+ IGNF : {
+ LAMB93 : Register["IGNF"]["LAMB93"],
+ LAMBE : Register["IGNF"]["LAMBE"],
+ LAMB1 : Register["IGNF"]["LAMB1"],
+ LAMB2 : Register["IGNF"]["LAMB2"],
+ LAMB3 : Register["IGNF"]["LAMB3"],
+ LAMB4 : Register["IGNF"]["LAMB4"],
+ RGF93G : Register["IGNF"]["RGF93G"],
+ WGS84G : Register["IGNF"]["WGS84G"]
+ }
+ };
+
+ for (var register in registers) {
+ if (registers.hasOwnProperty(register)) {
+ var codes = registers[register];
+ for (var code in codes) {
+ if (codes.hasOwnProperty(code)) {
+ var name = register + ":" + code;
+ Proj4.defs(name, codes[code]);
+ }
+ }
+ }
+ }
+ },
+
+ /**
+ * load only a def to proj4
+ * @param {Object} Proj4 - proj4 instance
+ * @param {String} name - ie. EPSG:2154 (Lambert)
+ * @returns {Boolean} true/false
+ */
+ loadByName : function (Proj4, name) {
+ if (!this.exist(name)) {
+ return false;
+ }
+
+ try {
+ Proj4.defs(name, this.get(name));
+ } catch (e) {
+ // FIXME !?
+ return false;
+ }
+
+ return true;
+ },
+
+ // definitions
+ EPSG : {
+ // 4978 : "+proj=geocent +datum=WGS84 +units=m +no_defs ",
+ 3857 : "+title=WGS 84 / Pseudo-Mercator +proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs",
+ 3785 : "+title=WGS 84 / Pseudo-Mercator (deprecated) +proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs",
+ 4149 : "+title=CH1903 +proj=longlat +ellps=bessel +towgs84=674.374,15.056,405.346,0,0,0,0 +no_defs ",
+ 4150 : "+title=CH1903plus +proj=longlat +ellps=bessel +towgs84=674.374,15.056,405.346,0,0,0,0 +no_defs ",
+ 4151 : "+title=CHTRF95 +proj=longlat +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +no_defs ",
+ 4171 : "+title=RGF93 +proj=longlat +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +no_defs ",
+ 4230 : "+title=ED50 +proj=longlat +ellps=intl +no_defs ",
+ 4235 : "+title=Guyane Francaise +proj=longlat +ellps=intl +no_defs ",
+ 4258 : "+title=ETRS89 +proj=longlat +ellps=GRS80 +no_defs ",
+ 4275 : "+title=NTF +proj=longlat +a=6378249.2 +b=6356515 +towgs84=-168,-60,320,0,0,0,0 +no_defs ",
+ 4322 : "+title=WGS 72 +proj=longlat +ellps=WGS72 +no_defs ",
+ 4326 : "+title=WGS 84 +proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs ",
+ 4467 : "+proj=utm +zone=21 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ",
+ 4470 : "+proj=longlat +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +no_defs ",
+ 4471 : "+proj=utm +zone=38 +south +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ",
+ 4474 : "+proj=utm +zone=38 +south +ellps=intl +towgs84=-382,-59,-262,0,0,0,0 +units=m +no_defs ",
+ 4558 : "+proj=longlat +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +no_defs ",
+ 4559 : "+proj=utm +zone=20 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ",
+ 4621 : "+title=Fort Marigot +proj=longlat +ellps=intl +towgs84=137,248,-430,0,0,0,0 +no_defs ",
+ 4622 : "+title=Guadeloupe 1948 +proj=longlat +ellps=intl +no_defs ",
+ 4623 : "+title=CSG67 +proj=longlat +ellps=intl +towgs84=-186,230,110,0,0,0,0 +no_defs ",
+ 4624 : "+title=RGFG95 +proj=longlat +ellps=GRS80 +towgs84=2,2,-2,0,0,0,0 +no_defs ",
+ 4625 : "+title=Martinique 1938 +proj=longlat +ellps=intl +no_defs ",
+ 4626 : "+title=Reunion 1947 +proj=longlat +ellps=intl +no_defs ",
+ 4627 : "+title=RGR92 +proj=longlat +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +no_defs ",
+ 4628 : "+title=Tahiti 52 +proj=longlat +ellps=intl +towgs84=162,117,154,0,0,0,0 +no_defs ",
+ 4629 : "+title=Tahaa 54 +proj=longlat +ellps=intl +no_defs ",
+ 4630 : "+title=IGN72 Nuku Hiva +proj=longlat +ellps=intl +no_defs ",
+ 4632 : "+title=Combani 1950 +proj=longlat +ellps=intl +towgs84=-382,-59,-262,0,0,0,0 +no_defs ",
+ 4633 : "+title=IGN56 Lifou +proj=longlat +ellps=intl +no_defs ",
+ 4634 : "+title=IGN72 Grand Terre +proj=longlat +ellps=intl +no_defs ",
+ 4637 : "+title=Perroud 1950 +proj=longlat +ellps=intl +towgs84=325,154,172,0,0,0,0 +no_defs ",
+ 4638 : "+title=Saint Pierre et Miquelon 1950 +proj=longlat +ellps=clrk66 +towgs84=30,430,368,0,0,0,0 +no_defs ",
+ 4640 : "+title=RRAF 1991 +proj=longlat +ellps=WGS84 +towgs84=0,0,0,0,0,0,0 +no_defs ",
+ 4641 : "+title=IGN53 Mare +proj=longlat +ellps=intl +no_defs ",
+ 4645 : "+title=RGNC 1991 +proj=longlat +ellps=intl +towgs84=0,0,0,0,0,0,0 +no_defs ",
+ 4687 : "+proj=longlat +ellps=GRS80 +no_defs ",
+ 4662 : "+title=IGN72 Grande Terre +proj=longlat +ellps=intl +no_defs ",
+ 4689 : "+title=IGN63 Hiva Oa +proj=longlat +ellps=intl +no_defs ",
+ 4690 : "+title=Tahiti 79 +proj=longlat +ellps=intl +no_defs ",
+ 4691 : "+title=Moorea 87 +proj=longlat +ellps=intl +towgs84=215.525,149.593,176.229,-3.2624,-1.692,-1.1571,10.4773 +no_defs ",
+ 4692 : "+title=Maupiti 83 +proj=longlat +ellps=intl +towgs84=217.037,86.959,23.956,0,0,0,0 +no_defs ",
+ 4698 : "+title=IGN 1962 Kerguelen +proj=longlat +ellps=intl +towgs84=145,-187,103,0,0,0,0 +no_defs ",
+ 4749 : "+title=RGNC91-93 +proj=longlat +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +no_defs ",
+ 4750 : "+title=ST87 Ouvea +proj=longlat +ellps=WGS84 +towgs84=-56.263,16.136,-22.856,0,0,0,0 +no_defs ",
+ 4807 : "+title=NTF (Paris) +proj=longlat +a=6378249.2 +b=6356515 +towgs84=-168,-60,320,0,0,0,0 +pm=paris +no_defs ",
+ 2056 : "+title=CH1903+ / LV95 +proj=somerc +lat_0=46.95240555555556 +lon_0=7.439583333333333 +x_0=2600000 +y_0=1200000 +ellps=bessel +towgs84=674.374,15.056,405.346,0,0,0,0 +units=m +no_defs ",
+ 2154 : "+title=RGF93 / Lambert-93 +proj=lcc +lat_1=49 +lat_2=44 +lat_0=46.5 +lon_0=3 +x_0=700000 +y_0=6600000 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ",
+ 2213 : "+title=ETRS89 / TM 30 NE +proj=tmerc +lat_0=0 +lon_0=30 +k=0.9996 +x_0=500000 +y_0=0 +ellps=GRS80 +units=m +no_defs ",
+ 2969 : "+title=Fort Marigot / UTM zone 20N +proj=utm +zone=20 +ellps=intl +towgs84=137,248,-430,0,0,0,0 +units=m +no_defs ",
+ 2970 : "+title=Guadeloupe 1948 / UTM zone 20N +proj=utm +zone=20 +ellps=intl +units=m +no_defs ",
+ 2971 : "+title=CSG67 / UTM zone 22N +proj=utm +zone=22 +ellps=intl +towgs84=-186,230,110,0,0,0,0 +units=m +no_defs ",
+ 2972 : "+title=RGFG95 / UTM zone 22N +proj=utm +zone=22 +ellps=GRS80 +towgs84=2,2,-2,0,0,0,0 +units=m +no_defs ",
+ 2973 : "+title=Martinique 1938 / UTM zone 20N +proj=utm +zone=20 +ellps=intl +units=m +no_defs ",
+ 2975 : "+title=RGR92 / UTM zone 40S +proj=utm +zone=40 +south +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ",
+ 2976 : "+title=Tahiti 52 / UTM zone 6S +proj=utm +zone=6 +south +ellps=intl +towgs84=162,117,154,0,0,0,0 +units=m +no_defs ",
+ 2977 : "+title=Tahaa 54 / UTM zone 5S +proj=utm +zone=5 +south +ellps=intl +units=m +no_defs ",
+ 2978 : "+title=IGN72 Nuku Hiva / UTM zone 7S +proj=utm +zone=7 +south +ellps=intl +units=m +no_defs ",
+ 2980 : "+title=Combani 1950 / UTM zone 38S +proj=utm +zone=38 +south +ellps=intl +towgs84=-382,-59,-262,0,0,0,0 +units=m +no_defs ",
+ 2981 : "+title=IGN56 Lifou / UTM zone 58S +proj=utm +zone=58 +south +ellps=intl +units=m +no_defs ",
+ 2982 : "+title=IGN72 Grand Terre / UTM zone 58S (deprecated) +proj=utm +zone=58 +south +ellps=intl +units=m +no_defs ",
+ 2984 : "+title=RGNC 1991 / Lambert New Caledonia (deprecated) +proj=lcc +lat_1=-20.66666666666667 +lat_2=-22.33333333333333 +lat_0=-21.5 +lon_0=166 +x_0=400000 +y_0=300000 +ellps=intl +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ",
+ 2986 : "+title=Terre Adelie 1950 +proj=stere +towgs84=324.9120,153.2820,172.0260 +a=6378388.0000 +rf=297.0000000000000 +lat_0=-90.000000000 +lon_0=140.000000000 +lat_ts=-67.000000000 +k=0.96027295 +x_0=300000.000 +y_0=-2299363.482 +units=m +no_defs",
+ 2987 : "+title=Saint Pierre et Miquelon 1950 / UTM zone 21N +proj=utm +zone=21 +ellps=clrk66 +towgs84=30,430,368,0,0,0,0 +units=m +no_defs ",
+ 2989 : "+title=RRAF 1991 / UTM zone 20N +proj=utm +zone=20 +ellps=WGS84 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ",
+ 2990 : "+title=Reunion 1947 / TM Reunion (deprecated) +proj=tmerc +lat_0=-21.11666666666667 +lon_0=55.53333333333333 +k=1 +x_0=50000 +y_0=160000 +ellps=intl +units=m +no_defs ",
+ 2995 : "+title=IGN53 Mare / UTM zone 58S +proj=utm +zone=58 +south +ellps=intl +units=m +no_defs ",
+ 3038 : "+proj=utm +zone=26 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ",
+ 3039 : "+proj=utm +zone=27 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ",
+ 3040 : "+proj=utm +zone=28 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ",
+ 3041 : "+proj=utm +zone=29 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ",
+ // 3042 : "+proj=utm +zone=30 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ",
+ // 3043 : "+proj=utm +zone=31 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ",
+ // 3044 : "+proj=utm +zone=32 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ",
+ 3045 : "+proj=utm +zone=33 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ",
+ 3046 : "+proj=utm +zone=34 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ",
+ 3047 : "+proj=utm +zone=35 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ",
+ 3048 : "+proj=utm +zone=36 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ",
+ 3049 : "+proj=utm +zone=37 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ",
+ 3050 : "+proj=utm +zone=38 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ",
+ 3051 : "+proj=utm +zone=39 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ",
+ 3034 : "+title=ETRS89 / ETRS-LCC +proj=lcc +lat_1=35 +lat_2=65 +lat_0=52 +lon_0=10 +x_0=4000000 +y_0=2800000 +ellps=GRS80 +units=m +no_defs ",
+ 3035 : "+title=ETRS89 / ETRS-LAEA +proj=laea +lat_0=52 +lon_0=10 +x_0=4321000 +y_0=3210000 +ellps=GRS80 +units=m +no_defs ",
+ 3042 : "+title=ETRS89 / ETRS-TM30 +proj=utm +zone=30 +ellps=GRS80 +units=m +no_defs ",
+ 3043 : "+title=ETRS89 / ETRS-TM31 +proj=utm +zone=31 +ellps=GRS80 +units=m +no_defs ",
+ 3044 : "+title=ETRS89 / ETRS-TM32 +proj=utm +zone=32 +ellps=GRS80 +units=m +no_defs ",
+ 25828 : "+proj=utm +zone=28 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ",
+ 25829 : "+proj=utm +zone=29 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ",
+ // 25830 : "+proj=utm +zone=30 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ",
+ // 25831 : "+proj=utm +zone=31 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ",
+ // 25832 : "+proj=utm +zone=32 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ",
+ 25833 : "+proj=utm +zone=33 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ",
+ 25834 : "+proj=utm +zone=34 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ",
+ 25835 : "+proj=utm +zone=35 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ",
+ 25836 : "+proj=utm +zone=36 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ",
+ 25837 : "+proj=utm +zone=37 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ",
+ 25838 : "+proj=utm +zone=38 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ",
+ 3060 : "+title=IGN72 Grande Terre / UTM zone 58S +proj=utm +zone=58 +south +ellps=intl +units=m +no_defs ",
+ 3163 : "+title=RGNC91-93 / Lambert New Caledonia +proj=lcc +lat_1=-20.66666666666667 +lat_2=-22.33333333333333 +lat_0=-21.5 +lon_0=166 +x_0=400000 +y_0=300000 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ",
+ 3164 : "+title=ST87 Ouvea / UTM zone 58S +proj=utm +zone=58 +south +ellps=WGS84 +towgs84=-56.263,16.136,-22.856,0,0,0,0 +units=m +no_defs ",
+ 3165 : "+title=NEA74 Noumea / Noumea Lambert +proj=lcc +lat_1=-22.24469175 +lat_2=-22.29469175 +lat_0=-22.26969175 +lon_0=166.44242575 +x_0=0.66 +y_0=1.02 +ellps=intl +units=m +no_defs ",
+ 3166 : "+title=NEA74 Noumea / Noumea Lambert 2 +proj=lcc +lat_1=-22.24472222222222 +lat_2=-22.29472222222222 +lat_0=-22.26972222222222 +lon_0=166.4425 +x_0=8.313000000000001 +y_0=-2.354 +ellps=intl +units=m +no_defs ",
+ 3169 : "+title=RGNC91-93 / UTM zone 57S +proj=utm +zone=57 +south +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ",
+ 3170 : "+title=RGNC91-93 / UTM zone 58S +proj=utm +zone=58 +south +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ",
+ 3171 : "+title=RGNC91-93 / UTM zone 59S +proj=utm +zone=59 +south +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ",
+ 3172 : "+title=IGN53 Mare / UTM zone 59S +proj=utm +zone=59 +south +ellps=intl +units=m +no_defs ",
+ 3296 : "+title=RGPF / UTM zone 5S +proj=utm +zone=5 +south +ellps=GRS80 +units=m +no_defs ",
+ 3297 : "+title=RGPF / UTM zone 6S +proj=utm +zone=6 +south +ellps=GRS80 +units=m +no_defs ",
+ 3298 : "+title=RGPF / UTM zone 7S +proj=utm +zone=7 +south +ellps=GRS80 +units=m +no_defs ",
+ 3299 : "+title=RGPF / UTM zone 8S +proj=utm +zone=8 +south +ellps=GRS80 +units=m +no_defs ",
+ 3302 : "+title=IGN63 Hiva Oa / UTM zone 7S +proj=utm +zone=7 +south +ellps=intl +units=m +no_defs ",
+ 3303 : "+title=Fatu Iva 72 / UTM zone 7S +proj=utm +zone=7 +south +ellps=intl +towgs84=347.103,1078.12,2623.92,-33.8875,70.6773,-9.3943,186.074 +units=m +no_defs ",
+ 3304 : "+title=Tahiti 79 / UTM zone 6S +proj=utm +zone=6 +south +ellps=intl +units=m +no_defs ",
+ 3305 : "+title=Moorea 87 / UTM zone 6S +proj=utm +zone=6 +south +ellps=intl +towgs84=215.525,149.593,176.229,-3.2624,-1.692,-1.1571,10.4773 +units=m +no_defs ",
+ 3306 : "+title=Maupiti 83 / UTM zone 5S +proj=utm +zone=5 +south +ellps=intl +towgs84=217.037,86.959,23.956,0,0,0,0 +units=m +no_defs ",
+ 3312 : "+title=CSG67 / UTM zone 21N +proj=utm +zone=21 +ellps=intl +towgs84=-186,230,110,0,0,0,0 +units=m +no_defs ",
+ 3313 : "+title=RGFG95 / UTM zone 21N +proj=utm +zone=21 +ellps=GRS80 +towgs84=2,2,-2,0,0,0,0 +units=m +no_defs ",
+ 3336 : "+title=IGN 1962 Kerguelen / UTM zone 42S +proj=utm +zone=42 +south +ellps=intl +towgs84=145,-187,103,0,0,0,0 +units=m +no_defs ",
+ 3395 : "+title=WGS 84 / World Mercator +proj=merc +lon_0=0 +k=1 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 3727 : "+title=Reunion 1947 / TM Reunion +proj=tmerc +lat_0=-21.11666666666667 +lon_0=55.53333333333333 +k=1 +x_0=160000 +y_0=50000 +ellps=intl +units=m +no_defs ",
+ 21781 : "+title=CH1903 / LV03 +proj=somerc +lat_0=46.95240555555556 +lon_0=7.439583333333333 +x_0=600000 +y_0=200000 +ellps=bessel +towgs84=674.374,15.056,405.346,0,0,0,0 +units=m +no_defs ",
+ 25830 : "+title=ETRS89 / UTM zone 30N +proj=utm +zone=30 +ellps=GRS80 +units=m +no_defs ",
+ 25831 : "+title=ETRS89 / UTM zone 31N +proj=utm +zone=31 +ellps=GRS80 +units=m +no_defs ",
+ 25832 : "+title=ETRS89 / UTM zone 32N +proj=utm +zone=32 +ellps=GRS80 +units=m +no_defs ",
+ 27561 : "+title=NTF (Paris) / Lambert Nord France +proj=lcc +lat_1=49.50000000000001 +lat_0=49.50000000000001 +lon_0=0 +k_0=0.999877341 +x_0=600000 +y_0=200000 +a=6378249.2 +b=6356515 +towgs84=-168,-60,320,0,0,0,0 +pm=paris +units=m +no_defs ",
+ 27562 : "+title=NTF (Paris) / Lambert Centre France +proj=lcc +lat_1=46.8 +lat_0=46.8 +lon_0=0 +k_0=0.99987742 +x_0=600000 +y_0=200000 +a=6378249.2 +b=6356515 +towgs84=-168,-60,320,0,0,0,0 +pm=paris +units=m +no_defs ",
+ 27563 : "+title=NTF (Paris) / Lambert Sud France +proj=lcc +lat_1=44.10000000000001 +lat_0=44.10000000000001 +lon_0=0 +k_0=0.9998774990000001 +x_0=600000 +y_0=200000 +a=6378249.2 +b=6356515 +towgs84=-168,-60,320,0,0,0,0 +pm=paris +units=m +no_defs ",
+ 27564 : "+title=NTF (Paris) / Lambert Corse +proj=lcc +lat_1=42.16500000000001 +lat_0=42.16500000000001 +lon_0=0 +k_0=0.9999447100000001 +x_0=234.358 +y_0=185861.369 +a=6378249.2 +b=6356515 +towgs84=-168,-60,320,0,0,0,0 +pm=paris +units=m +no_defs ",
+ 27571 : "+title=NTF (Paris) / Lambert zone I +proj=lcc +lat_1=49.50000000000001 +lat_0=49.50000000000001 +lon_0=0 +k_0=0.999877341 +x_0=600000 +y_0=1200000 +a=6378249.2 +b=6356515 +towgs84=-168,-60,320,0,0,0,0 +pm=paris +units=m +no_defs ",
+ 27572 : "+title=NTF (Paris) / Lambert zone II +proj=lcc +lat_1=46.8 +lat_0=46.8 +lon_0=0 +k_0=0.99987742 +x_0=600000 +y_0=2200000 +a=6378249.2 +b=6356515 +towgs84=-168,-60,320,0,0,0,0 +pm=paris +units=m +no_defs ",
+ 27573 : "+title=NTF (Paris) / Lambert zone III +proj=lcc +lat_1=44.10000000000001 +lat_0=44.10000000000001 +lon_0=0 +k_0=0.9998774990000001 +x_0=600000 +y_0=3200000 +a=6378249.2 +b=6356515 +towgs84=-168,-60,320,0,0,0,0 +pm=paris +units=m +no_defs ",
+ 27574 : "+title=NTF (Paris) / Lambert zone IV +proj=lcc +lat_1=42.16500000000001 +lat_0=42.16500000000001 +lon_0=0 +k_0=0.9999447100000001 +x_0=234.358 +y_0=4185861.369 +a=6378249.2 +b=6356515 +towgs84=-168,-60,320,0,0,0,0 +pm=paris +units=m +no_defs ",
+ 27581 : "+title=NTF (Paris) / France I (deprecated) +proj=lcc +lat_1=49.50000000000001 +lat_0=49.50000000000001 +lon_0=0 +k_0=0.999877341 +x_0=600000 +y_0=1200000 +a=6378249.2 +b=6356515 +towgs84=-168,-60,320,0,0,0,0 +pm=paris +units=m +no_defs ",
+ 27582 : "+title=NTF (Paris) / France II (deprecated) +proj=lcc +lat_1=46.8 +lat_0=46.8 +lon_0=0 +k_0=0.99987742 +x_0=600000 +y_0=2200000 +a=6378249.2 +b=6356515 +towgs84=-168,-60,320,0,0,0,0 +pm=paris +units=m +no_defs ",
+ 27583 : "+title=NTF (Paris) / France III (deprecated) +proj=lcc +lat_1=44.10000000000001 +lat_0=44.10000000000001 +lon_0=0 +k_0=0.9998774990000001 +x_0=600000 +y_0=3200000 +a=6378249.2 +b=6356515 +towgs84=-168,-60,320,0,0,0,0 +pm=paris +units=m +no_defs ",
+ 27584 : "+title=NTF (Paris) / France IV (deprecated) +proj=lcc +lat_1=42.16500000000001 +lat_0=42.16500000000001 +lon_0=0 +k_0=0.9999447100000001 +x_0=234.358 +y_0=4185861.369 +a=6378249.2 +b=6356515 +towgs84=-168,-60,320,0,0,0,0 +pm=paris +units=m +no_defs ",
+ 27591 : "+title=NTF (Paris) / Nord France (deprecated) +proj=lcc +lat_1=49.50000000000001 +lat_0=49.50000000000001 +lon_0=0 +k_0=0.999877341 +x_0=600000 +y_0=200000 +a=6378249.2 +b=6356515 +towgs84=-168,-60,320,0,0,0,0 +pm=paris +units=m +no_defs ",
+ 27592 : "+title=NTF (Paris) / Centre France (deprecated) +proj=lcc +lat_1=46.8 +lat_0=46.8 +lon_0=0 +k_0=0.99987742 +x_0=600000 +y_0=200000 +a=6378249.2 +b=6356515 +towgs84=-168,-60,320,0,0,0,0 +pm=paris +units=m +no_defs ",
+ 27593 : "+title=NTF (Paris) / Sud France (deprecated) +proj=lcc +lat_1=44.10000000000001 +lat_0=44.10000000000001 +lon_0=0 +k_0=0.9998774990000001 +x_0=600000 +y_0=200000 +a=6378249.2 +b=6356515 +towgs84=-168,-60,320,0,0,0,0 +pm=paris +units=m +no_defs ",
+ 27594 : "+title=NTF (Paris) / Corse (deprecated) +proj=lcc +lat_1=42.16500000000001 +lat_0=42.16500000000001 +lon_0=0 +k_0=0.9999447100000001 +x_0=234.358 +y_0=185861.369 +a=6378249.2 +b=6356515 +towgs84=-168,-60,320,0,0,0,0 +pm=paris +units=m +no_defs ",
+ 32601 : "+proj=utm +zone=1 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32602 : "+proj=utm +zone=2 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32603 : "+proj=utm +zone=3 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32604 : "+proj=utm +zone=4 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32605 : "+proj=utm +zone=5 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32606 : "+proj=utm +zone=6 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32607 : "+proj=utm +zone=7 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32608 : "+proj=utm +zone=8 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32609 : "+proj=utm +zone=9 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32610 : "+proj=utm +zone=10 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32611 : "+proj=utm +zone=11 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32612 : "+proj=utm +zone=12 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32613 : "+proj=utm +zone=13 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32614 : "+proj=utm +zone=14 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32615 : "+proj=utm +zone=15 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32616 : "+proj=utm +zone=16 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32617 : "+proj=utm +zone=17 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32618 : "+proj=utm +zone=18 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32619 : "+proj=utm +zone=19 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32620 : "+proj=utm +zone=20 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32621 : "+proj=utm +zone=21 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32622 : "+proj=utm +zone=22 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32623 : "+proj=utm +zone=23 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32624 : "+proj=utm +zone=24 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32625 : "+proj=utm +zone=25 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32626 : "+proj=utm +zone=26 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32627 : "+proj=utm +zone=27 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32628 : "+proj=utm +zone=28 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32629 : "+proj=utm +zone=29 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32630 : "+proj=utm +zone=30 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32631 : "+proj=utm +zone=31 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32632 : "+proj=utm +zone=32 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32633 : "+proj=utm +zone=33 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32634 : "+proj=utm +zone=34 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32635 : "+proj=utm +zone=35 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32636 : "+proj=utm +zone=36 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32637 : "+proj=utm +zone=37 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32638 : "+proj=utm +zone=38 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32639 : "+proj=utm +zone=39 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32640 : "+proj=utm +zone=40 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32641 : "+proj=utm +zone=41 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32642 : "+proj=utm +zone=42 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32643 : "+proj=utm +zone=43 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32644 : "+proj=utm +zone=44 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32645 : "+proj=utm +zone=45 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32646 : "+proj=utm +zone=46 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32647 : "+proj=utm +zone=47 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32648 : "+proj=utm +zone=48 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32649 : "+proj=utm +zone=49 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32650 : "+proj=utm +zone=50 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32651 : "+proj=utm +zone=51 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32652 : "+proj=utm +zone=52 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32653 : "+proj=utm +zone=53 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32654 : "+proj=utm +zone=54 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32655 : "+proj=utm +zone=55 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32656 : "+proj=utm +zone=56 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32657 : "+proj=utm +zone=57 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32658 : "+proj=utm +zone=58 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32659 : "+proj=utm +zone=59 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32660 : "+proj=utm +zone=60 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32661 : "+proj=stere +lat_0=90 +lat_ts=90 +lon_0=0 +k=0.994 +x_0=2000000 +y_0=2000000 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32662 : "+title=WGS 84 / Plate Carree +proj=eqc +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32701 : "+proj=utm +zone=1 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32702 : "+proj=utm +zone=2 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32703 : "+proj=utm +zone=3 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32704 : "+proj=utm +zone=4 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32705 : "+proj=utm +zone=5 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32706 : "+proj=utm +zone=6 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32707 : "+proj=utm +zone=7 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32708 : "+proj=utm +zone=8 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32709 : "+proj=utm +zone=9 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32710 : "+proj=utm +zone=10 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32711 : "+proj=utm +zone=11 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32712 : "+proj=utm +zone=12 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32713 : "+proj=utm +zone=13 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32714 : "+proj=utm +zone=14 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32715 : "+proj=utm +zone=15 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32716 : "+proj=utm +zone=16 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32717 : "+proj=utm +zone=17 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32718 : "+proj=utm +zone=18 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32719 : "+proj=utm +zone=19 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32720 : "+proj=utm +zone=20 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32721 : "+proj=utm +zone=21 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32722 : "+proj=utm +zone=22 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32723 : "+proj=utm +zone=23 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32724 : "+proj=utm +zone=24 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32725 : "+proj=utm +zone=25 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32726 : "+proj=utm +zone=26 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32727 : "+proj=utm +zone=27 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32728 : "+proj=utm +zone=28 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32729 : "+proj=utm +zone=29 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32730 : "+proj=utm +zone=30 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32731 : "+proj=utm +zone=31 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32732 : "+proj=utm +zone=32 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32733 : "+proj=utm +zone=33 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32734 : "+proj=utm +zone=34 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32735 : "+proj=utm +zone=35 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32736 : "+proj=utm +zone=36 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32737 : "+proj=utm +zone=37 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32738 : "+proj=utm +zone=38 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32739 : "+proj=utm +zone=39 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32740 : "+proj=utm +zone=40 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32741 : "+proj=utm +zone=41 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32742 : "+proj=utm +zone=42 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32743 : "+proj=utm +zone=43 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32744 : "+proj=utm +zone=44 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32745 : "+proj=utm +zone=45 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32746 : "+proj=utm +zone=46 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32747 : "+proj=utm +zone=47 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32748 : "+proj=utm +zone=48 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32749 : "+proj=utm +zone=49 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32750 : "+proj=utm +zone=50 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32751 : "+proj=utm +zone=51 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32752 : "+proj=utm +zone=52 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32753 : "+proj=utm +zone=53 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32754 : "+proj=utm +zone=54 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32755 : "+proj=utm +zone=55 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32756 : "+proj=utm +zone=56 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32757 : "+proj=utm +zone=57 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32758 : "+proj=utm +zone=58 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32759 : "+proj=utm +zone=59 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32760 : "+proj=utm +zone=60 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 32761 : "+proj=stere +lat_0=-90 +lat_ts=-90 +lon_0=0 +k=0.994 +x_0=2000000 +y_0=2000000 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ",
+ 310024802 : "+title=Geoportail - France metropolitaine +proj=eqc +nadgrids=null +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=0.000000000 +lat_ts=46.500000000 +x_0=0.000 +y_0=0.000 +units=m +no_defs",
+ 310915814 : "+title=Geoportail - Antilles francaises +proj=eqc +nadgrids=null +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=0.000000000 +lat_ts=15.000000000 +x_0=0.000 +y_0=0.000 +units=m +no_defs",
+ 310486805 : "+title=Geoportail - Guyane +proj=eqc +nadgrids=null +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=0.000000000 +lat_ts=4.000000000 +x_0=0.000 +y_0=0.000 +units=m +no_defs",
+ 310700806 : "+title=Geoportail - Reunion et dependances +proj=eqc +nadgrids=null +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=0.000000000 +lat_ts=-21.000000000 +x_0=0.000 +y_0=0.000 +units=m +no_defs",
+ 310702807 : "+title=Geoportail - Mayotte +proj=eqc +nadgrids=null +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=0.000000000 +lat_ts=-12.000000000 +x_0=0.000 +y_0=0.000 +units=m +no_defs",
+ 310706808 : "+title=Geoportail - Saint-Pierre et Miquelon +proj=eqc +nadgrids=null +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=0.000000000 +lat_ts=47.000000000 +x_0=0.000 +y_0=0.000 +units=m +no_defs",
+ 310547809 : "+title=Geoportail - Nouvelle-Caledonie +proj=eqc +nadgrids=null +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=0.000000000 +lat_ts=-22.000000000 +x_0=0.000 +y_0=0.000 +units=m +no_defs",
+ 310642810 : "+title=Geoportail - Wallis et Futuna +proj=eqc +nadgrids=null +towgs84=0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.000000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=0.000000000 +lat_ts=-14.000000000 +x_0=0.000 +y_0=0.000 +units=m +no_defs",
+ 310032811 : "+title=Geoportail - Polynesie francaise +proj=eqc +nadgrids=null +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=0.000000000 +lat_ts=-15.000000000 +x_0=0.000 +y_0=0.000 +units=m +no_defs",
+ 310642812 : "+title=Geoportail - Kerguelen +proj=eqc +nadgrids=null +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=0.000000000 +lat_ts=-49.500000000 +x_0=0.000 +y_0=0.000 +units=m +no_defs",
+ 310642801 : "+title=Geoportail - Crozet +proj=eqc +nadgrids=null +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=0.000000000 +lat_ts=-46.000000000 +x_0=0.000 +y_0=0.000 +units=m +no_defs",
+ 310642813 : "+title=Geoportail - Amsterdam et Saint-Paul +proj=eqc +nadgrids=null +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=0.000000000 +lat_ts=-38.000000000 +x_0=0.000 +y_0=0.000 +units=m +no_defs",
+ 310642901 : "+title=Geoportail - Monde +proj=mill +towgs84=0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.000000 +a=6378137.0000 +rf=298.2572221010000 +lon_0=0.000000000 +x_0=0.000 +y_0=0.000 +units=m +no_defs",
+ 5489 : "+title=RGAF09 geographiques (dms) +proj=longlat +nadgrids=@null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137 +rf=298.257222101 +units=m +no_defs",
+ 5490 : "+title=RGAF09 UTM Nord Fuseau 20 +proj=tmerc +nadgrids=@null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137 +rf=298.257222101 +lat_0=0.000000000 +lon_0=-63.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=0.000 +units=m +no_defs"
+ },
+ CRS : {
+ 84 : "+title=WGS 84 longitude-latitude +proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs "
+ },
+ IGNF : {
+ // AMST63 : "+title=Amsterdam 1963 +proj=geocent +towgs84=109.753,-528.133,-362.244,0,0,0,0 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs",
+ // CROZ63 : "+title=Crozet 1963 +proj=geocent +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs",
+ // CSG67 : "+title=Guyane CSG67 +proj=geocent +towgs84=-193.0660,236.9930,105.4470,0.4814,-0.8074,0.1276,1.564900 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs",
+ // ED50 : "+title=ED50 +proj=geocent +towgs84=-84.0000,-97.0000,-117.0000 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs",
+ // ETRS89 : "+title=Systeme de reference terrestre Europeen (1989) +proj=geocent +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +units=m +no_defs",
+ // GUAD48 : "+title=Guadeloupe Ste Anne +proj=geocent +towgs84=-472.2900,-5.6300,-304.1200,0.4362,-0.8374,0.2563,1.898400 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs",
+ // GUADFM49 : "+title=Guadeloupe Fort Marigot +proj=geocent +towgs84=136.5960,248.1480,-429.7890 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs",
+ // IGN63 : "+title=IGN 1963 (Hiva Oa, Tahuata, Mohotani) +proj=geocent +towgs84=410.7210,55.0490,80.7460,-2.5779,-2.3514,-0.6664,17.331100 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs",
+ // IGN72 : "+title=IGN 1972 Grande-Terre / Ile des Pins +proj=geocent +towgs84=-11.6400,-348.6000,291.6800 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs",
+ // KERG62CAR : "+title=Kerguelen - K0 +proj=geocent +towgs84=144.8990,-186.7700,100.9230 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs",
+ // MART38 : "+title=Martinique Fort-Desaix +proj=geocent +towgs84=126.9260,547.9390,130.4090,-2.7867,5.1612,-0.8584,13.822650 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs",
+ // MAYO50 : "+title=Mayotte Combani +proj=geocent +towgs84=-599.9280,-275.5520,-195.6650,-0.0835,-0.4715,0.0602,49.281400 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs",
+ // MOOREA87 : "+title=Moorea 1987 +proj=geocent +towgs84=215.9820,149.5930,176.2290,3.2624,1.6920,1.1571,10.477300 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs",
+ // NTF : "+title=Nouvelle Triangulation Francaise +proj=geocent +nadgrids=ntf_r93.gsb,null +wktext +towgs84=-168.0000,-60.0000,320.0000 +a=6378249.2000 +rf=293.4660210000000 +units=m +no_defs",
+ // NUKU72 : "+title=IGN 1972 Nuku Hiva +proj=geocent +towgs84=165.7320,216.7200,180.5050,-0.6434,-0.4512,-0.0791,7.420400 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs",
+ // REUN47 : "+title=Reunion 1947 +proj=geocent +towgs84=789.5240,-626.4860,-89.9040,0.6006,76.7946,-10.5788,-32.324100 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs",
+ // RGF93 : "+title=Reseau geodesique francais 1993 +proj=geocent +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +units=m +no_defs",
+ // RGFG95 : "+title=Reseau geodesique francais de Guyane 1995 +proj=geocent +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +units=m +no_defs",
+ // RGM04 : "+title=RGM04 (Reseau Geodesique de Mayotte 2004) +proj=geocent +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +units=m +no_defs",
+ // RGNC : "+title=Reseau Geodesique de Nouvelle-Caledonie +proj=geocent +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +units=m +no_defs",
+ // RGPF : "+title=RGPF (Reseau Geodesique de Polynesie Francaise) +proj=geocent +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +units=m +no_defs",
+ // RGR92 : "+title=Reseau geodesique Reunion 1992 +proj=geocent +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +units=m +no_defs",
+ // RGSPM06 : "+title=Reseau Geodesique Saint-Pierre-et-Miquelon (2006) +proj=geocent +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +units=m +no_defs",
+ // RGTAAF07 : "+title=Reseau Geodesique des TAAF (2007) +proj=geocent +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +units=m +no_defs",
+ // RRAF91 : "+title=RRAF 1991 (Reseau de Reference des Antilles Francaises) +proj=geocent +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +units=m +no_defs",
+ // STPL69 : "+title=Saint-Paul 1969 +proj=geocent +towgs84=225.571,-346.608,-46.567,0,0,0,0 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs",
+ // STPM50 : "+title=St Pierre et Miquelon 1950 +proj=geocent +towgs84=-95.5930,573.7630,173.4420,-0.9602,1.2510,-1.3918,42.626500 +a=6378206.4000 +rf=294.9786982000000 +units=m +no_defs",
+ // TAHAA : "+title=Raiatea - Tahaa 51-54 (Tahaa, Base Terme Est) +proj=geocent +towgs84=72.4380,345.9180,79.4860,-1.6045,-0.8823,-0.5565,1.374600 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs",
+ // TAHI79 : "+title=IGN79 (Tahiti) Iles de la Societe +proj=geocent +towgs84=221.5250,152.9480,176.7680,2.3847,1.3896,0.8770,11.474100 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs",
+ // TERA50 : "+title=Pointe Geologie - Perroud 1950 +proj=geocent +towgs84=324.9120,153.2820,172.0260 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs",
+ // WALL78 : "+title=Wallis-Uvea 1978 (MOP78) +proj=geocent +towgs84=253.0000,-133.0000,-127.0000 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs",
+ // WGS72 : "+title=World Geodetic System 1972 +proj=geocent +towgs84=0.0000,12.0000,6.0000 +a=6378135.0000 +rf=298.2600000000000 +units=m +no_defs",
+ // WGS84 : "+title=World Geodetic System 1984 +proj=geocent +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +units=m +no_defs",
+ AMST63GEO : "+title=Amsterdam 1963 +proj=longlat +towgs84=109.753,-528.133,-362.244,0,0,0,0 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs",
+ CROZ63GEO : "+title=Crozet 1963 +proj=longlat +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs",
+ CSG67GEO : "+title=Guyane CSG67 +proj=longlat +towgs84=-193.0660,236.9930,105.4470,0.4814,-0.8074,0.1276,1.564900 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs",
+ ED50G : "+title=ED50 +proj=longlat +towgs84=-84.0000,-97.0000,-117.0000 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs",
+ GUAD48GEO : "+title=Guadeloupe Ste Anne +proj=longlat +towgs84=-472.2900,-5.6300,-304.1200,0.4362,-0.8374,0.2563,1.898400 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs",
+ GUADFM49GEO : "+title=Guadeloupe Fort Marigot +proj=longlat +towgs84=136.5960,248.1480,-429.7890 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs",
+ IGN63GEO : "+title=IGN 1963 (Hiva Oa, Tahuata, Mohotani) +proj=longlat +towgs84=410.7210,55.0490,80.7460,-2.5779,-2.3514,-0.6664,17.331100 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs",
+ IGN72GEO : "+title=IGN 1972 Grande-Terre / Ile des Pins +proj=longlat +towgs84=-11.6400,-348.6000,291.6800 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs",
+ KERG62GEO : "+title=Kerguelen - K0 +proj=longlat +towgs84=144.8990,-186.7700,100.9230 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs",
+ MART38GEO : "+title=Martinique Fort-Desaix +proj=longlat +towgs84=126.9260,547.9390,130.4090,-2.7867,5.1612,-0.8584,13.822650 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs",
+ MAYO50GEO : "+title=Mayotte Combani +proj=longlat +towgs84=-599.9280,-275.5520,-195.6650,-0.0835,-0.4715,0.0602,49.281400 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs",
+ MOOREA87GEO : "+title=Moorea 1987 +proj=longlat +towgs84=215.9820,149.5930,176.2290,3.2624,1.6920,1.1571,10.477300 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs",
+ NTFG : "+title=Nouvelle Triangulation Francaise Greenwich degres sexagesimaux +proj=longlat +nadgrids=ntf_r93.gsb,null +wktext +towgs84=-168.0000,-60.0000,320.0000 +a=6378249.2000 +rf=293.4660210000000 +units=m +no_defs",
+ NTFP : "+title=Nouvelle Triangulation Francaise Paris grades +proj=longlat +nadgrids=ntf_r93.gsb,null +wktext +towgs84=-168.0000,-60.0000,320.0000 +a=6378249.2000 +rf=293.4660210000000 +pm=2.337229167 +units=m +no_defs",
+ NUKU72GEO : "+title=IGN 1972 Nuku Hiva +proj=longlat +towgs84=165.7320,216.7200,180.5050,-0.6434,-0.4512,-0.0791,7.420400 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs",
+ REUN47GEO : "+title=Reunion 1947 +proj=longlat +towgs84=789.5240,-626.4860,-89.9040,0.6006,76.7946,-10.5788,-32.324100 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs",
+ RGF93G : "+title=Reseau geodesique francais 1993 +proj=longlat +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +units=m +no_defs",
+ RGFG95GEO : "+title=Reseau geodesique francais de Guyane 1995 +proj=longlat +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +units=m +no_defs",
+ RGM04GEO : "+title=RGM04 (Reseau Geodesique de Mayotte 2004) +proj=longlat +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +units=m +no_defs",
+ RGNCGEO : "+title=Reseau Geodesique de Nouvelle-Caledonie +proj=longlat +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +units=m +no_defs",
+ RGPFGEO : "+title=RGPF (Reseau Geodesique de Polynesie Francaise) +proj=longlat +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +units=m +no_defs",
+ RGR92GEO : "+title=Reseau geodesique de la Reunion 1992 +proj=longlat +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +units=m +no_defs",
+ RGSPM06GEO : "+title=Saint-Pierre-et-Miquelon (2006) +proj=longlat +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +units=m +no_defs",
+ RGTAAF07G : "+title=Reseau Geodesique des TAAF (2007) (dms) +proj=longlat +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +units=m +no_defs",
+ STPL69GEO : "+title=Saint-Paul 1969 +proj=longlat +towgs84=225.571,-346.608,-46.567,0,0,0,0 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs",
+ STPM50GEO : "+title=St Pierre et Miquelon 1950 +proj=longlat +towgs84=-95.5930,573.7630,173.4420,-0.9602,1.2510,-1.3918,42.626500 +a=6378206.4000 +rf=294.9786982000000 +units=m +no_defs",
+ TAHAAGEO : "+title=Raiatea - Tahaa 51-54 (Tahaa, Base Terme Est) +proj=longlat +towgs84=72.4380,345.9180,79.4860,-1.6045,-0.8823,-0.5565,1.374600 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs",
+ TAHI79GEO : "+title=IGN79 (Tahiti) Iles de la Societe +proj=longlat +towgs84=221.5250,152.9480,176.7680,2.3847,1.3896,0.8770,11.474100 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs",
+ TERA50G : "+title=Pointe Geologie - Perroud 1950 +proj=longlat +towgs84=324.9120,153.2820,172.0260 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs",
+ WALL78GEO : "+title=Wallis - Uvea 1978 (MOP78) +proj=longlat +towgs84=253.0000,-133.0000,-127.0000 +a=6378388.0000 +rf=297.0000000000000 +units=m +no_defs",
+ WGS72G : "+title=WGS72 +proj=longlat +towgs84=0.0000,12.0000,6.0000 +a=6378135.0000 +rf=298.2600000000000 +units=m +no_defs",
+ WGS84G : "+title=World Geodetic System 1984 +proj=longlat +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +units=m +no_defs",
+ WGS84RRAFGEO : "+title=Reseau de reference des Antilles francaises (1988-1991) +proj=longlat +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +units=m +no_defs",
+ XGEO : "+title=Systeme CIO-BIH +proj=longlat +towgs84=0.0000,0.0000,0.5000,0.0000,0.0000,0.0140,-0.100000 +a=6378137.0000 +rf=298.2572221010000 +units=m +no_defs",
+ AMST63UTM43S : "+title=Amsterdam 1963 UTM fuseau 43 Sud +proj=tmerc +towgs84=109.753,-528.133,-362.244,0,0,0,0 +a=6378388.0000 +rf=297.0000000000000 +lat_0=0.000000000 +lon_0=75.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=10000000.000 +units=m +no_defs",
+ CROZ63UTM39S : "+title=Crozet 1963 +proj=tmerc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378388.0000 +rf=297.0000000000000 +lat_0=0.000000000 +lon_0=51.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=10000000.000 +units=m +no_defs",
+ CSG67UTM21 : "+title=Guyane CSG67 UTM fuseau 21 +proj=tmerc +towgs84=-193.0660,236.9930,105.4470,0.4814,-0.8074,0.1276,1.564900 +a=6378388.0000 +rf=297.0000000000000 +lat_0=0.000000000 +lon_0=-57.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=0.000 +units=m +no_defs",
+ CSG67UTM22 : "+title=Guyane CSG67 UTM fuseau 22 +proj=tmerc +towgs84=-193.0660,236.9930,105.4470,0.4814,-0.8074,0.1276,1.564900 +a=6378388.0000 +rf=297.0000000000000 +lat_0=0.000000000 +lon_0=-51.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=0.000 +units=m +no_defs",
+ GEOPORTALANF : "+title=Geoportail - Antilles francaises +proj=eqc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=0.000000000 +lat_ts=15.000000000 +x_0=0.000 +y_0=0.000 +units=m +no_defs",
+ GEOPORTALASP : "+title=Geoportail - Amsterdam et Saint-Paul +proj=eqc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=0.000000000 +lat_ts=-38.000000000 +x_0=0.000 +y_0=0.000 +units=m +no_defs",
+ GEOPORTALCRZ : "+title=Geoportail - Crozet +proj=eqc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=0.000000000 +lat_ts=-46.000000000 +x_0=0.000 +y_0=0.000 +units=m +no_defs",
+ GEOPORTALFXX : "+title=Geoportail - France metropolitaine +proj=eqc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=0.000000000 +lat_ts=46.500000000 +x_0=0.000 +y_0=0.000 +units=m +no_defs",
+ GEOPORTALGUF : "+title=Geoportail - Guyane +proj=eqc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=0.000000000 +lat_ts=4.000000000 +x_0=0.000 +y_0=0.000 +units=m +no_defs",
+ GEOPORTALKER : "+title=Geoportail - Kerguelen +proj=eqc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=0.000000000 +lat_ts=-49.500000000 +x_0=0.000 +y_0=0.000 +units=m +no_defs",
+ GEOPORTALMYT : "+title=Geoportail - Mayotte +proj=eqc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=0.000000000 +lat_ts=-12.000000000 +x_0=0.000 +y_0=0.000 +units=m +no_defs",
+ GEOPORTALNCL : "+title=Geoportail - Nouvelle-Caledonie +proj=eqc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=0.000000000 +lat_ts=-22.000000000 +x_0=0.000 +y_0=0.000 +units=m +no_defs",
+ GEOPORTALPYF : "+title=Geoportail - Polynesie francaise +proj=eqc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=0.000000000 +lat_ts=-15.000000000 +x_0=0.000 +y_0=0.000 +units=m +no_defs",
+ GEOPORTALREU : "+title=Geoportail - Reunion et dependances +proj=eqc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=0.000000000 +lat_ts=-21.000000000 +x_0=0.000 +y_0=0.000 +units=m +no_defs",
+ GEOPORTALSPM : "+title=Geoportail - Saint-Pierre et Miquelon +proj=eqc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=0.000000000 +lat_ts=47.000000000 +x_0=0.000 +y_0=0.000 +units=m +no_defs",
+ GEOPORTALWLF : "+title=Geoportail - Wallis et Futuna +proj=eqc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=0.000000000 +lat_ts=-14.000000000 +x_0=0.000 +y_0=0.000 +units=m +no_defs",
+ GUAD48UTM20 : "+title=Guadeloupe Ste Anne +proj=tmerc +towgs84=-472.2900,-5.6300,-304.1200,0.4362,-0.8374,0.2563,1.898400 +a=6378388.0000 +rf=297.0000000000000 +lat_0=0.000000000 +lon_0=-63.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=0.000 +units=m +no_defs",
+ GUADFM49U20 : "+title=Guadeloupe Fort Marigot +proj=tmerc +towgs84=136.5960,248.1480,-429.7890 +a=6378388.0000 +rf=297.0000000000000 +lat_0=0.000000000 +lon_0=-63.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=0.000 +units=m +no_defs",
+ IGN63UTM7S : "+title=IGN 1963 - Hiva Oa, Tahuata, Mohotani - UTM fuseau 7 Sud +proj=tmerc +towgs84=410.7210,55.0490,80.7460,-2.5779,-2.3514,-0.6664,17.331100 +a=6378388.0000 +rf=297.0000000000000 +lat_0=0.000000000 +lon_0=-141.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=10000000.000 +units=m +no_defs",
+ IGN72UTM58S : "+title=IGN 1972 - UTM fuseau 58 Sud +proj=tmerc +towgs84=-11.6400,-348.6000,291.6800 +a=6378388.0000 +rf=297.0000000000000 +lat_0=0.000000000 +lon_0=165.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=10000000.000 +units=m +no_defs",
+ KERG62UTM42S : "+title=Kerguelen 1962 +proj=tmerc +towgs84=144.8990,-186.7700,100.9230 +a=6378388.0000 +rf=297.0000000000000 +lat_0=0.000000000 +lon_0=69.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=10000000.000 +units=m +no_defs",
+ LAMB1 : "+title=Lambert I +proj=lcc +nadgrids=ntf_r93.gsb,null +wktext +towgs84=-168.0000,-60.0000,320.0000 +a=6378249.2000 +rf=293.4660210000000 +pm=2.337229167 +lat_0=49.500000000 +lon_0=0.000000000 +k_0=0.99987734 +lat_1=49.500000000 +x_0=600000.000 +y_0=200000.000 +units=m +no_defs",
+ LAMB1C : "+title=Lambert I Carto +proj=lcc +nadgrids=ntf_r93.gsb,null +wktext +towgs84=-168.0000,-60.0000,320.0000 +a=6378249.2000 +rf=293.4660210000000 +pm=2.337229167 +lat_0=49.500000000 +lon_0=0.000000000 +k_0=0.99987734 +lat_1=49.500000000 +x_0=600000.000 +y_0=1200000.000 +units=m +no_defs",
+ LAMB2 : "+title=Lambert II +proj=lcc +nadgrids=ntf_r93.gsb,null +wktext +towgs84=-168.0000,-60.0000,320.0000 +a=6378249.2000 +rf=293.4660210000000 +pm=2.337229167 +lat_0=46.800000000 +lon_0=0.000000000 +k_0=0.99987742 +lat_1=46.800000000 +x_0=600000.000 +y_0=200000.000 +units=m +no_defs",
+ LAMB2C : "+title=Lambert II Carto +proj=lcc +nadgrids=ntf_r93.gsb,null +wktext +towgs84=-168.0000,-60.0000,320.0000 +a=6378249.2000 +rf=293.4660210000000 +pm=2.337229167 +lat_0=46.800000000 +lon_0=0.000000000 +k_0=0.99987742 +lat_1=46.800000000 +x_0=600000.000 +y_0=2200000.000 +units=m +no_defs",
+ LAMB3 : "+title=Lambert III +proj=lcc +nadgrids=ntf_r93.gsb,null +wktext +towgs84=-168.0000,-60.0000,320.0000 +a=6378249.2000 +rf=293.4660210000000 +pm=2.337229167 +lat_0=44.100000000 +lon_0=0.000000000 +k_0=0.99987750 +lat_1=44.100000000 +x_0=600000.000 +y_0=200000.000 +units=m +no_defs",
+ LAMB3C : "+title=Lambert III Carto +proj=lcc +nadgrids=ntf_r93.gsb,null +wktext +towgs84=-168.0000,-60.0000,320.0000 +a=6378249.2000 +rf=293.4660210000000 +pm=2.337229167 +lat_0=44.100000000 +lon_0=0.000000000 +k_0=0.99987750 +lat_1=44.100000000 +x_0=600000.000 +y_0=3200000.000 +units=m +no_defs",
+ LAMB4 : "+title=Lambert IV +proj=lcc +nadgrids=ntf_r93.gsb,null +wktext +towgs84=-168.0000,-60.0000,320.0000 +a=6378249.2000 +rf=293.4660210000000 +pm=2.337229167 +lat_0=42.165000000 +lon_0=0.000000000 +k_0=0.99994471 +lat_1=42.165000000 +x_0=234.358 +y_0=185861.369 +units=m +no_defs",
+ LAMB4C : "+title=Lambert IV Carto +proj=lcc +nadgrids=ntf_r93.gsb,null +wktext +towgs84=-168.0000,-60.0000,320.0000 +a=6378249.2000 +rf=293.4660210000000 +pm=2.337229167 +lat_0=42.165000000 +lon_0=0.000000000 +k_0=0.99994471 +lat_1=42.165000000 +x_0=234.358 +y_0=4185861.369 +units=m +no_defs",
+ LAMB93 : "+title=Lambert 93 +proj=lcc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=46.500000000 +lon_0=3.000000000 +lat_1=44.000000000 +lat_2=49.000000000 +x_0=700000.000 +y_0=6600000.000 +units=m +no_defs",
+ RGF93CC42 : "+title=Lambert conique conforme Zone 1 +proj=lcc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=42.000000000 +lon_0=3.000000000 +lat_1=41.200000000 +lat_2=42.800000000 +x_0=1700000.000 +y_0=1200000.000 +units=m +no_defs",
+ RGF93CC43 : "+title=Lambert conique conforme Zone 2 +proj=lcc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=43.000000000 +lon_0=3.000000000 +lat_1=42.200000000 +lat_2=43.800000000 +x_0=1700000.000 +y_0=2200000.000 +units=m +no_defs",
+ RGF93CC44 : "+title=Lambert conique conforme Zone 3 +proj=lcc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=44.000000000 +lon_0=3.000000000 +lat_1=43.200000000 +lat_2=44.800000000 +x_0=1700000.000 +y_0=3200000.000 +units=m +no_defs",
+ RGF93CC45 : "+title=Lambert conique conforme Zone 4 +proj=lcc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=45.000000000 +lon_0=3.000000000 +lat_1=44.200000000 +lat_2=45.800000000 +x_0=1700000.000 +y_0=4200000.000 +units=m +no_defs",
+ RGF93CC46 : "+title=Lambert conique conforme Zone 5 +proj=lcc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=46.000000000 +lon_0=3.000000000 +lat_1=45.200000000 +lat_2=46.800000000 +x_0=1700000.000 +y_0=5200000.000 +units=m +no_defs",
+ RGF93CC47 : "+title=Lambert conique conforme Zone 6 +proj=lcc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=47.000000000 +lon_0=3.000000000 +lat_1=46.200000000 +lat_2=47.800000000 +x_0=1700000.000 +y_0=6200000.000 +units=m +no_defs",
+ RGF93CC48 : "+title=Lambert conique conforme Zone 7 +proj=lcc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=48.000000000 +lon_0=3.000000000 +lat_1=47.200000000 +lat_2=48.800000000 +x_0=1700000.000 +y_0=7200000.000 +units=m +no_defs",
+ RGF93CC49 : "+title=Lambert conique conforme Zone 8 +proj=lcc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=49.000000000 +lon_0=3.000000000 +lat_1=48.200000000 +lat_2=49.800000000 +x_0=1700000.000 +y_0=8200000.000 +units=m +no_defs",
+ RGF93CC50 : "+title=Lambert conique conforme Zone 9 +proj=lcc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=50.000000000 +lon_0=3.000000000 +lat_1=49.200000000 +lat_2=50.800000000 +x_0=1700000.000 +y_0=9200000.000 +units=m +no_defs",
+ LAMBE : "+title=Lambert II etendu +proj=lcc +nadgrids=ntf_r93.gsb,null +wktext +towgs84=-168.0000,-60.0000,320.0000 +a=6378249.2000 +rf=293.4660210000000 +pm=2.337229167 +lat_0=46.800000000 +lon_0=0.000000000 +k_0=0.99987742 +lat_1=46.800000000 +x_0=600000.000 +y_0=2200000.000 +units=m +no_defs",
+ MART38UTM20 : "+title=Martinique Fort-Desaix +proj=tmerc +towgs84=126.9260,547.9390,130.4090,-2.7867,5.1612,-0.8584,13.822650 +a=6378388.0000 +rf=297.0000000000000 +lat_0=0.000000000 +lon_0=-63.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=0.000 +units=m +no_defs",
+ MAYO50UTM38S : "+title=Mayotte Combani +proj=tmerc +towgs84=-599.9280,-275.5520,-195.6650,-0.0835,-0.4715,0.0602,49.281400 +a=6378388.0000 +rf=297.0000000000000 +lat_0=0.000000000 +lon_0=45.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=10000000.000 +units=m +no_defs",
+ MILLER : "+title=Geoportail - Monde +proj=mill +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lon_0=0.000000000 +x_0=0.000 +y_0=0.000 +units=m +no_defs",
+ MOOREA87U6S : "+title=Moorea 1987 - UTM fuseau 6 Sud +proj=tmerc +towgs84=215.9820,149.5930,176.2290,3.2624,1.6920,1.1571,10.477300 +a=6378388.0000 +rf=297.0000000000000 +lat_0=0.000000000 +lon_0=-147.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=10000000.000 +units=m +no_defs",
+ NUKU72U7S : "+title=IGN 1972 Nuku Hiva - UTM fuseau 7 Sud +proj=tmerc +towgs84=165.7320,216.7200,180.5050,-0.6434,-0.4512,-0.0791,7.420400 +a=6378388.0000 +rf=297.0000000000000 +lat_0=0.000000000 +lon_0=-141.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=10000000.000 +units=m +no_defs",
+ // REUN47GAUSSL : "+title=Reunion Gauss Laborde +proj=gstmerc +towgs84=789.5240,-626.4860,-89.9040,0.6006,76.7946,-10.5788,-32.324100 +a=6378388.0000 +rf=297.0000000000000 +lat_0=-21.116666667 +lon_0=55.533333333 +k_0=1.00000000 +x_0=160000.000 +y_0=50000.000 +units=m +no_defs",
+ RGM04UTM38S : "+title=UTM fuseau 38 Sud (Reseau Geodesique de Mayotte 2004) +proj=tmerc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=45.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=10000000.000 +units=m +no_defs",
+ RGNCUTM57S : "+title=Reseau Geodesique de Nouvelle-Caledonie - UTM fuseau 57 Sud +proj=tmerc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=159.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=10000000.000 +units=m +no_defs",
+ RGNCUTM58S : "+title=Reseau Geodesique de Nouvelle-Caledonie - UTM fuseau 58 Sud +proj=tmerc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=165.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=10000000.000 +units=m +no_defs",
+ RGNCUTM59S : "+title=Reseau Geodesique de Nouvelle-Caledonie - UTM fuseau 59 Sud +proj=tmerc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=171.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=10000000.000 +units=m +no_defs",
+ RGPFUTM5S : "+title=RGPF - UTM fuseau 5 Sud +proj=tmerc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=-153.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=10000000.000 +units=m +no_defs",
+ RGPFUTM6S : "+title=RGPF - UTM fuseau 6 Sud +proj=tmerc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=-147.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=10000000.000 +units=m +no_defs",
+ RGPFUTM7S : "+title=RGPF - UTM fuseau 7 Sud +proj=tmerc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=-141.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=10000000.000 +units=m +no_defs",
+ RGR92UTM40S : "+title=RGR92 UTM fuseau 40 Sud +proj=tmerc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=57.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=10000000.000 +units=m +no_defs",
+ RGSPM06U21 : "+title=Saint-Pierre-et-Miquelon (2006) UTM Fuseau 21 Nord +proj=tmerc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=-57.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=0.000 +units=m +no_defs",
+ STPL69UTM43S : "+title=Saint-Paul 1969 UTM fuseau 43 Sud +proj=tmerc +towgs84=225.571,-346.608,-46.567,0,0,0,0 +a=6378388.0000 +rf=297.0000000000000 +lat_0=0.000000000 +lon_0=75.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=10000000.000 +units=m +no_defs",
+ STPM50UTM21 : "+title=St Pierre et Miquelon 1950 +proj=tmerc +towgs84=-95.5930,573.7630,173.4420,-0.9602,1.2510,-1.3918,42.626500 +a=6378206.4000 +rf=294.9786982000000 +lat_0=0.000000000 +lon_0=-57.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=0.000 +units=m +no_defs",
+ TAHAAUTM05S : "+title=Tahaa 1951 +proj=tmerc +towgs84=72.4380,345.9180,79.4860,-1.6045,-0.8823,-0.5565,1.374600 +a=6378388.0000 +rf=297.0000000000000 +lat_0=0.000000000 +lon_0=-153.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=10000000.000 +units=m +no_defs",
+ TAHI51UTM06S : "+title=Tahiti-Terme Nord UTM fuseau 6 Sud +proj=tmerc +towgs84=162.0000,117.0000,154.0000 +a=6378388.0000 +rf=297.0000000000000 +lat_0=0.000000000 +lon_0=-147.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=10000000.000 +units=m +no_defs",
+ TAHI79UTM6S : "+title=Tahiti 1979 +proj=tmerc +towgs84=221.5250,152.9480,176.7680,2.3847,1.3896,0.8770,11.474100 +a=6378388.0000 +rf=297.0000000000000 +lat_0=0.000000000 +lon_0=-147.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=10000000.000 +units=m +no_defs",
+ TERA50STEREO : "+title=Terre Adelie 1950 +proj=stere +towgs84=324.9120,153.2820,172.0260 +a=6378388.0000 +rf=297.0000000000000 +lat_0=-90.000000000 +lon_0=140.000000000 +lat_ts=-67 +k=0.96027295 +x_0=300000.000 +y_0=-2299363.482 +units=m +no_defs",
+ UTM01SW84 : "+title=World Geodetic System 1984 UTM fuseau 01 Sud +proj=tmerc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=-177.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=10000000.000 +units=m +no_defs",
+ UTM20W84GUAD : "+title=World Geodetic System 1984 UTM fuseau 20 Nord-Guadeloupe +proj=tmerc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=-63.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=0.000 +units=m +no_defs",
+ UTM20W84MART : "+title=World Geodetic System 1984 UTM fuseau 20 Nord-Martinique +proj=tmerc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=-63.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=0.000 +units=m +no_defs",
+ UTM22RGFG95 : "+title=RGFG95 UTM fuseau 22 Nord-Guyane +proj=tmerc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=-51.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=0.000 +units=m +no_defs",
+ UTM39SW84 : "+title=World Geodetic System 1984 UTM fuseau 39 Sud +proj=tmerc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=51.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=10000000.000 +units=m +no_defs",
+ UTM42SW84 : "+title=World Geodetic System 1984 UTM fuseau 42 Sud +proj=tmerc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=69.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=10000000.000 +units=m +no_defs",
+ UTM43SW84 : "+title=World Geodetic System 1984 UTM fuseau 43 Sud +proj=tmerc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=75.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=10000000.000 +units=m +no_defs",
+ WALL78UTM1S : "+title=Wallis-Uvea 1978 (MOP78) UTM 1 SUD +proj=tmerc +towgs84=253.0000,-133.0000,-127.0000 +a=6378388.0000 +rf=297.0000000000000 +lat_0=0.000000000 +lon_0=-177.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=10000000.000 +units=m +no_defs",
+ ETRS89GEO : "+title=ETRS89 geographiques (dms) +proj=longlat +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +units=m +no_defs",
+ ETRS89LAEA : "+title=ETRS89 Lambert Azimutal Equal Area +proj=laea +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=52.000000000 +lon_0=10.000000000 +x_0=4321000.000 +y_0=3210000.000 +units=m +no_defs",
+ ETRS89LCC : "+title=ETRS89 Lambert Conformal Conic +proj=lcc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=52.000000000 +lon_0=9.999999995 +lat_1=35.000000000 +lat_2=65.000000000 +x_0=4000000.000 +y_0=2800000.000 +units=m +no_defs",
+ UTM26ETRS89 : "+title=Europe - de 30d a 24d Ouest +proj=tmerc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=-27.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=0.000 +units=m +no_defs",
+ UTM27ETRS89 : "+title=Europe - de 24d a 18d Ouest +proj=tmerc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=-21.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=0.000 +units=m +no_defs",
+ UTM28ETRS89 : "+title=Europe - de 18d a 12d Ouest +proj=tmerc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=-15.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=0.000 +units=m +no_defs",
+ UTM29ETRS89 : "+title=Europe - de 12d a 6d Ouest +proj=tmerc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=-9.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=0.000 +units=m +no_defs",
+ UTM30ETRS89 : "+title=Europe - de -6d a 0d Ouest +proj=tmerc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=-3.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=0.000 +units=m +no_defs",
+ UTM31ETRS89 : "+title=Europe - de 0d a 6d Est +proj=tmerc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=3.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=0.000 +units=m +no_defs",
+ UTM32ETRS89 : "+title=Europe - de 6d a 12d Est +proj=tmerc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=9.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=0.000 +units=m +no_defs",
+ UTM33ETRS89 : "+title=Europe - de 12d a 18d Est +proj=tmerc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=15.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=0.000 +units=m +no_defs",
+ UTM34ETRS89 : "+title=Europe - de 18d a 24d Est +proj=tmerc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=21.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=0.000 +units=m +no_defs",
+ UTM35ETRS89 : "+title=Europe - de 24d a 30d Est +proj=tmerc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=27.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=0.000 +units=m +no_defs",
+ UTM36ETRS89 : "+title=Europe - de 30d a 36d Est +proj=tmerc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=33.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=0.000 +units=m +no_defs",
+ UTM37ETRS89 : "+title=Europe - de 36d a 42d Est +proj=tmerc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=39.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=0.000 +units=m +no_defs",
+ UTM38ETRS89 : "+title=Europe - de 42d a 48d Est +proj=tmerc +nadgrids=null +wktext +towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000 +lat_0=0.000000000 +lon_0=45.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=0.000 +units=m +no_defs"
+ }
+};
+
+export default Register;
diff --git a/src/Common-review/Utils/SearchEngineUtils.js b/src/Common-review/Utils/SearchEngineUtils.js
new file mode 100644
index 000000000..666a72f6d
--- /dev/null
+++ b/src/Common-review/Utils/SearchEngineUtils.js
@@ -0,0 +1,145 @@
+var SearchEngineUtils = {
+ /**
+ * Advanced Search Filters by default
+ */
+ advancedSearchFiltersByDefault : {
+ PositionOfInterest : [{
+ name : "importance",
+ title : "Importance"
+ }, {
+ name : "nature",
+ title : "Nature"
+ }, {
+ name : "territory",
+ title : "Territoire"
+ }, {
+ name : "insee",
+ title : "Code INSEE"
+ }, {
+ name : "municipality",
+ title : "Ville"
+ }, {
+ name : "department",
+ title : "Département"
+ }],
+ StreetAddress : [
+ // INFO
+ // ce ne sont pas des filtres mais une location dite structurée !
+ // {name : "number", title : "Numéro"},
+ // {name : "street", title : "Rue"},
+ // {name : "postalCode", title : "Code Postal"},
+ // {name : "city", title : "Commune"},
+ {
+ name : "territory",
+ title : "Territoire"
+ }, {
+ name : "insee",
+ title : "Code INSEE"
+ }, {
+ name : "municipality",
+ title : "Ville"
+ }, {
+ name : "department",
+ title : "Département"
+ }
+ ],
+ CadastralParcel : [{
+ name : "department",
+ title : "Département",
+ description : "Numéro du département (ex: 01, 94)"
+ }, {
+ name : "commune",
+ title : "Code commune (INSEE)",
+ description : "Code commune (INSEE) : 3 chiffres (ex: 067)"
+ },
+ // {
+ // name : "insee",
+ // title : "Code INSEE"
+ // },
+ {
+ name : "absorbedCity",
+ title : "Commune absorbée",
+ description : "Commune absorbée : 3 chiffres (ex: 000, 001)"
+ }, {
+ name : "section",
+ title : "Section",
+ description : "Section : 2 caractères (ex: AA, 0D)"
+ }, {
+ name : "number",
+ title : "Numéro",
+ description : "Numéro de la parcelle : 4 chiffres (ex: 0041, 0250)"
+ }
+ ],
+ Administratif : [{
+ name : "prefecture",
+ title : "Préfecture"
+ }, {
+ name : "inseeRegion",
+ title : "Code région (INSEE)"
+ }, {
+ name : "inseeDepartment",
+ title : "Code département (INSEE)"
+ }, {
+ name : "municipality",
+ title : "Ville"
+ }]
+ },
+
+ /**
+ * Provides default zoom based on results.
+ *
+ * @param {Object} info - location information
+ * @returns {Integer} zoom level
+ */
+ zoomToResultsByDefault : function (info) {
+ // FIXME
+ // la classification du geocodage est differente de l'importance de l'autocompletion !
+
+ var zoom = 15;
+
+ var service = info.service;
+ var fields = info.fields;
+ var type = info.type;
+
+ var importance = {
+ 1 : 11,
+ 2 : 12,
+ 3 : 13,
+ 4 : 14,
+ 5 : 15,
+ 6 : 16,
+ 7 : 17,
+ 8 : 17
+ };
+
+ // AutoCompletion POI
+ if (service === "SuggestedLocation") {
+ if (type === "PositionOfInterest") {
+ zoom = importance[fields.classification];
+ }
+ }
+
+ // Geocodage POI
+ if (service === "DirectGeocodedLocation") {
+ if (type === "PositionOfInterest") {
+ zoom = importance[fields.importance] || 14; // au cas où la recherche est en freeform !
+ }
+ }
+
+ if (type === "StreetAddress") {
+ zoom = 17;
+ }
+
+ if (type === "CadastralParcel") {
+ zoom = 17;
+ }
+
+ if (type === "Administratif") {
+ zoom = 12;
+ }
+
+ return zoom;
+ }
+};
+
+export default SearchEngineUtils;
diff --git a/src/Common-review/Utils/SelectorID.js b/src/Common-review/Utils/SelectorID.js
new file mode 100644
index 000000000..d5b0dc6d1
--- /dev/null
+++ b/src/Common-review/Utils/SelectorID.js
@@ -0,0 +1,80 @@
+/**
+ * formalisme d'un tag ID :
+ * -> NAME(_ORDER)-1460636385836
+ *
+ * Ex.
+ * GProutePoints-1460636385836
+ * GProutePoint_10-1460636385836
+ */
+var SelectorID = {
+
+ /**
+ * Construction d'un identifiant statique basé sur le timestamp,
+ * et qui s'incremente de +1 à chaque appel
+ */
+ generate : (function () {
+ var timestamp = Math.floor(Date.now());
+ return function () {
+ return timestamp++;
+ };
+ })(),
+
+ /**
+ * nom du tag
+ * @param {String} id - the id
+ *
+ * @returns {String} index
+ */
+ name : function (id) {
+ var name = null;
+
+ var i = id.lastIndexOf("-");
+ if (i === -1) {
+ name = id;
+ } else {
+ name = id.substring(0, i);
+ }
+
+ return name;
+ },
+
+ /**
+ * numero d'identifiant du tag
+ * @param {String} id - the id
+ *
+ * @returns {String} index
+ */
+ index : function (id) {
+ var index = null;
+
+ var name = this.name(id);
+ // if (name !== id) {
+ var i = name.lastIndexOf("_");
+ if (i !== -1) {
+ index = name.substring(i + 1);
+ }
+ // }
+
+ return index;
+ },
+
+ /**
+ * uuid du tag
+ * @param {String} id - the id
+ *
+ * @returns {String} uuid
+ */
+ uuid : function (id) {
+ var uuid = null;
+
+ var i = id.lastIndexOf("-");
+ if (i !== -1) {
+ uuid = parseInt(id.substring(i + 1), 10);
+ }
+
+ return uuid;
+ }
+
+};
+
+export default SelectorID;
diff --git a/src/Itowns-review/CRS/CRS.js b/src/Itowns-review/CRS/CRS.js
new file mode 100644
index 000000000..b38835df4
--- /dev/null
+++ b/src/Itowns-review/CRS/CRS.js
@@ -0,0 +1,204 @@
+var CRS = {
+
+ /**
+ * CRS : WGS84
+ *
+ * @property EPSG:4326
+ * @private
+ */
+ "EPSG:4326" : "+title=WGS 84 (long/lat) +proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs +units=degrees",
+
+ /**
+ * CRS : PseudoMercator
+ *
+ * @property EPSG:3857
+ * @private
+ */
+ "EPSG:3857" : "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs",
+
+ /**
+ * CRS : Lambert 93
+ *
+ * @property EPSG:2154
+ * @private
+ */
+ "EPSG:2154" : "+proj=lcc +lat_1=49 +lat_2=44 +lat_0=46.5 +lon_0=3 +x_0=700000 +y_0=6600000 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs",
+
+ /**
+ * CRS : Lambert 2 extended
+ *
+ * @property EPSG:27572
+ * @private
+ */
+ "EPSG:27572" : "+proj=lcc +lat_1=46.8 +lat_0=46.8 +lon_0=0 +k_0=0.99987742 +x_0=600000 +y_0=2200000 +a=6378249.2 +b=6356515 +towgs84=-168,-60,320,0,0,0,0 +pm=paris +units=m +no_defs",
+
+ /**
+ * CRS : UTM 20N (Guadeloupe, Martinique)
+ *
+ * @property EPSG:32620
+ * @private
+ */
+ "EPSG:32620" : "+proj=utm +zone=20 +ellps=WGS84 +datum=WGS84 +units=m +no_defs",
+
+ /**
+ * CRS : UTM 21N (Saint-Pierre-et-Miquelon)
+ *
+ * @property EPSG:4467
+ * @private
+ */
+ "EPSG:4467" : "+proj=utm +zone=21 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs",
+
+ /**
+ * CRS : UTM 22N (Guyane)
+ *
+ * @property EPSG:2972
+ * @private
+ */
+ "EPSG:2972" : "+proj=utm +zone=22 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs",
+
+ /**
+ * CRS : UTM 30N (France métropolitaine)
+ *
+ * @property EPSG:32630
+ * @private
+ */
+ "EPSG:32630" : "+proj=utm +zone=30 +datum=WGS84 +units=m +no_defs",
+
+ /**
+ * CRS : UTM 31N (France métropolitaine)
+ *
+ * @property EPSG:32631
+ * @private
+ */
+ "EPSG:32631" : "+proj=utm +zone=31 +datum=WGS84 +units=m +no_defs",
+
+ /**
+ * CRS : UTM 32N (France métropolitaine)
+ *
+ * @property EPSG:32632
+ * @private
+ */
+ "EPSG:32632" : "+proj=utm +zone=32 +datum=WGS84 +units=m +no_defs",
+
+ /**
+ * CRS : UTM 38S (Mayotte)
+ *
+ * @property EPSG:4471
+ * @private
+ */
+ "EPSG:4471" : "+proj=utm +zone=38 +south +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs",
+
+ /**
+ * CRS : UTM 40S (Réunion)
+ *
+ * @property EPSG:2975
+ * @private
+ */
+ "EPSG:2975" : "+proj=utm +zone=40 +south +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs",
+
+ /**
+ * CRS : UTM 5S (Polynésie)
+ *
+ * @property EPSG:3296
+ * @private
+ */
+ "EPSG:3296" : "+proj=utm +zone=5 +south +ellps=GRS80 +towgs84=0.072,-0.507,-0.245,-0.0183,0.0003,-0.007,-0.0093 +units=m +no_defs",
+
+ /**
+ * CRS : UTM 6S (Polynésie)
+ *
+ * @property EPSG:3297
+ * @private
+ */
+ "EPSG:3297" : "+proj=utm +zone=6 +south +ellps=GRS80 +towgs84=0.072,-0.507,-0.245,-0.0183,0.0003,-0.007,-0.0093 +units=m +no_defs",
+
+ /**
+ * CRS : UTM 7S (Polynésie)
+ *
+ * @property EPSG:32707
+ * @private
+ */
+ "EPSG:32707" : "+proj=utm +zone=7 +south +datum=WGS84 +units=m +no_defs",
+
+ /**
+ * CRS : UTM 8S (Polynésie)
+ *
+ * @property EPSG:32708
+ * @private
+ */
+ "EPSG:32708" : "+proj=utm +zone=8 +south +datum=WGS84 +units=m +no_defs",
+
+ /**
+ * CRS : UTM 12N (Ile de Clipperton)
+ *
+ * @property EPSG:26912
+ * @private
+ */
+ "EPSG:26912" : "+proj=utm +zone=12 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs",
+
+ /**
+ * CRS : UTM 42S (Iles Kerguelen)
+ *
+ * @property EPSG:32742
+ * @private
+ */
+ "EPSG:32742" : "+proj=utm +zone=42 +south +datum=WGS84 +units=m +no_defs",
+
+ /**
+ * CRS : UTM 39S (Iles Crozet)
+ *
+ * @property EPSG:32739
+ * @private
+ */
+ "EPSG:32739" : "+proj=utm +zone=39 +south +datum=WGS84 +units=m +no_defs",
+
+ /**
+ * CRS : UTM 43S (Iles St-Paul et Amsterdam)
+ *
+ * @property EPSG:32743
+ * @private
+ */
+ "EPSG:32743" : "+proj=utm +zone=43 +south +datum=WGS84 +units=m +no_defs",
+
+ /**
+ * CRS : Stéréographique polaire (Terre Adelie)
+ *
+ * @property EPSG:2986
+ * @private
+ */
+ "EPSG:2986" : "",
+
+ /**
+ * CRS : UTM 37S (Iles du canal de Mozambique)
+ *
+ * @property EPSG:32737
+ * @private
+ */
+ "EPSG:32737" : "+proj=utm +zone=37 +south +datum=WGS84 +units=m +no_defs",
+
+ /**
+ * CRS : UTM 38S (Iles du canal de Mozambique)
+ *
+ * @property EPSG:32738
+ * @private
+ */
+ "EPSG:32738" : "+proj=utm +zone=38 +south +datum=WGS84 +units=m +no_defs",
+
+ /**
+ * CRS : UTM 1S (Wallis-et-Futuna)
+ *
+ * @property EPSG:2988
+ * @private
+ */
+ "EPSG:2988" : "+proj=utm +zone=1 +south +ellps=intl +towgs84=253,-132,-127,0,0,0,0 +units=m +no_defs",
+
+ /**
+ * CRS : RGNC91-93 (Nouvelle-Calédonie)
+ *
+ * @property EPSG:3163
+ * @private
+ */
+ "EPSG:3163" : "+proj=lcc +lat_1=-20.66666666666667 +lat_2=-22.33333333333333 +lat_0=-21.5 +lon_0=166 +x_0=400000 +y_0=300000 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs"
+};
+
+export default CRS;
diff --git a/src/Itowns-review/CSS/Controls/Attribution/GPattributionItowns.css b/src/Itowns-review/CSS/Controls/Attribution/GPattributionItowns.css
new file mode 100644
index 000000000..686655603
--- /dev/null
+++ b/src/Itowns-review/CSS/Controls/Attribution/GPattributionItowns.css
@@ -0,0 +1,66 @@
+div[id^=GPAttribution-] {
+ display: flex;
+ bottom: 8px;
+ right: 8px;
+ width: calc(90% - 1.3em);
+}
+
+div[id^=GPAttributionsListContainer-] {
+ display: none;
+ width: 80%;
+ height: 80%;
+ background: white;
+ opacity: 0.5;
+ border-radius: 4px;
+ z-index: 0;
+ position: absolute;
+}
+
+div[id^=GPAttributionsListContainer-] ul {
+ display: flex;
+ margin: auto;
+ list-style: none;
+}
+
+label[id^=GPshowAttributionsListPicto-] {
+ display: flex;
+ z-index: 1;
+ position: relative;
+ margin-left: auto;
+}
+
+input[id^=GPshowAttributionsList-]:checked + div[id^=GPAttributionsListContainer-] {
+ display: flex;
+}
+
+input[id^=GPshowAttributionsList-]:checked + div[id^=GPAttributionsListContainer-] + label[id^=GPshowAttributionsListPicto-] {
+ background-color: transparent;
+}
+
+span[id^=GPshowAttributionsListOpenClose-] {
+ color: #fff;
+ font-size: 1.6em;
+ font-weight: 700;
+ text-align: center;
+ line-height: 1.2em;
+}
+
+div[id^=GPAttributionsListContainer-] li:before {
+ content: " | ";
+}
+
+div[id^=GPAttributionsListContainer-] ul li:nth-child(1):before {
+ content: "";
+}
+
+div[id^=GPAttributionsListContainer-] ul li:first-child:before {
+ content: "";
+}
+
+div[id^=GPAttributionsListContainer-] a:link {
+ text-decoration: none;
+}
+
+div[id^=GPAttributionsListContainer-] a:visited {
+ text-decoration: none;
+}
diff --git a/src/Itowns-review/CSS/Controls/BoostRelief/GPboostReliefItowns.css b/src/Itowns-review/CSS/Controls/BoostRelief/GPboostReliefItowns.css
new file mode 100644
index 000000000..a183b9068
--- /dev/null
+++ b/src/Itowns-review/CSS/Controls/BoostRelief/GPboostReliefItowns.css
@@ -0,0 +1,74 @@
+/* BOOST RELIEF ITOWNS */
+
+div[id^=GPboostRelief-] {
+ top: 8px;
+ left: 8px;
+}
+
+/* Showing/hiding boostRelief panel */
+label[id^=GPshowBoostReliefPicto-] {
+ display: flex;
+ z-index: 1;
+ position: relative;
+ margin-left: auto;
+}
+
+label[id^=GPshowBoostReliefListPicto-] {
+ display: flex;
+ z-index: 1;
+ position: relative;
+}
+
+/*
+span[id^=GPshowBoostReliefOpenClose-] {
+ color: #fff;
+ font-size: 1.6em;
+ font-weight: 700;
+ text-align: center;
+ line-height: 1.2em;
+}*/
+
+span[id^="GPshowBoostReliefOpenClose-"] {
+ background-image: url("img/GPboostReliefOpen.png");
+}
+
+.spanClose span[id^="GPshowBoostReliefOpenClose-"] {
+ background-position: 0 0;
+}
+
+.spanOpen span[id^="GPshowBoostReliefOpenClose-"] {
+ background-position: -26px 0;
+}
+
+/*
+div[id^=GPboostRelief-] input[type="checkbox"]:checked + div + label[id^=GPshowBoostReliefPicto] span[id^=GPshowBoostReliefOpen] {
+ opacity: 0.7;
+}
+
+div[id^=GPboostRelief-] input[type="checkbox"]:checked + div + label[id^=GPshowBoostReliefPicto] span[id^=GPshowBoostReliefClose] {
+ background-color: rgba(0,60,136,0.3);
+}
+
+div[id^=GPboostRelief-] input[type="checkbox"]:checked + div + label[id^=GPshowBoostReliefPicto] :hover span[id^=GPshowBoostReliefClose] {
+ background-color: rgba(0,60,136,0.4);
+}
+
+*/
+
+/* Relief slider : Chrome, Safari, Opera */
+
+.GPlayerRelief input[type="range"]::-webkit-slider-runnable-track {
+ background: url("img/GPreliefSlider.png");
+}
+
+/* Relief slider : Firefox */
+
+.GPlayerRelief input[type="range"]::-moz-range-track {
+ background: url("img/GPreliefSlider.png");
+}
+
+/* Relief slider : IE */
+
+.GPlayerRelief input[type="range"]::-ms-track {
+ background: url("img/GPreliefSlider.png");
+}
diff --git a/src/Itowns-review/CSS/Controls/BoostRelief/img/GPboostReliefOpen.png b/src/Itowns-review/CSS/Controls/BoostRelief/img/GPboostReliefOpen.png
new file mode 100644
index 000000000..d083722cc
Binary files /dev/null and b/src/Itowns-review/CSS/Controls/BoostRelief/img/GPboostReliefOpen.png differ
diff --git a/src/Itowns-review/CSS/Controls/BoostRelief/img/GPreliefSlider.png b/src/Itowns-review/CSS/Controls/BoostRelief/img/GPreliefSlider.png
new file mode 100644
index 000000000..301e289bc
Binary files /dev/null and b/src/Itowns-review/CSS/Controls/BoostRelief/img/GPreliefSlider.png differ
diff --git a/src/Itowns-review/CSS/Controls/LayerSwitcher/GPlayerSwitcherItowns.css b/src/Itowns-review/CSS/Controls/LayerSwitcher/GPlayerSwitcherItowns.css
new file mode 100644
index 000000000..ecc932010
--- /dev/null
+++ b/src/Itowns-review/CSS/Controls/LayerSwitcher/GPlayerSwitcherItowns.css
@@ -0,0 +1,91 @@
+/* LAYER SWITCHER OL3 */
+
+div[id^=GPlayerSwitcher-] {
+ top: 8px;
+ right: 8px;
+}
+
+/* Showing/hiding layers list */
+
+label[id^=GPshowLayersListPicto] {
+ width: 38px;
+ height: 38px;
+}
+
+span[id^=GPshowLayersListOpen] ,
+span[id^=GPshowLayersListClose] {
+ top: 3px;
+ left: 3px;
+ width: 32px;
+ height: 32px;
+ background-image: url("img/GPshowLayersList.png");
+}
+
+span[id^=GPshowLayersListClose] {
+ background-position: -32px 0;
+}
+
+
+div[id^=GPlayerSwitcher-] input[type="checkbox"]:checked + div + label[id^=GPshowLayersListPicto] span[id^=GPshowLayersListOpen] {
+ opacity: 0.7;
+}
+
+div[id^=GPlayerSwitcher-] input[type="checkbox"]:checked + div + label[id^=GPshowLayersListPicto] span[id^=GPshowLayersListClose] {
+ background-color: rgba(0,60,136,0.3);
+}
+
+div[id^=GPlayerSwitcher-] input[type="checkbox"]:checked + div + label[id^=GPshowLayersListPicto] :hover span[id^=GPshowLayersListClose] {
+ background-color: rgba(0,60,136,0.4);
+}
+
+/* Layers list */
+
+.GPlayerVisibility,
+.GPshowLayerAdvancedTools,
+.GPlayerInfo,
+.GPlayerInfoOpened,
+.GPlayerRemove {
+ background-image: url("img/GPlayerTools.png");
+}
+
+/* Opacity slider : Chrome, Safari, Opera */
+
+.GPlayerOpacity input[type="range"]::-webkit-slider-runnable-track {
+ background: url("img/GPopacitySlider.png");
+}
+
+/* Opacity slider : Firefox */
+
+.GPlayerOpacity input[type="range"]::-moz-range-track {
+ background: url("img/GPopacitySlider.png");
+}
+
+/* Opacity slider : IE */
+
+.GPlayerOpacity input[type="range"]::-ms-track {
+ background: url("img/GPopacitySlider.png");
+}
+
+/* Layer info panel */
+
+div[id^=GPlayerInfoPanel] {
+ right: 190px;
+}
+
+div[id^=GPlayerInfoTitle] {
+ color: #366291;
+ border-bottom: 1px solid #366291;
+}
+
+div[id^=GPlayerInfoQuicklook] {
+ background-image: url("img/GPlayerInfo.png");
+}
+
+div[id^=GPlayerInfoClose] {
+ background-image: url("img/GPlayerInfoClose.png");
+}
+
+.GPlayerInfoLink,
+.GPlayerInfoPopup {
+ background-image: url("img/GPlayerInfo.png");
+}
diff --git a/src/Itowns-review/CSS/Controls/LayerSwitcher/img/GPlayerInfo.png b/src/Itowns-review/CSS/Controls/LayerSwitcher/img/GPlayerInfo.png
new file mode 100644
index 000000000..b7d5a0be8
Binary files /dev/null and b/src/Itowns-review/CSS/Controls/LayerSwitcher/img/GPlayerInfo.png differ
diff --git a/src/Itowns-review/CSS/Controls/LayerSwitcher/img/GPlayerInfoClose.png b/src/Itowns-review/CSS/Controls/LayerSwitcher/img/GPlayerInfoClose.png
new file mode 100644
index 000000000..1d61d5dec
Binary files /dev/null and b/src/Itowns-review/CSS/Controls/LayerSwitcher/img/GPlayerInfoClose.png differ
diff --git a/src/Itowns-review/CSS/Controls/LayerSwitcher/img/GPlayerTools.png b/src/Itowns-review/CSS/Controls/LayerSwitcher/img/GPlayerTools.png
new file mode 100644
index 000000000..6c696c089
Binary files /dev/null and b/src/Itowns-review/CSS/Controls/LayerSwitcher/img/GPlayerTools.png differ
diff --git a/src/Itowns-review/CSS/Controls/LayerSwitcher/img/GPopacitySlider.png b/src/Itowns-review/CSS/Controls/LayerSwitcher/img/GPopacitySlider.png
new file mode 100644
index 000000000..301e289bc
Binary files /dev/null and b/src/Itowns-review/CSS/Controls/LayerSwitcher/img/GPopacitySlider.png differ
diff --git a/src/Itowns-review/CSS/Controls/LayerSwitcher/img/GPshowLayersList.png b/src/Itowns-review/CSS/Controls/LayerSwitcher/img/GPshowLayersList.png
new file mode 100644
index 000000000..9f4c4fd30
Binary files /dev/null and b/src/Itowns-review/CSS/Controls/LayerSwitcher/img/GPshowLayersList.png differ
diff --git a/src/Itowns-review/CSS/Controls/MiniGlobe/GPminiGlobeItowns.css b/src/Itowns-review/CSS/Controls/MiniGlobe/GPminiGlobeItowns.css
new file mode 100644
index 000000000..5da731735
--- /dev/null
+++ b/src/Itowns-review/CSS/Controls/MiniGlobe/GPminiGlobeItowns.css
@@ -0,0 +1,8 @@
+div[id^=GPminiglobeContainer-] {
+ display: block;
+ width:100px;
+ height:100px;
+ left: 20px;
+ bottom: 20px;
+ color: white;
+}
diff --git a/src/Itowns-review/CSS/Controls/MousePosition/GPmousePositionItowns.css b/src/Itowns-review/CSS/Controls/MousePosition/GPmousePositionItowns.css
new file mode 100644
index 000000000..ffe326dc0
--- /dev/null
+++ b/src/Itowns-review/CSS/Controls/MousePosition/GPmousePositionItowns.css
@@ -0,0 +1,30 @@
+/* MOUSE POSITION */
+
+div[id^=GPmousePosition-] {
+ bottom: 8px;
+ left: 10px;
+}
+
+/* Showing/hiding mouse position panel */
+
+span[id^=GPshowMousePositionOpen] {
+ background-image: url("img/GPmousePositionOpen.png");
+}
+
+/* General panels */
+
+div[id^=GPmousePositionPanel-] {
+ position: relative;
+ left: 0px;
+ top: 0px;
+}
+
+div[id^=GPmousePositionPanelClose] {
+ background-image: url("img/GPmousePositionOpen.png");
+}
+
+/* Map center localisation */
+
+#GPmapCenter {
+ background-image: url("img/GPmapCenter.png");
+}
diff --git a/src/Itowns-review/CSS/Controls/MousePosition/img/GPmapCenter.png b/src/Itowns-review/CSS/Controls/MousePosition/img/GPmapCenter.png
new file mode 100644
index 000000000..a10837a90
Binary files /dev/null and b/src/Itowns-review/CSS/Controls/MousePosition/img/GPmapCenter.png differ
diff --git a/src/Itowns-review/CSS/Controls/MousePosition/img/GPmousePositionOpen.png b/src/Itowns-review/CSS/Controls/MousePosition/img/GPmousePositionOpen.png
new file mode 100644
index 000000000..142f8f98a
Binary files /dev/null and b/src/Itowns-review/CSS/Controls/MousePosition/img/GPmousePositionOpen.png differ
diff --git a/src/Itowns-review/CSS/Controls/Scale/GPscaleItowns.css b/src/Itowns-review/CSS/Controls/Scale/GPscaleItowns.css
new file mode 100644
index 000000000..83a84dd10
--- /dev/null
+++ b/src/Itowns-review/CSS/Controls/Scale/GPscaleItowns.css
@@ -0,0 +1,15 @@
+div[id^=GPscaleContainer-] {
+ border: 2px solid white;
+ border-top: none;
+ text-align: center;
+ display: block;
+ background-image: linear-gradient(rgba(200, 200, 200, 0.3), rgba(200, 200, 200, 0.3));
+ height: 18px;
+ width: 200px;
+ color: white;
+ font-family: 'Open Sans',
+ sans-serif;
+ font-size: 16px;
+ right: 20px;
+ bottom: 20px;
+}
diff --git a/src/Itowns-review/CSS/GPgeneralWidgetItowns.css b/src/Itowns-review/CSS/GPgeneralWidgetItowns.css
new file mode 100644
index 000000000..9a0d6b4e0
--- /dev/null
+++ b/src/Itowns-review/CSS/GPgeneralWidgetItowns.css
@@ -0,0 +1,67 @@
+/* General panels */
+
+.GPpanel {
+ box-shadow: 0 0 6px #000;
+ border-radius: 4px;
+}
+
+.GPpanelHeader {
+ height: 32px;
+ padding: 3px;
+ background-color: #9DB1BD;
+ border-top-left-radius: 4px;
+ border-top-right-radius: 4px;
+}
+
+.GPpanelTitle {
+ line-height: 26px;
+ border-top-left-radius: 2px;
+ border-top-right-radius: 2px;
+ background-color: #366291;
+ color: #FFF;
+}
+
+.GPpanelClose {
+ top: 3px;
+ right: 3px;
+ width: 26px;
+ height: 26px;
+ background-position: -26px 0;
+}
+
+/* Showing/hiding advanced panels */
+
+.GPshowAdvancedToolPicto {
+ width: 32px;
+ height: 32px;
+ padding: 3px;
+ background-color: rgba(255, 255, 255, 0.4);
+ border-radius: 4px;
+}
+
+.GPshowAdvancedToolPicto:hover {
+ background-color: rgba(255, 255, 255, 0.6);
+}
+
+.GPshowAdvancedToolOpen {
+ width: 26px;
+ height: 26px;
+ background-color: rgba(0,60,136,0.5);
+ border-radius: 2px;
+}
+
+.GPshowAdvancedToolPicto:hover .GPshowAdvancedToolOpen {
+ background-color: rgba(0,60,136,0.7);
+}
+
+/* Submit inputs */
+
+input.GPinputSubmit {
+ background-color: #366291;
+}
+
+/* Showing additional hidden options */
+
+.GPshowMoreOptionsImage {
+ background-image: url("img/GPshowMoreOptions.png");
+}
diff --git a/src/Itowns-review/CSS/img/GPshowMoreOptions.png b/src/Itowns-review/CSS/img/GPshowMoreOptions.png
new file mode 100644
index 000000000..fc109295c
Binary files /dev/null and b/src/Itowns-review/CSS/img/GPshowMoreOptions.png differ
diff --git a/src/Itowns-review/Controls/Attributions.js b/src/Itowns-review/Controls/Attributions.js
new file mode 100644
index 000000000..306c35c98
--- /dev/null
+++ b/src/Itowns-review/Controls/Attributions.js
@@ -0,0 +1,318 @@
+import GlobeViewExtended from "../GlobeViewExtended";
+import Logger from "../../Common/Utils/LoggerByDefault";
+import Utils from "../../Common/Utils";
+import SelectorID from "../../Common/Utils/SelectorID";
+import LayerUtils from "../../Common/Utils/LayerUtils";
+import AttributionDOM from "../../Common/Controls/AttributionDOM";
+import Widget from "./Widget";
+
+var logger = Logger.getLogger("Attributions");
+
+/**
+ * @classdesc
+ * Control to manage layers attributions
+ *
+ * @constructor
+ * @alias itowns.control.Attributions
+ * @extends {itowns.control.Widget}
+ * @param {Object} aOptions - control options
+ * @param {Object} [aOptions.options] - Itowns.control.Control options
+ * @param {Boolean} [aOptions.options.collapsed = false] - Specify if the control has to be opened or not.
+ * @example
+ * var attribution = new itowns.control.Attritbution({
+ * options : {
+ * collapsed: true
+ * }
+ * ));
+ */
+function Attributions (aOptions) {
+ aOptions = aOptions || {};
+ var options = aOptions.options || {};
+
+ if (!(this instanceof Attributions)) {
+ throw new TypeError("ERROR CLASS_CONSTRUCTOR");
+ }
+
+ if (options && typeof options !== "object") {
+ throw new Error("ERROR WRONG_TYPE : options should be an object");
+ }
+
+ this._initialize(options);
+
+ var container = this._initContainer(options);
+
+ Widget.call(
+ this, {
+ name : "Attributions",
+ element : container,
+ target : options.target,
+ position : options.position
+ }
+ );
+}
+
+/*
+ * @lends module:Attributions
+ */
+Attributions.prototype = Object.create(Widget.prototype, {});
+
+// retrieves methods of the common class AttributionDOM
+Utils.assign(Attributions.prototype, AttributionDOM);
+
+/**
+ * Constructor (alias)
+ *
+ * @private
+ */
+Attributions.prototype.constructor = Attributions;
+
+// ################################################################### //
+// ############## public methods (getters, setters) ################## //
+// ################################################################### //
+
+/**
+ * Bind globe to control
+ *
+ * @param {GlobeViewExtended} globe - the globe
+ */
+Attributions.prototype.setGlobe = function (globe) {
+ // info : this function is called after a globe.addWidget() or a globe.removeWidget()
+
+ if (globe) { // In the case of the adding of a control to the globe
+ var self = this;
+
+ // Adding of the listeners
+
+ // At every globe movement, attributions may be updated,
+ // according to layers on globe, and their visibility.
+ this._callbacks.onPreRenderCallBack = function (e) {
+ var allLayers = e.colorLayersId.concat(e.elevationLayersId);
+
+ self._inRangeUpdate(allLayers, e.extent);
+ };
+
+ globe.listen(GlobeViewExtended.EVENTS.PRE_RENDER, this._callbacks.onPreRenderCallBack);
+ globe.preRenderEventFetchViewExtent();
+ globe.preRenderEventFetchLayersDisplayed();
+ } else {
+ // delete listener
+ this._globe.forget(GlobeViewExtended.EVENTS.PRE_RENDER, this._callbacks.onPreRenderCallBack);
+
+ // delete DOM
+ while (this._element.hasChildNodes()) {
+ this._element.removeChild(this._element.lastChild);
+ }
+ this._element.parentNode.removeChild(this._element);
+ }
+
+ // call original setGlobe method
+ Widget.prototype.setGlobe.call(this, globe);
+};
+
+/**
+ * Collapse or display control main container
+ *
+ * @param {Boolean} collapsed - True to collapse control, False to display it
+ */
+Attributions.prototype.setCollapsed = function (collapsed) {
+ if (collapsed === undefined) {
+ logger.error("Attributions:setCollapsed - missing collapsed parameter");
+ return;
+ }
+ var isCollapsed = this.getCollapsed();
+ if ((collapsed && isCollapsed) || (!collapsed && !isCollapsed)) {
+ return;
+ }
+
+ document.getElementById(this._addUID("GPshowAttributionsList")).checked = !collapsed;
+};
+
+/**
+ * Returns true if widget is collapsed (minimize), false otherwise
+ *
+ * @return {Boolean} collapsed
+ */
+Attributions.prototype.getCollapsed = function () {
+ return !document.getElementById(this._addUID("GPshowAttributionsList")).checked;
+};
+
+// ################################################################### //
+// ##################### init component ############################## //
+// ################################################################### //
+
+/**
+ * Initialize Attributions control (called by constructor)
+ *
+ * @param {Object} options - Itowns.control.Control options
+ * @private
+ */
+Attributions.prototype._initialize = function (options) {
+ // id of the widget : usefull to suffix the CSS ids (to handle cases with several widgets on the same page)
+ this._uid = SelectorID.generate();
+
+ // div which will contain the list divs.
+ this._AttributionContainer = null;
+
+ // callbacks
+ this._callbacks = {};
+
+ // options
+ this._options = options;
+};
+
+/**
+ * Creates control main container
+ *
+ * @method _initContainer
+ * @param {Object} options - control options
+ * @returns {DOMElement} container - widget container
+ * @private
+ */
+Attributions.prototype._initContainer = function (options) {
+ var container = this._createMainContainerElement();
+
+ // adds in the main container the layer display selector
+ var inputShow = this._createMainAttributionsShowElement();
+ container.appendChild(inputShow);
+
+ // handles the "collapsed" mode
+ if (!options.collapsed) {
+ inputShow.checked = "checked";
+ }
+ // adds the layer list in the main container
+ var divA = this._attributionListContainer = this._createMainAttributionsListContainer();
+ var ulA = this._createAttributionsList();
+ divA.appendChild(ulA);
+ container.appendChild(divA);
+
+ // adds the widget picto in the main container
+ var picto = this._createMainPictoElement(options.collapsed);
+ container.appendChild(picto);
+
+ return container;
+};
+
+/**
+ * Checks layers range
+ *
+ * @method _inRangeUpdate
+ * @param {Array} layersDisplayed - Id of the layers diplayed on screen
+ * @param {Object} extent - The globe view extent
+ * @private
+ */
+
+Attributions.prototype._inRangeUpdate = function (layersDisplayed, extent) {
+ var globe = this.getGlobe();
+
+ var scaleDenominator = 1 / globe.getScale();
+
+ var attributions = new Map();
+
+ for (var h = 0; h < layersDisplayed.length; h++) {
+ var layer = globe.getLayerById(layersDisplayed[h]);
+
+ var ori = layer.source.attribution;
+
+ if (ori) {
+ for (var j = 0; j < ori.length; j++) {
+ // if the attribution is already added, we skip to not add it several times
+ if (attributions.has(ori[j].name)) {
+ continue;
+ };
+ // if no constraints are associated to the originator, we just add the attribution
+ if (!ori[j].constraints || !ori[j].constraints[0]) {
+ // adds the attribution in the Map() called 'attributions'
+ attributions.set(ori[j].name, ori[j]);
+ continue;
+ }
+ // if the minScaleDenominator exists
+ if (ori[j].constraints[0].minScaleDenominator) {
+ // if min/maxScaleDenominator are equals, we display the attribution corresponding to the zoom level associated to the scale denominator
+ if (ori[j].constraints[0].minScaleDenominator === ori[j].constraints[0].maxScaleDenominator) {
+ // retrieves the zoom level
+ var attributionZoomLevel = LayerUtils.getZoomLevelFromScaleDenominator(ori[j].constraints[0].minScaleDenominator);
+ // selects the scaledenominators around the corresponding zoom level
+ var maxAttributionScaleDenominator = (this._resolutionsWGS84[attributionZoomLevel] + this._resolutionsWGS84[attributionZoomLevel - 1]) / (0.00028 * 2);
+ var minAttributionScaleDenominator = (this._resolutionsWGS84[attributionZoomLevel] + this._resolutionsWGS84[attributionZoomLevel + 1]) / (0.00028 * 2);
+ if (!(maxAttributionScaleDenominator > scaleDenominator && scaleDenominator > minAttributionScaleDenominator)) {
+ continue;
+ }
+ // either, we check we are located between the minScaleDenominator and the maxScaleDenominator
+ } else if (!(ori[j].constraints[0].minScaleDenominator < scaleDenominator && scaleDenominator < ori[j].constraints[0].maxScaleDenominator)) {
+ continue;
+ }
+ }
+ // checks if 'bbox" exists
+ if (ori[j].constraints[0].bbox) {
+ // checks if we are into the bbox limits
+ var intersectsX = (ori[j].constraints[0].bbox.left <= extent.east) && (extent.west <= ori[j].constraints[0].bbox.right);
+ var intersectsY = (ori[j].constraints[0].bbox.bottom <= extent.north) && (extent.south <= ori[j].constraints[0].bbox.top);
+ if (intersectsX && intersectsY) {
+ // adds the attribution in the Map() called 'attributions'
+ attributions.set(ori[j].name, ori[j]);
+ }
+ // if 'bbox' attribute doesn't exist
+ } else if (!ori[j].constraints[0].bbox) {
+ attributions.set(ori[j].name, ori[j]);
+ }
+ }
+ }
+ }
+ this._updateAttributionListContainer(attributions);
+};
+
+// ################################################################### //
+// ######################### DOM events ############################## //
+// ################################################################### //
+
+/**
+ * Updates the layer list container
+ *
+ * @method _updateAttributionListContainer
+ * @param {Map} attributions - map of attributions
+ * @private
+ */
+Attributions.prototype._updateAttributionListContainer = function (attributions) {
+ var element = document.getElementById(this._addUID("GPAttributionsList"));
+ document.getElementById(this._addUID("GPAttributionsList")).parentNode.removeChild(element);
+
+ var ul = this._createAttributionsList();
+ attributions.forEach(function (a) {
+ var li = document.createElement("li");
+ var link = document.createElement("a");
+ link.href = a.url;
+ link.innerHTML = a.name + " ";
+ link.target = "_blank";
+ li.id = a.name.replace(/\s/g, "");
+ li.appendChild(link);
+ ul.appendChild(li);
+ });
+ this._attributionListContainer.appendChild(ul);
+};
+
+Attributions.prototype._resolutionsWGS84 = {
+ 0 : 156543.033928041,
+ 1 : 78271.51696402048,
+ 2 : 39135.758482010235,
+ 3 : 19567.87924100512,
+ 4 : 9783.93962050256,
+ 5 : 4891.96981025128,
+ 6 : 2445.98490512564,
+ 7 : 1222.99245256282,
+ 8 : 611.49622628141,
+ 9 : 305.7481131407048,
+ 10 : 152.8740565703525,
+ 11 : 76.43702828517624,
+ 12 : 38.21851414258813,
+ 13 : 19.10925707129406,
+ 14 : 9.554628535647032,
+ 15 : 4.777314267823516,
+ 16 : 2.388657133911758,
+ 17 : 1.194328566955879,
+ 18 : 0.5971642834779395,
+ 19 : 0.2985821417389697,
+ 20 : 0.1492910708694849,
+ 21 : 0.0746455354347424
+};
+
+export default Attributions;
diff --git a/src/Itowns-review/Controls/BoostRelief.js b/src/Itowns-review/Controls/BoostRelief.js
new file mode 100644
index 000000000..266b3c77f
--- /dev/null
+++ b/src/Itowns-review/Controls/BoostRelief.js
@@ -0,0 +1,281 @@
+import Logger from "../../Common/Utils/LoggerByDefault";
+import Utils from "../../Common/Utils";
+import SelectorID from "../../Common/Utils/SelectorID";
+import BoostReliefDOM from "../../Common/Controls/BoostReliefDOM";
+import Widget from "./Widget";
+
+var logger = Logger.getLogger("BoostRelief");
+
+/**
+ * @classdesc
+ * Control to manage globe layers : their order, visibility and relief, and display their informations (title, description, legends, metadata...)
+ *
+ * @constructor
+ * @extends {itowns.control.Widget}
+ * @alias itowns.control.BoostRelief
+ * @param {Object} brOptions - control options
+ * @param {Object} [brOptions.scale] - Defines the scale used to boost the relief
+ * @param {Number} [brOptions.scale.min] - Minimum of the scale - 1 by default
+ * @param {Number} [brOptions.scale.max] - Maximum of the scale - 50 by default
+ * @param {Number} [brOptions.scale.step] - Step of the scale - 1 by default
+ * @param {Boolean} [brOptions.collapsed = true] - Specify if widget has to be collapsed (true) or not (false) on globe loading.
+ * @param {Boolean} [brOptions.defaultBoost = 1] - Default boost value applied to the widget and the elevation layers when loaded
+ * @example
+ * var boostRelief = new itowns.control.BoostRelief({
+ * scale : {
+ * max : 30,
+ * step : 2
+ * },
+ * defaultBoost : 6
+ * })
+ */
+function BoostRelief (brOptions) {
+ brOptions = brOptions || {};
+ var options = brOptions.options || {};
+
+ if (!(this instanceof BoostRelief)) {
+ throw new TypeError("ERROR CLASS_CONSTRUCTOR");
+ }
+
+ if (options && typeof options !== "object") {
+ throw new Error("ERROR WRONG_TYPE : options should be an object");
+ }
+
+ this._initialize();
+
+ var container = this._initContainer(brOptions);
+ var targetDiv = document.getElementById(options.target) || null;
+
+ Widget.call(
+ this, {
+ name : "BoostRelief",
+ element : container,
+ target : targetDiv
+ }
+ );
+}
+
+/*
+ * @lends module:BoostRelief
+ */
+BoostRelief.prototype = Object.create(Widget.prototype, {});
+
+// retrieves methods of the common class BoostReliefDOM
+Utils.assign(BoostRelief.prototype, BoostReliefDOM);
+
+/**
+ * Constructor (alias)
+ *
+ * @private
+ */
+BoostRelief.prototype.constructor = BoostRelief;
+
+// ################################################################### //
+// ############## public methods (getters, setters) ################## //
+// ################################################################### //
+
+/**
+ * Bind globe to control
+ *
+ * @param {GlobeViewExtended} globe - the globe
+ */
+BoostRelief.prototype.setGlobe = function (globe) {
+ // TODO - removing listeners
+ // this._globe.removeLayerListener(layers[j], GlobeViewExtended.EVENTS.Relief_PROPERTY_CHANGED, this._callbacks.onReliefLayerCallBack);
+ // deletes the layerSwitcher DOM
+ if (!globe) {
+ while (this._element.hasChildNodes()) {
+ this._element.removeChild(this._element.lastChild);
+ }
+ this._element.parentNode.removeChild(this._element);
+ }
+ // calls original setGlobe method
+ Widget.prototype.setGlobe.call(this, globe);
+};
+
+/**
+ * Collapse or display control main container
+ *
+ * @param {Boolean} collapsed - True to collapse control, False to display it
+ */
+BoostRelief.prototype.setCollapsed = function (collapsed) {
+ if (collapsed === undefined) {
+ logger.error("BoostRelief:setCollapsed - missing collapsed parameter");
+ return;
+ }
+ if (typeof collapsed !== "boolean") {
+ logger.error("BoostRelief:setCollapsed - collapsed parameter is not a boolean");
+ return;
+ }
+ var isCollapsed = this.getCollapsed();
+
+ if ((collapsed && isCollapsed) || (!collapsed && !isCollapsed)) {
+ return;
+ }
+ var controlDiv = document.getElementById(this._addUID("GPBoostReliefListContainer"));
+ if (collapsed) {
+ controlDiv.style.display = "block";
+ document.getElementById(this._addUID("GPshowBoostReliefList")).checked = true;
+ } else {
+ controlDiv.style.display = "none";
+ document.getElementById(this._addUID("GPshowBoostReliefList")).checked = false;
+ }
+};
+
+/**
+ * Returns true if widget is collapsed (minimize), false otherwise
+ * @return {Boolean} is collapsed
+ */
+BoostRelief.prototype.getCollapsed = function () {
+ return document.getElementById(this._addUID("GPshowBoostReliefList")).checked;
+};
+
+// ################################################################### //
+// ##################### init component ############################## //
+// ################################################################### //
+
+/**
+ * Initialize BoostRelief control (called by constructor)
+ *
+ * @private
+ */
+BoostRelief.prototype._initialize = function () {
+ // id of the control ; used to suffix the CSS id (handles cases with severel controls on the same page)
+ this._uid = SelectorID.generate();
+
+ // {Object} control layers list. Each key is a layer id, and its value is an object of layers options (layer, id, relief, visibility, title, description...)
+ this._layers = {};
+
+ // callbacks
+ this._callbacks = {};
+};
+
+/**
+ * Creates control main container
+ *
+ * @method _initContainer
+ * @param {Object} brOptions - control options
+ * @returns {DOMElement} container - widget container
+ * @private
+ */
+BoostRelief.prototype._initContainer = function (brOptions) {
+ var container = this._createMainContainerElement();
+
+ // adds in the main container the layer display selector
+ var inputShow = this._createMainBoostReliefShowElement(brOptions.collapsed);
+ container.appendChild(inputShow);
+
+ // adds the layer list in the main container
+ var divA = this._boostReliefListContainer = this._createMainBoostReliefListContainer();
+ var boostReliefList = this._createAdvancedToolElement(brOptions);
+
+ divA.appendChild(boostReliefList);
+ container.appendChild(divA);
+
+ // adds the widget picto in the main container
+ var picto = this._createMainPictoElement();
+ container.appendChild(picto);
+
+ if (brOptions.collapsed) {
+ divA.style.display = "block";
+ } else {
+ divA.style.display = "none";
+ }
+
+ return container;
+};
+
+// ################################################################### //
+// ######################### DOM events ############################## //
+// ################################################################### //
+
+/**
+ * Changes layer relief on layer relief picto click
+ *
+ * @method _onChangeLayerRelief
+ * @param {Object} e - HTML event
+ * @private
+ */
+BoostRelief.prototype._onChangeLayerRelief = function (e) {
+
+ var reliefValue = parseInt(e.target.value);
+ var reliefId = document.getElementById(this._addUID("GPreliefValue"));
+
+ reliefId.innerHTML = "x" + reliefValue;
+
+ this._updateLayersRelief(reliefValue);
+};
+
+/**
+ * Updates relief values of all elevation layers
+ *
+ * @method _updateLayerRelief
+ * @param {Number} reliefValue - relief value
+ * @private
+ */
+
+BoostRelief.prototype._updateLayersRelief = function (reliefValue) {
+ var globe = this.getGlobe();
+
+ function updateScale (layer, value) {
+ layer.scale = value;
+ globe.notifyChange(layer);
+ }
+ // if the scale of a single elevationLayer change, we update the scale of all others
+ var elevationLayers = globe.getElevationLayers();
+
+ for (var i = 0; i < elevationLayers.length; i++) {
+ updateScale(elevationLayers[i], reliefValue);
+ }
+
+};
+
+/**
+ * Updates relief slider and all elevation layers with the given boost value
+ *
+ * @method changeBoost
+ * @param {Number} reliefValue - relief value
+ */
+BoostRelief.prototype.changeBoost = function (reliefValue) {
+ var layerReliefInput = document.getElementById(this._addUID("GPreliefValueDiv"));
+
+ if (!layerReliefInput) {
+ logger.error("BoostRelief:changeBoost - boostRelief slider not loaded");
+ return;
+ }
+
+ // the reliefValue given must me in the slider range
+ if (reliefValue > layerReliefInput.max) {
+ reliefValue = layerReliefInput.max;
+ }
+ if (reliefValue < layerReliefInput.min) {
+ reliefValue = layerReliefInput.min;
+ }
+
+ // updates the relief of all the elevationlayers
+ this._updateLayersRelief(reliefValue);
+
+ // updates the slider cursor
+ layerReliefInput.value = reliefValue;
+
+ // updates the slider text
+ var layerReliefSpan = document.getElementById(this._addUID("GPreliefValue"));
+ if (layerReliefSpan) {
+ layerReliefSpan.innerHTML = "x" + reliefValue;
+ }
+};
+
+/**
+ * Gets layer id from div id
+ *
+ * @method _resolveLayerId
+ * @param {String} divId - HTML div id
+ * @returns {String} layer id
+ * @private
+ */
+BoostRelief.prototype._resolveLayerId = function (divId) {
+ var divName = SelectorID.name(divId); // ex GPvisibilityPicto_ID_26
+ return divName.substring(divName.indexOf("_ID_") + 4); // ex. 26
+};
+
+export default BoostRelief;
diff --git a/src/Itowns-review/Controls/LayerSwitcher.js b/src/Itowns-review/Controls/LayerSwitcher.js
new file mode 100644
index 000000000..e15c56e73
--- /dev/null
+++ b/src/Itowns-review/Controls/LayerSwitcher.js
@@ -0,0 +1,909 @@
+import GlobeViewExtended from "../GlobeViewExtended";
+import Logger from "../../Common/Utils/LoggerByDefault";
+import Utils from "../../Common/Utils";
+import SelectorID from "../../Common/Utils/SelectorID";
+import LayerSwitcherDOM from "../../Common/Controls/LayerSwitcherDOM";
+import Widget from "./Widget";
+
+var logger = Logger.getLogger("LayerSwitcher");
+
+/**
+ * @classdesc
+ * Control to manage globe layers : their order, visibility and opacity, and display their informations (title, description, legends, metadata...)
+ *
+ * @constructor
+ * @extends {itowns.control.Widget}
+ * @alias itowns.control.LayerSwitcher
+ * @param {Object} lsOptions - control options
+ * @param {Array} [lsOptions.layers] - list of layers to be configured. Each array element is an object, with following properties :
+ * @param {String} [lsOptions.layers.id] - ol.layer.Layer layer to be configured (that has been added to globe)
+ * @param {Object} [lsOptions.layers.config] - custom configuration object for layer information (title, description, legends, metadata, quicklook url), with following properties :
+ * @param {String} [lsOptions.layers.config.title] - layer alias, to be displayed in widget layer list. E.g. : "Cartes IGN"
+ * @param {String} [lsOptions.layers.config.description] - layer description, to be displayed on title hover, or in layer information panel.
+ * @param {String} [lsOptions.layers.config.quicklookUrl] - link to a quick look image for this layer.
+ * @param {Array} [lsOptions.layers.config.legends] - array of layer legends. Each array element is an object, with following properties :
+ * - url (String, mandatory) : link to a legend
+ * - minScaleDenominator (Number, optional) : min scale denominator for legend validity.
+ * @param {Array} [lsOptions.layers.config.metadata] - array of layer metadata. Each array element is an object, with property url (String, mandatory) : link to a metadata
+ * @param {Object} [lsOptions.options] - Itowns.control.Control options
+ * @param {Boolean} [lsOptions.options.collapsed = true] - Specify if widget has to be collapsed (true) or not (false) on globe loading.
+ * @example
+ * var layerSwitcher = new itowns.control.LayerSwitcher({
+ * layers : [
+ * {
+ * id : "myLayer",
+ * config : {
+ * title : "test layer name 1",
+ * description : "test layer desc 1",
+ * }
+ * }
+ * ],
+ * options : {
+ * collapsed : false
+ * }
+ * ));
+ */
+function LayerSwitcher (lsOptions) {
+ lsOptions = lsOptions || {};
+ var options = lsOptions.options || {};
+ var layers = lsOptions.layers || [];
+
+ if (!(this instanceof LayerSwitcher)) {
+ throw new TypeError("ERROR CLASS_CONSTRUCTOR");
+ }
+
+ if (layers && !Array.isArray(layers)) {
+ throw new Error("ERROR WRONG_TYPE : layers should be an array");
+ }
+
+ if (options && typeof options !== "object") {
+ throw new Error("ERROR WRONG_TYPE : options should be an object");
+ }
+
+ this._initialize(options, layers);
+
+ var container = this._initContainer(options);
+ // property to save layers conf added after the LS is initialized
+ this._addedLayerConf = {};
+
+ Widget.call(
+ this, {
+ name : "LayerSwitcher",
+ element : container,
+ target : options.target,
+ position : options.position
+ }
+ );
+}
+
+/*
+ * @lends module:LayerSwitcher
+ */
+LayerSwitcher.prototype = Object.create(Widget.prototype, {});
+
+// retrieves methods of the common class LayerSwitcherDOM
+Utils.assign(LayerSwitcher.prototype, LayerSwitcherDOM);
+
+/**
+ * Constructor (alias)
+ *
+ * @private
+ */
+LayerSwitcher.prototype.constructor = LayerSwitcher;
+
+// ################################################################### //
+// ############## public methods (getters, setters) ################## //
+// ################################################################### //
+
+/**
+ * Bind globe to control
+ *
+ * @param {GlobeViewExtended} globe - the globe
+ */
+LayerSwitcher.prototype.setGlobe = function (globe) {
+ var layers;
+ if (globe) { // in the case the control is added to the globe
+ var self = this;
+
+ // add options layers to layerlist.
+ // (only the layers configurated by the user in the options of the layerSwitcher )
+ // the other layers of the map will be added in the setGlobe method
+ for (var i = 0; i < this._initLayers.length; i++) {
+ // retrieves the layer...
+ var layer = null;
+
+ if (this._initLayers[i].id) {
+ layer = globe.getLayerById(this._initLayers[i].id);
+ }
+
+ if (layer && this._initLayers[i].displayed) {
+ // .. and the infos of the configuration if they exist (title, description, legends, quicklook, metadata)
+ var conf = this._initLayers[i].config || {};
+ var layerOptions = {
+ title : conf.title || layer.title || this._initLayers[i].id,
+ description : conf.description || null,
+ legends : conf.legends || [],
+ metadata : conf.metadata || [],
+ quicklookUrl : conf.quicklookUrl || null
+ };
+ if (typeof conf.ipr !== "undefined") {
+ layerOptions.ipr = conf.ipr;
+ }
+ if (typeof conf.opacity !== "undefined") {
+ layerOptions.opacity = conf.opacity;
+ }
+ if (typeof conf.visibility !== "undefined") {
+ layerOptions.visibility = conf.visibility;
+ }
+ this._layers[layer.id] = layerOptions;
+ }
+ }
+
+ // adds the layers
+ this._addGlobeLayers(globe);
+
+ // adding of listeners
+ this._callbacks.onOpacityLayerCallBack = function (e) {
+ self._updateLayerOpacity(e.target.id, e.new.opacity);
+ };
+
+ this._callbacks.onVisibilityLayerCallBack = function (e) {
+ self._updateLayerVisibility(e.target.id, e.new.visible);
+ };
+
+ // At every globe movement, layer switcher may be updated,
+ // according to layers on globe, and their range.
+ this._callbacks.onChangedViewCallBack = function (e) {
+ self._inRangeUpdate(e.colorLayersId);
+ };
+ globe.listen(GlobeViewExtended.EVENTS.PRE_RENDER, this._callbacks.onChangedViewCallBack);
+ // prerender events returns visible layers
+ globe.preRenderEventFetchColorLayersDisplayed();
+
+ this._callbacks.onAddedLayerCallBack = function (e) {
+ var id = e.layerId;
+ if (self) {
+ if (!self._layerDisplayedInLayerSwitcher(id)) {
+ return;
+ }
+ var layer = self.getGlobe().getLayerById(id);
+ if (layer.type === "elevation") {
+ return;
+ }
+ var layerConf = self._getLayerConf(id) || self._addedLayerConf[id];
+ if (layerConf) {
+ self.addLayer(layer, layerConf);
+ } else {
+ self.addLayer(layer);
+ }
+ }
+ };
+ globe.listen(GlobeViewExtended.EVENTS.LAYER_ADDED, this._callbacks.onAddedLayerCallBack);
+
+ this._callbacks.onRemovedLayerCallBack = function (e) {
+ var id = e.layerId;
+
+ // update the index max and delete the layer from the layerswitcher
+ if (self) {
+ self.removeLayer(id);
+ }
+ };
+ globe.listen(GlobeViewExtended.EVENTS.LAYER_REMOVED, this._callbacks.onRemovedLayerCallBack);
+
+ this._callbacks.onIndexLayerCallBack = function (e) {
+ var arraysEquals = function (a1, a2) {
+ if (a1.length !== a2.length) {
+ return false;
+ }
+ for (var i = 0; i < a1.length; ++i) {
+ if (a1[i] !== a2[i]) {
+ return false;
+ }
+ }
+ return true;
+ };
+
+ if (!arraysEquals(e.new.sequence, e.previous.sequence)) {
+ self._updateLayerListContainer();
+ }
+ };
+ globe.listen(GlobeViewExtended.EVENTS.LAYERS_ORDER_CHANGED, this._callbacks.onIndexLayerCallBack);
+
+ layers = globe.getColorLayers();
+ for (var ii = 0; ii < layers.length; ++ii) {
+ globe.addLayerListener(layers[ii], GlobeViewExtended.EVENTS.OPACITY_PROPERTY_CHANGED, this._callbacks.onOpacityLayerCallBack);
+ globe.addLayerListener(layers[ii], GlobeViewExtended.EVENTS.VISIBLE_PROPERTY_CHANGED, this._callbacks.onVisibilityLayerCallBack);
+ self._updateLayerVisibility(layers[ii].id, layers[ii].visible);
+ self._updateLayerOpacity(layers[ii].id, layers[ii].opacity);
+ }
+ } else {
+ // removes the listeners associated to the deleted layerswitcher
+ this._globe.forget(GlobeViewExtended.EVENTS.PRE_RENDER, this._callbacks.onChangedViewCallBack);
+ this._globe.forget(GlobeViewExtended.EVENTS.LAYER_ADDED, this._callbacks.onAddedLayerCallBack);
+ this._globe.forget(GlobeViewExtended.EVENTS.LAYER_REMOVED, this._callbacks.onRemovedLayerCallBack);
+ this._globe.forget(GlobeViewExtended.EVENTS.LAYERS_ORDER_CHANGED, this._callbacks.onIndexLayerCallBack);
+ layers = this._globe.getColorLayers();
+ for (var j = 0; j < layers.length; ++j) {
+ this._globe.removeLayerListener(layers[j], GlobeViewExtended.EVENTS.OPACITY_PROPERTY_CHANGED, this._callbacks.onOpacityLayerCallBack);
+ this._globe.removeLayerListener(layers[j], GlobeViewExtended.EVENTS.VISIBLE_PROPERTY_CHANGED, this._callbacks.onVisibilityLayerCallBack);
+ }
+ // deletes the layerSwitcher DOM
+ while (this._element.hasChildNodes()) {
+ this._element.removeChild(this._element.lastChild);
+ }
+ this._element.parentNode.removeChild(this._element);
+ }
+
+ // calls original setGlobe method
+ Widget.prototype.setGlobe.call(this, globe);
+};
+
+/**
+ * Adds a new layer to control (when added to globe) or add new layer configuration
+ *
+ * @param {Object} layer - layer to add to layer switcher
+ * @param {Object} [config] - additional options for layer configuration
+ * @param {Object} [config.title] - layer title (default is layer identifier)
+ * @param {Object} [config.description] - layer description (default is null)
+ * @param {Object} [config.legends] - layer legends (default is an empty array)
+ * @param {Object} [config.metadata] - layer metadata (default is an empty array)
+ * @param {Object} [config.quicklookUrl] - layer quicklookUrl (default is null)
+ * @example
+ * layerSwitcher.addLayer({
+ * layer : gpParcels,
+ * config : {
+ * title : "Parcelles cadastrales",
+ * description : "description de la couche",
+ * quicklookUrl : "http://quicklookUrl.fr"
+ * }
+ * })
+ */
+LayerSwitcher.prototype.addLayer = function (layer, config) {
+ config = config || {};
+ var globe = this.getGlobe();
+
+ if (!layer) {
+ logger.error("LayerSwitcher:addLayer - missing layer parameter");
+ return;
+ }
+
+ var id = layer.id;
+ if (id === "undefined") {
+ logger.error("LayerSwitcher:addLayer - configuration cannot be set for " + layer + " layer (layer id not found)");
+ return;
+ }
+
+ // subscription to the events
+ globe.addLayerListener(layer, GlobeViewExtended.EVENTS.OPACITY_PROPERTY_CHANGED, this._callbacks.onOpacityLayerCallBack);
+ globe.addLayerListener(layer, GlobeViewExtended.EVENTS.VISIBLE_PROPERTY_CHANGED, this._callbacks.onVisibilityLayerCallBack);
+
+ // make sure layer is in globe layers
+ var LayerInGlobe = globe.getLayerById(id);
+
+ if (!LayerInGlobe) {
+ logger.error("LayerSwitcher:addLayer - configuration cannot be set for ", layer, " layer (layer is not in globe layers )");
+ return;
+ }
+
+ // if layer is not already in layers list, add it to control (layers list and container div)
+ if (!this._layers[id]) {
+ // 1. add layer to layers list
+ var layerInfos = this._getLayerInfo(layer) || {};
+ var layerOptions = {
+ title : config.title || layerInfos._title || id,
+ description : config.description || layerInfos._description || null,
+ legends : config.legends || layerInfos._legends || [],
+ metadata : config.metadata || layerInfos._metadata || [],
+ quicklookUrl : config.quicklookUrl || layerInfos._quicklookUrl || null
+ };
+ if (typeof config.ipr !== "undefined") {
+ layerOptions.ipr = config.ipr;
+ layer.attribution = layerOptions.ipr;
+ }
+ if (typeof config.opacity !== "undefined") {
+ layerOptions.opacity = config.opacity;
+ layer.opacity = layerOptions.opacity;
+ }
+ if (typeof config.visibility !== "undefined") {
+ layerOptions.visibility = config.visibility;
+ layer.visible = layerOptions.visibility;
+ }
+ this._layers[id] = layerOptions;
+
+ // creation of the div of the layer which will be added to the layerSwitcher
+ this._layers[id].div = this._createLayerDiv(id);
+
+ this._updateLayerListContainer();
+
+ // user may also add a new configuration for an already added layer
+ } else if (this._layers[id] && config) {
+ // add new configuration parameters to layer informations
+ for (var prop in config) {
+ if (config.hasOwnProperty(prop)) {
+ this._layers[id][prop] = config[prop];
+ }
+ }
+ if (typeof config.ipr !== "undefined") {
+ layer.attribution = config.ipr;
+ }
+ if (typeof config.opacity !== "undefined") {
+ layer.opacity = config.opacity;
+ }
+ if (typeof config.visibility !== "undefined") {
+ layer.visible = config.visibility;
+ }
+ // set new title in layer div
+ if (config.title) {
+ var nameDiv = document.getElementById(this._addUID("GPname_ID_" + id));
+ if (nameDiv) {
+ nameDiv.innerHTML = config.title;
+ // FIXME a ajouter?
+ // nameDiv.title = config.description || config.title;
+ }
+ }
+ // add layer info picto if necessary
+ var infodiv = document.getElementById(this._addUID("GPinfo_ID_" + id));
+ if (!document.getElementById(this._addUID("GPinfo_ID_" + id)) && config.description && (config.legends || config.metadata || config.quicklookUrl)) {
+ var advancedTools = document.getElementById(this._addUID("GPadvancedTools_ID_" + id));
+ if (advancedTools) {
+ advancedTools.appendChild(
+ this._createAdvancedToolInformationElement({
+ id : id
+ })
+ );
+ }
+ }
+ // close layer info element if open, to update information.
+ if (infodiv && infodiv.className === "GPlayerInfoOpened") {
+ document.getElementById(this._addUID("GPlayerInfoPanel")).className = "GPlayerInfoPanelClosed";
+ infodiv.className = "GPlayerInfo";
+ }
+ }
+};
+
+/**
+ * Removes a layer from control
+ *
+ * @param {Object} layerId - layer to remove to layer switcher
+ */
+LayerSwitcher.prototype.removeLayer = function (layerId) {
+ var layerList = document.getElementById(this._addUID("GPlayersList"));
+ // close layer info element if open.
+ var infodiv = document.getElementById(this._addUID("GPinfo_ID_" + layerId));
+ if (infodiv && infodiv.className === "GPlayerInfoOpened") {
+ document.getElementById(this._addUID("GPlayerInfoPanel")).className = "GPlayerInfoPanelClosed";
+ infodiv.className = "GPlayerInfo";
+ }
+ // remove layer div
+ var layerDiv = document.getElementById(this._addUID("GPlayerSwitcher_ID_" + layerId));
+ layerList.removeChild(layerDiv);
+
+ // removes layer of the layer list
+ delete this._layers[layerId];
+};
+
+/**
+ * Collapse or display control main container
+ *
+ * @param {Boolean} collapsed - True to collapse control, False to display it
+ */
+LayerSwitcher.prototype.setCollapsed = function (collapsed) {
+ if (collapsed === undefined) {
+ logger.error("LayerSwitcher:setCollapsed - missing collapsed parameter");
+ return;
+ }
+ var isCollapsed = this.getCollapsed();
+ if ((collapsed && isCollapsed) || (!collapsed && !isCollapsed)) {
+ return;
+ }
+ // simulates the panel opening after a click
+ if (!isCollapsed) {
+ var layers = document.getElementsByClassName("GPlayerInfoOpened");
+ for (var i = 0; i < layers.length; i++) {
+ layers[i].className = "GPlayerInfo";
+ }
+ document.getElementById(this._addUID("GPlayerInfoPanel")).className = "GPlayerInfoPanelClosed";
+ }
+ document.getElementById(this._addUID("GPshowLayersList")).checked = !collapsed;
+};
+
+/**
+ * Returns true if widget is collapsed (minimize), false otherwise
+ * @return {Boolean} is collapsed
+ */
+LayerSwitcher.prototype.getCollapsed = function () {
+ return !document.getElementById(this._addUID("GPshowLayersList")).checked;
+};
+
+// ################################################################### //
+// ##################### init component ############################## //
+// ################################################################### //
+
+/**
+ * Initialize LayerSwitcher control (called by constructor)
+ *
+ * @param {Object} options - Itowns.control.Control options
+ * @param {Array} layers - list of layers to be configured. Each array element is an object, with following properties :
+ * @private
+ */
+LayerSwitcher.prototype._initialize = function (options, layers) {
+ // id of the control ; used to suffix the CSS id (handles cases with severel controls on the same page)
+ this._uid = SelectorID.generate();
+
+ // {Object} control layers list. Each key is a layer id, and its value is an object of layers options (layer, id, opacity, visibility, title, description...)
+ this._layers = {};
+
+ // div which will contain the divs of the lists
+ this._layerListContainer = null;
+
+ // callbacks
+ this._callbacks = {};
+
+ // options
+ this._options = options;
+ this._initLayers = layers;
+};
+
+/**
+ * Returns the layer configuration defined at widget initialization
+ *
+ * @method _getLayerConf
+ * @param {String} layerId - layer id
+ * @return {Object} layerConfig - layer configuration
+ * @private
+ */
+LayerSwitcher.prototype._getLayerConf = function (layerId) {
+ for (var i = 0; i < this._initLayers.length; ++i) {
+ if (this._initLayers[i].id === layerId) {
+ return this._initLayers[i].config;
+ }
+ }
+ return null;
+};
+
+/**
+ * Indicates if the layer must be displayed in the layerSwitcher
+ *
+ * @method _layerDisplayedInLayerSwitcher
+ * @param {String} layerId - layer id
+ * @return {Boolean} displayed
+ * @private
+ */
+LayerSwitcher.prototype._layerDisplayedInLayerSwitcher = function (layerId) {
+ for (var i = 0; i < this._initLayers.length; ++i) {
+ if (this._initLayers[i].id === layerId) {
+ return (typeof this._initLayers[i].displayed === "undefined" || this._initLayers[i].displayed);
+ }
+ }
+ return true;
+};
+
+/**
+ * Creates control main container
+ *
+ * @method _initContainer
+ * @param {Object} options - control options
+ * @returns {DOMElement} container - widget container
+ * @private
+ */
+LayerSwitcher.prototype._initContainer = function (options) {
+ // creation of the main container
+ var container = this._createMainContainerElement();
+
+ // adding in the main container
+ var input = this._createMainLayersShowElement();
+ container.appendChild(input);
+
+ // handling of the "collapsed" mode
+ if (!options.collapsed) {
+ input.checked = "checked";
+ }
+ // adds the layer list in the main container
+ var divL = this._layerListContainer = this._createMainLayersElement();
+ container.appendChild(divL);
+
+ // creates the draggable mode
+ this._createDraggableElement(divL, this);
+
+ // adds the control picto in the main container
+ var picto = this._createMainPictoElement();
+ container.appendChild(picto);
+
+ // adds the info panel in the main container
+ var divI = this._createMainInfoElement();
+ container.appendChild(divI);
+
+ return container;
+};
+
+/**
+ * Adds control layers to control main container
+ *
+ * @method _addGlobeLayers
+ * @param {Object} globe - the Itowns.GlobeViewExtended object
+ * @private
+ */
+LayerSwitcher.prototype._addGlobeLayers = function (globe) {
+ // Retrieves the element which contains the different layers
+ var elementLayersList;
+ var childNodes = this.getElement().childNodes;
+
+ for (var i = 0; i < childNodes.length; i++) {
+ if (childNodes[i].id === this._addUID("GPlayersList")) {
+ elementLayersList = childNodes[i];
+ break;
+ }
+ }
+ // reorders layers according to the layer stack (globe.getLayers returns an reverse ordenered array)
+ var layers = globe.getColorLayers();
+ var orderedLayers = layers.sort(function (a, b) {
+ return b.sequence - a.sequence;
+ });
+
+ // loop over all the layers of the map in order to add them to the control layer list (if they are not already added)
+ orderedLayers.forEach(
+ function (layer) {
+ // adds the map layers to the list
+ var id;
+ id = layer.id;
+ if (!this._layerDisplayedInLayerSwitcher(id)) {
+ return;
+ }
+ var layerConf = this._getLayerConf(id) || this._addedLayerConf[id] || {};
+ var layerInfos = this._getLayerInfo(layer) || {};
+ if (!this._layers[id]) {
+ // if the layer is not yet in the layer list (this._layers), we add it
+ var layerOptions = {
+ title : layerConf.title || layerInfos._title || id,
+ description : layerConf.description || layerInfos._description || null,
+ legends : layerConf.legends || layerInfos._legends || [],
+ metadata : layerConf.metadata || layerInfos._metadata || [],
+ quicklookUrl : layerConf.quicklookUrl || layerInfos._quicklookUrl || null
+ };
+ this._layers[id] = layerOptions;
+ } else {
+ var lsLayerConf = this._layers[id];
+ if (typeof lsLayerConf.ipr !== "undefined") {
+ layer.options.attribution = lsLayerConf.ipr;
+ }
+ if (typeof lsLayerConf.opacity !== "undefined") {
+ layer.opacity = lsLayerConf.opacity;
+ }
+ if (typeof lsLayerConf.visibility !== "undefined") {
+ layer.visible = lsLayerConf.visibility;
+ }
+ }
+
+ var layerDiv = this._createLayerDiv(id);
+ this._layers[id].div = layerDiv;
+ elementLayersList.appendChild(layerDiv);
+ },
+ this
+ );
+};
+
+/**
+ * creates layer div (to append to control DOM element).
+ *
+ * @method _createLayerDiv
+ * @param {String} layerId - layer id
+ * @returns {DOMElement} layer div
+ * @private
+ */
+LayerSwitcher.prototype._createLayerDiv = function (layerId) {
+ var layerOptions = this._layers[layerId];
+ var isLegends = layerOptions.legends && layerOptions.legends.length !== 0;
+ var isMetadata = layerOptions.metadata && layerOptions.metadata.length !== 0;
+ var isQuicklookUrl = layerOptions.quicklookUrl;
+ if (isLegends || isMetadata || isQuicklookUrl) {
+ layerOptions.displayInformationElement = true;
+ }
+
+ // adds a specific div in the control for the layer
+ layerOptions.id = layerId;
+ var layerDiv = this._createContainerLayerElement(layerOptions);
+
+ if (!layerOptions.inRange) {
+ layerDiv.classList.add("outOfRange");
+ }
+
+ return layerDiv;
+};
+
+// ################################################################### //
+// ######################### DOM events ############################## //
+// ################################################################### //
+
+/**
+ * Changes layer opacity on layer opacity picto click
+ *
+ * @method _onChangeLayerOpacity
+ * @param {Object} e - HTML event
+ * @private
+ */
+LayerSwitcher.prototype._onChangeLayerOpacity = function (e) {
+ var globe = this.getGlobe();
+ var layerID = this._resolveLayerId(e.target.id);
+
+ var opacityValue = e.target.value;
+ var opacityId = document.getElementById(this._addUID("GPopacityValue_ID_" + layerID));
+ opacityId.innerHTML = opacityValue + "%";
+ globe.setLayerOpacity(layerID, opacityValue / 100);
+};
+
+/**
+ * Updates picto opacity value on layer opacity change
+ *
+ * @method _updateLayerOpacity
+ * @param {String} layerId - layer id
+ * @param {Number} opacity - opacity value
+ * @private
+ */
+LayerSwitcher.prototype._updateLayerOpacity = function (layerId, opacity) {
+ if (opacity > 1) {
+ opacity = 1;
+ }
+ if (opacity < 0) {
+ opacity = 0;
+ }
+
+ var layerOpacityInput = document.getElementById(this._addUID("GPopacityValueDiv_ID_" + layerId));
+ if (layerOpacityInput) {
+ layerOpacityInput.value = Math.round(opacity * 100);
+ }
+
+ var layerOpacitySpan = document.getElementById(this._addUID("GPopacityValue_ID_" + layerId));
+ if (layerOpacitySpan) {
+ layerOpacitySpan.innerHTML = Math.round(opacity * 100) + "%";
+ }
+};
+
+/**
+ * Changes layer visibility on layer visibility picto click
+ *
+ * @method _onVisibilityLayerClick
+ * @param {Object} e - HTML event
+ * @private
+ */
+LayerSwitcher.prototype._onVisibilityLayerClick = function (e) {
+ var globe = this.getGlobe();
+
+ var layerID = this._resolveLayerId(e.target.id);
+ globe.setLayerVisibility(layerID, e.target.checked); // update viewer
+};
+
+/**
+ * Changes picto visibility on layer visibility change
+ *
+ * @method _updateLayerVisibility
+ * @param {String} layerId - layer id
+ * @param {Boolean} visibility - visible if true
+ * @private
+ */
+LayerSwitcher.prototype._updateLayerVisibility = function (layerId, visibility) {
+ var layerVisibilityInput = document.getElementById(this._addUID("GPvisibility_ID_" + layerId));
+ if (layerVisibilityInput) {
+ layerVisibilityInput.checked = visibility;
+ }
+};
+
+/**
+ * Opens layer information panel on picto click
+ *
+ * @method _onOpenLayerInfoClick
+ * @param {Event} e - MouseEvent
+ * @private
+ */
+LayerSwitcher.prototype._onOpenLayerInfoClick = function (e) {
+ var layerID = this._resolveLayerId(e.target.id);
+
+ var layerOptions = this._layers[layerID];
+
+ var panel;
+ var info;
+
+ // Close layer info panel
+ var divId = document.getElementById(e.target.id);
+ if (divId.className === "GPlayerInfoOpened") {
+ if (divId.classList !== undefined) {
+ divId.classList.remove("GPlayerInfoOpened");
+ divId.classList.add("GPlayerInfo");
+ }
+
+ panel = document.getElementById(this._addUID("GPlayerInfoPanel"));
+ if (panel.classList !== undefined) {
+ panel.classList.remove("GPpanel");
+ panel.classList.remove("GPlayerInfoPanelOpened");
+ panel.classList.add("GPlayerInfoPanelClosed");
+ }
+
+ info = document.getElementById(this._addUID("GPlayerInfoContent"));
+ panel.removeChild(info);
+ return;
+ }
+
+ var layers = document.getElementsByClassName("GPlayerInfoOpened");
+ for (var i = 0; i < layers.length; i++) {
+ layers[i].className = "GPlayerInfo";
+ }
+
+ // Open layer info panel
+ if (divId.classList !== undefined) {
+ divId.classList.remove("GPlayerInfo");
+ divId.classList.add("GPlayerInfoOpened");
+ }
+
+ panel = document.getElementById(this._addUID("GPlayerInfoPanel"));
+ if (panel.classList !== undefined) {
+ panel.classList.add("GPpanel");
+ panel.classList.remove("GPlayerInfoPanelClosed");
+ panel.classList.add("GPlayerInfoPanelOpened");
+ }
+
+ info = document.getElementById(this._addUID("GPlayerInfoContent"));
+ if (info) {
+ panel.removeChild(info);
+ }
+
+ // on récupère les infos associées au layer pour mettre dynamiquement le contenu du panel d'informations
+ var obj = {
+ title : layerOptions.title,
+ description : layerOptions.description,
+ quicklookUrl : layerOptions.quicklookUrl,
+ metadata : layerOptions.metadata,
+ legends : layerOptions.legends
+ };
+
+ var infoLayer = this._createContainerLayerInfoElement(obj);
+ panel.appendChild(infoLayer);
+};
+
+/**
+ * removes layer from layer switcher and globe on picto click
+ *
+ * @method _onDropLayerClick
+ * @param {Event} e - MouseEvent
+ * @private
+ */
+LayerSwitcher.prototype._onDropLayerClick = function (e) {
+ var globe = this.getGlobe();
+
+ var layerID = this._resolveLayerId(e.target.id);
+ // removing the layer will trigger the event listener
+ // which will call this.removeLayer and delete the div
+ globe.removeLayer(layerID);
+
+ this._updateLayerListContainer();
+};
+
+/**
+ * changes layers order on drag and drop
+ *
+ * @method _onDropLayerClick
+ * @param {Event} e - HTML event
+ * @private
+ */
+LayerSwitcher.prototype._onDragAndDropLayerClick = function (e) {
+ var globe = this.getGlobe();
+
+ // Handling of the indexes : gives the little indexes (lowest layers) to the non-visible layers (displayed: false)
+ // when the index of a visible layer changes.
+ // Always moves the non-visible layers under the other layers (to not hide them)
+
+ if (e.newIndex - e.oldIndex === 0) {
+ return;
+ }
+
+ var targetIndex = null;
+ if (!e.newIndex || e.newIndex === 0) {
+ targetIndex = globe.getColorLayers().length - 1;
+ } else {
+ var layerTargetID = this._resolveLayerId(e.from.childNodes[e.newIndex + (e.newIndex - e.oldIndex < 0 ? 1 : -1)].id);
+ targetIndex = globe.getLayerById(layerTargetID).sequence;
+ }
+
+ var layerID = this._resolveLayerId(e.item.id);
+
+ globe.moveLayerToIndex(layerID, targetIndex);
+};
+
+/**
+ * Checks layers range
+ *
+ * @method _inRangeUpdate
+ * @param {Array} layersDisplayed - list of displayed layers id
+ * @private
+ */
+LayerSwitcher.prototype._inRangeUpdate = function (layersDisplayed) {
+ for (var layerKey in this._layers) {
+ var layer = this._layers[layerKey];
+ if (!layer) {
+ continue;
+ }
+ // Check if layer is displayed.
+ var layerDiv;
+ var bInRange = layersDisplayed.indexOf(layer.id) >= 0;
+ if (bInRange && !layer.inRange) {
+ layer.inRange = true;
+ layerDiv = document.getElementById(this._addUID("GPlayerSwitcher_ID_" + layer.id));
+ layerDiv.classList.remove("outOfRange");
+ } else if (!bInRange && layer.inRange) {
+ layer.inRange = false;
+ layerDiv = document.getElementById(this._addUID("GPlayerSwitcher_ID_" + layer.id));
+ layerDiv.classList.add("outOfRange");
+ }
+ }
+};
+
+/**
+ * Update the layer list container
+ *
+ * @method _updateLayerListContainer
+ * @private
+ */
+LayerSwitcher.prototype._updateLayerListContainer = function () {
+ if (this._layerListContainer) {
+ var globe = this.getGlobe();
+
+ // empty the previous container
+ while (this._layerListContainer.firstChild) {
+ this._layerListContainer.removeChild(this._layerListContainer.firstChild);
+ }
+ // reorders layers according to the layer stack (globe.getLayers returns an reverse ordenered array)..
+ var layers = globe.getColorLayers();
+ var orderedLayers = layers.sort(function (a, b) {
+ return b.sequence - a.sequence;
+ });
+ // ... and adds the correct div to the different layers, in the zindex decreasing order
+ for (var j = 0; j < orderedLayers.length; j++) {
+ if (!this._layers[orderedLayers[j].id]) {
+ continue;
+ }
+ // retrieves the div of the layer, stored in the _layers array
+ var layerDiv = this._layers[orderedLayers[j].id].div;
+ this._layerListContainer.appendChild(layerDiv);
+ }
+ } else {
+ logger.error("[Itowns.control.LayerSwitcher] _updateLayerListContainer : layer list container not found to update layers order ?!");
+ }
+};
+
+// ################################################################### //
+// ############################ Utils ################################ //
+// ################################################################### //
+
+/**
+ * Gets layer informations : title, description, quicklookurl, legends, metadata
+ *
+ * @private
+ * @memberof LayerSwitcher
+ * @method _getLayerInfo
+ * @param {Object} layer - the layer object
+ * @returns {Object} layerInfo - layer informations
+ */
+LayerSwitcher.prototype._getLayerInfo = function (layer) {
+ var layerInfo = {};
+ if (layer) {
+ layerInfo._title = layer.title || null;
+ layerInfo._description = layer.description || null;
+ layerInfo._quicklookUrl = layer.quicklookUrl || null;
+ layerInfo._metadata = layer.metadata || null;
+ layerInfo._legends = layer.legends || null;
+ }
+ return layerInfo;
+};
+
+/**
+ * Gets layer id from div id
+ *
+ * @method _resolveLayerId
+ * @param {String} divId - HTML div id
+ * @returns {String} layer id
+ * @private
+ */
+LayerSwitcher.prototype._resolveLayerId = function (divId) {
+ var divName = SelectorID.name(divId); // ex GPvisibilityPicto_ID_26
+ return divName.substring(divName.indexOf("_ID_") + 4); // ex. 26
+};
+
+export default LayerSwitcher;
diff --git a/src/Itowns-review/Controls/MiniGlobe.js b/src/Itowns-review/Controls/MiniGlobe.js
new file mode 100644
index 000000000..8c4c21ac8
--- /dev/null
+++ b/src/Itowns-review/Controls/MiniGlobe.js
@@ -0,0 +1,161 @@
+import GlobeViewExtended from "../GlobeViewExtended";
+import Utils from "../../Common/Utils";
+import SelectorID from "../../Common/Utils/SelectorID";
+import MiniGlobeDOM from "../../Common/Controls/MiniGlobeDOM";
+import Widget from "./Widget";
+
+/**
+ * @classdesc
+ * Control to display the MiniGlobe with itowns
+ *
+ * @constructor
+ * @extends {itowns.control.Widget}
+ * @alias itowns.control.MiniGlobe
+ * @param {Object} [options] - control options
+ * @param {Object} [options.layer] - custom itowns layer to display on the mini globe
+ * @example
+ * var miniglobe = new itowns.control.MiniGlobe();
+ *
+ */
+function MiniGlobe (options) {
+ options = options || {};
+
+ if (!(this instanceof MiniGlobe)) {
+ throw new TypeError("ERROR CLASS_CONSTRUCTOR");
+ }
+
+ if (options && typeof options !== "object") {
+ throw new Error("ERROR WRONG_TYPE : options should be an object");
+ }
+
+ this._initialize();
+
+ var container = this._initContainer();
+ this._options = options;
+
+ Widget.call(
+ this, {
+ name : "Overview",
+ element : container,
+ target : options.target,
+ position : options.position
+ }
+ );
+}
+
+/*
+ * @lends module:MiniGlobe
+ */
+MiniGlobe.prototype = Object.create(Widget.prototype, {});
+
+// retrieves methods of the common class MiniGlobeDOM
+Utils.assign(MiniGlobe.prototype, MiniGlobeDOM);
+
+/**
+ * Constructor (alias)
+ *
+ * @private
+ */
+MiniGlobe.prototype.constructor = MiniGlobe;
+
+// ################################################################### //
+// ############## public methods (getters, setters) ################## //
+// ################################################################### //
+
+/**
+ * Bind globe to control
+ *
+ * @param {GlobeViewExtended} globe - the globe
+ */
+MiniGlobe.prototype.setGlobe = function (globe) {
+ // info : this function is called after a globe.addWidget() or a globe.removeWidget()
+
+ if (globe) { // In the case of the adding of a control to the globe
+ var minDistance = 6650000;
+ var maxDistance = 30000000;
+ var positionOnGlobe = globe.getCenter();
+ var miniView = new GlobeViewExtended(this._element, positionOnGlobe, {
+ // `limit globe' subdivision level:
+ // we're don't need a precise globe model
+ // since the mini globe will always be seen from a far point of view (see minDistance above)
+ maxSubdivisionLevel : 6,
+ sseSubdivisionThreshold : 3,
+ // Don't instance default controls since miniview's camera will be synced
+ // on the main view's one (see globeView.onAfterRender)
+ noControls : true
+ });
+
+ miniView.setBackground();
+
+ var updateMiniGlobeHandler = function () {
+ // clamp distance camera from globe
+ var distanceCamera = globe.getGlobeView().camera.camera3D.position.length();
+ var distance = Math.min(Math.max(distanceCamera, minDistance), maxDistance);
+ var camera = miniView.getGlobeView().camera.camera3D;
+ var cameraTargetPosition = globe.getGlobeView().controls.getCameraTargetPosition();
+ // Update target miniview's camera
+ camera.position.copy(cameraTargetPosition).setLength(distance);
+ camera.lookAt(cameraTargetPosition);
+ miniView.notifyChange(camera);
+ };
+ globe.listen(GlobeViewExtended.EVENTS.AFTER_RENDER, updateMiniGlobeHandler);
+ if (globe.isInitialized()) {
+ updateMiniGlobeHandler();
+ } else {
+ globe.listen(GlobeViewExtended.EVENTS.GLOBE_INITIALIZED, updateMiniGlobeHandler);
+ }
+
+ /**
+ * Add one imagery layer to the miniview (by default, the ortho)
+ */
+ var miniGlobeLayer = this._options.layer;
+ miniView.addLayer(miniGlobeLayer);
+ // save as property of the control the globe created for the overview
+ this._globeObj = miniView;
+ } else if (globe == null) {
+ // if globe == null we remove the overview control
+ // we delete the overview control DOM
+ while (this.getElement().hasChildNodes()) {
+ this.getElement().removeChild(this.getElement().lastChild);
+ }
+ this.getElement().parentNode.removeChild(this.getElement());
+ }
+
+ // call original setGlobe method
+ Widget.prototype.setGlobe.call(this, globe);
+};
+
+// ################################################################### //
+// ##################### init component ############################## //
+// ################################################################### //
+
+/**
+ * Initialize MiniGlobe control (called by constructor)
+ *
+ * @private
+ */
+MiniGlobe.prototype._initialize = function () {
+ // id of the widget : usefull to suffix the CSS ids (to handle cases with several widgets on the same page)
+ this._uid = SelectorID.generate();
+
+ // div which will contain the list divs.
+ this._MiniGlobeContainer = null;
+
+ // callbacks
+ this._callbacks = {};
+};
+
+/**
+ * Creates control main container
+ *
+ * @method _initContainer
+ * @returns {DOMElement} container - widget container
+ * @private
+ */
+MiniGlobe.prototype._initContainer = function () {
+ var container = this._createMainContainerElement();
+
+ return container;
+};
+
+export default MiniGlobe;
diff --git a/src/Itowns-review/Controls/MousePosition.js b/src/Itowns-review/Controls/MousePosition.js
new file mode 100644
index 000000000..9a96a292e
--- /dev/null
+++ b/src/Itowns-review/Controls/MousePosition.js
@@ -0,0 +1,1278 @@
+import proj4 from "proj4";
+import Logger from "../../Common/Utils/LoggerByDefault";
+import Gp from "geoportal-access-lib";
+import GlobeViewExtended from "../GlobeViewExtended";
+import Utils from "../../Common/Utils";
+import RightManagement from "../../Common/Utils/CheckRightManagement";
+import SelectorID from "../../Common/Utils/SelectorID";
+import MousePositionDOM from "../../Common/Controls/MousePositionDOM";
+import Widget from "./Widget";
+import PositionFormater from "./Utils/PositionFormater";
+import CRS from "../CRS/CRS";
+
+var logger = Logger.getLogger("MousePosition");
+
+/**
+ * @classdesc
+ *
+ * MousePosition Control.
+ *
+ * @constructor
+ * @alias itowns.control.MousePosition
+ * @extends {itowns.control.Control}
+ * @param {Object} options - options for function call.
+ * @param {Boolean} [options.ssl = true] - use of ssl or not (default true, service requested using https protocol)
+ * @param {Boolean} [options.collapsed = true] - Specify if MousePosition control should be collapsed at startup. Default is true.
+ * @param {Array} [options.systems] - list of projection systems, default are Geographical ("EPSG:4326"), Web Mercator ("EPSG:3857"), Lambert 93 ("EPSG:2154") and extended Lambert 2 ("EPSG:27572").
+ * Each array element (=system) is an object with following properties :
+ * @param {String} options.systems.crs - Proj4 crs alias (from proj4 defs). e.g. : "EPSG:4326". Required
+ * @param {String} [options.systems.label] - CRS label to be displayed in control. Default is crs code (e.g. "EPSG:4326")
+ * @param {String} options.systems.type - CRS units type for coordinates conversion : "Geographical" or "Metric". Default: "Metric"
+ * @param {Object} [options.systems.geoBBox] - Aera covered by the system (WGS84 coordinates).
+ * @param {Number} options.systems.geoBBox.right - Right bound.
+ * @param {Number} options.systems.geoBBox.left - Left bound.
+ * @param {Number} options.systems.geoBBox.top - Top bound.
+ * @param {Number} options.systems.geoBBox.bottom - Bottom bound.
+ * @param {Array} [options.units] - list of coordinates units, to be displayed in control units list.
+ * Values may be "DEC" (decimal degrees), "DMS" (sexagecimal), "RAD" (radians) and "GON" (grades) for geographical coordinates,
+ * and "M" or "KM" for metric coordinates
+ * @param {Array} [options.displayAltitude = true] - activate (true) or deactivate (false) the altitude panel. True by default
+ * @param {Array} [options.displayCoordinates = true] - activate (true) or deactivate (false) the coordinates panel. True by default
+ * @param {Object} [options.altitude] - elevation configuration
+ * @param {Object} [options.altitude.serviceOptions] - options of elevation service
+ * @param {Number} [options.altitude.responseDelay] - latency for altitude request, 500 ms by default
+ * @param {Number} [options.altitude.triggerDelay] - immobilisation time of movement on the globe to trigger the elevation calculation, 200 ms by default
+ * @example
+ * var mousePosition = new itowns.control.MousePosition({
+ * collapsed : false,
+ * displayCoordinates : true,
+ * displayAltitude : true,
+ * altitude : {
+ * triggerDelay : 100,
+ * responseDelay : 500,
+ * serviceOptions : {}
+ * },
+ * systems : [
+ * {
+ * crs : "EPSG:3857",
+ * label : "Mercator",
+ * type : "Metric"
+ * },
+ * {
+ * crs : "EPSG:32620",
+ * label : "UTM 20N (Guadeloupe, Martinique)",
+ * type : "Metric",
+ * geoBBox : {
+ * left: -66.00,
+ * bottom : 0.00,
+ * right : -60.00,
+ * top : 84.00
+ * }
+ * }
+ * ],
+ * units : ["DEC", "DMS"]
+ * });
+ */
+function MousePosition (options) {
+ options = options || {};
+
+ if (!(this instanceof MousePosition)) {
+ throw new TypeError("ERROR CLASS_CONSTRUCTOR");
+ }
+
+ if (options && typeof options !== "object") {
+ throw new Error("ERROR WRONG_TYPE : options should be an object");
+ }
+
+ this._initialize(options);
+
+ this._callbacks = {};
+
+ // init control DOM container
+ var container = this._initContainer(options);
+
+ Widget.call(
+ this, {
+ name : "MousePosition",
+ element : container,
+ target : options.target,
+ position : options.position
+ }
+ );
+};
+
+/**
+ * @lends module:MousePosition
+ */
+MousePosition.prototype = Object.create(Widget.prototype, {});
+
+Utils.assign(MousePosition.prototype, MousePositionDOM);
+
+/**
+ * Constructor (alias)
+ */
+MousePosition.prototype.constructor = MousePosition;
+
+/**
+ * Bind globe to control
+ *
+ * @param {GlobeViewExtended} globe - the globe
+ */
+MousePosition.prototype.setGlobe = function (globe) {
+ if (globe) { // In the case of the adding of a control to the globe
+ this._centerElement = this._createMapCenter();
+ globe.getTargetElement().appendChild(this._centerElement);
+
+ // defines the callback on the map to retrieve the coordinates
+ this._callbacks.mouseMove = this.onMouseMove.bind(this);
+
+ // valid event for desktop mode
+ if (!this.collapsed) {
+ if (this._isDesktop) {
+ globe.listen(GlobeViewExtended.EVENTS.MOUSE_MOVE, this._callbacks.mouseMove);
+ } else {
+ globe.listen(GlobeViewExtended.EVENTS.CENTER_CHANGED, this.onGlobeMove);
+ }
+ }
+ } else if (globe == null) { // if globe == null we remove the MP control
+ // deletes the listener associated to the mousePosition control
+ this._globe.forget(GlobeViewExtended.EVENTS.MOUSE_MOVE, this._callbacks.mouseMove);
+ // deletes the mousePosition control DOM
+ while (this.getElement().hasChildNodes()) {
+ this.getElement().removeChild(this.getElement().lastChild);
+ }
+ this.getElement().parentNode.removeChild(this.getElement());
+ this._globe.getTargetElement().removeChild(this._centerElement);
+ }
+ // call original setGlobe method
+ Widget.prototype.setGlobe.call(this, globe);
+};
+
+// ################################################################### //
+// #################### user interface methods ####################### //
+// ################################################################### //
+
+/**
+ * Sets additional projection system
+ *
+ * @param {Object} system - Projection system defined in the Itowns/CRS/CRS.js class
+ * @param {String} system.crs - Proj4 crs alias (from proj4 defs) e.g. "EPSG:4326"
+ * @param {String} [system.label] - CRS label to be displayed in control. Default is system.crs alias
+ * @param {String} [system.type] - CRS units type for coordinates conversion (one of control options.units). Default is "Metric"
+ */
+MousePosition.prototype.addSystem = function (system) {
+ if (typeof system !== "object") {
+ logger.error("MousePosition:addSystem - system parameter should be an object");
+ return;
+ }
+ if (!system.crs) {
+ logger.error("crs not defined !");
+ return;
+ }
+ if (!system.label) {
+ logger.warn("crs label not defined, use crs code by default.");
+ system.label = system.crs;
+ }
+ if (!system.type) {
+ logger.warn("type srs not defined, use 'Metric' by default.");
+ system.type = "Metric";
+ }
+
+ // 1. adds system to control systems
+ for (var j = 0; j < this._projectionSystems.length; j++) {
+ var obj = this._projectionSystems[j];
+ if (system.crs === obj.crs) {
+ // warn user
+ logger.warn("crs '{}' already configured", obj.crs);
+ }
+ }
+
+ system.code = this._projectionSystems.length;
+ this._projectionSystems.push(system);
+
+ // 2. adds system settings option to container (if it was already build)
+ var selectSystem = document.getElementById(this._addUID("GPmousePositionProjectionSystem"));
+ if (selectSystem) {
+ var option = document.createElement("option");
+ option.value = system.code;
+ option.text = system.label;
+ selectSystem.appendChild(option);
+ }
+};
+
+/**
+ * Sets additional projection systems
+ *
+ * @param {Array} systems - Array of system object, with following properties :
+ * @param {String} systems.crs - Proj4 CRS alias (from proj4 defs) e.g. "EPSG:4326"
+ * @param {String} systems.label - CRS label (for coordinates conversion)
+ * @param {String} systems.type - CRS units type to be displayed in control (one of control options.units). Default is "Metric"
+ */
+MousePosition.prototype.addSystems = function (systems) {
+ if (!systems) {
+ return;
+ }
+ if (!Array.isArray(systems)) {
+ logger.error("MousePosition:addSystems - systems parameter should be an array");
+ return;
+ }
+ for (var i = 0; i < systems.length; i++) {
+ this.addSystem(systems[i]);
+ }
+};
+
+/**
+ * Removes projection system (in case there are several system with same code, only the first one will be removed)
+ *
+ * @param {String} systemCrs - CRS alias (from proj4 defs)
+ */
+MousePosition.prototype.removeSystem = function (systemCrs) {
+ if (!systemCrs || typeof systemCrs !== "string") {
+ logger.error("MousePosition:removeSystem - systemCode parameter should be a string");
+ return;
+ }
+
+ var systemCode = null;
+ // finds system in control projection systems list
+ for (var i = 0; i < this._projectionSystems.length; i++) {
+ var proj = this._projectionSystems[i];
+ if (systemCrs === proj.crs) {
+ systemCode = proj.code;
+ // removes system from control projection systems list
+ this._projectionSystems.splice(i, 1);
+ break;
+ }
+ }
+
+ if (systemCode == null) {
+ logger.warn("MousePosition:removeSystem - system not found");
+ return;
+ }
+
+ // re-initialization of codes
+ var oldNewCodeGlobe = [];
+ for (var ii = 0; ii < this._projectionSystems.length; ii++) {
+ oldNewCodeGlobe[Number(this._projectionSystems[ii].code)] = ii;
+ this._projectionSystems[ii].code = ii;
+ }
+
+ // finds system in control container systems list
+ var indexChildToRemove = null;
+ var systemList = document.getElementById(this._addUID("GPmousePositionProjectionSystem"));
+ for (var j = 0; j < systemList.childNodes.length; j++) {
+ if (systemCode === systemList.childNodes[j].value) {
+ indexChildToRemove = j;
+ continue;
+ }
+ systemList.childNodes[j].value = oldNewCodeGlobe[Number(systemList.childNodes[j].value)];
+ }
+ // removes system from control container systems list
+ if (indexChildToRemove != null) {
+ systemList.removeChild(systemList.childNodes[indexChildToRemove]);
+ }
+
+ // choose arbitrarily a new current system if needed
+ if (this._currentProjectionSystems.code === systemCode) {
+ systemList.childNodes[0].setAttribute("selected", "selected");
+ this._setCurrentSystem(systemList.childNodes[0].value);
+ }
+};
+
+/**
+ * Sets control units (to be displayed)
+ *
+ * @param {Array} units - list of all coordinates units, to be displayed in control units list.
+ * Values may be "DEC" (decimal degrees), "DMS" (sexagecimal), "RAD" (radians) and "GON" (grades) for geographical coordinates,
+ * and "M" or "KM" for metric coordinates
+ */
+MousePosition.prototype.setUnits = function (units) {
+ if (!units || !Array.isArray(units)) {
+ return;
+ }
+ this.options.units = units;
+ this._projectionUnits = {};
+ this._initProjectionUnits();
+ if (this._currentProjectionType) {
+ this._setTypeUnitsPanel(this._currentProjectionType);
+ }
+};
+
+/**
+ * Sets control altitude options (useless if displayAltitude == false)
+ *
+ * @param {Object} options - altitude options
+ * @param {Object} [options.serviceOptions] - options of elevation service
+ * @param {Number} [options.responseDelay] - latency for elevation request, 500 ms by default
+ * @param {Number} [options.triggerDelay] - immobilisation time of movement on the globe to trigger the elevation calculation, 200 ms by default
+ */
+MousePosition.prototype.setAltitudeOptions = function (options) {
+ if (!options || typeof options !== "object") {
+ return;
+ }
+ this.options.altitude.triggerDelay = options.triggerDelay;
+ this.options.altitude.responseDelay = options.responseDelay;
+ if (options.serviceOptions) {
+ for (var opt in options.serviceOptions) {
+ if (options.serviceOptions.hasOwnProperty(opt)) {
+ this.options.altitude.serviceOptions[opt] = options.serviceOptions[opt];
+ }
+ }
+ }
+};
+
+/**
+ * Displays or hides elevation panel
+ *
+ * @param {Boolean} displayAltitude - true to display elevation panel, false to hide it
+ */
+MousePosition.prototype.displayAltitude = function (displayAltitude) {
+ if (displayAltitude === undefined) {
+ return;
+ }
+ if (typeof this._noRightManagement === "undefined") {
+ this._checkRightsManagement();
+ }
+ this.options.displayAltitude = displayAltitude;
+ this._setElevationPanel(displayAltitude);
+};
+
+/**
+ * Displays or hides coordinates panel
+ *
+ * @param {Boolean} displayCoordinates - true to display coordinates panel, false to hide it
+ */
+MousePosition.prototype.displayCoordinates = function (displayCoordinates) {
+ if (displayCoordinates === undefined) {
+ return;
+ }
+ this.options.displayCoordinates = displayCoordinates;
+ this._setCoordinatesPanel(displayCoordinates);
+ this._setSettingsPanel(displayCoordinates);
+};
+
+/**
+ * Collapses or displays control main container
+ *
+ * @param {Boolean} collapsed - True to collapse control, False to display it
+ */
+MousePosition.prototype.setCollapsed = function (collapsed) {
+ if (collapsed === undefined) {
+ logger.error("MousePosition:setCollapsed - missing collapsed parameter");
+ return;
+ }
+ if ((collapsed && this.collapsed) || (!collapsed && !this.collapsed)) {
+ return;
+ }
+ if (!this._isDesktop) {
+ document.getElementById(this._addUID("GPmapCenter")).className = collapsed ? "" : "GPmapCenterVisible";
+ }
+ // simulates the opening of the panel after a click
+ this.onShowMousePositionClick();
+ this._showMousePositionContainer.checked = !collapsed;
+};
+
+// ################################################################### //
+// ######################## initialize control ####################### //
+// ################################################################### //
+
+/**
+ * Initializes control (called by MousePosition constructor)
+ *
+ * @method _initialize
+ * @param {Object} options - control options (set by user)
+ * @private
+ */
+MousePosition.prototype._initialize = function (options) {
+ // Set default options
+ // {Object} control options - set by user or by default
+ this.options = options || {};
+ this.options.collapsed = (options.collapsed !== undefined) ? options.collapsed : true;
+ /** {Boolean} specify if MousePosition control is collapsed (true) or not (false) */
+ this.collapsed = this.options.collapsed;
+ this.options.units = options.units || [];
+ this.options.displayAltitude = (options.displayAltitude !== undefined) ? options.displayAltitude : true;
+ this.options.displayCoordinates = (options.displayCoordinates !== undefined) ? options.displayCoordinates : true;
+ this.options.systems = options.systems || [];
+ if (options.altitude) {
+ var altitude = options.altitude;
+ this.options.altitude = {
+ triggerDelay : (altitude.triggerDelay !== undefined) ? altitude.triggerDelay : 200,
+ responseDelay : (altitude.responseDelay !== undefined) ? altitude.responseDelay : 500,
+ serviceOptions : altitude.serviceOptions || {},
+ noDataValue : (altitude.noDataValue !== undefined) ? altitude.noDataValue : -99999,
+ noDataValueTolerance : (altitude.noDataValueTolerance !== undefined) ? altitude.noDataValueTolerance : 90000
+ };
+ } else {
+ this.options.altitude = {
+ triggerDelay : 200,
+ responseDelay : 500,
+ serviceOptions : {}
+ };
+ }
+
+ // id of the widget : usefull to suffix the CSS ids (to handle cases with several widgets on the same page)
+ this._uid = SelectorID.generate();
+
+ // initialization of the projections systems
+ this._projectionSystems = [];
+ this._initProjectionSystems();
+
+ // initialization of the units systems
+ this._projectionUnits = {};
+ this._initProjectionUnits();
+
+ // support detect : desktop or tactile
+ this._isDesktop = Utils.detectSupport();
+
+ // implements a timer threshold
+ if (this.options.altitude.triggerDelay < 100) {
+ this.options.altitude.triggerDelay = 100;
+ }
+
+ // {Number} timer on movestopped delay (altitude calculation)
+ this._timer = this.options.altitude.triggerDelay;
+
+ // {Object} Selected projection system
+ this._currentProjectionSystems = this._projectionSystems[0];
+
+ // {String} Selected projection units typs : Geographical or metric
+ this._currentProjectionType = this._projectionSystems[0].type;
+
+ // {String} Selected projection unit
+ this._currentProjectionUnits = this._projectionUnits[this._currentProjectionType][0].code;
+
+ // {Object} Projection units container (DOM Element)
+ this._projectionUnitsContainer = null;
+
+ // {Object} control panel container (DOM Element)
+ this._showMousePositionContainer = null;
+
+ // management of the altitude panel display
+ if (!this.options.displayAltitude && !this.options.displayCoordinates) {
+ // reactivate the display of coordinates, to not display an empty panel
+ this.options.displayCoordinates = true;
+ }
+
+ // rights management on resources and services
+ // if we want an altitude calculation, we check the alti resources rights...
+ if (this.options.displayAltitude) {
+ this._checkRightsManagement();
+ }
+};
+
+/**
+ * this method is called by the constructor and initialize the projection
+ * systems.
+ * getting coordinates in the requested projection :
+ * see this.onMousePositionProjectionSystemChange()
+ *
+ * @method _initProjectionSystems
+ * @private
+ */
+MousePosition.prototype._initProjectionSystems = function () {
+ // user has the possibility to modify the list of systems to display
+ // Ex. this.options.systems
+
+ // available projection systems vy default
+ var projectionSystemsByDefault = [{
+ label : "Géographique",
+ crs : "EPSG:4326",
+ type : "Geographical"
+ }, {
+ label : "Mercator",
+ crs : "EPSG:3857",
+ type : "Metric"
+ }, {
+ label : "Lambert 93",
+ crs : "EPSG:2154",
+ type : "Metric",
+ geoBBox : {
+ left : -9.86,
+ bottom : 41.15,
+ right : 10.38,
+ top : 51.56
+ }
+ }, {
+ label : "Lambert II étendu",
+ crs : "EPSG:27572",
+ type : "Metric",
+ geoBBox : {
+ left : -4.87,
+ bottom : 42.33,
+ right : 8.23,
+ top : 51.14
+ }
+ }];
+
+ var systems = this.options.systems;
+ for (var i = 0; i < systems.length; i++) {
+ // definition of a reference system
+ var sys = systems[i];
+ this.addSystem(sys);
+ }
+
+ if (this._projectionSystems.length === 0) {
+ // we add the default projection systems
+ for (var ii = 0; ii < projectionSystemsByDefault.length; ii++) {
+ this.addSystem(projectionSystemsByDefault[ii]);
+ }
+ }
+};
+
+/**
+ * this method is called by the constructor and initialize the units.
+ * getting coordinates in the requested units :
+ * see this.onMousePositionProjectionUnitsChange()
+ *
+ * @method _initProjectionUnits
+ * @private
+ */
+MousePosition.prototype._initProjectionUnits = function () {
+ // user has the possibility to modify the list of units to display
+ // Ex.
+ // this.options.units : ["DEC", "DMS"]
+
+ // available units systems by default
+ var projectionUnitsByDefault = {
+ Geographical : [{
+ code : "DEC",
+ label : "degrés décimaux",
+ convert : this._displayDEC
+ }, {
+ code : "DMS",
+ label : "degrés sexagésimaux",
+ convert : this._displayDMS
+ }, {
+ code : "RAD",
+ label : "radians",
+ convert : this._displayRAD
+ }, {
+ code : "GON",
+ label : "grades",
+ convert : this._displayGON
+ }],
+ Metric : [{
+ code : "M",
+ label : "mètres",
+ convert : this._displayMeter
+ }, {
+ code : "KM",
+ label : "kilomètres",
+ convert : this._displayKMeter
+ }]
+ };
+
+ var units = this.options.units;
+
+ for (var type in projectionUnitsByDefault) {
+ if (projectionUnitsByDefault.hasOwnProperty(type)) {
+ var found = false;
+ for (var j = 0; j < projectionUnitsByDefault[type].length; j++) {
+ var obj = projectionUnitsByDefault[type][j];
+ for (var i = 0; i < units.length; i++) {
+ var unit = units[i];
+ if (obj.code === unit) {
+ found = true;
+ if (!this._projectionUnits[type]) {
+ this._projectionUnits[type] = [];
+ }
+ this._projectionUnits[type].push(obj);
+ }
+ }
+ }
+ if (!found) {
+ this._projectionUnits[type] = projectionUnitsByDefault[type];
+ }
+ }
+ }
+
+ // in case of...
+ if (typeof this._projectionUnits === "object" && Object.keys(this._projectionUnits).length === 0) {
+ this._projectionUnits = projectionUnitsByDefault;
+ }
+};
+
+/**
+ * this method is called by constructor
+ * and check the rights to resources
+ *
+ * @method _checkRightsManagement
+ * @private
+ */
+MousePosition.prototype._checkRightsManagement = function () {
+ var rightManagement = RightManagement.check({
+ key : this.options.apiKey,
+ resources : ["SERVICE_CALCUL_ALTIMETRIQUE_RSC"],
+ services : ["Elevation"]
+ });
+
+ this._noRightManagement = !rightManagement;
+
+ // retrieves the usefull infos
+ // on this control, we do not care about the ressource bescause it is unique
+ // Ex : the API key from the autoconfiguration if it has not been given
+ if (!this.options.apiKey) {
+ this.options.apiKey = rightManagement.key;
+ }
+};
+
+// ################################################################### //
+// ######################## methods handle dom ####################### //
+// ################################################################### //
+
+/**
+ * Create control main container (called by MousePosition constructor)
+ *
+ * @method _initContainer
+ * @param {Object} options - options
+ * @param {Boolean} options.collapsed - Specify if MousePosition control should be collapsed
+ * @param {Array} options.displayAltitude - activate (true) or deactivate (false) the altitude panel
+ * @param {Array} options.displayCoordinates - activate (true) or deactivate (false) the coordinates panel
+ * @returns {DOMElement} container - widget container
+ * @private
+ */
+MousePosition.prototype._initContainer = function (options) {
+ // creates the main container
+ var container = this._createMainContainerElement();
+
+ var inputShow = this._showMousePositionContainer = this._createShowMousePositionElement();
+ if (!options.collapsed) {
+ inputShow.checked = "checked";
+ }
+ container.appendChild(inputShow);
+
+ var picto = this._createShowMousePositionPictoElement(this._isDesktop);
+ container.appendChild(picto);
+
+ var panel = this._createMousePositionPanelElement();
+
+ var header = this._createMousePositionPanelHeaderElement();
+ panel.appendChild(header);
+
+ var basic = this._createMousePositionPanelBasicElement(
+ options.displayAltitude,
+ options.displayCoordinates
+ );
+ panel.appendChild(basic);
+
+ var arraySettings = this._createShowMousePositionSettingsElement(options.displayCoordinates);
+ for (var j = 0; j < arraySettings.length; j++) {
+ panel.appendChild(arraySettings[j]);
+ }
+
+ var settings = this._createMousePositionSettingsElement(options.displayCoordinates);
+ var systems = this._projectionSystemsContainer = this._createMousePositionSettingsSystemsElement(this._projectionSystems);
+ var units = this._projectionUnitsContainer = this._createMousePositionSettingsUnitsElement(this._projectionUnits[this._currentProjectionType]);
+
+ settings.appendChild(systems);
+ settings.appendChild(units);
+ panel.appendChild(settings);
+ container.appendChild(panel);
+
+ return container;
+};
+
+/**
+ * this method is called by this.()
+ * and it changes the elevation view panel into the dom.
+ *
+ * @method _setElevationPanel
+ * @param {Boolean} active - true:active, false:disable
+ * @private
+ */
+MousePosition.prototype._setElevationPanel = function (active) {
+ var div = null;
+
+ if (!active) {
+ div = document.getElementById("GPmousePositionAltitude-" + this._uid);
+ div.style.display = "none";
+ } else {
+ if (this._noRightManagement) {
+ div = document.getElementById("GPmousePositionAlt-" + this._uid);
+ div.innerHTML = "No rights!";
+ } else {
+ div = document.getElementById("GPmousePositionAltitude-" + this._uid);
+ div.style.display = "";
+ }
+ }
+};
+
+/**
+ * this method is called by this.()
+ * and it changes the coordinate view panel into the dom.
+ *
+ * @method _setCoordinatesPanel
+ * @param {Boolean} active - true:active, false:disable
+ * @private
+ */
+MousePosition.prototype._setCoordinatesPanel = function (active) {
+ var div = document.getElementById("GPmousePositionCoordinate-" + this._uid);
+ if (!active) {
+ div.style.display = "none";
+ } else {
+ div.style.display = "";
+ }
+};
+
+/**
+ * this method is called by this.()
+ * and it changes the settings view panel into the dom.
+ *
+ * @method _setSettingsPanel
+ * @param {Boolean} active - true:active, false:disable
+ * @private
+ */
+MousePosition.prototype._setSettingsPanel = function (active) {
+ var divPicto = document.getElementById("GPshowMousePositionSettingsPicto-" + this._uid);
+ var divPanel = document.getElementById("GPmousePositionSettings-" + this._uid);
+ if (!active) {
+ divPicto.style.display = "none";
+ divPanel.style.display = "none";
+ } else {
+ divPicto.style.display = "";
+ divPanel.style.display = "";
+ }
+};
+
+/**
+ * this method is called by this.onMousePositionProjectionSystemChange()
+ * when changes to a metric or a geographical units.
+ *
+ * @method _setTypeUnitsPanel
+ * @param {String} type - Geographical or Metric
+ * @private
+ */
+MousePosition.prototype._setTypeUnitsPanel = function (type) {
+ var container = this._projectionUnitsContainer;
+
+ // deletes the childNodes
+ while (container.firstChild) {
+ container.removeChild(container.firstChild);
+ }
+
+ var units = this._projectionUnits[type];
+ for (var j = 0; j < units.length; j++) {
+ var obj = units[j];
+ var option = document.createElement("option");
+ option.value = (obj.code) ? obj.code : j;
+ option.text = obj.label || j;
+ // option.label = obj.label;
+ container.appendChild(option);
+ }
+
+ // the new type of system
+ this._currentProjectionType = type;
+ // as the system changed, the unit system has to change too !
+ this._currentProjectionUnits = this._projectionUnits[type][0].code;
+};
+
+// ################################################################### //
+// ######################## method units convert ##################### //
+// ################################################################### //
+
+/**
+ * degreedecimal
+ *
+ * @method _displayDEC
+ * @param {Object} coords - coordinatesobject {lon, lat}
+ * @return {Object} coordinate - coordinate object : {lat : 48, lng : 2} par exemple
+ * @private
+ */
+MousePosition.prototype._displayDEC = function (coords) {
+ var coordinate = {};
+ coordinate.lat = PositionFormater.roundToDecimal(coords.lat, 6);
+ coordinate.lng = PositionFormater.roundToDecimal(coords.lon, 6);
+ return coordinate;
+};
+
+/**
+ * degreedecimal2sexagecimal
+ *
+ * @method _displayDMS
+ * @param {Object} coords - coordinates object {lon, lat}
+ * @return {Object} coordinate - coordinate object : {lng : "2° 00′ 00″ E", lat : "48° 00′ 00″ N"} par exemple
+ * @private
+ */
+MousePosition.prototype._displayDMS = function (coords) {
+ var coordinate = {};
+ coordinate.lat = PositionFormater.decimalLatToDMS(coords.lat);
+ coordinate.lng = PositionFormater.decimalLongToDMS(coords.lon);
+ return coordinate;
+};
+
+/**
+ * degreedecimal2radian
+ *
+ * @method _displayRAD
+ * @param {Object} coords - coordinates object {lon, lat}
+ * @return {Object} coordinate - coordinate object : {lat : "0.02837864", lng : "0.84300269"} par exemple
+ * @private
+ */
+MousePosition.prototype._displayRAD = function (coords) {
+ var coordinate = {};
+ coordinate.lat = PositionFormater.decimalToRadian(coords.lat);
+ coordinate.lng = PositionFormater.decimalToRadian(coords.lon);
+ return coordinate;
+};
+
+/**
+ * degreedecimal2grade
+ *
+ * @method _displayGON
+ * @param {Object} coords - coordinates object {lon, lat}
+ * @return {Object} coordinate - coordinate object : {lat : "4.09545898", lng : "53.68751528"} par exemple
+ * @private
+ */
+MousePosition.prototype._displayGON = function (coords) {
+ var coordinate = {};
+ coordinate.lat = PositionFormater.decimalToGrade(coords.lat);
+ coordinate.lng = PositionFormater.decimalToGrade(coords.lon);
+ return coordinate;
+};
+
+/**
+ * meter
+ *
+ * @method _displayMeter
+ * @param {Object} coords - coords object {lon, lat}
+ * @return {Object} coordinate - coordinate object : {x : "148593.58", y : "6176560.95"} par exemple
+ * @private
+ */
+MousePosition.prototype._displayMeter = function (coords) {
+ // on recoit toujours des coordonnées metriques
+ var coordinate = {};
+ coordinate.x = coords.lon.toFixed(2);
+ coordinate.y = coords.lat.toFixed(2);
+ coordinate.unit = "m";
+ return coordinate;
+};
+
+/**
+ * kilometer
+ *
+ * @method _displayKMeter
+ * @param {Object} coords - coords object {lon, lat}
+ * @return {Object} coordinate - coordinate object : {x : "214.96", y : "6250.09"} par exemple
+ * @private
+ */
+MousePosition.prototype._displayKMeter = function (coords) {
+ var coordinate = {};
+ coordinate.x = (coords.lon / 1000).toFixed(2);
+ coordinate.y = (coords.lat / 1000).toFixed(2);
+ coordinate.unit = "km";
+ return coordinate;
+};
+
+// ################################################################### //
+// ##################### handlers events to control ################## //
+// ################################################################### //
+
+/**
+ * this sends the coordinates to the panel.
+ * (cf. this.GPdisplayCoords() into the DOM functions)
+ *
+ * @method _setCoordinate
+ * @param {Array} coords - coordinate object {lon, lat}
+ * @private
+ */
+MousePosition.prototype._setCoordinate = function (coords) {
+ // structure
+ // coords
+ // {
+ // lon: 5,
+ // lat : 48
+ // }
+ //
+ // structure for the coordinates depending on the system type :
+ // {x:, y:, unit:} or {lng:, lat:} or {lon:, lat:} or {e:, n:, unit:}...
+
+ var coord = [];
+ var coordinates = {};
+
+ // transforms the point in the wanted coords system
+ var oSrs = this._currentProjectionSystems;
+ var crsProp = oSrs.crs;
+
+ if (!oSrs || !crsProp) {
+ logger.error("system crs not found");
+ return;
+ }
+ // reproject coordinates from their CRS of origin (WGS84) to the wanted CRS (crsProp)
+ if (crsProp !== "EPSG:4326") {
+ coord = proj4(CRS[crsProp], [coords.lon, coords.lat]);
+ // projected values are affected to the coord var
+ coordinates.lon = coord[0];
+ coordinates.lat = coord[1];
+ } else {
+ coordinates = coords;
+ }
+
+ // system type : Geographical or Metric
+
+ var type = this._currentProjectionSystems.type;
+
+ // checks for a formatting function in the wanted unit
+ var convert = null;
+ var units = this._projectionUnits[type];
+
+ for (var i = 0; i < units.length; i++) {
+ if (units[i].code === this._currentProjectionUnits) {
+ convert = units[i].convert;
+ break;
+ }
+ }
+ if (!convert || typeof convert !== "function") {
+ logger.warn("coordinates format function not found");
+ return;
+ } else {
+ coord = convert(coordinates);
+ }
+
+ if (!coord || Object.keys(coord).length === 0) {
+ return;
+ }
+
+ this.GPdisplayCoords(coord);
+};
+
+/**
+ * this sends the coordinates to the panel.
+ * (cf. this.GPdisplayElevation() into the DOM functions)
+ *
+ * @method _setElevation
+ * @param {Object} coords - Coordinate position object {lon, lat}
+ * @private
+ */
+MousePosition.prototype._setElevation = function (coords) {
+ // management of the timer of the altitude service request
+ var delay = this.options.altitude.responseDelay;
+ this.GPdisplayElevation(coords, delay);
+};
+
+/**
+ * this method is triggered when the mouse or the globe is stopped.
+ * (cf. onMouseMove and onGlobeMove)
+ *
+ * @method onMoveStopped
+ * @param {Object} coords - Coordinate position object {lon, lat}
+ * @private
+ */
+MousePosition.prototype.onMoveStopped = function (coords) {
+ this._setElevation(coords);
+};
+
+/**
+ * this method is an handler event to control. The event is 'mousemove' on
+ * the globe. The handler sends the coordinates to the panel.
+ * (cf. this.GPdisplayCoords() into the DOM functions)
+ *
+ * @method onMouseMove
+ * @param {Object} e - HTMLElement
+ * @private
+ */
+MousePosition.prototype.onMouseMove = function (e) {
+ var self = this;
+
+ var position = this.getGlobe().getCoordinateFromMouseEvent(e);
+ if (!position) {
+ this.GPdisplayCoords({
+ lon : "---",
+ lat : "---"
+ });
+ this.GPresetElevation();
+ return;
+ }
+
+ var coordinate = {
+ lon : position.x,
+ lat : position.y
+ };
+
+ this._setCoordinate(coordinate);
+
+ // calculation of the altitude after a time limit from the moment where the mouse movement is stopped
+ if (this.options.displayAltitude) {
+ clearTimeout(this._timer);
+ this._timer = setTimeout(function () {
+ self.onMoveStopped(coordinate);
+ }, this.options.altitude.triggerDelay);
+ }
+};
+
+/**
+ * this method is an handler event to control. The event is 'moveend' on
+ * the globe. The handler sends the coordinates to the panel.
+ * (cf. this.GPdisplayCoords() into the DOM functions)
+ *
+ * @method onGlobeMove
+ * @private
+ */
+MousePosition.prototype.onGlobeMove = function () {
+
+ // var self = this;
+
+ // info: coordinate = [x, y]
+ // var coordinate = e.coordinate;
+ // if ( !e.map || !e.map.getView() ) {
+ // return;
+ // }
+ // var crs = e.map.getView().getProjection();
+ //
+ // this._setCoordinate(coordinate, crs);
+ //
+ // // calcul de l'altitude après un certain délai après l'arrêt du mouvement de la carte
+ // clearTimeout(this._timer);
+ // this._timer = setTimeout( function () {
+ // self.onMoveStopped(coordinate, crs);
+ // }, this.options.altitude.triggerDelay);
+};
+
+// ################################################################### //
+// ####################### handlers events to dom #################### //
+// ################################################################### //
+
+/**
+ * this method is called by this.GPdisplayElevation() in the dom, and
+ * it executes a request to the elevation service.
+ *
+ * @method onRequestAltitude
+ * @param {Object} coordinate - {lat:..., lng:...}
+ * @param {Function} callback - function callback
+ * @private
+ */
+MousePosition.prototype.onRequestAltitude = function (coordinate, callback) {
+ // INFORMATION
+ // we launch the request to the altitude services
+ // we implement callbacks in order to retrieve results or errors
+ // from the service.
+ // The result is displayed in a DOM element.
+ // The error messages are display in the dev console (?)
+
+ if (!coordinate || Object.keys(coordinate).length === 0) {
+ return;
+ }
+
+ // if we do not want any altitude calculation, we just stop !
+ if (!this.options.displayAltitude) {
+ return;
+ }
+
+ // if we don not have the rights on the requested resource, we just stop !
+ if (this._noRightManagement) {
+ logger.warn("contract key configuration has no rights to load geoportal elevation ");
+ document.getElementById(this._addUID("GPmousePositionAlt")).innerHTML = "No rights!";
+ return;
+ }
+
+ // we retrieve the service options...
+ var options = this.options.altitude.serviceOptions || {};
+
+ // ... and the coordinates...
+ options.zonly = true;
+ options.positions = [{
+ lon : coordinate.lon,
+ lat : coordinate.lat
+ }];
+
+ // ... and the callbacks
+ options.scope = this;
+
+ if (!options.rawResponse) {
+ // in the general case
+ options.onSuccess = function (results) {
+ if (results && Object.keys(results)) {
+ callback.call(this, results.elevations[0].z);
+ }
+ };
+ } else {
+ options.onSuccess = function (results) {
+ logger.info("alti service raw response : ", results);
+ };
+ }
+
+ options.onFailure = function (error) {
+ logger.error("[getAltitude] " + error.message);
+ };
+ // in the case of the API key is not given as option of the service,
+ // we use the key of the autoconf, or the key given in the control options
+ options.apiKey = options.apiKey || this.options.apiKey;
+
+ // si l'utilisateur a spécifié le paramètre ssl au niveau du control, on s'en sert
+ // true par défaut (https)
+ options.ssl = this.options.ssl;
+
+ Gp.Services.getAltitude(options);
+};
+
+/**
+ * this method is called by event 'click' on 'GPshowMousePositionPicto' tag label
+ * (cf. this._createShowMousePositionPictoElement),
+ * and toggles event 'mousemove' on globe.
+ *
+ * @method onShowMousePositionClick
+ * @private
+ */
+MousePosition.prototype.onShowMousePositionClick = function () {
+ // checked : true - panel close
+ // checked : false - panel open
+ var globe = this.getGlobe();
+
+ this.collapsed = this._showMousePositionContainer.checked;
+
+ // event triggered when opening/closing the panel
+ // and depending on the mode : desktop or tactile!
+ if (this._showMousePositionContainer.checked) {
+ // FIXME handle or not mobile case
+ if (this._isDesktop) {
+ globe.forget(GlobeViewExtended.EVENTS.MOUSE_MOVE, this._callbacks.mouseMove);
+ } else {
+ globe.forget(GlobeViewExtended.EVENTS.CENTER_CHANGED, this.onGlobeMove);
+ }
+ } else {
+ // FIXME handle or not mobile case
+ if (this._isDesktop) {
+ globe.listen(GlobeViewExtended.EVENTS.MOUSE_MOVE, this._callbacks.mouseMove);
+ } else {
+ globe.listen(GlobeViewExtended.EVENTS.CENTER_CHANGED, this.onGlobeMove);
+ }
+ }
+
+ // FIXME
+ // we handle here the panel display..., but this is not really the good
+ // place to do it...
+ this._setElevationPanel(this.options.displayAltitude);
+ this._setCoordinatesPanel(this.options.displayCoordinates);
+ if (!this.options.displayCoordinates) {
+ this._setSettingsPanel(false);
+ }
+};
+
+/**
+ * this method is called by event 'change' on 'GPmousePositionProjectionSystem'
+ * tag select (cf. this._createMousePositionSettingsElement),
+ * and selects the system projection.
+ *
+ * @method onMousePositionProjectionSystemChange
+ * @param {Object} e - HTMLElement
+ * @private
+ */
+MousePosition.prototype.onMousePositionProjectionSystemChange = function (e) {
+ var idx = e.target.selectedIndex; // index
+ var value = e.target.options[idx].value; // crs
+
+ this._setCurrentSystem(value);
+};
+
+/**
+ * this method selects the current system projection.
+ *
+ * @method _setCurrentSystem
+ * @param {String} systemCode - inner code (rank in array _projectionSystems)
+ * @private
+ */
+MousePosition.prototype._setCurrentSystem = function (systemCode) {
+ // if we change of system type, we must change the unit type too !
+ var type = null;
+ for (var i = 0; i < this._projectionSystems.length; ++i) {
+ if (this._projectionSystems[i].code === Number(systemCode)) {
+ type = this._projectionSystems[i].type;
+ break;
+ }
+ }
+
+ if (!type) {
+ logger.log("system not found in projection systems container");
+ return;
+ }
+
+ if (type !== this._currentProjectionType) {
+ this._setTypeUnitsPanel(type);
+ }
+
+ // registers the current system
+ this._currentProjectionSystems = this._projectionSystems[Number(systemCode)];
+
+ // simulates a movement in tactile mode to update the results
+ if (!this._isDesktop) {
+ this.onGlobeMove();
+ }
+};
+
+/**
+ * this method is called by event 'mouseover' on 'GPmousePositionProjectionSystem'
+ * tag select (cf. this._createMousePositionSettingsElement),
+ * and selects the system projection whose geoBBox interstects the current view extent.
+ *
+ * @method onMousePositionProjectionSystemMouseOver
+ * @private
+ */
+MousePosition.prototype.onMousePositionProjectionSystemMouseOver = function () {
+ // globe infos
+ var globe = this.getGlobe();
+ if (!globe) {
+ return;
+ }
+
+ var globeExtent = globe.getExtent();
+
+ // clear select
+ var systemList = document.getElementById(this._addUID("GPmousePositionProjectionSystem"));
+ systemList.innerHTML = "";
+
+ var option;
+
+ // add systems whose extent intersects the globe extent
+ for (var j = 0; j < this._projectionSystems.length; j++) {
+ var proj = this._projectionSystems[j];
+ if (proj.geoBBox) {
+ // bboxes intersection test
+ if (globeExtent.west > proj.geoBBox.right ||
+ globeExtent.south > proj.geoBBox.top ||
+ globeExtent.east < proj.geoBBox.left ||
+ globeExtent.north < proj.geoBBox.bottom
+ ) {
+ if (proj === this._currentProjectionSystems) {
+ option = document.createElement("option");
+ option.value = proj.code;
+ option.text = proj.label || j;
+ option.setAttribute("selected", "selected");
+ option.setAttribute("disabled", "disabled");
+
+ systemList.appendChild(option);
+ }
+ continue; // do not intersect
+ }
+ }
+ option = document.createElement("option");
+ option.value = proj.code;
+ option.text = proj.label || j;
+ if (proj === this._currentProjectionSystems) {
+ option.setAttribute("selected", "selected");
+ }
+
+ systemList.appendChild(option);
+ }
+};
+
+/**
+ * this method is called by event 'change' on 'GPmousePositionProjectionUnits'
+ * tag select (cf. this._createMousePositionSettingsElement),
+ * and selects the units projection.
+ *
+ * @method onMousePositionProjectionUnitsChange
+ * @param {Object} e - HTMLElement
+ * @private
+ */
+MousePosition.prototype.onMousePositionProjectionUnitsChange = function (e) {
+ var idx = e.target.selectedIndex;
+ var value = e.target.options[idx].value;
+
+ this._currentProjectionUnits = value;
+
+ // simulates a movement in tactile mode to update the results
+ if (!this._isDesktop) {
+ this.onGlobeMove();
+ }
+};
+
+export default MousePosition;
diff --git a/src/Itowns-review/Controls/Scale.js b/src/Itowns-review/Controls/Scale.js
new file mode 100644
index 000000000..861427bf5
--- /dev/null
+++ b/src/Itowns-review/Controls/Scale.js
@@ -0,0 +1,152 @@
+import GlobeViewExtended from "../GlobeViewExtended";
+import Utils from "../../Common/Utils";
+import SelectorID from "../../Common/Utils/SelectorID";
+import ScaleDOM from "../../Common/Controls/ScaleDOM";
+import Widget from "./Widget";
+
+/**
+ * @classdesc
+ * Control to display the scalebar with itowns
+ *
+ * @constructor
+ * @alias itowns.control.Scale
+ * @extends {itowns.control.Widget}
+ * @alias itowns.control.Scale
+ * @param {Object} options - widget options
+ * @param {String} options.target - HTML target element or HTML target element id
+ * @param {String} options.position - "absolute" or "relative"
+ * @example
+ * var scale = new itowns.control.Scale();
+ *
+ */
+function Scale (options) {
+ if (!(this instanceof Scale)) {
+ throw new TypeError("ERROR CLASS_CONSTRUCTOR");
+ }
+
+ if (typeof options !== "object") {
+ throw new Error("ERROR WRONG_TYPE : options should be an object");
+ }
+
+ this._initialize();
+
+ var container = this._initContainer();
+
+ Widget.call(
+ this, {
+ name : "GraphicScale",
+ element : container,
+ target : options.target,
+ position : options.position
+ }
+ );
+}
+
+/*
+ * @lends module:Scale
+ */
+Scale.prototype = Object.create(Widget.prototype, {});
+
+// retrieves methods of the common class ScaleDOM
+Utils.assign(Scale.prototype, ScaleDOM);
+
+/**
+ * Constructor (alias)
+ *
+ * @private
+ */
+Scale.prototype.constructor = Scale;
+
+// ################################################################### //
+// ############## public methods (getters, setters) ################## //
+// ################################################################### //
+
+/**
+ * Bind globe to control
+ *
+ * @param {GlobeViewExtended} globe - the globe
+ */
+Scale.prototype.setGlobe = function (globe) {
+ // info : this function is called after a globe.addWidget() or a globe.removeWidget()
+
+ if (globe) { // In the case of the adding of a control to the globe
+ var self = this;
+ /**
+ * Definition of the scaleControl callback :
+ * when the view is changing, we recalculate the graphic scale
+ */
+ this._callbacks.onChangedViewCallback = function () {
+ var value = globe.pixelsToMeters(200);
+ value = Math.floor(value);
+ var digit = Math.pow(10, value.toString().length - 1);
+ value = Math.round(value / digit) * digit;
+ var pix = globe.metersToPixels(value);
+ var unit = "m";
+ if (value >= 1000) {
+ value /= 1000;
+ unit = "km";
+ }
+ self.getElement().innerHTML = value + " " + unit;
+ self.getElement().style.width = pix + "px";
+ };
+ // Ajout des listeners
+ // initialization
+ if (globe.isInitialized()) {
+ this._callbacks.onChangedViewCallback();
+ } else {
+ globe.listen(GlobeViewExtended.EVENTS.GLOBE_INITIALIZED, this._callbacks.onChangedViewCallback);
+ }
+
+ // At every globe range movement, scale bar may be updated,
+ globe.listen(GlobeViewExtended.EVENTS.RANGE_CHANGED, this._callbacks.onChangedViewCallback);
+ } else if (globe == null) {
+ // we remove the listeners linked to the scalecontrol which has been deleted
+ this._globe.forget(GlobeViewExtended.EVENTS.GLOBE_INITIALIZED, this._callbacks.onChangedViewCallback);
+ this._globe.forget(GlobeViewExtended.EVENTS.RANGE_CHANGED, this._callbacks.onChangedViewCallback);
+
+ // if globe == null we remove the scale control
+ // delete the scaleControl DOM
+ while (this.getElement().hasChildNodes()) {
+ this.getElement().removeChild(this.getElement().lastChild);
+ }
+ this.getElement().parentNode.removeChild(this.getElement());
+ }
+
+ // call original setGlobe method
+ Widget.prototype.setGlobe.call(this, globe);
+};
+
+// ################################################################### //
+// ##################### init component ############################## //
+// ################################################################### //
+
+/**
+ * Initialize Scale control (called by constructor)
+ *
+ * @private
+ */
+Scale.prototype._initialize = function () {
+ // id of the widget : usefull to suffix the CSS ids (to handle cases with several widgets on the same page)
+ this._uid = SelectorID.generate();
+
+ // div which will contain the list divs.
+ this._ScaleContainer = null;
+
+ // callbacks
+ this._callbacks = {};
+};
+
+/**
+ * Create control main container
+ *
+ * @method _initContainer
+ * @returns {DOMElement} container - widget container
+ * @private
+ */
+Scale.prototype._initContainer = function () {
+ var container = this._createMainContainerElement();
+
+ return container;
+};
+
+export default Scale;
diff --git a/src/Itowns-review/Controls/Utils/PositionFormater.js b/src/Itowns-review/Controls/Utils/PositionFormater.js
new file mode 100644
index 000000000..1073648b0
--- /dev/null
+++ b/src/Itowns-review/Controls/Utils/PositionFormater.js
@@ -0,0 +1,88 @@
+/**
+* implementation :
+* cf. http://uihacker.blogspot.fr/2011/07/javascript-formatting-latitudelongitude.html?m=1
+* cf. http://andrew.hedges.name/experiments/convert_lat_long/
+* FIXME formater la sortie
+* cf. http://mottie.github.io/javascript-number-formatter/
+* cf. https://github.com/j-/number-formatter
+*
+*/
+/** ... */
+var PositionFormater = {
+
+ /** ... */
+ NORTH : "N",
+
+ /** ... */
+ SOUTH : "S",
+
+ /** ... */
+ EAST : "E",
+
+ /** ... */
+ WEST : "W",
+
+ /** ... */
+ digitSecond : 2,
+
+ /** ... */
+ digitDecimal : 5,
+
+ /** ... */
+ digitRadian : 8,
+
+ roundToDecimal : function (inputNum, numPoints) {
+ var multiplier = Math.pow(10, numPoints);
+ return Math.round(inputNum * multiplier) / multiplier;
+ },
+
+ decimalToRadian : function (location) {
+ var d = 0.01745329251994329577;
+ return this.roundToDecimal(location * d, this.digitRadian);
+ },
+
+ decimalToGrade : function (location) {
+ var d = 1.11111111111111111111;
+ return this.roundToDecimal(location * d, this.digitRadian);
+ },
+
+ decimalToDMS : function (location, hemisphere) {
+ if (location < 0) {
+ location *= -1; // strip dash '-'
+ }
+
+ var degrees = Math.floor(location); // strip decimal remainer for degrees
+ var minutesFromRemainder = (location - degrees) * 60; // multiply the remainer by 60
+ var minutes = Math.floor(minutesFromRemainder); // get minutes from integer
+ var secondsFromRemainder = (minutesFromRemainder - minutes) * 60; // multiply the remainer by 60
+ var seconds = this.roundToDecimal(secondsFromRemainder, this.digitSecond); // get minutes by rounding to integer
+
+ var dms = degrees + "° " + minutes + "' " + seconds + "\" ";
+ if (hemisphere) {
+ dms += hemisphere;
+ }
+
+ return dms;
+ },
+
+ decimalLatToDMS : function (location) {
+ var hemisphere = (location < 0) ? this.SOUTH : this.NORTH; // south if negative
+ return this.decimalToDMS(location, hemisphere);
+ },
+
+ decimalLongToDMS : function (location) {
+ var hemisphere = (location < 0) ? this.WEST : this.EAST; // west if negative
+ return this.decimalToDMS(location, hemisphere);
+ },
+
+ DMSToDecimal : function (degrees, minutes, seconds, hemisphere) {
+ var ddVal = degrees + minutes / 60 + seconds / 3600;
+ ddVal = (hemisphere === this.SOUTH || hemisphere === this.WEST) ? ddVal * -1 : ddVal;
+
+ var decimal = this.roundToDecimal(ddVal, this.digitDecimal);
+ return decimal;
+ }
+
+};
+
+export default PositionFormater;
diff --git a/src/Itowns-review/Controls/Widget.js b/src/Itowns-review/Controls/Widget.js
new file mode 100644
index 000000000..63d793884
--- /dev/null
+++ b/src/Itowns-review/Controls/Widget.js
@@ -0,0 +1,112 @@
+import Logger from "../../Common/Utils/LoggerByDefault";
+
+var logger = Logger.getLogger("Widget");
+
+/**
+* @classdesc
+* iTowns Widget class.
+* Every geoportal control inherits of this class.
+*
+* @constructor
+* @alias itowns.control.Widget
+* @param {Object} options - options for function call.
+* @param {String} options.name - Name of the widget.
+* @param {Object} options.element - HTML element of the widget
+* @param {Object|String} options.target - HTML element or HTML element id where to put the widget
+* @param {String} options.position - "absolute" or "relative"
+* @example
+* var myWidget = new itowns.control.Widget({
+* name : "myWidget",
+* element : myWidgetDiv,
+* target : myWidgetTargetDiv,
+* position: "absolute"
+* });
+*/
+function Widget (options) {
+ this._name = (options.name !== undefined) ? options.name : null;
+ this._element = (options.element !== undefined) ? options.element : null;
+ this._position = (options.position !== undefined) ? options.position : null;
+ this._target = null;
+ this._globe = null;
+
+ if (options.target) {
+ this.setTarget(options.target, this._position);
+ }
+}
+
+/**
+ * Constructor (alias)
+ */
+Widget.prototype.constructor = Widget;
+
+/**
+ * Return the widget's container element.
+ *
+ * @method
+ * @return {HTMLElement} widget's container element.
+ */
+Widget.prototype.getElement = function getElement () {
+ return this._element;
+};
+
+/**
+ * Associates the widget to a specified target div.
+ *
+ * @method
+ * @param {HTMLElement|String} target - widget target div html element or target div id.
+ * @param {String} position - html position attribute.
+ */
+Widget.prototype.setTarget = function setTarget (target, position) {
+ this._target = typeof target === "string" ? document.getElementById(target) : target;
+
+ if (!this._element) {
+ logger.error("Widget:setTarget - widget element not created");
+ return;
+ }
+
+ this._element.style.position = position || "relative";
+
+ this._target.appendChild(this._element);
+};
+
+/**
+ * Return the widget's target div.
+ *
+ * @method
+ * @return {HTMLElement} widget's target div.
+ */
+Widget.prototype.getTarget = function getTarget () {
+ return this._target;
+};
+
+/**
+ * Return the widget's element position.
+ *
+ * @method
+ * @return {String} widget's element position.
+ */
+Widget.prototype.getPosition = function getPosition () {
+ return this._position;
+};
+
+/**
+ * Get the globe associated with the widget. Undefined if the widget is not added to a globe.
+ *
+ * @method
+ * @return {Object} globe
+ */
+Widget.prototype.getGlobe = function getGlobe () {
+ return this._globe;
+};
+
+/**
+ * Associate a globe to the widget.
+ *
+ * @method
+ * @param {Object} globe - Globe to associate to the widget.
+ */
+Widget.prototype.setGlobe = function setGlobe (globe) {
+ this._globe = globe;
+};
+
+export default Widget;
diff --git a/src/Itowns-review/GlobeViewExtended.js b/src/Itowns-review/GlobeViewExtended.js
new file mode 100644
index 000000000..a5bbb7d87
--- /dev/null
+++ b/src/Itowns-review/GlobeViewExtended.js
@@ -0,0 +1,848 @@
+import Logger from "../Common/Utils/LoggerByDefault";
+import {
+ GlobeView as ItGlobeView,
+ Coordinates as ItCoordinates,
+ ColorLayersOrdering as ItColorLayersOrdering,
+ FeaturesUtils as ItFeaturesUtils,
+ Fetcher as ItParser,
+ MAIN_LOOP_EVENTS as IT_MAIN_LOOP_EVENTS,
+ CONTROL_EVENTS as IT_CONTROL_EVENTS,
+ GLOBE_VIEW_EVENTS as IT_GLOBE_VIEW_EVENTS,
+ VIEW_EVENTS as IT_VIEW_EVENTS
+} from "itowns";
+
+/* import GlobeView, { GLOBE_VIEW_EVENTS } from "itowns/Core/Prefab/GlobeView";
+import Coordinates from "itowns/Core/Geographic/Coordinates";
+import ColorLayersOrdering from "itowns/Renderer/ColorLayersOrdering";
+import FeaturesUtils from "itowns/Utils/FeaturesUtils";
+import { MAIN_LOOP_EVENTS } from "itowns/Core/MainLoop";
+import { CONTROL_EVENTS } from "itowns/Controls/GlobeControls";
+import { VIEW_EVENTS } from "itowns/Core/View"; */
+
+var logger = Logger.getLogger("GlobeViewExtended");
+
+/**
+ * @classdesc
+ *
+ * Extended itowns.GlobeView.
+ *
+ * @constructor
+ * @extends {itowns.GlobeView}
+ * @param {HTMLElement} viewerDiv - Where to instanciate the Three.js scene in the DOM
+ * @param {Object} coordCarto - longitude, latitude, altitude
+ * @param {Object} [options] - Optional properties.
+ * @param {String} [options.position="relative"] - "absolute" or "relative"
+ */
+function GlobeViewExtended (viewerDiv, coordCarto, options) {
+ if (!viewerDiv.style.position || (options & options.position)) {
+ viewerDiv.style.position = (!options || !options.position) ? "relative" : options.position;
+ }
+
+ // stockage de l'élément html porteur du globe
+ var globeViewDiv = document.createElement("div");
+ globeViewDiv.style.width = "100%";
+ globeViewDiv.style.height = "100%";
+ viewerDiv.appendChild(globeViewDiv);
+ this._viewerDiv = viewerDiv;
+
+ // widget container
+ this._widgets = [];
+
+ // mapping des evenements
+ this._initEventMap();
+
+ // pour savoir si le globe est initialise
+ this._isInitialized = false;
+
+ // call constructor
+ this._globeView = new ItGlobeView(globeViewDiv, coordCarto, options);
+
+ var self = this;
+ this.listen(GlobeViewExtended.EVENTS.GLOBE_INITIALIZED, function () {
+ self._isInitialized = true;
+ });
+
+ this._globeView.addFrameRequester(IT_MAIN_LOOP_EVENTS.BEFORE_RENDER, function () {
+ clearTimeout(this._preRenderTimer);
+ self._preRenderTimer = setTimeout(function () {
+ var visibleColorLayersIds = [];
+ var visibleElevationLayersIds = [];
+
+ for (var i = 0; i < self.getGlobeView().tileLayer.info.displayed.layers.length; ++i) {
+ if (self.getGlobeView().tileLayer.info.displayed.layers[i].isColorLayer) {
+ visibleColorLayersIds.push(self.getGlobeView().tileLayer.info.displayed.layers[i].id);
+ }
+ if (self.getGlobeView().tileLayer.info.displayed.layers[i].isElevationLayer) {
+ visibleElevationLayersIds.push(self.getGlobeView().tileLayer.info.displayed.layers[i].id);
+ }
+ }
+ var currentExtent = self.getGlobeView().tileLayer.info.displayed.extent;
+ self._globeView.dispatchEvent({
+ type : GlobeViewExtended.EVENTS.PRE_RENDER,
+ colorLayersId : visibleColorLayersIds,
+ elevationLayersId : visibleElevationLayersIds,
+ extent : currentExtent
+ });
+ }, 100);
+ }.bind(this));
+
+ if (this._globeView.controls) {
+ this.freezeControl();
+ }
+}
+
+/**
+ * intializes the evenements map
+ */
+GlobeViewExtended.prototype._initEventMap = function () {
+ if (!GlobeViewExtended.EVENTS) {
+ GlobeViewExtended.EVENTS = {
+ RANGE_CHANGED : IT_CONTROL_EVENTS.RANGE_CHANGED,
+ CENTER_CHANGED : IT_CONTROL_EVENTS.CAMERA_TARGET_CHANGED,
+ ORIENTATION_CHANGED : IT_CONTROL_EVENTS.ORIENTATION_CHANGED,
+ LAYER_ADDED : IT_GLOBE_VIEW_EVENTS.LAYER_ADDED,
+ LAYER_REMOVED : IT_GLOBE_VIEW_EVENTS.LAYER_REMOVED,
+ LAYERS_ORDER_CHANGED : IT_GLOBE_VIEW_EVENTS.COLOR_LAYERS_ORDER_CHANGED,
+ GLOBE_INITIALIZED : IT_GLOBE_VIEW_EVENTS.GLOBE_INITIALIZED,
+ LAYERS_INITIALIZED : IT_VIEW_EVENTS.LAYERS_INITIALIZED,
+ VIEW_INITIALIZED : "viewinitialized",
+ PRE_RENDER : "prerender",
+ MOUSE_MOVE : "mousemove",
+ AFTER_RENDER : IT_MAIN_LOOP_EVENTS.AFTER_RENDER,
+ OPACITY_PROPERTY_CHANGED : "opacity-property-changed",
+ VISIBLE_PROPERTY_CHANGED : "visible-property-changed",
+ SEQUENCE_PROPERTY_CHANGED : "sequence-property-changed"
+ };
+ }
+};
+
+/**
+ * Constructor (alias)
+ */
+GlobeViewExtended.prototype.constructor = GlobeViewExtended;
+
+/**
+ * Get GlobeViex Object (parent)
+ * @returns {Object} itowns GlobeView object
+ */
+GlobeViewExtended.prototype.getGlobeView = function () {
+ return this._globeView;
+};
+
+/**
+ * Indicates if the globe is initialized or not
+ *
+ * @return {Boolean} isInitialized
+ *
+ */
+GlobeViewExtended.prototype.isInitialized = function () {
+ return this._isInitialized;
+};
+
+/**
+ * Detects when the camera movement stops, then launch the callback given as parameter
+ *
+ * @param {Function} cb - The function to execute when the event occures.
+ *
+ */
+GlobeViewExtended.prototype.onCameraMoveStop = function (cb) {
+ var self = this;
+ function afterRenderHandler () {
+ self._globeView.removeFrameRequester(IT_MAIN_LOOP_EVENTS.AFTER_CAMERA_UPDATE, afterRenderHandler);
+ cb();
+ };
+ this._globeView.addFrameRequester(IT_MAIN_LOOP_EVENTS.AFTER_CAMERA_UPDATE, afterRenderHandler);
+};
+
+/**
+ * Disables globe controls until the globe rendering is completed
+ */
+GlobeViewExtended.prototype.freezeControl = function () {
+ // disable navigation
+ this._globeView.controls.enabled = false;
+
+ this.onCameraMoveStop(function () {
+ this._globeView.controls.enabled = true;
+ }.bind(this));
+};
+
+/**
+ * Associates a function to trigger when an event is received.
+ *
+ * @param {String} type - the event type. Can be any of {@link EVENTS}
+ * @param {Function} callback - The function to execute when the event occures.
+ * @return {Object} key - The event key
+ *
+ */
+GlobeViewExtended.prototype.listen = function (type, callback) {
+ if (typeof (callback) !== "function") {
+ logger.warn("no callback provided for event : " + type);
+ return null;
+ }
+
+ var target = this._getEventTarget(type);
+ if (!target) {
+ return null;
+ }
+
+ if (type === GlobeViewExtended.EVENTS.AFTER_RENDER) {
+ target.addFrameRequester(type, callback);
+ } else {
+ target.addEventListener(type, callback);
+ }
+
+ return {
+ target : target,
+ callback : callback,
+ type : type
+ };
+};
+
+/**
+ * Associates a function to trigger when a layer event is received.
+ *
+ * @param {Object} layer - The itowns layer.
+ * @param {String} type - the event type. Can be any of {@link EVENTS}.
+ * @param {Function} callback - The function to execute when the event occures.
+ * @return {Object} key - The event key
+ *
+ */
+GlobeViewExtended.prototype.addLayerListener = function (layer, type, callback) {
+ if (typeof (callback) !== "function") {
+ logger.warn("no callback provided for event : " + type);
+ return null;
+ }
+ layer.addEventListener(type, callback);
+ return {
+ target : layer,
+ callback : callback,
+ type : type
+ };
+};
+
+/**
+ * Returns the target of a given event type
+ *
+ * @param {String} type - the event type. Can be any of {@link EVENTS}
+ * @return {Object} target - The event target.
+ *
+ */
+GlobeViewExtended.prototype._getEventTarget = function (type) {
+ switch (type) {
+ case GlobeViewExtended.EVENTS.RANGE_CHANGED:
+ case GlobeViewExtended.EVENTS.CENTER_CHANGED:
+ case GlobeViewExtended.EVENTS.ORIENTATION_CHANGED:
+ return this.getGlobeView().controls;
+ case GlobeViewExtended.EVENTS.LAYER_ADDED:
+ case GlobeViewExtended.EVENTS.LAYER_REMOVED:
+ case GlobeViewExtended.EVENTS.LAYERS_ORDER_CHANGED:
+ case GlobeViewExtended.EVENTS.LAYERS_INITIALIZED:
+ case GlobeViewExtended.EVENTS.GLOBE_INITIALIZED:
+ case GlobeViewExtended.EVENTS.PRE_RENDER:
+ case GlobeViewExtended.EVENTS.AFTER_RENDER:
+ case GlobeViewExtended.EVENTS.VIEW_INITIALIZED:
+ return this.getGlobeView();
+ case GlobeViewExtended.EVENTS.MOUSE_MOVE:
+ return this._viewerDiv;
+ default:
+ logger.warn("unhandled event : " + type);
+ return null;
+ }
+};
+
+/**
+ * Cancels an event listening
+ *
+ * @param {Object} key - The event key
+ *
+ */
+GlobeViewExtended.prototype.forgetByKey = function (key) {
+ if (key.type === GlobeViewExtended.EVENTS.AFTER_RENDER) {
+ key.target.removeFrameRequester(key.type, key.callback);
+ } else {
+ key.target.removeEventListener(key.type, key.callback);
+ }
+};
+
+/**
+ * Cancels an layer event listening
+ *
+ * @param {Object} layer - The itowns layer
+ * @param {String} type - the event type
+ * @param {Function} callback - The function to execute when the event occures
+ *
+ */
+GlobeViewExtended.prototype.removeLayerListener = function (layer, type, callback) {
+ this.forgetByKey({
+ target : layer,
+ callback : callback,
+ type : type
+ });
+};
+
+/**
+ * Cancels an event listening
+ *
+ * @param {Object} type - The event type
+ * @param {Function} callback - The event handler
+ */
+GlobeViewExtended.prototype.forget = function (type, callback) {
+ var target = this._getEventTarget(type);
+ if (!target) return;
+
+ this.forgetByKey({
+ target : target,
+ callback : callback,
+ type : type
+ });
+};
+
+/**
+ * Overload itowns.GlobeView addLayer method
+ *
+ * @param {Object} layer - The itowns layer
+ * @return {Promise} promise
+ */
+GlobeViewExtended.prototype.addLayer = function (layer) {
+ // FIXME : to delete when itowns commit 2e9ed61eb4aa2a4bbe0e17c8e2650953844b099e
+ // is integrated into an iTowns release
+ try {
+ var promise = this.getGlobeView().addLayer(layer);
+ } catch (error) {
+ return Promise.reject(error);
+ }
+
+ return promise;
+};
+
+/**
+ * Overload itowns.GlobeView removeLayer method
+ *
+ * @param {String} layerId - The layer id
+ */
+GlobeViewExtended.prototype.removeLayer = function (layerId) {
+ this.getGlobeView().removeLayer(layerId);
+};
+
+/**
+ * Set layer opacity
+ *
+ * @param {String} layerId - Layer id
+ * @param {Number} opacityValue - opacity value in [0 1]
+ */
+GlobeViewExtended.prototype.setLayerOpacity = function (layerId, opacityValue) {
+ var layer = this.getColorLayerById(layerId);
+ layer.opacity = opacityValue;
+ this.getGlobeView().notifyChange(layer);
+};
+
+/**
+ * Set layer visibility
+ *
+ * @param {String} layerId - Layer id
+ * @param {Boolean} visible - New visibility of the layer
+ */
+GlobeViewExtended.prototype.setLayerVisibility = function (layerId, visible) {
+ var layer = this.getColorLayerById(layerId);
+ layer.visible = visible;
+ this.getGlobeView().notifyChange(layer);
+};
+
+/**
+ * Move layer to the specified index
+ *
+ * @param {String} layerId - Layer id
+ * @param {Boolean} index - new index of the layer
+ */
+GlobeViewExtended.prototype.moveLayerToIndex = function (layerId, index) {
+ ItColorLayersOrdering.moveLayerToIndex(this.getGlobeView(), layerId, index);
+};
+
+/**
+ * Remove event listener from the globe
+ *
+ * @param {String} type - event type
+ * @param {Function} callback - event handler
+ */
+GlobeViewExtended.prototype.removeEventListener = function (type, callback) {
+ switch (type) {
+ case "mousemove":
+ this._viewerDiv.removeEventListener(type, callback);
+ break;
+ case "centerchanged":
+ this.getGlobeView().controls.removeEventListener(type, callback);
+ break;
+ default:
+ this.getGlobeView().removeEventListener(type, callback);
+ break;
+ }
+};
+
+/**
+ * Defines if the current view extent have to be computed on pre-render event
+ *
+ * @param {Boolean} b - tells if the view extent info should be fetched by the event PRE_RENDER
+ */
+GlobeViewExtended.prototype.preRenderEventFetchViewExtent = function (b) {
+ if (typeof b === "undefined") {
+ b = true;
+ }
+ this._fetchExtent = b;
+};
+
+/**
+ * Defines if the list of the color layers displayed have to be computed on pre-render event
+ *
+ * @param {Boolean} b - tells if the displayed color layers info should be fetched by the event PRE_RENDER
+ */
+GlobeViewExtended.prototype.preRenderEventFetchColorLayersDisplayed = function (b) {
+ if (typeof b === "undefined") {
+ b = true;
+ }
+ this._fetchVisibleColorLayers = b;
+};
+
+/**
+ * Defines if the list of the elevation layers displayed have to be computed on pre-render event
+ *
+ * @param {Boolean} b - tells if the displayed elevation layers info should be fetched by the event PRE_RENDER
+ */
+GlobeViewExtended.prototype.preRenderEventFetchElevationLayersDisplayed = function (b) {
+ if (typeof b === "undefined") {
+ b = true;
+ }
+ this._fetchVisibleElevationLayers = b;
+};
+
+/**
+ * Defines if the list of the layers of all types displayed have to be computed on pre-render event
+ *
+ * @param {Boolean} b - tells if both displayed color layers and displayed elevation layers infos should be fetched by the event PRE_RENDER
+ */
+GlobeViewExtended.prototype.preRenderEventFetchLayersDisplayed = function (b) {
+ if (typeof b === "undefined") {
+ b = true;
+ }
+ this._fetchVisibleColorLayers = b;
+ this._fetchVisibleElevationLayers = b;
+};
+
+/**
+ * Get layer by its id
+ *
+ * @param {String} layerId - Layer id
+ * @return {Object} layer Object
+ */
+GlobeViewExtended.prototype.getLayerById = function (layerId) {
+ var layer = this.getGlobeView().getLayers(function (l) {
+ if (l.id === layerId) {
+ return l;
+ }
+ })[0];
+ if (!layer) {
+ logger.trace("[GlobeViewExtended] : no Layer found for the id '" + layerId + "'");
+ return;
+ }
+ return layer;
+};
+
+/**
+ * Get color layer by its id
+ *
+ * @param {String} layerId - Color layer id
+ * @return {Object} layer Object
+ */
+GlobeViewExtended.prototype.getColorLayerById = function (layerId) {
+ var layer = this.getGlobeView().getLayers(function (l) {
+ if (l.id === layerId && l.isColorLayer) {
+ return l;
+ }
+ })[0];
+ if (!layer) {
+ logger.trace("[GlobeViewExtended] : no colorLayer found for the id '" + layerId + "'");
+ return;
+ }
+ return layer;
+};
+
+/**
+ * Get imagery layers
+ *
+ * @return {Array} imagery layers
+ */
+GlobeViewExtended.prototype.getColorLayers = function () {
+ return this.getGlobeView().getLayers(function (layer) {
+ if (layer.isColorLayer) {
+ return layer;
+ }
+ });
+};
+
+/**
+ * Get vector layers
+ *
+ * @return {Array} vector layers
+ */
+GlobeViewExtended.prototype.getVectorLayers = function () {
+ return this.getGlobeView().getLayers(function (layer) {
+ if (layer.source && layer.source.isFileSource) {
+ return layer;
+ }
+ });
+};
+
+/**
+ * Get elevation layers
+ *
+ * @return {Array} elevation layers
+ */
+GlobeViewExtended.prototype.getElevationLayers = function () {
+ return this.getGlobeView().getLayers(function (layer) {
+ if (layer.isElevationLayer) {
+ return layer;
+ }
+ });
+};
+
+/**
+ * Get the current view extent
+ *
+ * @returns {Array} current view extent
+ */
+GlobeViewExtended.prototype.getExtent = function () {
+ return this.getGlobeView().tileLayer.info.displayed.extent;
+};
+
+/**
+ * Add a widget to the globe
+ *
+ * @param {Object} widget - The Widget object to add
+ */
+GlobeViewExtended.prototype.addWidget = function (widget) {
+ if (!widget.getTarget()) {
+ // default position value is 'absolute' if the target div is the viewer div
+ widget.setTarget(this._viewerDiv, widget.getPosition() ? widget.getPosition() : "absolute");
+ }
+ widget.setGlobe(this);
+ this._widgets.push(widget);
+};
+
+/**
+ * Returns all widgets.
+ *
+ * @return {Array} widgets - The array of widgets.
+ */
+GlobeViewExtended.prototype.getWidgets = function () {
+ return this._widgets;
+};
+
+/**
+ * Removes a widget.
+ *
+ * @param {Object} widget - The Widget object to remove
+ */
+GlobeViewExtended.prototype.removeWidget = function (widget) {
+ widget.setGlobe();
+ for (var idx = 0; idx < this._widgets.length; idx++) {
+ if (this._widgets[idx] === widget) {
+ this._widgets.splice(idx, 1);
+ }
+ }
+};
+
+/**
+ * Get html target element
+ *
+ * @return {HTMLElement} Globe container element
+ */
+GlobeViewExtended.prototype.getTargetElement = function () {
+ return this._viewerDiv;
+};
+
+/**
+ * Returns current view scale
+ *
+ * @return {Number} Scale
+ */
+GlobeViewExtended.prototype.getScale = function () {
+ return this.getGlobeView().getScale();
+};
+
+/**
+ * Sets tilt
+ *
+ * @param {Number} tilt - Tilt value
+ * @return {Promise}
+ */
+GlobeViewExtended.prototype.setTilt = function (tilt) {
+ return this.getGlobeView().controls.setTilt(tilt, false);
+};
+
+/**
+ * Returns tilt
+ *
+ * @return {Number} - Tilt
+ */
+GlobeViewExtended.prototype.getTilt = function () {
+ return this.getGlobeView().controls.getTilt();
+};
+
+/**
+ * Sets azimuth
+ *
+ * @param {Number} azimuth - Azimuth value
+ * @return {Promise}
+ */
+GlobeViewExtended.prototype.setAzimuth = function (azimuth) {
+ return this.getGlobeView().controls.setHeading(azimuth, false);
+};
+
+/**
+ * Returns azimuth
+ *
+ * @return {Number} azimuth
+ */
+GlobeViewExtended.prototype.getAzimuth = function () {
+ return this.getGlobeView().controls.getHeading();
+};
+
+/**
+ * Gets the coordinate in lat,lon for a given pixel.
+ *
+ * @param {Number} x - The pixel x-position inside the Globe element.
+ * @param {Number} y - The pixel y-position inside the Globe element.
+ * @return {Coordinates} position
+ */
+GlobeViewExtended.prototype.getCoordinateFromPixel = function (x, y) {
+ return this.getGlobeView().controls.pickGeoPosition({
+ x : x,
+ y : y
+ });
+};
+
+/**
+ * Gets the coordinate in lat,lon for a given mouse position.
+ *
+ * @param {MouseEvent} mouseEvent - A mouse event.
+ * @return {Coordinates} position
+ */
+GlobeViewExtended.prototype.getCoordinateFromMouseEvent = function (mouseEvent) {
+ var coords = this.getGlobeView().eventToViewCoords(mouseEvent);
+ return this.getGlobeView().controls.pickGeoPosition(coords);
+};
+
+/**
+ * Get all visible features that intersect a pixel
+ *
+ * @param {MouseEvent} mouseEvent - A mouse event.
+ * @return {Array} visibleFeatures - The array of visible features.
+ */
+GlobeViewExtended.prototype.getFeaturesAtMousePosition = function (mouseEvent) {
+ var vectorLayers = this.getVectorLayers();
+ if (!vectorLayers) {
+ return;
+ }
+ // array of the visible features on the clicker coord
+ var visibleFeatures = [];
+ var geoCoord = this.getCoordinateFromMouseEvent(mouseEvent);
+ if (geoCoord) {
+ // buffer around the click inside we retrieve the features
+ var precision = this.getGlobeView().controls.pixelsToDegrees(5);
+ for (var i = 0; i < vectorLayers.length; i++) {
+ var idx;
+ var layer = vectorLayers[i];
+ // if the layer is not visible, we ignore it
+ if (!layer.visible) {
+ continue;
+ }
+ var result = ItFeaturesUtils.filterFeaturesUnderCoordinate(geoCoord, layer.source.parsedData, precision);
+ // we add the features to the visible features array
+ for (idx = 0; idx < result.length; idx++) {
+ visibleFeatures.push(result[idx]);
+ }
+ }
+ }
+ return visibleFeatures;
+};
+
+/**
+ * Changes the center of the scene on screen to the specified in lat, lon.
+ *
+ * @param {Object} center - Center object
+ * @param {Number} center.longitude - Coordinate longitude WGS84 in degree
+ * @param {Number} center.latitude - Coordinate latitude WGS84 in degree
+ * @return {Promise} A promise that resolves when the next 'globe initilazed' event fires.
+ */
+GlobeViewExtended.prototype.setCameraTargetGeoPosition = function (center) {
+ const itownsCoord = this._transformCoords(center);
+ return this.getGlobeView().controls.lookAtCoordinate(itownsCoord, false);
+};
+
+/**
+ * Retuns the coordinates of the central point on screen in lat,lon and alt
+ *
+ * @return {Object} center
+ */
+GlobeViewExtended.prototype.getCenter = function () {
+ var cameraCenter = this.getGlobeView().controls.getLookAtCoordinate();
+ return this._fromItownsCoords(cameraCenter);
+};
+
+/**
+ * Returns the actual zoom.
+ *
+ * @return {Number} zoom
+ */
+GlobeViewExtended.prototype.getZoom = function () {
+ return this.getGlobeView().controls.getZoom();
+};
+
+/**
+ * Sets the current zoom.
+ *
+ * @param {Number} zoom - The zoom
+ * @return {Promise} promise
+ */
+GlobeViewExtended.prototype.setZoom = function (zoom) {
+ return this.getGlobeView().controls.setZoom(zoom, false);
+};
+
+/**
+ * To convert the projection in meters on the globe of a number of pixels of screen
+ * @param {Number} pixels - count pixels to project
+ * @return {Number} projection in meters on globe
+ */
+GlobeViewExtended.prototype.pixelsToMeters = function (pixels) {
+ return this.getGlobeView().getPixelsToMeters(pixels);
+};
+
+/**
+ * Projection on screen in pixels of length in meter on globe
+ * @param {Number} value - Length in meter on globe
+ * @return {Number} projection in pixels on screen
+ */
+GlobeViewExtended.prototype.metersToPixels = function (value) {
+ return this.getGlobeView().getMetersToPixels(value);
+};
+
+/**
+ * Returns the "range": the distance in meters between the camera and the current central point on the screen.
+ * @return {Number} number
+ */
+GlobeViewExtended.prototype.getRange = function () {
+ return this.getGlobeView().controls.getRange();
+};
+
+/**
+ * @return {THREE.Vector3} position
+ */
+GlobeViewExtended.prototype.getCameraTargetPosition = function () {
+ return this.getGlobeView().controls.getCameraTargetPosition();
+};
+
+/**
+ * To get the layer event infos
+ *
+ * @param {Object} evt - event
+ * @returns {Object} object with event properties
+ */
+GlobeViewExtended.prototype.getLayerEventInfos = function (evt) {
+ var propertyName = evt.type.replace("-property-changed", "");
+ return {
+ propertyName : propertyName,
+ previousValue : evt.previous[propertyName],
+ newValue : evt.new[propertyName]
+ };
+};
+
+/**
+ * Sets background (specific to miniglobe)
+ */
+GlobeViewExtended.prototype.setBackground = function () {
+ // Set a 0 alpha clear value (instead of the default '1')
+ // because we want a transparent background for the miniglobe view to be able
+ // to see the main view "behind"
+ this.getGlobeView().mainLoop.gfxEngine.renderer.setClearColor(0x000000, 0);
+};
+
+/**
+ * Sets camera position
+ * @param {THREE.Vector3} target - Target position
+ * @param {Number} distance - Distance from target
+ */
+GlobeViewExtended.prototype.setCameraPosition = function (target, distance) {
+ this.getGlobeView().camera.camera3D.position.copy(target).setLength(distance);
+};
+
+/**
+ * Sets camera orientation to look at specified target
+ * @param {THREE.Vector3} target - Target position
+ */
+GlobeViewExtended.prototype.lookAt = function (target) {
+ this.getGlobeView().camera.camera3D.lookAt(target);
+};
+
+/**
+ * Notifies the scene it needs to be updated
+ * @param {String} styleUrl - style url
+ * @returns {Object} json object
+ */
+GlobeViewExtended.prototype.parseMapboxStyle = function (styleUrl) {
+ return ItParser.json(styleUrl);
+};
+
+/**
+ * Notifies the scene it needs to be updated
+ */
+GlobeViewExtended.prototype.notifyChange = function () {
+ this.getGlobeView().notifyChange(this.getGlobeView().camera.camera3D);
+};
+
+/**
+* Resizes itowns
+*
+* @param {Integer} width - canvas width in pixels
+* @param {Integer} height - canvas height in pixels
+*/
+GlobeViewExtended.prototype.resize = function (width, height) {
+ this.getGlobeView().mainLoop.gfxEngine.onWindowResize(width, height);
+ this.notifyChange();
+};
+
+/**
+* Transform to itowns coordinates
+*
+* @param {Object} coordCarto - longitude, latitude, altitude
+* @returns {Object} itowns coordinates
+*/
+GlobeViewExtended.prototype._transformCoords = function (coordCarto) {
+ if (coordCarto === undefined) return;
+
+ const itownsCoord = {};
+
+ if (coordCarto.zoom !== undefined) itownsCoord.zoom = coordCarto.zoom;
+ if (coordCarto.tilt !== undefined) itownsCoord.tilt = coordCarto.tilt;
+ if (coordCarto.heading !== undefined) itownsCoord.heading = coordCarto.heading;
+
+ if (coordCarto.longitude !== undefined && coordCarto.latitude !== undefined) {
+ const altitude = coordCarto.altitude || 0;
+ itownsCoord.coord = new ItCoordinates("EPSG:4326", coordCarto.longitude, coordCarto.latitude, altitude);
+ }
+ return itownsCoord;
+};
+
+/**
+* Transform from itowns coordinates
+*
+* @param {Object} itownsCoord - itowns coordinates
+* @returns {Object} coordinates
+*/
+GlobeViewExtended.prototype._fromItownsCoords = function (itownsCoord) {
+ return {
+ lon : itownsCoord.x,
+ lat : itownsCoord.y,
+ alt : itownsCoord.z
+ };
+};
+
+export default GlobeViewExtended;
diff --git a/src/Itowns-review/Layer/LayerElevation.js b/src/Itowns-review/Layer/LayerElevation.js
new file mode 100644
index 000000000..887078424
--- /dev/null
+++ b/src/Itowns-review/Layer/LayerElevation.js
@@ -0,0 +1,131 @@
+/* globals self */
+import Gp from "geoportal-access-lib";
+import Utils from "../../Common/Utils";
+import Config from "../../Common/Utils/Config";
+import Logger from "../../Common/Utils/LoggerByDefault";
+import Pkg from "../../../package.json";
+import {
+ Extent as ItExtent,
+ WMTSSource as ItWMTSSource,
+ ElevationLayer as ItElevationLayer
+} from "itowns";
+/* import Extent from "itowns/Core/Geographic/Extent";
+import WMTSSource from "itowns/Source/WMTSSource";
+import ElevationLayer from "itowns/Layer/ElevationLayer"; */
+
+var logger = Logger.getLogger("elevationLayer");
+
+/**
+ * @classdesc
+ * Geoportal elevation source creation
+ *
+ * @constructor
+ * @alias itowns.layer.GeoportalElevation
+ * @param {Object} options - options for function call.
+ * @param {String} options.layer - Elevation layer name (e.g. "ELEVATION.ELEVATIONGRIDCOVERAGE")
+ * @param {Boolean} [options.ssl] - if set true, enforce protocol https (only for nodejs)
+ * @param {String} [options.apiKey] - Access key to Geoportal platform
+ * @param {Object} [options.itownsParams] - options to overload default geoportal layer options for itowns.GlobeView.addLayer function (see {@link http://www.itowns-project.org/itowns/API_Doc/GlobeView.html#addLayer GlobeView.addLayer})
+ * @example
+ * var geoportalElevation = new itowns.layer.GeoportalElevation({
+ * layer : "ELEVATION.ELEVATIONGRIDCOVERAGE"
+ * });
+ */
+function LayerElevation (options) {
+ if (!(this instanceof LayerElevation)) {
+ throw new TypeError("ERROR CLASS_CONSTRUCTOR");
+ }
+
+ // check layer params
+ if (!options.layer) {
+ throw new Error("ERROR PARAM_MISSING : layer");
+ }
+ if (typeof options.layer !== "string") {
+ throw new Error("ERROR WRONG TYPE : layer");
+ }
+
+ // par defaut
+ if (typeof options.ssl === "undefined") {
+ options.ssl = false;
+ }
+
+ // Check if configuration is loaded
+ if (!Config.isConfigLoaded()) {
+ throw new Error("ERROR : contract key configuration has to be loaded to load Geoportal layers. See http://ignf.github.io/evolution-apigeoportail/ol3/ol3-autoconf.html");
+ }
+
+ var layerId = Config.getLayerId(options.layer, "WMTS");
+
+ if (layerId && Config.configuration.getLayerConf(layerId)) {
+ var config = {};
+ var wmtsParams = Config.getLayerParams(options.layer, "WMTS", options.apiKey);
+
+ if (wmtsParams.projection === "EPSG:3857" && wmtsParams.extent) {
+ wmtsParams.extent = new ItExtent("EPSG:4326", wmtsParams.extent.left, wmtsParams.extent.right, wmtsParams.extent.bottom, wmtsParams.extent.top).as("EPSG:3857");
+ } else {
+ wmtsParams.projection = "EPSG:4326";
+ wmtsParams.extent = new ItExtent("EPSG:4326", wmtsParams.extent.left, wmtsParams.extent.right, wmtsParams.extent.bottom, wmtsParams.extent.top);
+ }
+
+ // gestion de mixContent dans l'url du service...
+ var ctx = typeof window !== "undefined" ? window : typeof self !== "undefined" ? self : null;
+ var protocol = (ctx)
+ ? (ctx.location && ctx.location.protocol && ctx.location.protocol.indexOf("https:") === 0 ? "https://" : "http://")
+ : (options.ssl ? "https://" : "http://");
+
+ config.id = layerId;
+ config.noDataValue = -99999;
+ config.updateStrategy = {
+ type : 0,
+ options : {
+ groups : [11, 14]
+ }
+ };
+ config.source = new ItWMTSSource({
+ protocol : "wmts",
+ url : wmtsParams.url.replace(/(http|https):\/\//, protocol),
+ networkOptions : {
+ crossOrigin : "omit"
+ },
+ attribution : wmtsParams.originators,
+ projection : wmtsParams.projection,
+ name : options.layer,
+ format : "image/x-bil;bits=32",
+ tileMatrixSet : wmtsParams.TMSLink,
+ tileMatrixSetLimits : wmtsParams.tileMatrixSetLimits,
+ extent : {
+ west : wmtsParams.extent.west,
+ east : wmtsParams.extent.east,
+ south : wmtsParams.extent.south,
+ north : wmtsParams.extent.north
+ }
+ });
+
+ // ajout du tag gp-itowns-ext dans les requêtes WMTS elevation
+ config.source.url = Gp.Helper.normalyzeUrl(config.source.url, {
+ "gp-itowns-ext" : Pkg.itownsExtVersion || Pkg.version
+ }, false);
+
+ // récupération des autres paramètres passés par l'utilisateur
+ Utils.mergeParams(config, options.itownsParams);
+
+ // add legends and metadata (to be added to LayerSwitcher control)
+ config.legends = wmtsParams.legends;
+ config.metadata = wmtsParams.metadata;
+ config.description = wmtsParams.description;
+ config.title = wmtsParams.title;
+ config.quicklookUrl = wmtsParams.quicklookUrl;
+
+ return new ItElevationLayer(config.id, config);
+ } else {
+ // If layer is not in Gp.Config
+ logger.log("[source WMTS] ERROR : " + options.layer + " cannot be found in Geoportal Configuration. Make sure that this resource is included in your contract key.");
+ }
+}
+
+/*
+ * Constructor (alias)
+ */
+LayerElevation.prototype.constructor = LayerElevation;
+
+export default LayerElevation;
diff --git a/src/Itowns-review/Layer/LayerWMS.js b/src/Itowns-review/Layer/LayerWMS.js
new file mode 100644
index 000000000..245b0815d
--- /dev/null
+++ b/src/Itowns-review/Layer/LayerWMS.js
@@ -0,0 +1,126 @@
+import Gp from "geoportal-access-lib";
+import Utils from "../../Common/Utils";
+import Config from "../../Common/Utils/Config";
+import Logger from "../../Common/Utils/LoggerByDefault";
+import Pkg from "../../../package.json";
+import {
+ Extent as ItExtent,
+ WMSSource as ItWMSSource,
+ ColorLayer as ItColorLayer
+} from "itowns";
+/* import Extent from "itowns/Core/Geographic/Extent";
+import WMSSource from "itowns/Source/WMSSource";
+import ColorLayer from "itowns/Layer/ColorLayer"; */
+
+var logger = Logger.getLogger("wmsLayer");
+
+/**
+ * @classdesc
+ * Geoportal WMTS source creation
+ *
+ * @constructor
+ * @alias itowns.layer.GeoportalWMS
+ * @param {Object} options - options for function call.
+ * @param {String} options.layer - Layer name (e.g. "ORTHOIMAGERY.ORTHOPHOTOS")
+ * @param {Boolean} [options.ssl = true] - use of ssl or not (default true, service requested using https protocol)
+ * @param {String} [options.apiKey] - Access key to Geoportal platform
+ * @param {Object} [options.itownsParams] - other options for itowns.GlobeView.addLayer function (see {@link http://www.itowns-project.org/itowns/API_Doc/GlobeView.html#addLayer GlobeView.addLayer})
+ * @example
+ * var geoportalWMS = new itowns.layer.GeoportalWMS({
+ * layer : "ORTHOIMAGERY.ORTHOPHOTOS"
+ * });
+ */
+function LayerWMS (options) {
+ if (!(this instanceof LayerWMS)) {
+ throw new TypeError("ERROR CLASS_CONSTRUCTOR");
+ }
+
+ // check layer params
+ if (!options.layer) {
+ throw new Error("ERROR PARAM_MISSING : layer");
+ }
+ if (typeof options.layer !== "string") {
+ throw new Error("ERROR WRONG TYPE : layer");
+ }
+
+ // par defaut
+ if (typeof options.ssl === "undefined") {
+ options.ssl = true;
+ }
+
+ // Check if configuration is loaded
+ if (!Config.isConfigLoaded()) {
+ throw new Error("ERROR : contract key configuration has to be loaded to load Geoportal layers. See http://ignf.github.io/evolution-apigeoportail/ol3/ol3-autoconf.html");
+ }
+
+ var layerId = Config.getLayerId(options.layer, "WMS");
+
+ if (layerId && Config.configuration.getLayerConf(layerId)) {
+ var config = {};
+ var wmsParams = Config.getLayerParams(options.layer, "WMS", options.apiKey);
+
+ if (wmsParams.projection === "EPSG:3857" && wmsParams.extent) {
+ wmsParams.extent = new ItExtent("EPSG:4326", wmsParams.extent.left, wmsParams.extent.right, wmsParams.extent.bottom, wmsParams.extent.top).as("EPSG:3857");
+ } else {
+ wmsParams.extent = new ItExtent("EPSG:4326", wmsParams.extent.left, wmsParams.extent.right, wmsParams.extent.bottom, wmsParams.extent.top);
+ }
+
+ // si ssl = false on fait du http
+ // par défaut, ssl = true, on fait du https
+ var protocol = options.ssl === false ? "http://" : "https://";
+
+ config.id = layerId;
+ config.source = new ItWMSSource({
+ protocol : "wms",
+ version : wmsParams.version,
+ attribution : wmsParams.originators,
+ url : wmsParams.url.replace(/(http|https):\/\//, protocol),
+ name : options.layer,
+ projection : wmsParams.projection,
+ style : "",
+ heightMapWidth : 256,
+ waterMask : false,
+ networkOptions : {
+ crossOrigin : "omit"
+ },
+ updateStrategy : {
+ type : 0,
+ options : {}
+ },
+ format : wmsParams.format,
+ extent : {
+ west : wmsParams.extent.west,
+ east : wmsParams.extent.east,
+ south : wmsParams.extent.south,
+ north : wmsParams.extent.north
+ }
+ });
+
+ // ajout du tag gp-itowns-ext dans les requêtes WMS
+ config.source.url = Gp.Helper.normalyzeUrl(config.source.url, {
+ "gp-itowns-ext" : Pkg.itownsExtVersion || Pkg.version
+ }, false);
+
+ // récupération des autres paramètres passés par l'utilisateur
+ Utils.mergeParams(config, options.itownsParams);
+
+ // add legends and metadata (to be added to LayerSwitcher control)
+ config.legends = wmsParams.legends;
+ config.metadata = wmsParams.metadata;
+ config.description = wmsParams.description;
+ config.title = wmsParams.title;
+ config.quicklookUrl = wmsParams.quicklookUrl;
+
+ return new ItColorLayer(config.id, config);
+ } else {
+ // If layer is not in Gp.Config
+ logger.error("ERROR layer id (layer name: " + options.layer + " / service: WMS ) was not found !?");
+ }
+}
+
+/*
+ * Constructor (alias)
+ */
+LayerWMS.prototype.constructor = LayerWMS;
+
+export default LayerWMS;
diff --git a/src/Itowns-review/Layer/LayerWMTS.js b/src/Itowns-review/Layer/LayerWMTS.js
new file mode 100644
index 000000000..d068a13ba
--- /dev/null
+++ b/src/Itowns-review/Layer/LayerWMTS.js
@@ -0,0 +1,129 @@
+import Gp from "geoportal-access-lib";
+import Utils from "../../Common/Utils";
+import Config from "../../Common/Utils/Config";
+import Logger from "../../Common/Utils/LoggerByDefault";
+import Pkg from "../../../package.json";
+import {
+ Extent as ItExtent,
+ WMTSSource as ItWMTSSource,
+ ColorLayer as ItColorLayer
+} from "itowns";
+/* import Extent from "itowns/Core/Geographic/Extent";
+import WMTSSource from "itowns/Source/WMTSSource";
+import ColorLayer from "itowns/Layer/ColorLayer"; */
+
+var logger = Logger.getLogger("wmtsLayer");
+
+/**
+ * @classdesc
+ * Geoportal WMTS source creation
+ *
+ * @constructor
+ * @alias itowns.layer.GeoportalWMTS
+ * @param {Object} options - options for function call.
+ * @param {String} options.layer - Layer name (e.g. "ORTHOIMAGERY.ORTHOPHOTOS")
+ * @param {Boolean} [options.ssl = true] - use of ssl or not (default true, service requested using https protocol)
+ * @param {String} [options.apiKey] - Access key to Geoportal platform
+ * @param {Object} [options.itownsParams] - other options for itowns.GlobeView.addLayer function (see {@link http://www.itowns-project.org/itowns/API_Doc/GlobeView.html#addLayer GlobeView.addLayer})
+ * @example
+ * var geoportalWMTS = new itowns.layer.GeoportalWMTS({
+ * layer : "ORTHOIMAGERY.ORTHOPHOTOS"
+ * });
+ */
+function LayerWMTS (options) {
+ if (!(this instanceof LayerWMTS)) {
+ throw new TypeError("ERROR CLASS_CONSTRUCTOR");
+ }
+
+ // check layer params
+ if (!options.layer) {
+ throw new Error("ERROR PARAM_MISSING : layer");
+ }
+ if (typeof options.layer !== "string") {
+ throw new Error("ERROR WRONG TYPE : layer");
+ }
+
+ // par defaut
+ if (typeof options.ssl === "undefined") {
+ options.ssl = true;
+ }
+
+ // Check if configuration is loaded
+ if (!Config.isConfigLoaded()) {
+ throw new Error("ERROR : contract key configuration has to be loaded to load Geoportal layers. See http://ignf.github.io/evolution-apigeoportail/ol3/ol3-autoconf.html");
+ }
+
+ var layerId = Config.getLayerId(options.layer, "WMTS");
+
+ if (layerId && Config.configuration.getLayerConf(layerId)) {
+ var config = {};
+ var wmtsParams = Config.getLayerParams(options.layer, "WMTS", options.apiKey);
+
+ if (wmtsParams.projection === "EPSG:3857" && wmtsParams.extent) {
+ wmtsParams.extent = new ItExtent("EPSG:4326", wmtsParams.extent.left, wmtsParams.extent.right, wmtsParams.extent.bottom, wmtsParams.extent.top).as("EPSG:3857");
+ } else {
+ wmtsParams.projection = "EPSG:4326";
+ wmtsParams.extent = new ItExtent("EPSG:4326", wmtsParams.extent.left, wmtsParams.extent.right, wmtsParams.extent.bottom, wmtsParams.extent.top);
+ }
+
+ if (Object.entries(wmtsParams.tileMatrixSetLimits).length === 0 && wmtsParams.tileMatrixSetLimits.constructor === Object) {
+ wmtsParams.tileMatrixSetLimits = undefined;
+ }
+
+ // si ssl = false on fait du http
+ // par défaut, ssl = true, on fait du https
+ var protocol = options.ssl === false ? "http://" : "https://";
+
+ config.id = layerId;
+ config.source = new ItWMTSSource({
+ protocol : "wmts",
+ url : wmtsParams.url.replace(/(http|https):\/\//, protocol),
+ networkOptions : {
+ crossOrigin : "omit"
+ },
+ updateStrategy : {
+ type : 0,
+ options : {}
+ },
+ projection : wmtsParams.projection,
+ attribution : wmtsParams.originators,
+ name : options.layer,
+ format : wmtsParams.format,
+ tileMatrixSet : wmtsParams.TMSLink,
+ tileMatrixSetLimits : wmtsParams.tileMatrixSetLimits,
+ extent : {
+ west : wmtsParams.extent.west,
+ east : wmtsParams.extent.east,
+ south : wmtsParams.extent.south,
+ north : wmtsParams.extent.north
+ }
+ });
+
+ // ajout du tag gp-itowns-ext dans les requêtes WMTS
+ config.source.url = Gp.Helper.normalyzeUrl(config.source.url, {
+ "gp-itowns-ext" : Pkg.itownsExtVersion || Pkg.version
+ }, false);
+
+ // récupération des autres paramètres passés par l'utilisateur
+ Utils.mergeParams(config, options.itownsParams);
+
+ // add legends and metadata (to be added to LayerSwitcher control)
+ config.legends = wmtsParams.legends;
+ config.metadata = wmtsParams.metadata;
+ config.description = wmtsParams.description;
+ config.title = wmtsParams.title;
+ config.quicklookUrl = wmtsParams.quicklookUrl;
+
+ return new ItColorLayer(config.id, config);
+ } else {
+ // If layer is not in Gp.Config
+ logger.error("ERROR layer id (layer name: " + options.layer + " / service: WMTS ) was not found !?");
+ }
+}
+
+/*
+ * Constructor (alias)
+ */
+LayerWMTS.prototype.constructor = LayerWMTS;
+
+export default LayerWMTS;
diff --git a/src/Itowns-review/Layer/VectorTileLayer.js b/src/Itowns-review/Layer/VectorTileLayer.js
new file mode 100644
index 000000000..0392bd864
--- /dev/null
+++ b/src/Itowns-review/Layer/VectorTileLayer.js
@@ -0,0 +1,89 @@
+import Logger from "../../Common/Utils/LoggerByDefault";
+import Config from "../../Common/Utils/Config";
+
+import {
+ VectorTilesSource as ItVectorTilesSource,
+ ColorLayer as ItColorLayer
+} from "itowns";
+/* import Extent from "itowns/Core/Geographic/Extent";
+import WMSSource from "itowns/Source/WMSSource";
+import ColorLayer from "itowns/Layer/ColorLayer"; */
+
+var logger = Logger.getLogger("vectorTileLayer");
+
+/**
+ * @classdesc
+ * Geoportal WMTS source creation
+ *
+ * @constructor
+ * @private
+ * @alias itowns.layer.VectorTileLayer
+ * @param {Object} options - options for function call.
+ * @param {String} options.id - id to give to the layer
+ * @param {String} options.layer - Layer name (e.g. "PLAN.IGN")
+ * @param {String} [options.url] - Url to the vector Tile json style
+ * @param {String} [options.urlService] - Url to the pbf file. Retrieved in the style file by default.
+ * @param {Function} [options.filter] - Filter applied to the vector layer style. Fill/Line layer type by default.
+ * @param {Object} [options.attributions] - Attributions of the layer.
+ * @param {Object} [options.zoom] - Between which zoom levels the layer is displayed (zoom.min and zoom.max)
+ * @example
+ * var vectorTileLayer = new itowns.layer.VectorTileLayer({
+ * layer : "PLAN.IGN"
+ * });
+ */
+function VectorTileLayer (options) {
+ if (!(this instanceof VectorTileLayer)) {
+ throw new TypeError("ERROR CLASS_CONSTRUCTOR");
+ }
+
+ // check layer params
+ if (!options.layer) {
+ throw new Error("ERROR PARAM_MISSING : layer");
+ }
+ if (typeof options.layer !== "string") {
+ throw new Error("ERROR WRONG TYPE : layer");
+ }
+
+ // Check if configuration is loaded
+ if (!Config.isConfigLoaded()) {
+ throw new Error("ERROR : contract key configuration has to be loaded to load Geoportal layers. See http://ignf.github.io/evolution-apigeoportail/ol3/ol3-autoconf.html");
+ }
+
+ var layerId = Config.getLayerId(options.layer, "TMS");
+
+ if (layerId && Config.configuration.getLayerConf(layerId)) {
+ var config = {};
+ var tmsParams = Config.getLayerParams(options.layer, "TMS", options.apiKey);
+
+ // si ssl = false on fait du http
+ // par défaut, ssl = true, on fait du https
+ var protocol = options.ssl === false ? "http://" : "https://";
+
+ config.id = layerId;
+
+ config.source = new ItVectorTilesSource({
+ style : tmsParams.url.replace(/(http|https):\/\//, protocol),
+ url : options.urlService,
+ attribution : options.attributions,
+ filter : options.filter || function (layer) { return ["fill", "line"].includes(layer.type); },
+ zoom : options.zoom
+ });
+
+ // FIXME wait for next itowns release to remove this
+ config.isValidData = function () {
+ return false;
+ };
+
+ return new ItColorLayer(config.id, config);
+ } else {
+ // If layer is not in Gp.Config
+ logger.error("ERROR layer id (layer name: " + options.layer + " / service: TMS ) was not found !?");
+ }
+};
+
+/*
+ * Constructor (alias)
+ */
+VectorTileLayer.prototype.constructor = VectorTileLayer;
+
+export default VectorTileLayer;
diff --git a/src/Itowns-review/Styles.js b/src/Itowns-review/Styles.js
new file mode 100644
index 000000000..a612d3d88
--- /dev/null
+++ b/src/Itowns-review/Styles.js
@@ -0,0 +1,7 @@
+import "./CSS/GPgeneralWidgetItowns.css";
+import "./CSS/Controls/Attribution/GPattributionItowns.css";
+import "./CSS/Controls/BoostRelief/GPboostReliefItowns.css";
+import "./CSS/Controls/LayerSwitcher/GPlayerSwitcherItowns.css";
+import "./CSS/Controls/MiniGlobe/GPminiGlobeItowns.css";
+import "./CSS/Controls/MousePosition/GPmousePositionItowns.css";
+import "./CSS/Controls/Scale/GPscaleItowns.css";
diff --git a/src/Itowns-review/index.js b/src/Itowns-review/index.js
new file mode 100644
index 000000000..16cb27210
--- /dev/null
+++ b/src/Itowns-review/index.js
@@ -0,0 +1,151 @@
+/**
+* Global variable Gp.
+*
+* @module Gp
+* @alias Gp
+* @desc
+*
+* This is the global variable that is exposed in the browser environment.
+* Content is composed of constructor, functions and properties...
+*
+* > Config: (...)
+*
+* > ColorUtils: (...)
+* > LayerUtils: (...)
+* > MathUtils: (...)
+* > ProxyUtils: (...)
+*
+* > itownsExtended: (...)
+*
+* > itownsExtVersion: "YYYY-MM-DD"
+* > itownsExtVersion: "X.X.X"
+*
+* > Error: (...)
+* > Helper: (...)
+* > Protocols: (...)
+* > Services: (...)
+* > servicesDate: "YYYY-MM-DD"
+* > servicesVersion: "X.X.X"
+*
+* The following variables are aslo global :
+* - proj4,
+* - itowns
+*/
+
+import Pkg from "../../package.json";
+
+// CSS communes aux extensions !
+import "../Common/Styles";
+import "./Styles";
+
+import MousePosition from "./Controls/MousePosition";
+import LayerSwitcher from "./Controls/LayerSwitcher";
+import BoostRelief from "./Controls/BoostRelief";
+import Attributions from "./Controls/Attributions";
+import Scale from "./Controls/Scale";
+import MiniGlobe from "./Controls/MiniGlobe";
+import GeoportalWMTS from "./Layer/LayerWMTS";
+import GeoportalWMS from "./Layer/LayerWMS";
+import GeoportalElevation from "./Layer/LayerElevation";
+import VectorTileLayer from "./Layer/VectorTileLayer";
+import GlobeViewExtended from "./GlobeViewExtended";
+
+import CRS from "./CRS/CRS";
+
+// Autoload...
+import "../Common/Utils/AutoLoadConfig";
+
+// export des services
+import Gp from "geoportal-access-lib";
+
+// reconstruction des ns
+var Services = Gp.Services;
+var Error = Gp.Error;
+var Helper = Gp.Helper;
+var Protocols = Gp.Protocols;
+var servicesDate = Gp.servicesDate;
+var servicesVersion = Gp.servicesVersion;
+
+export {
+ /** Services
+ * @see {@link http://ignf.github.io/geoportal-access-lib/current/jsdoc/module-Services.html|geoportal-access-lib}
+ */
+ Services,
+ /** Error
+ * @see {@link http://ignf.github.io/geoportal-access-lib/current/jsdoc/Gp.Error.html|geoportal-access-lib}
+ */
+ Error,
+ /** Helper
+ * @see {@link http://ignf.github.io/geoportal-access-lib/current/jsdoc/module-Helper.html|geoportal-access-lib}
+ */
+ Helper,
+ /** Protocols
+ * @see {@link http://ignf.github.io/geoportal-access-lib/current/jsdoc/module-XHR.html|geoportal-access-lib}
+ */
+ Protocols,
+ /** servicesDate
+ * @see {@link http://ignf.github.io/geoportal-access-lib/current/jsdoc/module-Gp.html|geoportal-access-lib}
+ */
+ servicesDate,
+ /** servicesVersion
+ * @see {@link http://ignf.github.io/geoportal-access-lib/current/jsdoc/module-Gp.html|geoportal-access-lib}
+ */
+ servicesVersion
+};
+
+// Adds the extensions properties in the namespace
+export { default as LayerUtils } from "../Common/Utils/LayerUtils";
+export { default as ProxyUtils } from "../Common/Utils/ProxyUtils";
+export { default as ColorUtils } from "../Common/Utils/ColorUtils";
+export { default as MathUtils } from "../Common/Utils/MathUtils";
+
+function deepCopy (source, target) {
+ // Implementing Tail Call Elimination
+ function tce (source, target) {
+ for (var prop in source) {
+ if (source.hasOwnProperty(prop)) {
+ if (!target.hasOwnProperty(prop)) {
+ target[prop] = source[prop];
+ } else if (typeof source[prop] === "object") {
+ tce(source[prop], target[prop]);
+ }
+ }
+ }
+ }
+ return tce(source, target);
+}
+
+// Adds extensions properties in the namespace
+/** Version */
+export const itownsExtVersion = Pkg.itownsExtVersion;
+/** Publication date */
+export const itownsExtDate = Pkg.date;
+
+// creation of the namespace for the itowns extensions
+var Itowns = {};
+Itowns.control = {};
+Itowns.control.MousePosition = MousePosition;
+Itowns.control.LayerSwitcher = LayerSwitcher;
+Itowns.control.BoostRelief = BoostRelief;
+Itowns.control.Attributions = Attributions;
+Itowns.control.Scale = Scale;
+Itowns.control.MiniGlobe = MiniGlobe;
+Itowns.layer = {};
+Itowns.layer.GeoportalWMTS = GeoportalWMTS;
+Itowns.layer.GeoportalWMS = GeoportalWMS;
+Itowns.layer.GeoportalElevation = GeoportalElevation;
+Itowns.layer.VectorTileLayer = VectorTileLayer;
+Itowns.CRS = CRS;
+Itowns.GlobeViewExtended = GlobeViewExtended;
+
+export {
+ /** Expose extensions extended */
+ Itowns as itownsExtended
+};
+
+// Expose extensions extended into itowns
+if (window.itowns) {
+ // on fusionne les fonctionnalités o
+ deepCopy(Itowns, window.itowns);
+ deepCopy(window.itowns, Itowns);
+}