From 09932b4b965ab77c16c1878a71131be351e08592 Mon Sep 17 00:00:00 2001 From: Norbert Renner Date: Wed, 14 May 2014 15:31:54 +0200 Subject: [PATCH] update leaflet-search --- bower_components/leaflet-search/.bower.json | 8 +- bower_components/leaflet-search/README.md | 71 ++++++++--- bower_components/leaflet-search/TODO | 72 ++++++++--- bower_components/leaflet-search/bower.json | 2 +- .../dist/leaflet-search.min.css | 2 +- .../leaflet-search/dist/leaflet-search.min.js | 4 +- .../dist/leaflet-search.mobile.min.css | 2 +- .../dist/leaflet-search.mobile.src.css | 2 +- .../dist/leaflet-search.src.css | 2 +- .../leaflet-search/dist/leaflet-search.src.js | 114 ++++++++++++------ bower_components/leaflet-search/index.html | 10 +- bower_components/leaflet-search/package.json | 3 +- bower_components/leaflet-search/smart.json | 4 +- .../leaflet-search/src/leaflet-search.js | 112 ++++++++++++----- 14 files changed, 284 insertions(+), 124 deletions(-) diff --git a/bower_components/leaflet-search/.bower.json b/bower_components/leaflet-search/.bower.json index 31bbe2d..e8d9d5b 100644 --- a/bower_components/leaflet-search/.bower.json +++ b/bower_components/leaflet-search/.bower.json @@ -1,6 +1,6 @@ { "name": "leaflet-search", - "version": "1.4.7", + "version": "1.5.1", "main": "leaflet-search.js", "ignore": [ "**/.*", @@ -10,11 +10,11 @@ "examples" ], "homepage": "https://github.com/stefanocudini/leaflet-search", - "_release": "1.4.7", + "_release": "1.5.1", "_resolution": { "type": "version", - "tag": "v1.4.7", - "commit": "411f216e1f407da9ef61047832b227c19ed47fab" + "tag": "v1.5.1", + "commit": "75ab103b838a966692cfb6cb3dc78c3b0f306eee" }, "_source": "git://github.com/stefanocudini/leaflet-search.git", "_target": "*", diff --git a/bower_components/leaflet-search/README.md b/bower_components/leaflet-search/README.md index 6e1cd54..08ed0fd 100644 --- a/bower_components/leaflet-search/README.md +++ b/bower_components/leaflet-search/README.md @@ -1,16 +1,17 @@ Leaflet.Control.Search ============ -#What -A leaflet control that search markers/features location by cutstom property. -With ajax/jsonp autocompletion and json fields re-mapping +A leaflet control that search markers/features location by custom property.
+With ajax/jsonp autocompletion and JSON fields filter/remap -Tested in Leaflet 0.6.4 +Copyright 2014 [Stefano Cudini](http://labs.easyblog.it/stefano-cudini/) + +Tested in Leaflet 0.7.2 #Where -**Demos:** +**Demo online:** [labs.easyblog.it/maps/leaflet-search](http://labs.easyblog.it/maps/leaflet-search/) **Source code:** @@ -19,36 +20,49 @@ Tested in Leaflet 0.6.4 [NPM](https://npmjs.org/package/leaflet-search) [Atmosphere](https://atmosphere.meteor.com/package/leaflet-search) -#How -Insert leaflet-search.css styles to your css page +#Build + +Since Version 1.4.7 this plugin support [Grunt](http://gruntjs.com/) for building process. +Therefore the deployment require [NPM](https://npmjs.org/) installed in your system. +After you've made sure to have npm working, run this in command line: +```bash +npm install +grunt +``` + +#Examples +(require src/leaflet-search.css) Adding the search control to the map: - -``` +```javascript map.addControl( new L.Control.Search({layer: searchLayer}) ); -//searchLayer if a L.LayerGroup contains searched markers -``` -short way: +//searchLayer is a L.LayerGroup contains searched markers ``` + +Short way: +```javascript var map = new L.Map('map', { searchControl: {layer: searchLayer} }); ``` -other examples: -``` -//ajax request to search.php for retrieve elements locations +#Advanced Examples + +Ajax request to search.php for retrieve elements locations: +```javascript map.addControl( new L.Control.Search({url: 'search.php?q={s}'}) ); +``` - -//jsonp request to 3rd party service, implements Geocode Searching using OSM API +Request to third party JSONP service, implements Geocode Searching using OSM API: +```javascript map.addControl( new L.Control.Search({ url: 'http://nominatim.openstreetmap.org/search?format=json&q={s}', jsonpParam: 'json_callback', propertyName: 'display_name', propertyLoc: ['lat','lon'] }) ); +``` - -//geojson layer, search and color feature vector +Search and color features vector in GeoJSON layer: +```javascript var searchControl = new L.Control.Search({layer: geojsonLayer, circleLocation:false}); searchControl.on('search_locationfound', function(e) { @@ -63,3 +77,22 @@ searchControl.on('search_locationfound', function(e) { map.addControl(searchControl); ``` +Static data source: +``` +var data = [ + {"loc":[41.575330,13.102411], "title":"aquamarine"}, + {"loc":[41.575730,13.002411], "title":"black"}, + {"loc":[41.219190,13.062145], "title":"cyan"} +]; + +map.addControl(new L.Control.Search({ + markerLocation: true, + callData: function(text, callResponse) { + + //here can use custom criteria or merge data from multiple layers + + callResponse(data); + } +}) ); +``` + diff --git a/bower_components/leaflet-search/TODO b/bower_components/leaflet-search/TODO index cbd61ac..b3585e0 100644 --- a/bower_components/leaflet-search/TODO +++ b/bower_components/leaflet-search/TODO @@ -1,27 +1,59 @@ Tasks found in: src/leaflet-search.js [Line: 22] [low] //TODO important! implements uniq option 'sourceData' that recognizes source type: url,array,callback or layer [Line: 23] [low] //TODO implement can do research on multiple sources - [Line: 26] [low] //TODO implement sub property filter for propertyName,propertyLoc like this: "prop.subprop.title" + [Line: 38] [low] //TODO add option for persist markerLoc after collapse! + [Line: 48] [low] //TODO add option collapsed, like control.layers + [Line: 53] [low] //TODO important optimization!!! always append data in this._recordsCache + [Line: 57] [low] //TODO here insert function that search inputText FIRST in _recordsCache keys and if not find results.. + [Line: 60] [low] //TODO change structure of _recordsCache + [Line: 342] [low] //TODO add option for case sesitive search, also showLocation + [Line: 345] [low] //TODO use .filter or .map + [Line: 407] [low] //TODO throw new Error("propertyName '"+propName+"' not found in JSON data"); + [Line: 412] [low] //TODO remove script node after call run + [Line: 421] [low] //TODO add rnd param or randomize callback name! in recordsFromJsonp + [Line: 441] [low] //TODO add rnd param or randomize callback name! in recordsFromAjax + [Line: 504] [low] //TODO implements autype without selection(useful for mobile device) + [Line: 604] [low] //TODO important optimization!!! always append data in this._recordsCache + [Line: 608] [low] //TODO here insert function that search inputText FIRST in _recordsCache keys and if not find results.. + [Line: 611] [low] //TODO change structure of _recordsCache + [Line: 662] [low] //TODO refact _handleAutoresize now is not accurate + [Line: 758] [low] //TODO showLocation: start animation after setView or panTo, maybe with map.on('moveend')... + [Line: 779] [low] //TODO add custom icon! + [Line: 787] [low] //TODO add inner circle + [Line: 843] [low] //TODO refact animate() more smooth! like this: http://goo.gl/DDlRs + [Line: 865] [low] //TODO use create event 'animateEnd' in SearchMarker + [Line: 50] [med] //FIXME option condition problem {autoCollapse: true, markerLocation: true} not show location + [Line: 51] [med] //FIXME option condition problem {autoCollapse: false } + [Line: 358] [med] //FIXME problem with jsonp/ajax when remote filter has different behavior of this._filterRecords + [Line: 731] [med] //FIXME if collapse in _handleSubmit hide _markerLoc! + [Line: 761] [med] //FIXME autoCollapse option hide this._markerLoc before that visualized!! +Tasks found in: src/leaflet-search_collapsed.js + [Line: 22] [low] //TODO important! implements uniq option 'sourceData' that recognizes source type: url,array,callback or layer + [Line: 23] [low] //TODO implement can do research on multiple sources [Line: 37] [low] //TODO add option for persist markerLoc after collapse! [Line: 47] [low] //TODO add option collapsed, like control.layers - [Line: 296] [low] //TODO add option for case sesitive search, also showLocation - [Line: 299] [low] //TODO use .filter or .map - [Line: 361] [low] //TODO verify json[n].hasOwnProperty(propName) - [Line: 367] [low] //TODO remove script node after call run - [Line: 376] [low] //TODO add rnd param or randomize callback name! in recordsFromJsonp - [Line: 396] [low] //TODO add rnd param or randomize callback name! in recordsFromAjax - [Line: 458] [low] //TODO implements autype without selection(useful for mobile device) - [Line: 558] [low] //TODO important optimization!!! always append data in this._recordsCache - [Line: 562] [low] //TODO here insert function that search inputText FIRST in _recordsCache keys and if not find results.. - [Line: 565] [low] //TODO change structure of _recordsCache - [Line: 616] [low] //TODO refact _handleAutoresize now is not accurate - [Line: 712] [low] //TODO showLocation: start animation after setView or panTo, maybe with map.on('moveend')... - [Line: 733] [low] //TODO add custom icon! - [Line: 741] [low] //TODO add inner circle - [Line: 797] [low] //TODO refact animate() more smooth! like this: http://goo.gl/DDlRs - [Line: 819] [low] //TODO use create event 'animateEnd' in SearchMarker + [Line: 52] [low] //TODO important optimization!!! always append data in this._recordsCache + [Line: 56] [low] //TODO here insert function that search inputText FIRST in _recordsCache keys and if not find results.. + [Line: 59] [low] //TODO change structure of _recordsCache + [Line: 87] [low] // TODO: touch + [Line: 358] [low] //TODO add option for case sesitive search, also showLocation + [Line: 361] [low] //TODO use .filter or .map + [Line: 423] [low] //TODO throw new Error("propertyName '"+propName+"' not found in JSON data"); + [Line: 428] [low] //TODO remove script node after call run + [Line: 437] [low] //TODO add rnd param or randomize callback name! in recordsFromJsonp + [Line: 457] [low] //TODO add rnd param or randomize callback name! in recordsFromAjax + [Line: 520] [low] //TODO implements autype without selection(useful for mobile device) + [Line: 620] [low] //TODO important optimization!!! always append data in this._recordsCache + [Line: 624] [low] //TODO here insert function that search inputText FIRST in _recordsCache keys and if not find results.. + [Line: 627] [low] //TODO change structure of _recordsCache + [Line: 678] [low] //TODO refact _handleAutoresize now is not accurate + [Line: 774] [low] //TODO showLocation: start animation after setView or panTo, maybe with map.on('moveend')... + [Line: 795] [low] //TODO add custom icon! + [Line: 803] [low] //TODO add inner circle + [Line: 859] [low] //TODO refact animate() more smooth! like this: http://goo.gl/DDlRs + [Line: 881] [low] //TODO use create event 'animateEnd' in SearchMarker [Line: 49] [med] //FIXME option condition problem {autoCollapse: true, markerLocation: true} not show location [Line: 50] [med] //FIXME option condition problem {autoCollapse: false } - [Line: 312] [med] //FIXME problem with jsonp/ajax when remote filter has different behavior of this._filterRecords - [Line: 685] [med] //FIXME if collapse in _handleSubmit hide _markerLoc! - [Line: 715] [med] //FIXME autoCollapse option hide this._markerLoc before that visualized!! + [Line: 374] [med] //FIXME problem with jsonp/ajax when remote filter has different behavior of this._filterRecords + [Line: 747] [med] //FIXME if collapse in _handleSubmit hide _markerLoc! + [Line: 777] [med] //FIXME autoCollapse option hide this._markerLoc before that visualized!! diff --git a/bower_components/leaflet-search/bower.json b/bower_components/leaflet-search/bower.json index f7568c1..e9fac8b 100644 --- a/bower_components/leaflet-search/bower.json +++ b/bower_components/leaflet-search/bower.json @@ -1,6 +1,6 @@ { "name": "leaflet-search", - "version": "1.4.6", + "version": "1.5.1", "main": "leaflet-search.js", "ignore": [ "**/.*", diff --git a/bower_components/leaflet-search/dist/leaflet-search.min.css b/bower_components/leaflet-search/dist/leaflet-search.min.css index 46e35a3..194352c 100644 --- a/bower_components/leaflet-search/dist/leaflet-search.min.css +++ b/bower_components/leaflet-search/dist/leaflet-search.min.css @@ -1,5 +1,5 @@ /* - * Leaflet Search Control v1.4.7 - 2014-01-04 + * Leaflet Search Control v1.5.1 - 2014-05-12 * * Copyright 2014 Stefano Cudini * stefano.cudini@gmail.com diff --git a/bower_components/leaflet-search/dist/leaflet-search.min.js b/bower_components/leaflet-search/dist/leaflet-search.min.js index 37b57da..e375541 100644 --- a/bower_components/leaflet-search/dist/leaflet-search.min.js +++ b/bower_components/leaflet-search/dist/leaflet-search.min.js @@ -1,5 +1,5 @@ /* - * Leaflet Search Control v1.4.7 - 2014-01-04 + * Leaflet Search Control v1.5.1 - 2014-05-12 * * Copyright 2014 Stefano Cudini * stefano.cudini@gmail.com @@ -14,4 +14,4 @@ * git@github.com:stefanocudini/leaflet-search.git * */ -(function(){L.Control.Search=L.Control.extend({includes:L.Mixin.Events,options:{url:"",jsonpParam:null,layer:null,callData:null,propertyName:"title",propertyLoc:"loc",callTip:null,filterJSON:null,minLength:1,initial:!0,autoType:!0,delayType:400,tooltipLimit:-1,tipAutoSubmit:!0,autoResize:!0,autoCollapse:!1,autoCollapseTime:1200,animateLocation:!0,circleLocation:!0,markerLocation:!1,zoom:null,text:"Search...",textCancel:"Cancel",textErr:"Location not found",position:"topleft"},initialize:function(a){L.Util.setOptions(this,a||{}),this._inputMinSize=this.options.text?this.options.text.length:10,this._layer=this.options.layer||new L.LayerGroup,this._filterJSON=this.options.filterJSON||this._defaultFilterJSON,this._autoTypeTmp=this.options.autoType,this._countertips=0,this._recordsCache={}},onAdd:function(b){return this._map=b,this._container=L.DomUtil.create("div","leaflet-control-search"),this._input=this._createInput(this.options.text,"search-input"),this._tooltip=this._createTooltip("search-tooltip"),this._cancel=this._createCancel(this.options.textCancel,"search-cancel"),this._button=this._createButton(this.options.text,"search-button"),this._alert=this._createAlert("search-alert"),(this.options.circleLocation||this.options.markerLocation)&&(this._markerLoc=new a([0,0],{marker:this.options.markerLocation})),this.setLayer(this._layer),b.on({resize:this._handleAutoresize},this),this._container},onRemove:function(){this._recordsCache={}},setLayer:function(a){return this._layer=a,this._layer.addTo(this._map),this._markerLoc&&this._layer.addLayer(this._markerLoc),this},showAlert:function(a){a=a||this.options.textErr,this._alert.style.display="block",this._alert.innerHTML=a,clearTimeout(this.timerAlert);var b=this;return this.timerAlert=setTimeout(function(){b.hideAlert()},this.options.autoCollapseTime),this},hideAlert:function(){return this._alert.style.display="none",this},cancel:function(){return this._input.value="",this._handleKeypress({keyCode:8}),this._input.size=this._inputMinSize,this._input.focus(),this._cancel.style.display="none",this},expand:function(){return this._input.style.display="block",L.DomUtil.addClass(this._container,"search-exp"),this._input.focus(),this._map.on("dragstart",this.collapse,this),this},collapse:function(){return this._hideTooltip(),this.cancel(),this._alert.style.display="none",this._input.style.display="none",this._input.blur(),this._cancel.style.display="none",L.DomUtil.removeClass(this._container,"search-exp"),this._map.off("dragstart",this.collapse,this),this.fire("search_collapsed"),this},collapseDelayed:function(){if(!this.options.autoCollapse)return this;var a=this;return clearTimeout(this.timerCollapse),this.timerCollapse=setTimeout(function(){a.collapse()},this.options.autoCollapseTime),this},collapseDelayedStop:function(){return clearTimeout(this.timerCollapse),this},_createAlert:function(a){var b=L.DomUtil.create("div",a,this._container);return b.style.display="none",L.DomEvent.on(b,"click",L.DomEvent.stop,this).on(b,"click",this.hideAlert,this),b},_createInput:function(a,b){var c=L.DomUtil.create("input",b,this._container);return c.type="text",c.size=this._inputMinSize,c.value="",c.autocomplete="off",c.placeholder=a,c.style.display="none",L.DomEvent.disableClickPropagation(c).on(c,"keyup",this._handleKeypress,this).on(c,"keydown",this._handleAutoresize,this).on(c,"blur",this.collapseDelayed,this).on(c,"focus",this.collapseDelayedStop,this),c},_createCancel:function(a,b){var c=L.DomUtil.create("a",b,this._container);return c.href="#",c.title=a,c.style.display="none",c.innerHTML="",L.DomEvent.on(c,"click",L.DomEvent.stop,this).on(c,"click",this.cancel,this),c},_createButton:function(a,b){var c=L.DomUtil.create("a",b,this._container);return c.href="#",c.title=a,L.DomEvent.on(c,"click",L.DomEvent.stop,this).on(c,"click",this._handleSubmit,this).on(c,"focus",this.collapseDelayedStop,this).on(c,"blur",this.collapseDelayed,this),c},_createTooltip:function(a){var b=L.DomUtil.create("div",a,this._container);b.style.display="none";var c=this;return L.DomEvent.disableClickPropagation(b).on(b,"blur",this.collapseDelayed,this).on(b,"mousewheel",function(a){c.collapseDelayedStop(),L.DomEvent.stopPropagation(a)},this).on(b,"mouseover",function(){c.collapseDelayedStop()},this),b},_createTip:function(a,b){var c;if(this.options.callTip){if(c=this.options.callTip(a,b),"string"==typeof c){var d=L.DomUtil.create("div");d.innerHTML=c,c=d.firstChild}}else c=L.DomUtil.create("a",""),c.href="#",c.innerHTML=a;return L.DomUtil.addClass(c,"search-tip"),c._text=a,L.DomEvent.disableClickPropagation(c).on(c,"click",L.DomEvent.stop,this).on(c,"click",function(){this._input.value=a,this._handleAutoresize(),this._input.focus(),this._hideTooltip(),this.options.tipAutoSubmit&&this._handleSubmit()},this),c},_filterRecords:function(a){var b,c,d=new RegExp("^[.]$|[[]|()*]","g"),e={};a=a.replace(d,""),b=this.options.initial?"^":"",c=new RegExp(b+a,"i");for(var f in this._recordsCache)c.test(f)&&(e[f]=this._recordsCache[f]);return e},showTooltip:function(){var a,b;this._countertips=0,a=this.options.layer?this._filterRecords(this._input.value):this._recordsCache,this._tooltip.innerHTML="",this._tooltip.currentSelection=-1;for(var c in a){if(++this._countertips==this.options.tooltipLimit)break;b=this._createTip(c,a[c]),this._tooltip.appendChild(b)}return this._countertips>0?(this._tooltip.style.display="block",this._autoTypeTmp&&this._autoType(),this._autoTypeTmp=this.options.autoType):this._hideTooltip(),this._tooltip.scrollTop=0,this._countertips},_hideTooltip:function(){return this._tooltip.style.display="none",this._tooltip.innerHTML="",0},_defaultFilterJSON:function(a){var b={},c=this.options.propertyName,d=this.options.propertyLoc;if(L.Util.isArray(d))for(var e in a)b[a[e][c]]=L.latLng(a[e][d[0]],a[e][d[1]]);else for(var f in a)b[a[f][c]]=L.latLng(a[f][d]);return b},_recordsFromJsonp:function(a,b){var c=this;L.Control.Search.callJsonp=function(a){var d=c._filterJSON(a);b(d)};var d=L.DomUtil.create("script","search-jsonp",document.getElementsByTagName("body")[0]),e=L.Util.template(this.options.url+"&"+this.options.jsonpParam+"=L.Control.Search.callJsonp",{s:a});return d.type="text/javascript",d.src=e,this},_recordsFromAjax:function(a,b){void 0===window.XMLHttpRequest&&(window.XMLHttpRequest=function(){try{return new ActiveXObject("Microsoft.XMLHTTP.6.0")}catch(a){try{return new ActiveXObject("Microsoft.XMLHTTP.3.0")}catch(b){throw new Error("XMLHttpRequest is not supported")}}});var c=new XMLHttpRequest,d=L.Util.template(this.options.url,{s:a}),e={};c.open("GET",d);var f=this;return c.onreadystatechange=function(){if(4===c.readyState&&200===c.status){e=JSON.parse(c.responseText);var a=f._filterJSON(e);b(a)}},c.send(),this},_recordsFromLayer:function(){var b,c={},d=this.options.propertyName;return this._layer.eachLayer(function(e){e instanceof a||(e instanceof L.Marker?e.options.hasOwnProperty(d)?(b=e.getLatLng(),b.layer=e,c[e.options[d]]=b):e.feature.properties.hasOwnProperty(d)?(b=e.getLatLng(),b.layer=e,c[e.feature.properties[d]]=b):console.log("propertyName '"+d+"' not found in marker",e):e.hasOwnProperty("feature")&&(e.feature.properties.hasOwnProperty(d)?(b=e.getBounds().getCenter(),b.layer=e,c[e.feature.properties[d]]=b):console.log("propertyName '"+d+"' not found in feature",e)))},this),c},_autoType:function(){var a=this._input.value.length,b=this._tooltip.firstChild._text,c=b.length;if(0===b.indexOf(this._input.value))if(this._input.value=b,this._handleAutoresize(),this._input.createTextRange){var d=this._input.createTextRange();d.collapse(!0),d.moveStart("character",a),d.moveEnd("character",c),d.select()}else this._input.setSelectionRange?this._input.setSelectionRange(a,c):this._input.selectionStart&&(this._input.selectionStart=a,this._input.selectionEnd=c)},_hideAutoType:function(){var a;if((a=this._input.selection)&&a.empty)a.empty();else if(this._input.createTextRange){a=this._input.createTextRange(),a.collapse(!0);var b=this._input.value.length;a.moveStart("character",b),a.moveEnd("character",b),a.select()}else this._input.getSelection&&this._input.getSelection().removeAllRanges(),this._input.selectionStart=this._input.selectionEnd},_handleKeypress:function(a){switch(a.keyCode){case 27:this.collapse();break;case 13:1==this._countertips&&this._handleArrowSelect(1),this._handleSubmit();break;case 38:this._handleArrowSelect(-1);break;case 40:this._handleArrowSelect(1);break;case 37:case 39:case 16:case 17:break;case 8:case 46:this._autoTypeTmp=!1;break;default:if(this._cancel.style.display=this._input.value.length?"block":"none",this._input.value.length>=this.options.minLength){var b=this;clearTimeout(this.timerKeypress),this.timerKeypress=setTimeout(function(){b._fillRecordsCache()},this.options.delayType)}else this._hideTooltip()}},_fillRecordsCache:function(){var a,b=this._input.value;L.DomUtil.addClass(this._container,"search-load"),this.options.callData?(a=this,this.options.callData(b,function(b){a._recordsCache=a._filterJSON(b),a.showTooltip(),L.DomUtil.removeClass(a._container,"search-load")})):this.options.url?this.options.jsonpParam?(a=this,this._recordsFromJsonp(b,function(b){a._recordsCache=b,a.showTooltip(),L.DomUtil.removeClass(a._container,"search-load")})):(a=this,this._recordsFromAjax(b,function(b){a._recordsCache=b,a.showTooltip(),L.DomUtil.removeClass(a._container,"search-load")})):this.options.layer&&(this._recordsCache=this._recordsFromLayer(),this.showTooltip(),L.DomUtil.removeClass(this._container,"search-load"))},_handleAutoresize:function(){this._input.style.maxWidth!=this._map._container.offsetWidth&&(this._input.style.maxWidth=L.DomUtil.getStyle(this._map._container,"width")),this.options.autoResize&&this._container.offsetWidth+45=b.length-1)L.DomUtil.addClass(b[this._tooltip.currentSelection],"search-tip-select");else if(-1==a&&this._tooltip.currentSelection<=0)this._tooltip.currentSelection=-1;else if("none"!=this._tooltip.style.display){this._tooltip.currentSelection+=a,L.DomUtil.addClass(b[this._tooltip.currentSelection],"search-tip-select"),this._input.value=b[this._tooltip.currentSelection]._text;var c=b[this._tooltip.currentSelection].offsetTop;c+b[this._tooltip.currentSelection].clientHeight>=this._tooltip.scrollTop+this._tooltip.clientHeight?this._tooltip.scrollTop=c-this._tooltip.clientHeight+b[this._tooltip.currentSelection].clientHeight:c<=this._tooltip.scrollTop&&(this._tooltip.scrollTop=c)}},_handleSubmit:function(){if(this._hideAutoType(),this.hideAlert(),this._hideTooltip(),"none"==this._input.style.display)this.expand();else if(""===this._input.value)this.collapse();else{var a=this._getLocation(this._input.value);a===!1?this.showAlert():(this.showLocation(a,this._input.value),this.fire("search_locationfound",{latlng:a,text:this._input.value,layer:a.layer?a.layer:null}))}},_getLocation:function(a){return this._recordsCache.hasOwnProperty(a)?this._recordsCache[a]:!1},showLocation:function(a,b){return this.options.zoom?this._map.setView(a,this.options.zoom):this._map.panTo(a),this._markerLoc&&(this._markerLoc.setLatLng(a),this._markerLoc.setTitle(b),this._markerLoc.show(),this.options.animateLocation&&this._markerLoc.animate()),this.options.autoCollapse&&this.collapse(),this}});var a=L.Marker.extend({includes:L.Mixin.Events,options:{radius:10,weight:3,color:"#e03",stroke:!0,fill:!1,title:"",marker:!1},initialize:function(a,b){L.setOptions(this,b),L.Marker.prototype.initialize.call(this,a,b),this._circleLoc=new L.CircleMarker(a,this.options)},onAdd:function(a){L.Marker.prototype.onAdd.call(this,a),a.addLayer(this._circleLoc),this.hide()},onRemove:function(a){L.Marker.prototype.onRemove.call(this,a),a.removeLayer(this._circleLoc)},setLatLng:function(a){return L.Marker.prototype.setLatLng.call(this,a),this._circleLoc.setLatLng(a),this},setTitle:function(a){return a=a||"",this.options.title=a,this._icon&&(this._icon.title=a),this},show:function(){return this.options.marker&&(this._icon&&(this._icon.style.display="block"),this._shadow&&(this._shadow.style.display="block")),this._circleLoc&&this._circleLoc.setStyle({fill:this.options.fill,stroke:this.options.stroke}),this},hide:function(){return this._icon&&(this._icon.style.display="none"),this._shadow&&(this._shadow.style.display="none"),this._circleLoc&&this._circleLoc.setStyle({fill:!1,stroke:!1}),this},animate:function(){var a=this._circleLoc,b=200,c=10,d=parseInt(a._radius/c),e=this.options.radius,f=2.5*a._radius,g=0;return a._timerAnimLoc=setInterval(function(){g+=.5,d+=g,f-=d,a.setRadius(f),e>f&&(clearInterval(a._timerAnimLoc),a.setRadius(e))},b),this}});L.Map.addInitHook(function(){this.options.searchControl&&(this.searchControl=L.control.search(this.options.searchControl),this.addControl(this.searchControl))}),L.control.search=function(a){return new L.Control.Search(a)}}).call(this); \ No newline at end of file +(function(){L.Control.Search=L.Control.extend({includes:L.Mixin.Events,options:{wrapper:"",url:"",jsonpParam:null,layer:null,callData:null,propertyName:"title",propertyLoc:"loc",callTip:null,filterJSON:null,minLength:1,initial:!0,autoType:!0,delayType:400,tooltipLimit:-1,tipAutoSubmit:!0,autoResize:!0,collapsed:!0,autoCollapse:!1,autoCollapseTime:1200,animateLocation:!0,circleLocation:!0,markerLocation:!1,zoom:null,text:"Search...",textCancel:"Cancel",textErr:"Location not found",position:"topleft"},initialize:function(a){L.Util.setOptions(this,a||{}),this._inputMinSize=this.options.text?this.options.text.length:10,this._layer=this.options.layer||new L.LayerGroup,this._filterJSON=this.options.filterJSON||this._defaultFilterJSON,this._autoTypeTmp=this.options.autoType,this._countertips=0,this._recordsCache={}},onAdd:function(b){return this._map=b,this._container=L.DomUtil.create("div","leaflet-control-search"),this._input=this._createInput(this.options.text,"search-input"),this._tooltip=this._createTooltip("search-tooltip"),this._cancel=this._createCancel(this.options.textCancel,"search-cancel"),this._button=this._createButton(this.options.text,"search-button"),this._alert=this._createAlert("search-alert"),this.options.collapsed===!1&&this.expand(),(this.options.circleLocation||this.options.markerLocation)&&(this._markerLoc=new a([0,0],{marker:this.options.markerLocation})),this.setLayer(this._layer),b.on({resize:this._handleAutoresize},this),this._container},addTo:function(a){return this.options.wrapper?(this._container=this.onAdd(a),this._wrapper=L.DomUtil.get(this.options.wrapper),this._wrapper.style.position="relative",this._wrapper.appendChild(this._container)):L.Control.prototype.addTo.call(this,a),this},onRemove:function(){this._recordsCache={}},_getPath:function(a,b){var c=b.split("."),d=c.pop(),e=c.length,f=c[0],g=1;if(e>0)for(;(a=a[f])&&e>g;)f=c[g++];return a?a[d]:void 0},setLayer:function(a){return this._layer=a,this._layer.addTo(this._map),this._markerLoc&&this._layer.addLayer(this._markerLoc),this},showAlert:function(a){a=a||this.options.textErr,this._alert.style.display="block",this._alert.innerHTML=a,clearTimeout(this.timerAlert);var b=this;return this.timerAlert=setTimeout(function(){b.hideAlert()},this.options.autoCollapseTime),this},hideAlert:function(){return this._alert.style.display="none",this},cancel:function(){return this._input.value="",this._handleKeypress({keyCode:8}),this._input.size=this._inputMinSize,this._input.focus(),this._cancel.style.display="none",this},expand:function(){return this._input.style.display="block",L.DomUtil.addClass(this._container,"search-exp"),this._input.focus(),this._map.on("dragstart",this.collapse,this),this},collapse:function(){return this._hideTooltip(),this.cancel(),this._alert.style.display="none",this._input.blur(),this.options.collapsed&&(this._input.style.display="none",this._cancel.style.display="none",L.DomUtil.removeClass(this._container,"search-exp"),this._map.off("dragstart",this.collapse,this)),this.fire("search_collapsed"),this},collapseDelayed:function(){if(!this.options.autoCollapse)return this;var a=this;return clearTimeout(this.timerCollapse),this.timerCollapse=setTimeout(function(){a.collapse()},this.options.autoCollapseTime),this},collapseDelayedStop:function(){return clearTimeout(this.timerCollapse),this},_createAlert:function(a){var b=L.DomUtil.create("div",a,this._container);return b.style.display="none",L.DomEvent.on(b,"click",L.DomEvent.stop,this).on(b,"click",this.hideAlert,this),b},_createInput:function(a,b){var c=L.DomUtil.create("input",b,this._container);return c.type="text",c.size=this._inputMinSize,c.value="",c.autocomplete="off",c.placeholder=a,c.style.display="none",L.DomEvent.disableClickPropagation(c).on(c,"keyup",this._handleKeypress,this).on(c,"keydown",this._handleAutoresize,this).on(c,"blur",this.collapseDelayed,this).on(c,"focus",this.collapseDelayedStop,this),c},_createCancel:function(a,b){var c=L.DomUtil.create("a",b,this._container);return c.href="#",c.title=a,c.style.display="none",c.innerHTML="",L.DomEvent.on(c,"click",L.DomEvent.stop,this).on(c,"click",this.cancel,this),c},_createButton:function(a,b){var c=L.DomUtil.create("a",b,this._container);return c.href="#",c.title=a,L.DomEvent.on(c,"click",L.DomEvent.stop,this).on(c,"click",this._handleSubmit,this).on(c,"focus",this.collapseDelayedStop,this).on(c,"blur",this.collapseDelayed,this),c},_createTooltip:function(a){var b=L.DomUtil.create("div",a,this._container);b.style.display="none";var c=this;return L.DomEvent.disableClickPropagation(b).on(b,"blur",this.collapseDelayed,this).on(b,"mousewheel",function(a){c.collapseDelayedStop(),L.DomEvent.stopPropagation(a)},this).on(b,"mouseover",function(){c.collapseDelayedStop()},this),b},_createTip:function(a,b){var c;if(this.options.callTip){if(c=this.options.callTip(a,b),"string"==typeof c){var d=L.DomUtil.create("div");d.innerHTML=c,c=d.firstChild}}else c=L.DomUtil.create("a",""),c.href="#",c.innerHTML=a;return L.DomUtil.addClass(c,"search-tip"),c._text=a,L.DomEvent.disableClickPropagation(c).on(c,"click",L.DomEvent.stop,this).on(c,"click",function(){this._input.value=a,this._handleAutoresize(),this._input.focus(),this._hideTooltip(),this.options.tipAutoSubmit&&this._handleSubmit()},this),c},_filterRecords:function(a){var b,c,d=new RegExp("^[.]$|[[]|()*]","g"),e={};a=a.replace(d,""),b=this.options.initial?"^":"",c=new RegExp(b+a,"i");for(var f in this._recordsCache)c.test(f)&&(e[f]=this._recordsCache[f]);return e},showTooltip:function(){var a,b;this._countertips=0,a=this.options.layer?this._filterRecords(this._input.value):this._recordsCache,this._tooltip.innerHTML="",this._tooltip.currentSelection=-1;for(var c in a){if(++this._countertips==this.options.tooltipLimit)break;b=this._createTip(c,a[c]),this._tooltip.appendChild(b)}return this._countertips>0?(this._tooltip.style.display="block",this._autoTypeTmp&&this._autoType(),this._autoTypeTmp=this.options.autoType):this._hideTooltip(),this._tooltip.scrollTop=0,this._countertips},_hideTooltip:function(){return this._tooltip.style.display="none",this._tooltip.innerHTML="",0},_defaultFilterJSON:function(a){var b,c={},d=this.options.propertyName,e=this.options.propertyLoc;if(L.Util.isArray(e))for(b in a)c[this._getPath(a[b],d)]=L.latLng(a[b][e[0]],a[b][e[1]]);else for(b in a)c[this._getPath(a[b],d)]=L.latLng(this._getPath(a[b],e));return c},_recordsFromJsonp:function(a,b){var c=this;L.Control.Search.callJsonp=function(a){var d=c._filterJSON(a);b(d)};var d=L.DomUtil.create("script","search-jsonp",document.getElementsByTagName("body")[0]),e=L.Util.template(this.options.url+"&"+this.options.jsonpParam+"=L.Control.Search.callJsonp",{s:a});return d.type="text/javascript",d.src=e,this},_recordsFromAjax:function(a,b){void 0===window.XMLHttpRequest&&(window.XMLHttpRequest=function(){try{return new ActiveXObject("Microsoft.XMLHTTP.6.0")}catch(a){try{return new ActiveXObject("Microsoft.XMLHTTP.3.0")}catch(b){throw new Error("XMLHttpRequest is not supported")}}});var c=new XMLHttpRequest,d=L.Util.template(this.options.url,{s:a}),e={};c.open("GET",d);var f=this;return c.onreadystatechange=function(){if(4===c.readyState&&200===c.status){e=JSON.parse(c.responseText);var a=f._filterJSON(e);b(a)}},c.send(),this},_recordsFromLayer:function(){var b,c=this,d={},e=this.options.propertyName;return this._layer.eachLayer(function(f){f instanceof a||(f instanceof L.Marker?c._getPath(f.options,e)?(b=f.getLatLng(),b.layer=f,d[c._getPath(f.options,e)]=b):c._getPath(f.feature.properties,e)?(b=f.getLatLng(),b.layer=f,d[c._getPath(f.feature.properties,e)]=b):console.log("propertyName '"+e+"' not found in marker",f):f.hasOwnProperty("feature")&&(f.feature.properties.hasOwnProperty(e)?(b=f.getBounds().getCenter(),b.layer=f,d[f.feature.properties[e]]=b):console.log("propertyName '"+e+"' not found in feature",f)))},this),d},_autoType:function(){var a=this._input.value.length,b=this._tooltip.firstChild._text,c=b.length;if(0===b.indexOf(this._input.value))if(this._input.value=b,this._handleAutoresize(),this._input.createTextRange){var d=this._input.createTextRange();d.collapse(!0),d.moveStart("character",a),d.moveEnd("character",c),d.select()}else this._input.setSelectionRange?this._input.setSelectionRange(a,c):this._input.selectionStart&&(this._input.selectionStart=a,this._input.selectionEnd=c)},_hideAutoType:function(){var a;if((a=this._input.selection)&&a.empty)a.empty();else if(this._input.createTextRange){a=this._input.createTextRange(),a.collapse(!0);var b=this._input.value.length;a.moveStart("character",b),a.moveEnd("character",b),a.select()}else this._input.getSelection&&this._input.getSelection().removeAllRanges(),this._input.selectionStart=this._input.selectionEnd},_handleKeypress:function(a){switch(a.keyCode){case 27:this.collapse();break;case 13:1==this._countertips&&this._handleArrowSelect(1),this._handleSubmit();break;case 38:this._handleArrowSelect(-1);break;case 40:this._handleArrowSelect(1);break;case 37:case 39:case 16:case 17:break;case 8:case 46:this._autoTypeTmp=!1;break;default:if(this._cancel.style.display=this._input.value.length?"block":"none",this._input.value.length>=this.options.minLength){var b=this;clearTimeout(this.timerKeypress),this.timerKeypress=setTimeout(function(){b._fillRecordsCache()},this.options.delayType)}else this._hideTooltip()}},_fillRecordsCache:function(){var a,b=this._input.value;L.DomUtil.addClass(this._container,"search-load"),this.options.callData?(a=this,this.options.callData(b,function(b){a._recordsCache=a._filterJSON(b),a.showTooltip(),L.DomUtil.removeClass(a._container,"search-load")})):this.options.url?this.options.jsonpParam?(a=this,this._recordsFromJsonp(b,function(b){a._recordsCache=b,a.showTooltip(),L.DomUtil.removeClass(a._container,"search-load")})):(a=this,this._recordsFromAjax(b,function(b){a._recordsCache=b,a.showTooltip(),L.DomUtil.removeClass(a._container,"search-load")})):this.options.layer&&(this._recordsCache=this._recordsFromLayer(),this.showTooltip(),L.DomUtil.removeClass(this._container,"search-load"))},_handleAutoresize:function(){this._input.style.maxWidth!=this._map._container.offsetWidth&&(this._input.style.maxWidth=L.DomUtil.getStyle(this._map._container,"width")),this.options.autoResize&&this._container.offsetWidth+45=b.length-1)L.DomUtil.addClass(b[this._tooltip.currentSelection],"search-tip-select");else if(-1==a&&this._tooltip.currentSelection<=0)this._tooltip.currentSelection=-1;else if("none"!=this._tooltip.style.display){this._tooltip.currentSelection+=a,L.DomUtil.addClass(b[this._tooltip.currentSelection],"search-tip-select"),this._input.value=b[this._tooltip.currentSelection]._text;var c=b[this._tooltip.currentSelection].offsetTop;c+b[this._tooltip.currentSelection].clientHeight>=this._tooltip.scrollTop+this._tooltip.clientHeight?this._tooltip.scrollTop=c-this._tooltip.clientHeight+b[this._tooltip.currentSelection].clientHeight:c<=this._tooltip.scrollTop&&(this._tooltip.scrollTop=c)}},_handleSubmit:function(){if(this._hideAutoType(),this.hideAlert(),this._hideTooltip(),"none"==this._input.style.display)this.expand();else if(""===this._input.value)this.collapse();else{var a=this._getLocation(this._input.value);a===!1?this.showAlert():(this.showLocation(a,this._input.value),this.fire("search_locationfound",{latlng:a,text:this._input.value,layer:a.layer?a.layer:null}))}},_getLocation:function(a){return this._recordsCache.hasOwnProperty(a)?this._recordsCache[a]:!1},showLocation:function(a,b){return this.options.zoom?this._map.setView(a,this.options.zoom):this._map.panTo(a),this._markerLoc&&(this._markerLoc.setLatLng(a),this._markerLoc.setTitle(b),this._markerLoc.show(),this.options.animateLocation&&this._markerLoc.animate()),this.options.autoCollapse&&this.collapse(),this}});var a=L.Marker.extend({includes:L.Mixin.Events,options:{radius:10,weight:3,color:"#e03",stroke:!0,fill:!1,title:"",marker:!1},initialize:function(a,b){L.setOptions(this,b),L.Marker.prototype.initialize.call(this,a,b),this._circleLoc=new L.CircleMarker(a,this.options)},onAdd:function(a){L.Marker.prototype.onAdd.call(this,a),a.addLayer(this._circleLoc),this.hide()},onRemove:function(a){L.Marker.prototype.onRemove.call(this,a),a.removeLayer(this._circleLoc)},setLatLng:function(a){return L.Marker.prototype.setLatLng.call(this,a),this._circleLoc.setLatLng(a),this},setTitle:function(a){return a=a||"",this.options.title=a,this._icon&&(this._icon.title=a),this},show:function(){return this.options.marker&&(this._icon&&(this._icon.style.display="block"),this._shadow&&(this._shadow.style.display="block")),this._circleLoc&&this._circleLoc.setStyle({fill:this.options.fill,stroke:this.options.stroke}),this},hide:function(){return this._icon&&(this._icon.style.display="none"),this._shadow&&(this._shadow.style.display="none"),this._circleLoc&&this._circleLoc.setStyle({fill:!1,stroke:!1}),this},animate:function(){var a=this._circleLoc,b=200,c=10,d=parseInt(a._radius/c),e=this.options.radius,f=2.5*a._radius,g=0;return a._timerAnimLoc=setInterval(function(){g+=.5,d+=g,f-=d,a.setRadius(f),e>f&&(clearInterval(a._timerAnimLoc),a.setRadius(e))},b),this}});L.Map.addInitHook(function(){this.options.searchControl&&(this.searchControl=L.control.search(this.options.searchControl),this.addControl(this.searchControl))}),L.control.search=function(a){return new L.Control.Search(a)}}).call(this); \ No newline at end of file diff --git a/bower_components/leaflet-search/dist/leaflet-search.mobile.min.css b/bower_components/leaflet-search/dist/leaflet-search.mobile.min.css index 79dfd07..6adfa40 100644 --- a/bower_components/leaflet-search/dist/leaflet-search.mobile.min.css +++ b/bower_components/leaflet-search/dist/leaflet-search.mobile.min.css @@ -1,5 +1,5 @@ /* - * Leaflet Search Control v1.4.7 - 2014-01-04 + * Leaflet Search Control v1.5.1 - 2014-05-12 * * Copyright 2014 Stefano Cudini * stefano.cudini@gmail.com diff --git a/bower_components/leaflet-search/dist/leaflet-search.mobile.src.css b/bower_components/leaflet-search/dist/leaflet-search.mobile.src.css index 19aedd3..be556ab 100644 --- a/bower_components/leaflet-search/dist/leaflet-search.mobile.src.css +++ b/bower_components/leaflet-search/dist/leaflet-search.mobile.src.css @@ -1,5 +1,5 @@ /* - * Leaflet Search Control v1.4.7 - 2014-01-04 + * Leaflet Search Control v1.5.1 - 2014-05-12 * * Copyright 2014 Stefano Cudini * stefano.cudini@gmail.com diff --git a/bower_components/leaflet-search/dist/leaflet-search.src.css b/bower_components/leaflet-search/dist/leaflet-search.src.css index 1651c0a..ef08560 100644 --- a/bower_components/leaflet-search/dist/leaflet-search.src.css +++ b/bower_components/leaflet-search/dist/leaflet-search.src.css @@ -1,5 +1,5 @@ /* - * Leaflet Search Control v1.4.7 - 2014-01-04 + * Leaflet Search Control v1.5.1 - 2014-05-12 * * Copyright 2014 Stefano Cudini * stefano.cudini@gmail.com diff --git a/bower_components/leaflet-search/dist/leaflet-search.src.js b/bower_components/leaflet-search/dist/leaflet-search.src.js index 1bf93a3..6c7c1d1 100644 --- a/bower_components/leaflet-search/dist/leaflet-search.src.js +++ b/bower_components/leaflet-search/dist/leaflet-search.src.js @@ -1,5 +1,5 @@ /* - * Leaflet Search Control v1.4.7 - 2014-01-04 + * Leaflet Search Control v1.5.1 - 2014-05-12 * * Copyright 2014 Stefano Cudini * stefano.cudini@gmail.com @@ -14,32 +14,32 @@ * git@github.com:stefanocudini/leaflet-search.git * */ - (function() { L.Control.Search = L.Control.extend({ includes: L.Mixin.Events, // - // Name Data passed Description + // Name Data passed Description // //Managed Events: - // search_locationfound {latlng, title} fired after moved and show markerLocation - // search_collapsed {} fired after control was collapsed + // search_locationfound {latlng, title, layer} fired after moved and show markerLocation + // search_collapsed {} fired after control was collapsed // //Public methods: - // setLayer() L.LayerGroup() set layer search at runtime - // showAlert() 'Text message' Show alert message + // setLayer() L.LayerGroup() set layer search at runtime + // showAlert() 'Text message' Show alert message // options: { + wrapper: '', //container id to insert Search Control url: '', //url for search by ajax request, ex: "search.php?q={s}" jsonpParam: null, //jsonp param name for search by jsonp service, ex: "callback" layer: null, //layer where search markers(is a L.LayerGroup) callData: null, //function that fill _recordsCache, passed searching text by first param and callback in second //TODO important! implements uniq option 'sourceData' that recognizes source type: url,array,callback or layer //TODO implement can do research on multiple sources - propertyName: 'title', //property in marker.options(or feature.properties for vector layer) trough filter elements in layer - propertyLoc: 'loc', //field name for remapping location, using array: ['latname','lonname'] for select double fields(ex. ['lat','lon'] ) - //TODO implement sub property filter for propertyName,propertyLoc like this: "prop.subprop.title" + propertyName: 'title', //property in marker.options(or feature.properties for vector layer) trough filter elements in layer, + propertyLoc: 'loc', //field for remapping location, using array: ['latname','lonname'] for select double fields(ex. ['lat','lon'] ) + // support dotted format: 'prop.subprop.title' callTip: null, //function that return row tip html node(or html string), receive text tooltip in first param filterJSON: null, //callback for filtering data to _recordsCache minLength: 1, //minimal text length for autocomplete @@ -49,6 +49,7 @@ L.Control.Search = L.Control.extend({ tooltipLimit: -1, //limit max results to show in tooltip. -1 for no limit. tipAutoSubmit: true, //auto map panTo when click on tooltip autoResize: true, //autoresize on input change + collapsed: true, //collapse search control at startup autoCollapse: false, //collapse search control after submit(on button or on tips if enabled tipAutoSubmit) //TODO add option for persist markerLoc after collapse! autoCollapseTime: 1200, //delay for autoclosing alert and collapse after blur @@ -64,7 +65,18 @@ L.Control.Search = L.Control.extend({ }, //FIXME option condition problem {autoCollapse: true, markerLocation: true} not show location //FIXME option condition problem {autoCollapse: false } - +// +//TODO important optimization!!! always append data in this._recordsCache +// now _recordsCache content is emptied and replaced with new data founded +// always appending data on _recordsCache give the possibility of caching ajax, jsonp and layersearch! +// +//TODO here insert function that search inputText FIRST in _recordsCache keys and if not find results.. +// run one of callbacks search(callData,jsonpUrl or options.layer) and run this.showTooltip +// +//TODO change structure of _recordsCache +// like this: _recordsCache = {"text-key1": {loc:[lat,lng], ..other attributes.. }, {"text-key2": {loc:[lat,lng]}...}, ...} +// in this mode every record can have a free structure of attributes, only 'loc' is required + initialize: function(options) { L.Util.setOptions(this, options || {}); this._inputMinSize = this.options.text ? this.options.text.length : 10; @@ -83,7 +95,10 @@ L.Control.Search = L.Control.extend({ this._cancel = this._createCancel(this.options.textCancel, 'search-cancel'); this._button = this._createButton(this.options.text, 'search-button'); this._alert = this._createAlert('search-alert'); - + + if(this.options.collapsed===false) + this.expand(); + if(this.options.circleLocation || this.options.markerLocation) this._markerLoc = new SearchMarker([0,0], {marker: this.options.markerLocation});//see below @@ -91,10 +106,23 @@ L.Control.Search = L.Control.extend({ map.on({ // 'layeradd': this._onLayerAddRemove, // 'layerremove': this._onLayerAddRemove - 'resize':this._handleAutoresize() + 'resize': this._handleAutoresize }, this); return this._container; }, + addTo: function (map) { + + if(this.options.wrapper) { + this._container = this.onAdd(map); + this._wrapper = L.DomUtil.get(this.options.wrapper); + this._wrapper.style.position = 'relative'; + this._wrapper.appendChild(this._container); + } + else + L.Control.prototype.addTo.call(this, map); + + return this; + }, onRemove: function(map) { this._recordsCache = {}; @@ -111,7 +139,22 @@ L.Control.Search = L.Control.extend({ // if( L.stamp(e.layer) != L.stamp(this._layer) ) // this.setLayer(e.layer); // }, - + + _getPath: function(obj, prop) { + var parts = prop.split('.'), + last = parts.pop(), + len = parts.length, + cur = parts[0], + i = 1; + + if(len > 0) + while((obj = obj[cur]) && i < len) + cur = parts[i++]; + + if(obj) + return obj[last]; + }, + setLayer: function(layer) { //set search layer at runtime //this.options.layer = layer; //setting this, run only this._recordsFromLayer() this._layer = layer; @@ -147,7 +190,7 @@ L.Control.Search = L.Control.extend({ return this; }, - expand: function() { + expand: function() { this._input.style.display = 'block'; L.DomUtil.addClass(this._container, 'search-exp'); this._input.focus(); @@ -159,12 +202,15 @@ L.Control.Search = L.Control.extend({ this._hideTooltip(); this.cancel(); this._alert.style.display = 'none'; - this._input.style.display = 'none'; this._input.blur(); - this._cancel.style.display = 'none'; - L.DomUtil.removeClass(this._container, 'search-exp'); - //this._markerLoc.hide();//maybe unuseful - this._map.off('dragstart', this.collapse, this); + if(this.options.collapsed) + { + this._input.style.display = 'none'; + this._cancel.style.display = 'none'; + L.DomUtil.removeClass(this._container, 'search-exp'); + //this._markerLoc.hide();//maybe unuseful + this._map.off('dragstart', this.collapse, this); + } this.fire('search_collapsed'); return this; }, @@ -364,18 +410,17 @@ L.Control.Search = L.Control.extend({ }, _defaultFilterJSON: function(json) { //default callback for filter data - var jsonret = {}, + var jsonret = {}, i, propName = this.options.propertyName, propLoc = this.options.propertyLoc; if( L.Util.isArray(propLoc) ) - for(var i in json) - jsonret[ json[i][propName] ]= L.latLng( json[i][ propLoc[0] ], json[i][ propLoc[1] ] ); + for(i in json) + jsonret[ this._getPath(json[i],propName) ]= L.latLng( json[i][ propLoc[0] ], json[i][ propLoc[1] ] ); else - for(var n in json) - jsonret[ json[n][propName] ]= L.latLng( json[n][ propLoc ] ); - //TODO verify json[n].hasOwnProperty(propName) - //throw new Error("propertyName '"+propName+"' not found in JSON data"); + for(i in json) + jsonret[ this._getPath(json[i],propName) ]= L.latLng( this._getPath(json[i],propLoc) ); + //TODO throw new Error("propertyName '"+propName+"' not found in JSON data"); return jsonret; }, @@ -426,7 +471,8 @@ L.Control.Search = L.Control.extend({ }, _recordsFromLayer: function() { //return table: key,value from layer - var retRecords = {}, + var that = this, + retRecords = {}, propName = this.options.propertyName, loc; @@ -436,17 +482,17 @@ L.Control.Search = L.Control.extend({ if(layer instanceof L.Marker) { - if(layer.options.hasOwnProperty(propName)) + if(that._getPath(layer.options,propName)) { loc = layer.getLatLng(); loc.layer = layer; - retRecords[ layer.options[propName] ] = loc; + retRecords[ that._getPath(layer.options,propName) ] = loc; - }else if(layer.feature.properties.hasOwnProperty(propName)){ + }else if(that._getPath(layer.feature.properties,propName)){ loc = layer.getLatLng(); loc.layer = layer; - retRecords[ layer.feature.properties[propName] ] = loc; + retRecords[ that._getPath(layer.feature.properties,propName) ] = loc; }else{ console.log("propertyName '"+propName+"' not found in marker", layer); @@ -587,7 +633,7 @@ L.Control.Search = L.Control.extend({ L.DomUtil.addClass(this._container, 'search-load'); - if(this.options.callData) //CUSTOM SEARCH CALLBACK(USUALLY FOR AJAX SEARCHING) + if(this.options.callData) //CUSTOM SEARCH CALLBACK { that = this; this.options.callData(inputText, function(jsonraw) { @@ -837,7 +883,7 @@ var SearchMarker = L.Marker.extend({ }, tInt); return this; - } + } }); L.Map.addInitHook(function () { diff --git a/bower_components/leaflet-search/index.html b/bower_components/leaflet-search/index.html index 7617f48..e0a81ca 100644 --- a/bower_components/leaflet-search/index.html +++ b/bower_components/leaflet-search/index.html @@ -37,24 +37,26 @@
  • Customize tooltip menu
  • Many options to customize the behavior
  • Support search in features collection
  • +
  • Render Search Box Outside the Leaflet Map
  • diff --git a/bower_components/leaflet-search/package.json b/bower_components/leaflet-search/package.json index 4496e39..aec39c3 100644 --- a/bower_components/leaflet-search/package.json +++ b/bower_components/leaflet-search/package.json @@ -1,6 +1,6 @@ { "name": "leaflet-search", - "version": "1.4.7", + "version": "1.5.1", "description": "Leaflet Control for searching markers/features by attribute on map or remote searching in jsonp/ajax", "repository": { "type": "git", @@ -23,6 +23,7 @@ }, "devDependencies": { "grunt": "~0.4.2", + "grunt-cli": "~0.1.11", "grunt-contrib-uglify": "~0.2.7", "grunt-contrib-concat": "~0.3.0", "grunt-contrib-clean": "~0.5.0", diff --git a/bower_components/leaflet-search/smart.json b/bower_components/leaflet-search/smart.json index 2045685..03567b3 100644 --- a/bower_components/leaflet-search/smart.json +++ b/bower_components/leaflet-search/smart.json @@ -3,6 +3,6 @@ "description": "Leaflet Control for searching markers/features by attribute on map or remote searching in jsonp/ajax", "homepage": "http://labs.easyblog.it/maps/leaflet-search/", "author": "Stefano Cudini ", - "version": "1.4.7", + "version": "1.5.1", "git": "https://github.com/stefanocudini/leaflet-search.git" -} \ No newline at end of file +} diff --git a/bower_components/leaflet-search/src/leaflet-search.js b/bower_components/leaflet-search/src/leaflet-search.js index 4d603d3..538d7b4 100644 --- a/bower_components/leaflet-search/src/leaflet-search.js +++ b/bower_components/leaflet-search/src/leaflet-search.js @@ -1,29 +1,29 @@ - (function() { L.Control.Search = L.Control.extend({ includes: L.Mixin.Events, // - // Name Data passed Description + // Name Data passed Description // //Managed Events: - // search_locationfound {latlng, title} fired after moved and show markerLocation - // search_collapsed {} fired after control was collapsed + // search_locationfound {latlng, title, layer} fired after moved and show markerLocation + // search_collapsed {} fired after control was collapsed // //Public methods: - // setLayer() L.LayerGroup() set layer search at runtime - // showAlert() 'Text message' Show alert message + // setLayer() L.LayerGroup() set layer search at runtime + // showAlert() 'Text message' Show alert message // options: { + wrapper: '', //container id to insert Search Control url: '', //url for search by ajax request, ex: "search.php?q={s}" jsonpParam: null, //jsonp param name for search by jsonp service, ex: "callback" layer: null, //layer where search markers(is a L.LayerGroup) callData: null, //function that fill _recordsCache, passed searching text by first param and callback in second //TODO important! implements uniq option 'sourceData' that recognizes source type: url,array,callback or layer //TODO implement can do research on multiple sources - propertyName: 'title', //property in marker.options(or feature.properties for vector layer) trough filter elements in layer - propertyLoc: 'loc', //field name for remapping location, using array: ['latname','lonname'] for select double fields(ex. ['lat','lon'] ) - //TODO implement sub property filter for propertyName,propertyLoc like this: "prop.subprop.title" + propertyName: 'title', //property in marker.options(or feature.properties for vector layer) trough filter elements in layer, + propertyLoc: 'loc', //field for remapping location, using array: ['latname','lonname'] for select double fields(ex. ['lat','lon'] ) + // support dotted format: 'prop.subprop.title' callTip: null, //function that return row tip html node(or html string), receive text tooltip in first param filterJSON: null, //callback for filtering data to _recordsCache minLength: 1, //minimal text length for autocomplete @@ -33,6 +33,7 @@ L.Control.Search = L.Control.extend({ tooltipLimit: -1, //limit max results to show in tooltip. -1 for no limit. tipAutoSubmit: true, //auto map panTo when click on tooltip autoResize: true, //autoresize on input change + collapsed: true, //collapse search control at startup autoCollapse: false, //collapse search control after submit(on button or on tips if enabled tipAutoSubmit) //TODO add option for persist markerLoc after collapse! autoCollapseTime: 1200, //delay for autoclosing alert and collapse after blur @@ -48,7 +49,18 @@ L.Control.Search = L.Control.extend({ }, //FIXME option condition problem {autoCollapse: true, markerLocation: true} not show location //FIXME option condition problem {autoCollapse: false } - +// +//TODO important optimization!!! always append data in this._recordsCache +// now _recordsCache content is emptied and replaced with new data founded +// always appending data on _recordsCache give the possibility of caching ajax, jsonp and layersearch! +// +//TODO here insert function that search inputText FIRST in _recordsCache keys and if not find results.. +// run one of callbacks search(callData,jsonpUrl or options.layer) and run this.showTooltip +// +//TODO change structure of _recordsCache +// like this: _recordsCache = {"text-key1": {loc:[lat,lng], ..other attributes.. }, {"text-key2": {loc:[lat,lng]}...}, ...} +// in this mode every record can have a free structure of attributes, only 'loc' is required + initialize: function(options) { L.Util.setOptions(this, options || {}); this._inputMinSize = this.options.text ? this.options.text.length : 10; @@ -67,7 +79,10 @@ L.Control.Search = L.Control.extend({ this._cancel = this._createCancel(this.options.textCancel, 'search-cancel'); this._button = this._createButton(this.options.text, 'search-button'); this._alert = this._createAlert('search-alert'); - + + if(this.options.collapsed===false) + this.expand(); + if(this.options.circleLocation || this.options.markerLocation) this._markerLoc = new SearchMarker([0,0], {marker: this.options.markerLocation});//see below @@ -75,10 +90,23 @@ L.Control.Search = L.Control.extend({ map.on({ // 'layeradd': this._onLayerAddRemove, // 'layerremove': this._onLayerAddRemove - 'resize':this._handleAutoresize() + 'resize': this._handleAutoresize }, this); return this._container; }, + addTo: function (map) { + + if(this.options.wrapper) { + this._container = this.onAdd(map); + this._wrapper = L.DomUtil.get(this.options.wrapper); + this._wrapper.style.position = 'relative'; + this._wrapper.appendChild(this._container); + } + else + L.Control.prototype.addTo.call(this, map); + + return this; + }, onRemove: function(map) { this._recordsCache = {}; @@ -95,7 +123,22 @@ L.Control.Search = L.Control.extend({ // if( L.stamp(e.layer) != L.stamp(this._layer) ) // this.setLayer(e.layer); // }, - + + _getPath: function(obj, prop) { + var parts = prop.split('.'), + last = parts.pop(), + len = parts.length, + cur = parts[0], + i = 1; + + if(len > 0) + while((obj = obj[cur]) && i < len) + cur = parts[i++]; + + if(obj) + return obj[last]; + }, + setLayer: function(layer) { //set search layer at runtime //this.options.layer = layer; //setting this, run only this._recordsFromLayer() this._layer = layer; @@ -131,7 +174,7 @@ L.Control.Search = L.Control.extend({ return this; }, - expand: function() { + expand: function() { this._input.style.display = 'block'; L.DomUtil.addClass(this._container, 'search-exp'); this._input.focus(); @@ -143,12 +186,15 @@ L.Control.Search = L.Control.extend({ this._hideTooltip(); this.cancel(); this._alert.style.display = 'none'; - this._input.style.display = 'none'; this._input.blur(); - this._cancel.style.display = 'none'; - L.DomUtil.removeClass(this._container, 'search-exp'); - //this._markerLoc.hide();//maybe unuseful - this._map.off('dragstart', this.collapse, this); + if(this.options.collapsed) + { + this._input.style.display = 'none'; + this._cancel.style.display = 'none'; + L.DomUtil.removeClass(this._container, 'search-exp'); + //this._markerLoc.hide();//maybe unuseful + this._map.off('dragstart', this.collapse, this); + } this.fire('search_collapsed'); return this; }, @@ -348,18 +394,17 @@ L.Control.Search = L.Control.extend({ }, _defaultFilterJSON: function(json) { //default callback for filter data - var jsonret = {}, + var jsonret = {}, i, propName = this.options.propertyName, propLoc = this.options.propertyLoc; if( L.Util.isArray(propLoc) ) - for(var i in json) - jsonret[ json[i][propName] ]= L.latLng( json[i][ propLoc[0] ], json[i][ propLoc[1] ] ); + for(i in json) + jsonret[ this._getPath(json[i],propName) ]= L.latLng( json[i][ propLoc[0] ], json[i][ propLoc[1] ] ); else - for(var n in json) - jsonret[ json[n][propName] ]= L.latLng( json[n][ propLoc ] ); - //TODO verify json[n].hasOwnProperty(propName) - //throw new Error("propertyName '"+propName+"' not found in JSON data"); + for(i in json) + jsonret[ this._getPath(json[i],propName) ]= L.latLng( this._getPath(json[i],propLoc) ); + //TODO throw new Error("propertyName '"+propName+"' not found in JSON data"); return jsonret; }, @@ -410,7 +455,8 @@ L.Control.Search = L.Control.extend({ }, _recordsFromLayer: function() { //return table: key,value from layer - var retRecords = {}, + var that = this, + retRecords = {}, propName = this.options.propertyName, loc; @@ -420,17 +466,17 @@ L.Control.Search = L.Control.extend({ if(layer instanceof L.Marker) { - if(layer.options.hasOwnProperty(propName)) + if(that._getPath(layer.options,propName)) { loc = layer.getLatLng(); loc.layer = layer; - retRecords[ layer.options[propName] ] = loc; + retRecords[ that._getPath(layer.options,propName) ] = loc; - }else if(layer.feature.properties.hasOwnProperty(propName)){ + }else if(that._getPath(layer.feature.properties,propName)){ loc = layer.getLatLng(); loc.layer = layer; - retRecords[ layer.feature.properties[propName] ] = loc; + retRecords[ that._getPath(layer.feature.properties,propName) ] = loc; }else{ console.log("propertyName '"+propName+"' not found in marker", layer); @@ -571,7 +617,7 @@ L.Control.Search = L.Control.extend({ L.DomUtil.addClass(this._container, 'search-load'); - if(this.options.callData) //CUSTOM SEARCH CALLBACK(USUALLY FOR AJAX SEARCHING) + if(this.options.callData) //CUSTOM SEARCH CALLBACK { that = this; this.options.callData(inputText, function(jsonraw) { @@ -821,7 +867,7 @@ var SearchMarker = L.Marker.extend({ }, tInt); return this; - } + } }); L.Map.addInitHook(function () {