UNPKG

kmap-ui

Version:

A components of zmap base on vue2.X

312 lines (290 loc) 11.2 kB
/* 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_ext_inherits from '../util/ext' import ol_control_SearchGeoportail from "./SearchGeoportail"; import {fromLonLat as ol_proj_fromLonLat} from 'ol/proj' /** * Search places using the French National Base Address (BAN) API. * * @constructor * @extends {ol.control.SearchJSON} * @fires select * @param {any} options extend ol.control.SearchJSON options * @param {string} options.className control class name * @param {boolean | undefined} options.apiKey the service api key. * @param {string | undefined} options.authentication: basic authentication for the service API as btoa("login:pwd") * @param {Element | string | undefined} options.target Specify a target if you want the control to be rendered outside of the map's viewport. * @param {string | undefined} options.label Text label to use for the search button, default "search" * @param {string | undefined} options.placeholder placeholder, default "Search..." * @param {number | undefined} options.typing a delay on each typing to start searching (ms), default 500. * @param {integer | undefined} options.minLength minimum length to start searching, default 3 * @param {integer | undefined} options.maxItems maximum number of items to display in the autocomplete list, default 10 * * @param {Number} options.pageSize item per page for parcelle list paging, use -1 for no paging, default 5 * @see {@link https://geoservices.ign.fr/documentation/geoservices/geocodage.html} */ var ol_control_SearchGeoportailParcelle = function(options) { var self = this; options.type = "Commune"; options.className = (options.className ? options.className:"")+" IGNF-parcelle ol-collapsed-list ol-collapsed-num"; options.inputLabel = "Commune"; options.noCollapse = true; options.placeholder = options.placeholder || "Choisissez une commune..."; ol_control_SearchGeoportail.call(this, options); this.set('copy', null); var element = this.element; // Add parcel form var div = document.createElement("DIV"); element.appendChild(div); var label = document.createElement("LABEL"); label.innerText = 'Préfixe' div.appendChild(label); label = document.createElement("LABEL"); label.innerText = 'Section' div.appendChild(label); label = document.createElement("LABEL"); label.innerText = 'Numéro' div.appendChild(label); div.appendChild(document.createElement("BR")); // Input this._inputParcelle = { prefix: document.createElement("INPUT"), section: document.createElement("INPUT"), numero: document.createElement("INPUT") }; this._inputParcelle.prefix.setAttribute('maxlength',3); this._inputParcelle.section.setAttribute('maxlength',2); this._inputParcelle.numero.setAttribute('maxlength',4); // Delay search var tout; var doSearch = function() { if (tout) clearTimeout(tout); tout = setTimeout(function() { self.autocompleteParcelle(); }, options.typing || 0); } // Add inputs for (var i in this._inputParcelle) { div.appendChild(this._inputParcelle[i]); this._inputParcelle[i].addEventListener("keyup", doSearch); this._inputParcelle[i].addEventListener('blur', function() { tout = setTimeout(function(){ element.classList.add('ol-collapsed-num'); }, 200); }); this._inputParcelle[i].addEventListener('focus', function() { clearTimeout(tout); element.classList.remove('ol-collapsed-num'); }); } this.activateParcelle(false); // Autocomplete list var auto = document.createElement('DIV'); auto.className = 'autocomplete-parcelle'; element.appendChild(auto); var ul = document.createElement('UL'); ul.classList.add('autocomplete-parcelle'); auto.appendChild(ul); ul = document.createElement('UL'); ul.classList.add('autocomplete-page'); auto.appendChild(ul); // Show/hide list on fcus/blur this._input.addEventListener('blur', function() { setTimeout(function(){ element.classList.add('ol-collapsed-list') }, 200); }); this._input.addEventListener('focus', function() { element.classList.remove('ol-collapsed-list'); self._listParcelle([]); if (self._commune) { self._commune = null; self._input.value = ''; self.drawList_(); } self.activateParcelle(false); }); this.on('select', this.selectCommune.bind(this)); this.set('pageSize', options.pageSize || 5); }; ol_ext_inherits(ol_control_SearchGeoportailParcelle, ol_control_SearchGeoportail); /** Select a commune => start searching parcelle * @param {any} e * @private */ ol_control_SearchGeoportailParcelle.prototype.selectCommune = function(e) { this._commune = e.search.insee; this._input.value = e.search.insee + ' - ' + e.search.fulltext; this.activateParcelle(true); this._inputParcelle.numero.focus(); this.autocompleteParcelle(); }; /** Set the input parcelle * @param {*} p parcel * @param {string} p.Commune * @param {string} p.CommuneAbsorbee * @param {string} p.Section * @param {string} p.Numero * @param {boolean} search start a search */ ol_control_SearchGeoportailParcelle.prototype.setParcelle = function(p, search) { this._inputParcelle.prefix.value = (p.Commune||'') + (p.CommuneAbsorbee||''); this._inputParcelle.section.value = p.Section||''; this._inputParcelle.numero.value = p.Numero||''; if (search) this._triggerCustomEvent("keyup", this._inputParcelle.prefix); }; /** Activate parcelle inputs * @param {bolean} b */ ol_control_SearchGeoportailParcelle.prototype.activateParcelle = function(b) { for (var i in this._inputParcelle) { this._inputParcelle[i].readOnly = !b; } if (b) { this._inputParcelle.section.parentElement.classList.add('ol-active'); } else { this._inputParcelle.section.parentElement.classList.remove('ol-active'); } }; /** Send search request for the parcelle * @private */ ol_control_SearchGeoportailParcelle.prototype.autocompleteParcelle = function() { // Add 0 to fit the format function complete (s, n, c) { if (!s) return s; c = c || "0"; while (s.length < n) s = c+s; return s.replace(/\*/g,'_'); } // The selected commune var commune = this._commune; var prefix = complete (this._inputParcelle.prefix.value, 3); if (prefix === '000') { prefix = '___'; } // Get parcelle number var section = complete (this._inputParcelle.section.value, 2); var numero = complete (this._inputParcelle.numero.value, 4, "0"); var search = commune + (prefix||'___') + (section||"__") + (numero ? numero : section ? "____":"0001"); this.searchParcelle(search, function(jsonResp) { this._listParcelle(jsonResp); }.bind(this), function() { console.log('oops') }) }; /** Send search request for a parcelle number * @param {string} search search parcelle number * @param {function} success callback function called on success * @param {function} error callback function called on error */ ol_control_SearchGeoportailParcelle.prototype.searchParcelle = function(search, success /*, error */) { // Request var request = '<?xml version="1.0" encoding="UTF-8"?>' +'<XLS xmlns:xls="http://www.opengis.net/xls" xmlns:gml="http://www.opengis.net/gml" xmlns="http://www.opengis.net/xls" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="http://www.opengis.net/xls http://schemas.opengis.net/ols/1.2/olsAll.xsd">' +'<RequestHeader/>' +'<Request requestID="1" version="1.2" methodName="LocationUtilityService">' +'<GeocodeRequest returnFreeForm="false">' +'<Address countryCode="CadastralParcel">' +'<freeFormAddress>'+search+'+</freeFormAddress>' +'</Address>' +'</GeocodeRequest>' +'</Request>' +'</XLS>' // Geocode this.ajax( this.get('url').replace('ols/apis/completion','geoportail/ols'), { xls: request }, function(xml) { // XML to JSON var parser = new DOMParser(); var xmlDoc = parser.parseFromString(xml,"text/xml"); var parcelles = xmlDoc.getElementsByTagName('GeocodedAddress'); var jsonResp = [] for (var i=0, parc; parc= parcelles[i]; i++) { var node = parc.getElementsByTagName('gml:pos')[0] || parc.getElementsByTagName('pos')[0]; var p = node.childNodes[0].nodeValue.split(' '); var att = parc.getElementsByTagName('Place'); var json = { lon: Number(p[1]), lat: Number(p[0]) }; for (var k=0, a; a=att[k]; k++) { json[a.attributes.type.value] = a.childNodes[0].nodeValue; } jsonResp.push(json); } success(jsonResp); }, { dataType: 'XML' } ); }; /** * Draw the autocomplete list * @param {*} resp * @private */ ol_control_SearchGeoportailParcelle.prototype._listParcelle = function(resp) { var self = this; var ul = this.element.querySelector("ul.autocomplete-parcelle"); ul.innerHTML=''; var page = this.element.querySelector("ul.autocomplete-page"); page.innerHTML=''; this._listParc = []; // Show page i function showPage(i) { var l = ul.children; var visible = "ol-list-"+i; var k; for (k=0; k<l.length; k++) { l[k].style.display = (l[k].className===visible) ? '' : 'none'; } l = page.children; for (k=0; k<l.length; k++) { l[k].className = (l[k].innerText==i) ? 'selected' : ''; } page.style.display = l.length>1 ? '' : 'none'; } // Sort table resp.sort(function(a,b) { var na = a.INSEE+a.CommuneAbsorbee+a.Section+a.Numero; var nb = b.INSEE+b.CommuneAbsorbee+b.Section+b.Numero; return na===nb ? 0 : na<nb ? -1 : 1; }); // Show list var n = this.get('pageSize'); for (var i=0, r; r = resp[i]; i++) { var li = document.createElement("LI"); li.setAttribute("data-search", i); if (n>0) li.classList.add("ol-list-"+Math.floor(i/n)); this._listParc.push(r); li.addEventListener("click", function(e) { self._handleParcelle(self._listParc[e.currentTarget.getAttribute("data-search")]); }); li.innerHTML = r.INSEE+r.CommuneAbsorbee+r.Section+r.Numero; ul.appendChild(li); // if (n>0 && !(i%n)) { li = document.createElement("LI"); li.innerText = Math.floor(i/n); li.addEventListener("click", function(e) { showPage(e.currentTarget.innerText); }); page.appendChild(li); } } if (n>0) showPage(0); }; /** * Handle parcelle section * @param {*} parc * @private */ ol_control_SearchGeoportailParcelle.prototype._handleParcelle = function(parc) { this.dispatchEvent({ type:"parcelle", search: parc, coordinate: ol_proj_fromLonLat([parc.lon, parc.lat], this.getMap().getView().getProjection()) }); }; export default ol_control_SearchGeoportailParcelle