/* Copyright (c) 2017 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_control_SelectBase from './SelectBase.js'
import ol_ext_element from '../util/element.js'
/**
* Select Control.
* A control to select features by attributes
*
* @constructor
* @extends {ol_control_SelectBase}
* @fires select
* @param {Object=} options
* @param {string} options.className control class name
* @param {Element | undefined} options.target Specify a target if you want the control to be rendered outside of the map's viewport.
* @param {ol.source.Vector | Array
} options.source the source to search in
* @param {string} [options.selectLabel=select] select button label
* @param {string} [options.addLabel=add] add button label
* @param {string} [options.caseLabel=case sensitive] case checkbox label
* @param {string} [options.allLabel=match all] match all checkbox label
* @param {string} [options.attrPlaceHolder=attribute]
* @param {string} [options.valuePlaceHolder=value]
*/
var ol_control_Select = class olcontrolSelect extends ol_control_SelectBase {
constructor(options) {
options = options || {};
// Container
var div = options.content = document.createElement('div');
super(options);
var bt = div.querySelector('button');
// Autocompletion list
this._ul = ol_ext_element.create('UL', {
parent: div
});
// All conditions
this._all = ol_ext_element.create('INPUT', {
type: 'checkbox',
checked: true
});
var label_match_all = ol_ext_element.create('LABEL', {
html: this._all,
parent: div
});
ol_ext_element.appendText(label_match_all, options.allLabel || 'match all');
// Use case
this._useCase = ol_ext_element.create('INPUT', {
type: 'checkbox'
});
var label_case_sensitive = ol_ext_element.create('LABEL', {
html: this._useCase,
parent: div
});
ol_ext_element.appendText(label_case_sensitive, options.caseLabel || 'case sensitive');
// Add ok button at the end
div.appendChild(bt);
// Add button
ol_ext_element.create('BUTTON', {
className: 'ol-append',
html: options.addLabel || 'add rule',
click: function () {
this.addCondition();
}.bind(this),
parent: div
});
this._conditions = [];
this.set('attrPlaceHolder', options.attrPlaceHolder || 'attribute');
this.set('valuePlaceHolder', options.valuePlaceHolder || 'value');
this.addCondition();
}
/** Add a new condition
* @param {*} options
* @param {string} options.attr attribute name
* @param {string} options.op operator
* @param {string} options.val attribute value
*/
addCondition(options) {
options = options || {};
this._conditions.push({
attr: options.attr || '',
op: options.op || '=',
val: options.val || ''
});
this._drawlist();
}
/** Get the condition list
*/
getConditions() {
return {
usecase: this._useCase.checked,
all: this._all.checked,
conditions: this._conditions
};
}
/** Set the condition list
*/
setConditions(cond) {
this._useCase.checked = cond.usecase;
this._all.checked = cond.all;
this._conditions = cond.conditions;
this._drawlist();
}
/** Get the conditions as string
*/
getConditionsString(cond) {
var st = '';
for (var i = 0, c; c = cond.conditions[i]; i++) {
if (c.attr) {
st += (st ? (cond.all ? ' AND ' : ' OR ') : '')
+ c.attr
+ this.operationsList[c.op]
+ c.val;
}
}
return st;
}
/** Draw the liste
* @private
*/
_drawlist() {
this._ul.innerHTML = '';
for (var i = 0; i < this._conditions.length; i++) {
this._ul.appendChild(this._getLiCondition(i));
}
}
/** Get a line
* @return {*}
* @private
*/
_autocomplete(val, ul) {
ul.classList.remove('ol-hidden');
ul.innerHTML = '';
var attributes = {};
var sources = this.get('source');
for (var i = 0, s; s = sources[i]; i++) {
var features = s.getFeatures();
for (var j = 0, f; f = features[j]; j++) {
Object.assign(attributes, f.getProperties());
if (j > 100)
break;
}
}
var rex = new RegExp(val, 'i');
for (var a in attributes) {
if (a === 'geometry')
continue;
if (rex.test(a)) {
var li = document.createElement('li');
li.textContent = a;
li.addEventListener("click", function () {
ul.previousElementSibling.value = this.textContent;
var event = document.createEvent('HTMLEvents');
event.initEvent('change', true, false);
ul.previousElementSibling.dispatchEvent(event);
ul.classList.add('ol-hidden');
});
ul.appendChild(li);
}
}
}
/** Get a line
* @return {*}
* @private
*/
_getLiCondition(i) {
var self = this;
var li = document.createElement('li');
// Attribut
var autocomplete = document.createElement('div');
autocomplete.classList.add('ol-autocomplete');
autocomplete.addEventListener("mouseleave", function () {
this.querySelector('ul').classList.add('ol-hidden');
});
li.appendChild(autocomplete);
var input_attr = document.createElement('input');
input_attr.classList.add('ol-attr');
input_attr.setAttribute('type', 'search');
input_attr.setAttribute('placeholder', this.get('attrPlaceHolder'));
input_attr.addEventListener('keyup', function () {
self._autocomplete(this.value, this.nextElementSibling);
});
input_attr.addEventListener('focusout', function () {
setTimeout(function () {
autocomplete.querySelector('ul').classList.add('ol-hidden');
}, 300);
});
input_attr.addEventListener('click', function () {
setTimeout(function () {
self._autocomplete(this.value, this.nextElementSibling);
this.nextElementSibling.classList.remove('ol-hidden');
}.bind(this));
});
input_attr.addEventListener('change', function () {
self._conditions[i].attr = this.value;
});
input_attr.value = self._conditions[i].attr;
autocomplete.appendChild(input_attr);
// Autocomplete list
var ul_autocomplete = document.createElement('ul');
ul_autocomplete.classList.add('ol-hidden');
autocomplete.appendChild(ul_autocomplete);
// Operation
var select = document.createElement('select');
li.appendChild(select);
for (var k in this.operationsList) {
var option = document.createElement('option');
option.value = k;
option.textContent = this.operationsList[k];
select.appendChild(option);
}
select.value = self._conditions[i].op;
select.addEventListener('change', function () {
self._conditions[i].op = this.value;
});
// Value
var input_value = document.createElement('input');
input_value.setAttribute('type', 'text');
input_value.setAttribute('placeholder', this.get('valuePlaceHolder'));
input_value.addEventListener('change', function () {
self._conditions[i].val = this.value;
});
input_value.value = self._conditions[i].val;
li.appendChild(input_value);
if (this._conditions.length > 1) {
var div_delete = document.createElement('div');
div_delete.classList.add('ol-delete');
div_delete.addEventListener("click", function () { self.removeCondition(i); });
li.appendChild(div_delete);
}
//
return li;
}
/** Remove the ith condition
* @param {int} i condition index
*/
removeCondition(i) {
this._conditions.splice(i, 1);
this._drawlist();
}
/** Select features by attributes
* @param {*} options
* @param {Array|undefined} options.sources source to apply rules, default the select sources
* @param {bool} options.useCase case sensitive, default checkbox state
* @param {bool} options.matchAll match all conditions, , default checkbox state
* @param {Array} options.conditions array of conditions
* @fires select
*/
doSelect(options) {
options = options || {};
options.useCase = options.useCase || this._useCase.checked;
options.matchAll = options.matchAll || this._all.checked;
options.conditions = options.conditions || this._conditions;
return super.doSelect(options);
}
}
export default ol_control_Select