geopf-extensions-openlayers
Version:
French Geoportal Extensions for OpenLayers libraries
468 lines (411 loc) • 14.8 kB
JavaScript
import EventBus from "eventbusjs";
import EventEditor from "./Event";
import Utils from "../../Utils/Helper";
import Logger from "../../Utils/LoggerByDefault";
var logger = Logger.getLogger("editor-style");
/**
* @classdesc
*
* MapBox styles management
*
* @constructor
* @alias ol.style.editor.Style
* @param {Object} options - options for function call.
* @example
* var style = new Style ({
* target : ...,
* position : 1, // identifiant de position (unique !)
* tools : {
* edition : false,
* scale : true
* },
* title : "Styles (JSON)",
* obj : {
* paint : {},
* layout : {}
* }
* });
* style.add();
* style.display(true);
* style.getContainer();
*/
class Style {
constructor (options) {
logger.trace("[constructor] Style", options);
// options
this.options = options || {
// default...
target : null,
position : 0,
tools : null,
title : null,
obj : null
};
if (!(this instanceof Style)) {
throw new TypeError("ERROR CLASS_CONSTRUCTOR");
}
this._initialize();
this._initContainer();
}
/**
* Initialize component
* (called by constructor)
*
* @private
*/
_initialize () {
// unique editor id (optional!)
this.id = this.options.id || null;
if (!this.options.target) {
// cf. add()
}
if (!this.options.position) {
this.options.position = 0;
}
var _toolsDefault = {
scale : true,
edition : false
};
if (!this.options.tools) {
this.options.tools = _toolsDefault;
}
Utils.mergeParams(this.options.tools, _toolsDefault, false);
if (!this.options.obj) {
// choix d'avoir un objet vide pour une edition futur...
this.options.obj = {
paint : {},
layout : {}
};
}
if (!this.options.title) {
this.options.title = "JSON Styles :";
}
this.container = null;
// DOM : className or id
this.name = {
target : "GPEditorMapBoxStyleTarget",
container : "GPEditorMapBoxStyleContainer",
containerjson : "GPEditorMapBoxStyleJsonContainer",
jsonlabel : "GPEditorMapBoxStyleJsonTitle",
jsondisplay : "GPEditorMapBoxStyleJsonDisplay",
containertoolsscale : "GPEditorMapBoxStyleToolsScaleContainer",
scaletitle : "GPEditorMapBoxStyleScaleTitle",
containertoolsminscale : "GPEditorMapBoxStyleToolsScaleMinContainer",
scalelabelmin : "GPEditorMapBoxStyleScaleLabelMin",
scaleinputmin : "GPEditorMapBoxStyleScaleInputMin",
containertoolsmaxscale : "GPEditorMapBoxStyleToolsScaleMaxContainer",
scalelabelmax : "GPEditorMapBoxStyleScaleLabelMax",
scaleinputmax : "GPEditorMapBoxStyleScaleInputMax",
containertoolsedit : "GPEditorMapBoxStyleToolsEditionContainer"
};
}
/**
* Graphical rendering of the component
* ie. this.container
* (called by constructor)
*
* @private
* @example
* <div class="GPEditorMapBoxStyleContainer">
* <div class ="GPEditorMapBoxStyleJsonContainer">
* <label class="GPEditorMapBoxStyleJsonTitle">JSON Styles :</label>
* <pre class="GPEditorMapBoxStyleJsonDisplay">...</pre>
* </div>
* <div class ="GPEditorMapBoxStyleToolsScaleContainer"></div>
* <div class ="GPEditorMapBoxStyleToolsEditionContainer"></div>
* </div>
*/
_initContainer () {
// contexte
var self = this;
var _found = false;
var _obj = JSON.parse(JSON.stringify(this.options.obj)); // on manipule une copie !
var _style = {};
// styles into tag 'paint' ?
if (_obj.paint) {
_found = true;
_style.paint = _obj.paint;
if (Object.keys(_obj.paint).length === 0) {
logger.info("tag 'paint' is empty !");
}
}
// if not, search into tag 'layout' !
if (_obj.layout) {
_found = true;
_style.layout = _obj.layout;
// FIXME delete visibility from display ?
if (_obj.layout.visibility) {
delete _style.visibility;
}
if (Object.keys(_obj.layout).length === 0) {
logger.info("tag 'layout' is empty !");
}
}
var div = document.createElement("div");
div.className = this.name.container;
var json = null;
if (_found) {
var strJson = JSON.stringify(_style, null, 4);
json = this._syntaxHighlight(strJson);
}
var divJson = document.createElement("div");
divJson.className = this.name.containerjson;
var label = document.createElement("label");
label.className = this.name.jsonlabel;
label.innerHTML = this.options.title;
divJson.appendChild(label);
var pre = document.createElement("pre");
pre.className = this.name.jsondisplay;
pre.innerHTML = json;
if (pre.addEventListener) {
pre.addEventListener("click", function (e) {
if (self.options.tools.edition) {
self.onEditJsonStyleMapBox(e);
}
});
} else if (pre.attachEvent) {
pre.attachEvent("onclick", function (e) {
if (self.options.tools.edition) {
self.onEditJsonStyleMapBox(e);
}
});
}
divJson.appendChild(pre);
div.appendChild(divJson);
// scale
if (this.options.tools.scale) {
div.appendChild(this._createElementToolsScale({
min : (_style.layout) ? _style.layout.minzoom : 0,
max : (_style.layout) ? _style.layout.maxzoom : 21
}));
}
// TODO menu d'edition
if (this.options.tools.edition) {
div.appendChild(this._createElementToolsEdition());
}
// main container
this.container = div;
}
/**
* Graphical rendering of the scale tools
*
* @param {Object} scale - {min,max} or 0|21
* @returns {HTMLElement} DOM element
*
* @private
* @example
* <div class ="GPEditorMapBoxStyleToolsScaleContainer"></div>
*/
_createElementToolsScale (scale) {
logger.trace("_createElementToolsScale");
var self = this;
var obj = this.options.obj;
var divToolsScale = document.createElement("div");
divToolsScale.className = this.name.containertoolsscale;
// FIXME Titre ?
// var label = document.createElement("label");
// label.className = this.name.scaletitle;
// label.innerHTML = "Scale :";
// divToolsScale.appendChild(label);
var divMin = document.createElement("div");
divMin.className = this.name.containertoolsminscale;
var labelMin = document.createElement("label");
labelMin.className = this.name.scalelabelmin;
labelMin.innerHTML = "min :";
divMin.appendChild(labelMin);
var inputMin = document.createElement("input");
inputMin.className = this.name.scaleinputmin;
inputMin.type = "range";
inputMin.value = scale.min || 0;
inputMin.title = scale.min || 0;
inputMin.disabled = false;
inputMin.min = 0;
inputMin.max = 21;
inputMin.data = obj; // on lie le DOM et la couche, utile lors d'evenement !
if (inputMin.addEventListener) {
inputMin.addEventListener("change", function (e) {
self.onChangeStyleScaleMinMapBox(e);
});
} else if (inputMin.appendChild) {
inputMin.appendChild("onchange", function (e) {
self.onChangeStyleScaleMinMapBox(e);
});
}
divMin.appendChild(inputMin);
divToolsScale.appendChild(divMin);
var divMax = document.createElement("div");
divMax.className = this.name.containertoolsmaxscale;
var labelMax = document.createElement("label");
labelMax.className = this.name.scalelabelmax;
labelMax.innerHTML = "max :";
divMax.appendChild(labelMax);
var inputMax = document.createElement("input");
inputMax.className = this.name.scaleinputmin;
inputMax.type = "range";
inputMax.value = scale.max || 21;
inputMax.title = scale.max || 21;
inputMax.disabled = false;
inputMax.min = 0;
inputMax.max = 21;
inputMax.data = obj; // on lie le DOM et la couche, utile lors d'evenement !
if (inputMax.addEventListener) {
inputMax.addEventListener("change", function (e) {
self.onChangeStyleScaleMaxMapBox(e);
});
} else if (inputMax.appendChild) {
inputMax.appendChild("onchange", function (e) {
self.onChangeStyleScaleMaxMapBox(e);
});
}
divMax.appendChild(inputMax);
divToolsScale.appendChild(divMax);
return divToolsScale;
}
/**
* Graphical rendering of the edition tools
*
* @returns {HTMLElement} DOM element
*
* @private
* @example
* <div class ="GPEditorMapBoxStyleToolsScaleContainer"></div>
*/
_createElementToolsEdition () {
logger.warn("_createElementToolsEdition, it's not yet implemented !");
var divToolsEdit = document.createElement("div");
divToolsEdit.className = this.name.containertoolsedit;
return divToolsEdit;
}
// ################################################################### //
// ##################### private methods ############################# //
// ################################################################### //
/**
* Transform a JSON into a DOM with a syntax in color
*
* @private
* @param {Object} json - json.
* @returns {HTMLElement} dom element
*/
_syntaxHighlight (json) {
json = json.replace(/&/g, "&").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 "<span class='" + cls + "'>" + match + "</span>";
});
}
// ################################################################### //
// ##################### public methods ############################## //
// ################################################################### //
/**
* Add element into target DOM
* @returns {Object} - Legend instance
*/
add () {
if (!this.options.target) {
if (!document.getElementById(this.name.target)) {
var div = document.createElement("div");
div.id = this.name.target;
var node = document.documentElement ||
document.getElementsByTagName("body")[0] ||
document.getElementsByTagName("head")[0];
node.appendChild(div);
}
this.options.target = document.getElementById(this.name.target);
}
if (this.container) {
this.options.target.appendChild(this.container);
}
return this;
}
/**
* Set display container or get
*
* @param {Boolean} display - show/hidden container or get status
* @returns {Boolean} - true/false
*/
display (display) {
logger.trace("display()", display);
if (typeof display !== "undefined") {
this.container.style.display = (display) ? "flex" : "none";
}
return (this.container.style.display === "flex");
}
/**
* Get container (DOM)
*
* @returns {HTMLElement} DOM element
*/
getContainer () {
return this.container;
}
// ################################################################### //
// ####################### handlers events to dom #################### //
// ################################################################### //
/**
* this method is called by event '' on '' tag form...
*
* 'e' contains the option object into 'e.target.data' !
* 'e' contains the id editor into 'e.target.editorID' !
*
* @param {Object} e - HTMLElement
* @private
* @fires Style#editor:style:oneditjson
*/
onEditJsonStyleMapBox (e) {
logger.trace("onEditJsonStyleMapBox", e);
e.editorID = this.id;
e.data = this.options;
EventBus.dispatch(EventEditor.style.oneditjson, e);
}
/**
* this method is called by event '' on '' tag form...
*
* 'e' contains the option object into 'e.target.data' !
* 'e' contains the id editor into 'e.target.editorID' !
*
* @param {Object} e - HTMLElement
* @private
* @fires Style#editor:style:scale:onchangemin
*/
onChangeStyleScaleMinMapBox (e) {
logger.trace("onChangeStyleScaleMinMapBox", e);
e.editorID = this.id;
e.data = this.options;
EventBus.dispatch(EventEditor.style.scale.onchangemin, e);
}
/**
* this method is called by event '' on '' tag form...
*
* 'e' contains the option object into 'e.target.data' !
* 'e' contains the id editor into 'e.target.editorID' !
*
* @param {Object} e - HTMLElement
* @private
* @fires Style#editor:style:scale:onchangemax
*/
onChangeStyleScaleMaxMapBox (e) {
logger.trace("onChangeStyleScaleMaxMapBox", e);
e.editorID = this.id;
e.data = this.options;
EventBus.dispatch(EventEditor.style.scale.onchangemax, e);
}
};
export default Style;
// Expose Editor as ol.editor.View (for a build bundle)
if (window.ol && window.ol.style) {
if (!window.ol.style.editor) {
window.ol.style.editor = {};
}
window.ol.style.editor.Style = Style;
}