kmap-ui
Version:
A components of zmap base on vue2.X
272 lines (251 loc) • 10.1 kB
JavaScript
/* Copyright (c) 2018 Jean-Marc VIGLINO,
released under the CeCILL-B license (French BSD license)
(http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt).
*/
import ol_Feature from 'ol/Feature'
import ol_ext_inherits from '../util/ext'
import ol_Overlay_Popup from './Popup'
import ol_ext_element from '../util/element'
/** Template attributes for popup
* @typedef {Object} TemplateAttributes
* @property {string} title
* @property {function} format a function that takes an attribute and a feature and returns the formated attribute
* @property {string} before string to instert before the attribute (prefix)
* @property {string} after string to instert after the attribute (sudfix)
* @property {boolean|function} visible boolean or a function (feature, value) that decides the visibility of a attribute entry
*/
/** Template
* @typedef {Object} Template
* @property {string|function} title title of the popup, attribute name or a function that takes a feature and returns the title
* @property {Object.<TemplateAttributes>} attributes a list of template attributes
*/
/**
* A popup element to be displayed on a feature.
*
* @constructor
* @extends {ol_Overlay_Popup}
* @param {} options Extend Popup options
* @param {String} options.popupClass the a class of the overlay to style the popup.
* @param {bool} options.closeBox popup has a close box, default false.
* @param {function|undefined} options.onclose: callback function when popup is closed
* @param {function|undefined} options.onshow callback function when popup is shown
* @param {Number|Array<number>} options.offsetBox an offset box
* @param {ol.OverlayPositioning | string | undefined} options.positionning
* the 'auto' positioning var the popup choose its positioning to stay on the map.
* @param {Template|function} options.template A template with a list of properties to use in the popup or a function that takes a feature and returns a Template
* @param {boolean} options.canFix Enable popup to be fixed, default false
* @param {boolean} options.showImage display image url as image, default false
* @param {boolean} options.maxChar max char to display in a cell, default 200
* @api stable
*/
var ol_Overlay_PopupFeature = function (options) {
options = options || {};
ol_Overlay_Popup.call(this, options);
this.setTemplate(options.template);
this.set('canFix', options.canFix)
this.set('showImage', options.showImage)
this.set('maxChar', options.maxChar||200)
// Bind with a select interaction
if (options.select && (typeof options.select.on ==='function')) {
this._select = options.select;
options.select.on('select', function(e){
if (!this._noselect) this.show(e.mapBrowserEvent.coordinate, options.select.getFeatures().getArray());
}.bind(this));
}
};
ol_ext_inherits(ol_Overlay_PopupFeature, ol_Overlay_Popup);
/** Set the template
* @param {Template} template A template with a list of properties to use in the popup
*/
ol_Overlay_PopupFeature.prototype.setTemplate = function(template) {
this._template = template;
if (this._template && this._template.attributes instanceof Array) {
var att = {};
this._template.attributes.forEach(function (a) {
att[a] = true;
});
this._template.attributes = att;
}
};
/** Show the popup on the map
* @param {ol.coordinate|undefined} coordinate Position of the popup
* @param {ol.Feature|Array<ol.Feature>} features The features on the popup
*/
ol_Overlay_PopupFeature.prototype.show = function(coordinate, features) {
if (coordinate instanceof ol_Feature
|| (coordinate instanceof Array && coordinate[0] instanceof ol_Feature)) {
features = coordinate;
coordinate = null;
}
if (!(features instanceof Array)) features = [features];
this._features = features.slice();
if (!this._count) this._count = 1;
// Calculate html upon feaures attributes
this._count = 1;
var html = this._getHtml(features[0]);
this.hide();
if (html) {
if (!coordinate || features[0].getGeometry().getType()==='Point') {
coordinate = features[0].getGeometry().getFirstCoordinate();
}
ol_Overlay_Popup.prototype.show.call(this, coordinate, html);
}
};
/**
* @private
*/
ol_Overlay_PopupFeature.prototype._getHtml = function(feature) {
if (!feature) return '';
var html = ol_ext_element.create('DIV', { className: 'ol-popupfeature' });
if (this.get('canFix')) {
ol_ext_element.create('I', { className:'ol-fix', parent: html })
.addEventListener('click', function(){
this.element.classList.toggle('ol-fixed');
}.bind(this));
}
var template = this._template;
// calculate template
if (typeof(template) === 'function') {
template = template(feature, this._count, this._features.length);
} else if (!template || !template.attributes) {
template = template || {};
template. attributes = {};
for (var i in feature.getProperties()) if (i!='geometry') {
template.attributes[i] = i;
}
}
// Display title
if (template.title) {
var title;
if (typeof template.title === 'function') {
title = template.title(feature);
} else {
title = feature.get(template.title);
}
ol_ext_element.create('H1', { html:title, parent: html });
}
// Display properties in a table
if (template.attributes) {
var tr, table = ol_ext_element.create('TABLE', { parent: html });
var atts = template.attributes;
for (var att in atts) {
var a = atts[att];
var content, val = feature.get(att);
// Get calculated value
if (typeof(a.format)==='function') {
val = a.format(val, feature);
}
// Is entry visible?
var visible = true;
if (typeof(a.visible)==='boolean') {
visible = a.visible;
} else if (typeof(a.visible)==='function') {
visible = a.visible(feature, val);
}
if (visible) {
tr = ol_ext_element.create('TR', { parent: table });
ol_ext_element.create('TD', { html: a.title || att, parent: tr });
// Show image or content
if (this.get('showImage') && /(http(s?):)([/|.|\w|\s|-])*\.(?:jpg|gif|png)/.test(val)) {
content = ol_ext_element.create('IMG',{
src: val
});
} else {
content = (a.before||'') + val + (a.after||'');
var maxc = this.get('maxChar') || 200;
if (typeof(content) === 'string' && content.length>maxc) content = content.substr(0,maxc)+'[...]';
}
// Add value
ol_ext_element.create('TD', {
html: content,
parent: tr
});
}
}
}
// Zoom button
ol_ext_element.create('BUTTON', { className: 'ol-zoombt', parent: html })
.addEventListener('click', function() {
if (feature.getGeometry().getType()==='Point') {
this.getMap().getView().animate({
center: feature.getGeometry().getFirstCoordinate(),
zoom: Math.max(this.getMap().getView().getZoom(), 18)
});
} else {
var ext = feature.getGeometry().getExtent();
this.getMap().getView().fit(ext, { duration:1000 });
}
}.bind(this));
// Counter
if (this._features.length > 1) {
var div = ol_ext_element.create('DIV', { className: 'ol-count', parent: html });
ol_ext_element.create('DIV', {
className: 'ol-prev',
parent: div,
click: function() {
this._count--;
if (this._count<1) this._count = this._features.length;
html = this._getHtml(this._features[this._count-1]);
setTimeout(function() {
ol_Overlay_Popup.prototype.show.call(this, this.getPosition(), html);
}.bind(this), 350 );
}.bind(this)
});
ol_ext_element.create('TEXT', { html:this._count+'/'+this._features.length, parent: div });
ol_ext_element.create('DIV', {
className: 'ol-next',
parent: div,
click: function() {
this._count++;
if (this._count>this._features.length) this._count = 1;
html = this._getHtml(this._features[this._count-1]);
setTimeout(function() {
ol_Overlay_Popup.prototype.show.call(this, this.getPosition(), html);
}.bind(this), 350 );
}.bind(this)
});
}
// Use select interaction
if (this._select) {
this._noselect = true;
this._select.getFeatures().clear();
this._select.getFeatures().push(feature);
this._noselect = false;
}
return html;
};
/** Fix the popup
* @param {boolean} fix
*/
ol_Overlay_PopupFeature.prototype.setFix = function (fix) {
if (fix) this.element.classList.add('ol-fixed');
else this.element.classList.remove('ol-fixed');
};
/** Is a popup fixed
* @return {boolean}
*/
ol_Overlay_PopupFeature.prototype.getFix = function () {
return this.element.classList.contains('ol-fixed');
};
/** Get a function to use as format to get local string for an attribute
* if the attribute is a number: Number.toLocaleString()
* if the attribute is a date: Date.toLocaleString()
* otherwise the attibute itself
* @param {string} locales string with a BCP 47 language tag, or an array of such strings
* @param {*} options Number or Date toLocaleString options
* @return {function} a function that takes an attribute and return the formated attribute
*/
var ol_Overlay_PopupFeature_localString = function (locales , options) {
return function (a) {
if (a && a.toLocaleString) {
return a.toLocaleString(locales , options);
} else {
// Try to get a date from a string
var date = new Date(a);
if (isNaN(date)) return a;
else return date.toLocaleString(locales , options);
}
};
};
export {ol_Overlay_PopupFeature_localString}
export default ol_Overlay_PopupFeature