UNPKG

geopf-extensions-openlayers

Version:

French Geoportal Extensions for OpenLayers libraries

1,044 lines (982 loc) 42.7 kB
// import CSS import "../../CSS/Controls/Editor/GPFeditor.css"; // import "../../CSS/Controls/Editor/GPFeditorStyle.css"; // import library import EventBus from "eventbusjs"; // import local import Utils from "../../Utils/Helper"; import ID from "../../Utils/SelectorID"; import Logger from "../../Utils/LoggerByDefault"; import Style from "./Style"; import Themes from "./Themes"; import Filter from "./Filter"; import Legend from "./Legend"; import Layer from "./Layer"; import Group from "./Group"; import Event from "./Event"; import Search from "./Search"; // DOM import EditorDOM from "./EditorDOM"; var logger = Logger.getLogger("editor"); /** * @typedef {Object} EditorOptions * @property {string|HTMLElement} [target] - Sélecteur ou élément DOM cible pour l’insertion de l’éditeur. * @property {string|Object} style - URL du style MapBox ou objet JSON du style. * @property {Object} [themes] - Liste des thèmes MapBox (voir exemple). * @property {Object} [scope] - Contexte d’exécution pour les handlers d’événements. * @property {Object} [events] - Dictionnaire des handlers d’événements personnalisés. * @property {Object} [tools] - Configuration des outils et options d’affichage (voir ci-dessous). * @property {string|number} [id] - Identifiant unique du widget. * * @property {boolean|Object} [tools.themes=false] - Afficher/cacher les thèmes ou config avancée. * @property {boolean} [tools.layers=true] - Afficher la liste des couches. * @property {boolean} [tools.search=false] - Afficher l’outil de recherche de couches. * @property {boolean} [tools.style=false] - Afficher l’édition des styles. * @property {boolean} [tools.filter=false] - Afficher l’édition des filtres. * @property {boolean} [tools.legend=false] - Afficher l’édition des légendes. * @property {boolean} [tools.group=false] - Grouper les couches. * @property {boolean} [tools.groupAuto=false] - Construction automatique des groupes. * @property {boolean} [tools.sort=true] - Activer le tri des couches. * @property {string} [tools.sortBy="id"] - Critère de tri ("id", "class", "geom"). * @property {string} [tools.sortOrder="asc"] - Ordre de tri ("asc", "desc"). * @property {boolean} [tools.title=true] - Afficher les titres des rubriques. * @property {boolean|undefined} [tools.collapse] - Afficher/plie les groupes de couches. * @property {boolean} [tools.type=true] - Afficher le type de géométrie. * @property {boolean} [tools.pin=true] - Afficher la puce pour chaque couche. * @property {boolean} [tools.visibility=true] - Afficher l’icône de visibilité. * @property {Object} [tools.icon] - Configuration de l’icône de visibilité. * @property {boolean} [tools.icon.image=true] - Afficher l’icône image. * @property {string} [tools.icon.anchor="end"] - Position de l’icône ("start" ou "end"). * @property {boolean} [tools.editable=true] - Activer l’édition des légendes. */ /** * @classdesc * * Editor Styles MapBox... * * @alias ol.style.Editor * @module Editor */ class Editor { /** * @constructor * @param {EditorOptions} options - options for function call. * @fires editor:layer:onclickvisibility * @fires editor:layer:onclickclone * @fires editor:layer:onclickremove * @fires editor:style:oneditjson * @fires editor:style:scale:onchangemin * @fires editor:style:scale:onchangemax * @fires editor:legend:onclickedition * @fires editor:legend:onchangevalue * @fires editor:filter:oneditjson * @fires editor:themes:onclickimage * @fires editor:themes:onclicktitle * @fires editor:group:oncollapse * @fires editor:onloaded * @example * var editor = new Editor ({ * target : "", * style : "data/styles/layer.json", * themes: { * themesSummary : "", * themes : [{ * "thumbnail": "data/images/layer0.png", * "name": "standard0", * "url": "data/styles/layer0.json", * "description": "", * "selected" : true * },{ * "thumbnail": "data/images/layer1.png", * "name": "standard1", * "url": "data/styles/layer1.json", * "description": "" * }] * }, * scope : this, * events : { * "editor:layer:onclickvisibility" : ..., * "editor:layer:onclickclone" : ..., * "editor:layer:onclickremove" : ..., * "editor:style:oneditjson" : ..., * "editor:style:scale:onchangemin" : ..., * "editor:style:scale:onchangemax" : ..., * "editor:filter:oneditjson" : ..., * "editor:themes:onclickimage" : this._onClickEventImageTheme(), * "editor:themes:onclicktitle" : function(e) {...} * }, * tools : { * // afficher/cacher les themes (par defaut) ou utiliser les options * themes : true | false | { * target : "...", * tools : { * "thumbnails": true, * "button": { visible : true, type : "checkbox" } * }, * }, * layers : true | false, // afficher les couches (layers) * search : true | false, // TODO : afficher l'outil de recheche de couches * style : true | false, // afficher les styles (sous menu layers) * filter : true | false, // afficher les filtres (sous menu layers) * legend : true | false, // afficher les legendes (layers) * group : true | false, // grouper les couches, l'option 'sort' doit être activée (layers) * groupAuto : true | false, // definir la construction automatiques des groupes * sort : true | false, // trier les couches (layers) * sortBy : "id|class|geom", // definir le type de tri (layers) * sortOrder : "asc, desc", // definir l'ordre de tri (layers) * title : true | false // afficher les titres des rubriques, * collapse : true | false | undefined // afficher et/ou plier les couches ou ne pas afficher l'option, * type : true | false, // afficher le type de geometrie (layers) * pin : true | false, // afficher la puce pour chaque couche (layers) * visibility : true | false, // afficher l'icone de visibilité (layers), * icon : { // afficher l'icone "oeil" ou "checkbox" (layers), * "image" : true, * "anchor" : "start" // afficher l'icone au debut ou à la fin de la ligne * }, * editable : true | false // active l'edition de la legende (legendes) * } * }); * // options par defaut * { * themes : false, * layers : true, * search : false, * style : false, * filter : false, * legend : false, * group : false, * groupAuto : false, * sort : true, * sortBy : "id", * sortOrder : "asc", * title : true, * collapse : undefined, * type : true, * pin : true, * visibility : true, * icon : { * image : true, * anchor : "end" * }, * editable : true * } * // Context * editor.setContext("map", map); * editor.setContext("layer", layer); * // create DOM * editor.createElement() * .then(() => { * console.warn(editor.getID()); * console.log(this.getContext("map")); * console.log(this.getContext("layer")); * }) * .catch(error => {}); * // possibility to add listeners with globale variable : eventbus * eventbus.addEventListener("editor:style:scale:onchangemin", function (e) {...}); */ constructor (options) { logger.trace("[constructor] Editor", options); // options this.options = options || { // TODO default... }; if (!(this instanceof Editor)) { throw new TypeError("ERROR CLASS_CONSTRUCTOR"); } this._initialize(); } /** * Initialize component * (called by constructor) * * @private */ _initialize () { // gestion des options if (!this.options.target) { logger.info("La 'target' n'est pas renseignée (options.target)."); } if (!this.options.style) { logger.error("Le 'style' MapBox n'est pas renseigné (options.style) !"); return; } if (this.options.events) { this._initEvents(); } else { logger.warn("Les 'handlers' ne sont pas renseignés (options.events) !"); } if (!this.options.themes) { logger.info("Les 'themes' MapBox ne sont pas renseignés (options.themes)."); } // options par defaut var _toolsDefault = { themes : false, layers : true, search : false, style : false, filter : false, legend : false, group : false, groupAuto : false, sort : true, sortBy : "id", sortOrder : "asc", title : true, collapse : undefined, type : true, pin : true, visibility : true, icon : { image : true, anchor : "end" }, editable : true }; if (!this.options.tools) { logger.trace("Utilisation des outils MapBox par défaut (options.tools)."); this.options.tools = _toolsDefault; } Utils.mergeParams(this.options.tools, _toolsDefault, false); // id unique this.id = this.options.id || ID.generate(); // context this.context = {}; // property layers this.layers = []; // dom container this.container = null; // dom name this.name = { target : "GPEditorMapBoxTarget", container : "GPEditorMapBoxContainer", containerID : "GPEditorMapBoxContainer_ID_", containerLayers : "GPEditorMapBoxLayersContainer", titleLayers : "GPEditorMapBoxLayersTitle", titleLayersID : "GPEditorMapBoxLayersTitle_ID_", titleThemes : "GPEditorMapBoxThemesTitle", titleThemesID : "GPEditorMapBoxThemesTitle_ID_", sep : "GPEditorMapBoxSep" }; // style json this.mapbox = {}; // INFO // sprites : // { // url : null, // size : { // h : null, // w : null // }, // json : {} // } this.sprites = {}; } /** * Initialize events with handlers * (called by constructor) * * List Events : * "editor:layer:visibility" * "editor:layer:clone" * "editor:layer:remove" * "editor:style:edit" * "editor:style:minScale" * "editor:style:maxScale" * "editor:filter:edit" * "editor:themes:image", * "editor:themes:title" * @private */ _initEvents () { var ctx = this.options.scope || this; var events = this.options.events; if (events) { for (var event in events) { if (events.hasOwnProperty(event)) { var handler = events[event]; // test sur les events disponibles ! if (handler) { if (!EventBus.hasEventListener(event, handler, ctx)) { EventBus.addEventListener(event, handler, ctx); } } } } } } /** * Graphical rendering of the component * (called by constructor) * * @example * <div class="GPEditorMapBoxContainer" id="GPEditorMapBoxContainer_ID_0"> * <div id="GPEditorMapBoxThemesTitle" class="GPEditorMapBoxThemesTitle">Liste des 'thèmes'</div> * <div class="GPEditorMapBoxThemesContainer"> * ... * </div> * <div id="GPEditorMapBoxLayersTitle" class="GPEditorMapBoxLayersTitle">Liste des 'couches'</div> * <div class="GPEditorMapBoxLayersContainer"> * <div class="GPEditorMapBoxLayerContainer"> * <div id="GPEditorMapBoxLayerTitleContainer-0_1" class="GPEditorMapBoxLayerTitleContainer"> * <label class="GPEditorMapBoxLayerImageLabel"></label> * <input id="GPEditorMapBoxLayerTitleInput-0_1" class="GPEditorMapBoxLayerTitleInput" type="checkbox"> * <label class="GPEditorMapBoxLayerTitleLabel" for="GPEditorMapBoxLayerTitleInput-0_1" title="states">population_lt_2m</label> * </div> * </div> * <div class="GPEditorMapBoxLayerContainer">...</div> * <div class="GPEditorMapBoxLayerContainer">...</div> * </div> * </div> * @private */ _initContainer () { logger.trace(this.mapbox); // existance d'un autre container (editeur) ? // var _idx = 0; // var elements = document.querySelectorAll("div[id^=" + this.name.containerID + "]"); // for (var j = 0; j < elements.length; j++) { // var element = elements[j]; // var num = parseInt(element.id.substring(element.id.lastIndexOf("_") + 1), 10); // if (num > _idx) { // _idx = num; // } // } // if (elements.length) { // _idx += 1; // } // container principal de l'editeur var div = document.createElement("div"); div.id = this.name.containerID + this.id; div.className = this.name.container; // Themes var _toolsThemes = this.options.tools.themes; if (_toolsThemes && this.options.themes) { // title if (this.options.tools.title) { var titleThemes = document.createElement("div"); titleThemes.id = this.name.titleThemesID + this.id; titleThemes.className = this.name.titleThemes; titleThemes.innerHTML = "Liste des 'thèmes'"; div.appendChild(titleThemes); } // lien vers les styles var themes = new Themes({ id : this.id, target : div, tools : (typeof _toolsThemes === "object") ? _toolsThemes : {}, obj : this.options.themes }); themes.add(); } // TODO : Recheche / filtre de couches if (this.options.tools.search) { var search = new Search({ id : this.id, target : div, tools : {}, obj : this.mapbox.layers // liste des objets layers }); search.add(); } for (var source in this.mapbox.sources) { if (this.mapbox.sources.hasOwnProperty(source)) { if (this.options.tools.layers) { // multisources ? Si oui, on renseigne un titre... var multisources = (Object.keys(this.mapbox.sources).length > 1) ? 1 : 0; if (multisources) { var hr = document.createElement("hr"); hr.className = this.name.sep; div.appendChild(hr); } // title if (this.options.tools.title) { var titleLayers = document.createElement("div"); titleLayers.id = this.name.titleLayersID + this.id; titleLayers.className = this.name.titleLayers; titleLayers.innerHTML = (multisources) ? "Liste des 'couches' (" + source + ")" : "Liste des 'couches'"; div.appendChild(titleLayers); } } // gestion de l'ordre avant tri avec la metadata 'order' var _layers = this.mapbox.layers.slice(); // clone // une fois les layers triés, la metadata:geoportail:order permet // de savoir l'emplacement du layers dans le fichier de style. _layers.forEach(function (layer, order) { // on écarte les layers sans source: ex. "background" // if (!layer.source) { // return; // } // ajout de la metadata d'ordre var _metadata = layer["metadata"]; if (_metadata) { _metadata["geoportail:order"] = order; } else { layer["metadata"] = { "geoportail:order" : order }; } }); // tri des layers if (this.options.tools.sort) { var sortBy = this.options.tools.sortBy; var sortOrder = this.options.tools.sortOrder; var sortFct = function (a, b) { // si on utilise les groupements utilisateurs, ils doivent // tous être renseignés sinon..., ça va coincer ! var result = 0; if (a["metadata"] && a["metadata"]["geoportail:group"] && b["metadata"] && b["metadata"]["geoportail:group"]) { var cmpA = null; var cmpB = null; cmpA = a["metadata"]["geoportail:group"]; cmpB = b["metadata"]["geoportail:group"]; result = cmpA.localeCompare(cmpB); } else { switch (sortBy) { case "geom": result = sortOrder === "asc" ? a.type.localeCompare(b.type) || a.id.localeCompare(b.id) : b.type.localeCompare(a.type) || b.id.localeCompare(a.id); break; case "class": result = sortOrder === "asc" ? a["source-layer"].localeCompare(b["source-layer"]) || a.id.localeCompare(b.id) : b["source-layer"].localeCompare(a["source-layer"]) || b.id.localeCompare(a.id); break; case "id": default: // tri sur l'id par defaut result = sortOrder === "asc" ? a.id.localeCompare(b.id) : b.id.localeCompare(a.id); break; } } return result; }; _layers.sort(sortFct); } logger.trace("Layers : ", _layers); // gestion des groupes avec la metadata de groupe var groupBy = this.options.tools.sortBy; // le même type de tri que les couches ! var groupAuto = this.options.tools.groupAuto; var _groups = {}; // liste et comptage des layers dans chaque groupes _layers.forEach(function (layer) { // on écarte les layers sans source: ex. "background" // if (!layer.source) { // return; // } // balise metadata var _metadata = layer["metadata"]; // s'il existe déjà une meta de groupe, on l'utilise... // sinon, on la met en place. if (_metadata && _metadata["geoportail:group"]) { var _groupName = _metadata["geoportail:group"]; _groups[_groupName] = (_groups[_groupName]) ? _groups[_groupName] + 1 : 1; } else { var _field = null; switch (groupBy) { case "class": _field = layer["source-layer"]; break; case "geom": _field = layer.type; break; case "id": default: _field = layer.id; break; } var _newGroupName = _field; if (groupAuto) { // separateur var _regex = /_|-|:|=/; // TODO à definir via une option ! // index var _idx = _field.search(_regex); // y'a t il un separateur ? _newGroupName = (_idx !== -1) ? _field.substring(0, _idx).trim() : _field; } // on compte le nombre d'entrée dans un groupe _groups[_newGroupName] = (_groups[_newGroupName]) ? _groups[_newGroupName] + 1 : 1; // ajout de la metadata de groupe if (_metadata) { _metadata["geoportail:group"] = _newGroupName; } else { layer["metadata"] = { "geoportail:group" : _newGroupName }; } } }); logger.trace("Groups : ", _groups); // container principal des couches var divLayers = document.createElement("div"); divLayers.className = this.name.containerLayers; div.appendChild(divLayers); var details; if (this.options.tools.collapse !== undefined) { details = document.createElement("details"); details.className = ""; details.open = !this.options.tools.collapse; divLayers.appendChild(details); var summary = document.createElement("summary"); summary.className = ""; summary.innerHTML = ""; details.appendChild(summary); } // container courant (cf. groupe) pour l'ajout des elements var target = (this.options.tools.collapse !== undefined) ? details : divLayers; // Ex. Layers, Styles, Groups et Filtres // "id": "ocs - vegetation", // "type": "fill", // "source": "pyramide_proto", // "source-layer": "ocs_vegetation_surf", // "metadata" : { // "geoportail:group": "ocs" // }, // "layout": { // "visibility": "visible" // }, // "filter": ["in","symbo", // "SURFACE_D_EAU", // "BASSIN", // "ZONE_MARINE" // ], // "paint": { // "fill-color": "#2BB3E1" // } var index = -1; for (var ii = 0; ii < _layers.length; ii++) { var data = _layers[ii]; index++; // traitement dans l'ordre des sources if (data.source === source) { // Groups // INFO la gestion des groupes est basée sur la balise metadata::geoportail:group // ainsi que sur l'ordre des couches. // il n'y a pas de regroupement sans tri des couches ! if (this.options.tools.group && this.options.tools.sort) { var mtd = data.metadata; // creation du container de groupe // si le tag metadata existe if (mtd) { var grp = data.metadata["geoportail:group"]; if (grp) { // le groupe doit contenir plus d'un element if (_groups[grp] > 1) { // le groupe est déjà créé, on en veut plus par la suite... _groups[grp] = -1; // creation du groupe var oGroup = new Group({ id : this.id, target : (this.options.tools.collapse !== undefined) ? details : divLayers, title : grp, collapse : true }); oGroup.add(); // le nouveau container pour les elements suivants target = oGroup.getContainer(); } else if (_groups[grp] === 1) { // l'element est seul, donc pas d'ajout dans le // groupe en cours target = (this.options.tools.collapse !== undefined) ? details : divLayers; } else { // on ajoute l'element dans le groupe courant... } } else { target = (this.options.tools.collapse !== undefined) ? details : divLayers; } } else { target = (this.options.tools.collapse !== undefined) ? details : divLayers; } } // Layers if (this.options.tools.layers) { var oLayer = new Layer({ id : this.id, target : target, position : index + "_" + this.id, // unique ! tools : { visibility : this.options.tools.visibility, icon : this.options.tools.icon, type : this.options.tools.type, pin : this.options.tools.pin }, obj : { id : data.id, type : data.type, source : data.source, "source-layer" : data["source-layer"] } }); oLayer.add(); // update visibility layer if (data.layout && data.layout.visibility && data.layout.visibility === "none") { oLayer.visibility(false); } // sauvegarde des layers this.layers.push(oLayer); } // Legende if (this.options.tools.legend) { // gestion de l'edition de la legende : // l'option "editable" est prioritaire sur le tag "editable" du fichier de style ! var isEditable = this.options.tools.editable; if (typeof isEditable === "undefined") { isEditable = data.editable; } var oLegend = new Legend({ id : this.id, target : target, sprites : this.sprites, obj : { id : data.id, source : data.source, title : data.id, editable : (typeof isEditable !== "undefined") ? isEditable : false, paint : data.paint, layout : data.layout } }); oLegend.add(); oLegend.display(false); if (oLayer) { oLayer.addLegend(oLegend); oLayer.slotLegend(); // integration de la legende dans le container du layers ! } } // Style if (this.options.tools.style) { var oStyle = new Style({ id : this.id, target : target, position : index + "_" + this.id, // unique !, obj : { id : data.id, source : data.source, layout : data.layout, paint : data.paint } }); oStyle.add(); oStyle.display(false); if (oLayer) { oLayer.addStyle(oStyle); } // update visibility layer if (data.layout && data.layout.visibility && data.layout.visibility === "none") { oLayer.visibility(false); } } // Filter if (this.options.tools.filter) { var oFilter = new Filter({ id : this.id, target : target, position : index + "_" + this.id, // unique !, obj : { id : data.id, source : data.source, filter : data.Filter } }); oFilter.add(); oFilter.display(false); if (oLayer) { oLayer.addFilter(oFilter); } } } else { // on ecarte un layer car il n'est pas reconnu dans la source // on decremente la position du layer if (index >= 0) { index--; } } } } } // sauvegarde this.container = div; // container principal if (!this.options.target) { if (!document.getElementById(this.name.target)) { var _target = document.createElement("div"); _target.id = this.name.target; var node = document.getElementsByTagName("body")[0] || document.getElementsByTagName("head")[0] || document.documentElement; node.appendChild(_target); } this.options.target = document.getElementById(this.name.target); } if (this.container) { this.options.target.appendChild(this.container); } // dispatch event EventBus.dispatch(Event.onloaded, this); } /** * Getting Sprites informations * (called by _initialize) * * @param {String} sprites - url des sprites * @returns {Promise} - promise * @private */ _getSprites (sprites) { var self = this; // on ne doit pas mettre de promise en échec... // car on souhaite continuer le traitement même si on n'a pas de sprites ! // si le protocole est mapbox:// if (sprites && sprites.startsWith("mapbox://")) { return new Promise((resolve, reject) => { logger.error("Protocole mapbox:// non géré !"); resolve(self); }); } // si pas de sprites if (!sprites) { return new Promise((resolve, reject) => { logger.error("Auncun sprites disponibles !"); resolve(self); }); } var fetchSpritesImage = function () { var spritesImage = sprites + ".png"; return fetch(spritesImage, { credentials : "same-origin" }) .then(function (response) { if (response.ok) { return response.blob() .then(function (blob) { self.sprites.url = spritesImage; // decode de l'image var theImage = new Image(); theImage.src = spritesImage; return theImage.decode() .then(function () { self.sprites.size = {}; self.sprites.size.h = theImage.height; self.sprites.size.w = theImage.width; }); }) .catch(error => { logger.warn("fetch image sprites exception :", error); }); } else { var err = new Error("HTTP status code: " + response.status); throw err; } }) .catch(error => { return new Promise((resolve, reject) => { logger.error("fetch image sprites exception :", error); reject(error); }); }); }; var fetchSpritesJson = function () { var spritesJson = sprites + ".json"; return fetch(spritesJson, { credentials : "same-origin" }) .then(function (response) { if (response.ok) { return response.json() .then(function (json) { self.sprites.json = json; }) .catch(error => { logger.warn("fetch json sprites exception :", error); }); } else { var err = new Error("HTTP status code: " + response.status); throw err; } }) .catch(error => { return new Promise((resolve, reject) => { logger.error("fetch json sprites exception :", error); reject(error); }); }); }; // promise return Promise.all([ fetchSpritesImage(), fetchSpritesJson() ]); } // ################################################################### // // ########################## INTERFACE ############################## // // ################################################################### // /** * Create Editor * * @returns {Promise} - promise */ createElement () { var self = this; // objet json if (typeof this.options.style === "object") { this.mapbox = this.options.style; // les sprites sont utiles que si on veut une legende ! if (this.options.tools.legend) { return this._getSprites(this.mapbox.sprite) .then(function () { // init du DOM self._initContainer(); return self; }) .catch(error => { logger.warn("fetch sprites exception :", error); }); } else { return new Promise((resolve, reject) => { self._initContainer(); resolve(self); }); } } // url if (typeof this.options.style === "string") { return fetch(this.options.style, { credentials : "same-origin" }) .then(response => { // sauvegarde du json return response.json() .then(style => { self.mapbox = style; }) .then(function () { // les sprites sont utiles que si on veut une legende ! if (self.options.tools.legend) { return self._getSprites(self.mapbox.sprite) .then(function () { // init du DOM self._initContainer(); return self; }) .catch(error => { logger.warn("fetch sprites exception :", error); }); } else { return new Promise((resolve, reject) => { self._initContainer(); resolve(self); }); } }) .catch(error => { logger.error("json exception :", error); }); }) .catch(error => { logger.error("fetch exception :", error); }); } } /** * Set display container (DOM) * * @param {Boolean} display - show/hidden container */ display (display) { this.container.style.display = (display) ? "block" : "none"; } setContext (key, value) { this.context[key] = value; } getContext (key) { return this.context[key]; } // ################################################################### // // ##################### public methods ############################## // // ################################################################### // /** * Get id editor * @returns {Number} id */ getID () { return this.id; } /** * Get container (DOM) * @returns {HTMLElement} DOM element */ getContainer () { return this.container; } /** * Get Style (json) * @returns {Object} Style MapBox */ getStyle () { return this.mapbox; } /** * Get layer style (json) * @param {Number} i - index * @returns {Object} Style MapBox of a layers */ getStyleLayer (i) { var layer = null; var o = this.getLayer(i); var id = o.options.obj.id; for (var k = 0; k < this.mapbox.layers.length; k++) { var l = this.mapbox.layers[k]; if (l.id === id) { layer = l; break; } } return layer; } /** * Get layer object from json style * @param {Number} i - index into style json * @returns {Object} Style MapBox of a layers */ getLayerFromStyle (i) { var layer = null; var l = this.mapbox.layers[i]; for (var k = 0; k < this.getLayers().length; k++) { var o = this.getLayer(k); if (l.id === o.options.obj.id) { layer = o; break; } } return layer; } /** * Get a list of layer object sorted or not (see options.tools.sort) * @returns {Array} - List of layer object * @see {ol.style.editor.Layer} */ getLayers () { return this.layers; } /** * Get the layer object from a list sorted or not (see options.tools.sort) * @param {Number} i - index * @returns {Object} - layer object * @see {ol.style.editor.Layer} */ getLayer (i) { return this.layers[i]; } }; // on récupère les méthodes de la classe DOM Utils.assign(Editor.prototype, EditorDOM); // ################################################################### // // ####################### handlers events to dom #################### // // ################################################################### // export default Editor; // Expose Editor as ol.editor.View (for a build bundle) if (window.ol && window.ol.style) { window.ol.style.Editor = Editor; }