/* 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