check-in bower_components
This commit is contained in:
parent
4cc16bccd0
commit
9e08e74132
101 changed files with 90960 additions and 0 deletions
22
bower_components/leaflet-search/.bower.json
vendored
Normal file
22
bower_components/leaflet-search/.bower.json
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"name": "leaflet-search",
|
||||
"version": "1.4.7",
|
||||
"main": "leaflet-search.js",
|
||||
"ignore": [
|
||||
"**/.*",
|
||||
"node_modules",
|
||||
"components",
|
||||
"bower_components",
|
||||
"examples"
|
||||
],
|
||||
"homepage": "https://github.com/stefanocudini/leaflet-search",
|
||||
"_release": "1.4.7",
|
||||
"_resolution": {
|
||||
"type": "version",
|
||||
"tag": "v1.4.7",
|
||||
"commit": "411f216e1f407da9ef61047832b227c19ed47fab"
|
||||
},
|
||||
"_source": "git://github.com/stefanocudini/leaflet-search.git",
|
||||
"_target": "*",
|
||||
"_originalSource": "leaflet-search"
|
||||
}
|
||||
12
bower_components/leaflet-search/BUGS
vendored
Normal file
12
bower_components/leaflet-search/BUGS
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
. option condition problem {autoCollapse: true, markerLocation: true} not show location, row 61
|
||||
|
||||
. option condition problem {autoCollapse:false }, row 62
|
||||
|
||||
. problem with jsonp/ajax when remote filter has different behavior of this._filterRecords, row 322
|
||||
|
||||
. _handleAutoresize Should resize max search box size when map is resized., row 616
|
||||
|
||||
. if collapse in _handleSubmit hide _markerLoc!, row 684
|
||||
|
||||
. autoCollapse option hide this._markerLoc before that visualized!!, row 714
|
||||
|
||||
115
bower_components/leaflet-search/Gruntfile.js
vendored
Executable file
115
bower_components/leaflet-search/Gruntfile.js
vendored
Executable file
|
|
@ -0,0 +1,115 @@
|
|||
'use strict';
|
||||
|
||||
module.exports = function(grunt) {
|
||||
|
||||
grunt.loadNpmTasks('grunt-contrib-uglify');
|
||||
grunt.loadNpmTasks('grunt-contrib-concat');
|
||||
grunt.loadNpmTasks('grunt-contrib-clean');
|
||||
grunt.loadNpmTasks('grunt-contrib-cssmin');
|
||||
grunt.loadNpmTasks('grunt-contrib-jshint');
|
||||
grunt.loadNpmTasks('grunt-contrib-watch');
|
||||
grunt.loadNpmTasks('grunt-todos');
|
||||
|
||||
grunt.initConfig({
|
||||
pkg: grunt.file.readJSON('package.json'),
|
||||
meta: {
|
||||
banner:
|
||||
'/* \n'+
|
||||
' * Leaflet Search Control v<%= pkg.version %> - <%= grunt.template.today("yyyy-mm-dd") %> \n'+
|
||||
' * \n'+
|
||||
' * Copyright 2014 <%= pkg.author.name %> \n'+
|
||||
' * <%= pkg.author.email %> \n'+
|
||||
' * <%= pkg.author.url %> \n'+
|
||||
' * \n'+
|
||||
' * Licensed under the <%= pkg.license %> license. \n'+
|
||||
' * \n'+
|
||||
' * Demo: \n'+
|
||||
' * <%= pkg.homepage %> \n'+
|
||||
' * \n'+
|
||||
' * Source: \n'+
|
||||
' * <%= pkg.repository.url %> \n'+
|
||||
' * \n'+
|
||||
' */\n'
|
||||
},
|
||||
clean: {
|
||||
dist: {
|
||||
src: ['dist/*']
|
||||
}
|
||||
},
|
||||
jshint: {
|
||||
options: {
|
||||
globals: {
|
||||
console: true,
|
||||
module: true
|
||||
},
|
||||
"-W099": true, //ignora tabs e space warning
|
||||
"-W033": true,
|
||||
"-W044": true //ignore regexp
|
||||
},
|
||||
files: ['src/*.js']
|
||||
},
|
||||
concat: {
|
||||
//TODO cut out SearchMarker
|
||||
options: {
|
||||
banner: '<%= meta.banner %>'
|
||||
},
|
||||
dist: {
|
||||
files: {
|
||||
'dist/leaflet-search.src.js': ['src/leaflet-search.js'],
|
||||
'dist/leaflet-search.src.css': ['src/leaflet-search.css'],
|
||||
'dist/leaflet-search.mobile.src.css': ['src/leaflet-search.mobile.css']
|
||||
}
|
||||
}
|
||||
},
|
||||
uglify: {
|
||||
options: {
|
||||
banner: '<%= meta.banner %>'
|
||||
},
|
||||
dist: {
|
||||
files: {
|
||||
'dist/leaflet-search.min.js': ['dist/leaflet-search.src.js']
|
||||
}
|
||||
}
|
||||
},
|
||||
cssmin: {
|
||||
combine: {
|
||||
files: {
|
||||
'dist/leaflet-search.min.css': ['src/leaflet-search.css'],
|
||||
'dist/leaflet-search.mobile.min.css': ['src/leaflet-search.mobile.css']
|
||||
}
|
||||
},
|
||||
options: {
|
||||
banner: '<%= meta.banner %>'
|
||||
},
|
||||
minify: {
|
||||
expand: true,
|
||||
cwd: 'dist/',
|
||||
files: {
|
||||
'dist/leaflet-search.min.css': ['src/leaflet-search.css'],
|
||||
'dist/leaflet-search.mobile.min.css': ['src/leaflet-search.mobile.css']
|
||||
}
|
||||
}
|
||||
},
|
||||
todos: {
|
||||
options: { verbose: false },
|
||||
TODO: ['src/*.js'],
|
||||
},
|
||||
watch: {
|
||||
dist: {
|
||||
options: { livereload: true },
|
||||
files: ['src/*'],
|
||||
tasks: ['clean','concat','cssmin','jshint']
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
grunt.registerTask('default', [
|
||||
'clean',
|
||||
'concat',
|
||||
'cssmin',
|
||||
'jshint',
|
||||
'uglify',
|
||||
'todos'
|
||||
]);
|
||||
|
||||
};
|
||||
21
bower_components/leaflet-search/LICENSE.txt
vendored
Normal file
21
bower_components/leaflet-search/LICENSE.txt
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013 Stefano Cudini
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
65
bower_components/leaflet-search/README.md
vendored
Normal file
65
bower_components/leaflet-search/README.md
vendored
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
Leaflet.Control.Search
|
||||
============
|
||||
|
||||
#What
|
||||
A leaflet control that search markers/features location by cutstom property.
|
||||
With ajax/jsonp autocompletion and json fields re-mapping
|
||||
|
||||
Tested in Leaflet 0.6.4
|
||||
|
||||
|
||||
#Where
|
||||
|
||||
**Demos:**
|
||||
[labs.easyblog.it/maps/leaflet-search](http://labs.easyblog.it/maps/leaflet-search/)
|
||||
|
||||
**Source code:**
|
||||
[Github](https://github.com/stefanocudini/leaflet-search)
|
||||
[Bitbucket](https://bitbucket.org/zakis_/leaflet-search)
|
||||
[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
|
||||
|
||||
Adding the search control to the map:
|
||||
|
||||
```
|
||||
map.addControl( new L.Control.Search({layer: searchLayer}) );
|
||||
//searchLayer if a L.LayerGroup contains searched markers
|
||||
```
|
||||
short way:
|
||||
```
|
||||
var map = new L.Map('map', { searchControl: {layer: searchLayer} });
|
||||
```
|
||||
|
||||
other examples:
|
||||
```
|
||||
//ajax request to search.php for retrieve elements locations
|
||||
map.addControl( new L.Control.Search({url: 'search.php?q={s}'}) );
|
||||
|
||||
|
||||
//jsonp request to 3rd party service, implements Geocode Searching using OSM API
|
||||
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
|
||||
var searchControl = new L.Control.Search({layer: geojsonLayer, circleLocation:false});
|
||||
searchControl.on('search_locationfound', function(e) {
|
||||
|
||||
e.layer.setStyle({fillColor: '#3f0'});
|
||||
|
||||
}).on('search_collapsed', function(e) {
|
||||
|
||||
featuresLayer.eachLayer(function(layer) {
|
||||
featuresLayer.resetStyle(layer);
|
||||
});
|
||||
});
|
||||
map.addControl(searchControl);
|
||||
```
|
||||
|
||||
27
bower_components/leaflet-search/TODO
vendored
Normal file
27
bower_components/leaflet-search/TODO
vendored
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
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: 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: 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!!
|
||||
12
bower_components/leaflet-search/bower.json
vendored
Normal file
12
bower_components/leaflet-search/bower.json
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"name": "leaflet-search",
|
||||
"version": "1.4.6",
|
||||
"main": "leaflet-search.js",
|
||||
"ignore": [
|
||||
"**/.*",
|
||||
"node_modules",
|
||||
"components",
|
||||
"bower_components",
|
||||
"examples"
|
||||
]
|
||||
}
|
||||
18
bower_components/leaflet-search/dist/leaflet-search.min.css
vendored
Normal file
18
bower_components/leaflet-search/dist/leaflet-search.min.css
vendored
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* Leaflet Search Control v1.4.7 - 2014-01-04
|
||||
*
|
||||
* Copyright 2014 Stefano Cudini
|
||||
* stefano.cudini@gmail.com
|
||||
* http://labs.easyblog.it/
|
||||
*
|
||||
* Licensed under the MIT license.
|
||||
*
|
||||
* Demo:
|
||||
* http://labs.easyblog.it/maps/leaflet-search/
|
||||
*
|
||||
* Source:
|
||||
* git@github.com:stefanocudini/leaflet-search.git
|
||||
*
|
||||
*/
|
||||
|
||||
.leaflet-container .leaflet-control-search{position:relative;float:left;background:#fff;color:#1978cf;-moz-border-radius:4px;-webkit-border-radius:4px;border-radius:4px;background-color:rgba(255,255,255,.8);z-index:1000;box-shadow:0 1px 7px rgba(0,0,0,.65);margin-left:10px;margin-top:10px}.leaflet-control-search.search-exp{box-shadow:0 1px 7px #999;background:#fff}.leaflet-control-search .search-input{display:block;float:left;background:#fff;border:1px solid #666;border-radius:2px;height:18px;padding:0 18px 0 2px;margin:3px 0 3px 3px}.leaflet-control-search.search-load .search-input{background:url(../images/loader.gif) no-repeat center right #fff}.leaflet-control-search.search-load .search-cancel{visibility:hidden}.leaflet-control-search .search-cancel{display:block;width:22px;height:18px;position:absolute;right:22px;margin:3px 0;background:url(../images/search-icon.png) no-repeat 0 -46px;text-decoration:none;filter:alpha(opacity=80);opacity:.8}.leaflet-control-search .search-cancel:hover{filter:alpha(opacity=100);opacity:1}.leaflet-control-search .search-cancel span{display:none;font-size:18px;line-height:20px;color:#ccc;font-weight:700}.leaflet-control-search .search-cancel:hover span{color:#aaa}.leaflet-control-search .search-button{display:block;float:left;width:26px;height:26px;background:url(../images/search-icon.png) no-repeat 2px 2px;border-radius:4px}.leaflet-control-search .search-button:hover{background:url(../images/search-icon.png) no-repeat 2px -22px}.leaflet-control-search .search-tooltip{position:absolute;top:100%;left:0;float:left;min-width:80px;max-height:106px;box-shadow:0 0 8px rgba(0,0,0,.4);-webkit-border-radius:5px;-webkit-border-top-left-radius:0;-moz-border-radius:5px;-moz-border-radius-topleft:0;border-radius:5px;border-top-left-radius:0;background-color:rgba(0,0,0,.25);z-index:1010;overflow-y:auto;overflow-x:hidden}.leaflet-control-search .search-tip{margin:2px;padding:2px;display:block;color:#000;background:#ddd;border-radius:.25em;text-decoration:none;white-space:nowrap;font-size:.85em;vertical-align:center}.leaflet-control-search .search-button:hover,.leaflet-control-search .search-tip-select,.leaflet-control-search .search-tip:hover{background-color:#fff}.leaflet-control-search .search-alert{cursor:pointer;clear:both;font-size:.75em;margin-bottom:5px;padding:0 .25em;color:#e00;font-weight:700;border-radius:.25em}
|
||||
17
bower_components/leaflet-search/dist/leaflet-search.min.js
vendored
Normal file
17
bower_components/leaflet-search/dist/leaflet-search.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
18
bower_components/leaflet-search/dist/leaflet-search.mobile.min.css
vendored
Normal file
18
bower_components/leaflet-search/dist/leaflet-search.mobile.min.css
vendored
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* Leaflet Search Control v1.4.7 - 2014-01-04
|
||||
*
|
||||
* Copyright 2014 Stefano Cudini
|
||||
* stefano.cudini@gmail.com
|
||||
* http://labs.easyblog.it/
|
||||
*
|
||||
* Licensed under the MIT license.
|
||||
*
|
||||
* Demo:
|
||||
* http://labs.easyblog.it/maps/leaflet-search/
|
||||
*
|
||||
* Source:
|
||||
* git@github.com:stefanocudini/leaflet-search.git
|
||||
*
|
||||
*/
|
||||
|
||||
.leaflet-control.leaflet-control-search{z-index:2000}.leaflet-control-search .search-input{display:block;float:left;background:#fff;border:1px solid #666;border-radius:2px;height:24px;font-size:1.25em;padding:0 .125em;margin:3px;padding-right:30px}.leaflet-control-search .search-button,.leaflet-control-search .search-button:hover{background-image:url(../images/search-icon-mobile.png);-webkit-border-radius:4px;border-radius:4px;background-position:1px 1px;width:32px;height:32px}.leaflet-control-search.search-load .search-input{background:url(../images/loader.gif) no-repeat center right #fff}.leaflet-control-search .search-cancel{background-image:url(../images/search-icon-mobile.png);-webkit-border-radius:4px;border-radius:4px;background-position:0 -62px;width:26px;height:26px;right:34px;margin:3px}.leaflet-control-search .search-tooltip{max-height:142px}.leaflet-control-search .search-tip{font-size:1em;margin:2px;padding:2px;display:block;color:#000;background:rgba(255,255,255,.8);border-radius:.25em;text-decoration:none;white-space:nowrap;vertical-align:center}.leaflet-control-search .search-tip .climbo-icon-mini{float:right;display:block;white-space:nowrap}.leaflet-control-search .search-button:hover,.leaflet-control-search .search-tip-select,.leaflet-control-search .search-tip:hover{background-color:#fff}.leaflet-control-search .search-alert{font-size:1.2em}
|
||||
83
bower_components/leaflet-search/dist/leaflet-search.mobile.src.css
vendored
Normal file
83
bower_components/leaflet-search/dist/leaflet-search.mobile.src.css
vendored
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* Leaflet Search Control v1.4.7 - 2014-01-04
|
||||
*
|
||||
* Copyright 2014 Stefano Cudini
|
||||
* stefano.cudini@gmail.com
|
||||
* http://labs.easyblog.it/
|
||||
*
|
||||
* Licensed under the MIT license.
|
||||
*
|
||||
* Demo:
|
||||
* http://labs.easyblog.it/maps/leaflet-search/
|
||||
*
|
||||
* Source:
|
||||
* git@github.com:stefanocudini/leaflet-search.git
|
||||
*
|
||||
*/
|
||||
|
||||
/* SEARCH */
|
||||
.leaflet-control.leaflet-control-search {
|
||||
z-index:2000;
|
||||
}
|
||||
.leaflet-control-search .search-input {
|
||||
display:block;
|
||||
float:left;
|
||||
background: #fff;
|
||||
border:1px solid #666;
|
||||
border-radius:2px;
|
||||
height:24px;
|
||||
font-size:1.25em;
|
||||
padding:0 .125em;
|
||||
margin:3px;
|
||||
padding-right:30px;
|
||||
}
|
||||
.leaflet-control-search .search-button:hover,
|
||||
.leaflet-control-search .search-button {
|
||||
background-image: url('../images/search-icon-mobile.png');
|
||||
-webkit-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
background-position: 1px 1px;
|
||||
width:32px;
|
||||
height:32px;
|
||||
}
|
||||
.leaflet-control-search.search-load .search-input {
|
||||
background: url('../images/loader.gif') no-repeat center right #fff;
|
||||
}
|
||||
.leaflet-control-search .search-cancel {
|
||||
background-image: url('../images/search-icon-mobile.png');
|
||||
-webkit-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
background-position: 0px -62px;
|
||||
width:26px;
|
||||
height:26px;
|
||||
right:34px;
|
||||
margin:3px;
|
||||
}
|
||||
.leaflet-control-search .search-tooltip {
|
||||
max-height:142px;/*(.search-tip height * 5)*/
|
||||
}
|
||||
.leaflet-control-search .search-tip {
|
||||
font-size:1em;
|
||||
margin:2px;
|
||||
padding:2px;
|
||||
display:block;
|
||||
color:black;
|
||||
background: rgba(255,255,255,0.8);
|
||||
border-radius:.25em;
|
||||
text-decoration:none;
|
||||
white-space:nowrap;
|
||||
vertical-align:center;
|
||||
}
|
||||
.leaflet-control-search .search-tip .climbo-icon-mini {
|
||||
float:right;
|
||||
display:block;
|
||||
white-space:nowrap;
|
||||
}
|
||||
.leaflet-control-search .search-button:hover,
|
||||
.leaflet-control-search .search-tip-select,
|
||||
.leaflet-control-search .search-tip:hover {
|
||||
background-color: #fff;
|
||||
}
|
||||
.leaflet-control-search .search-alert {
|
||||
font-size:1.2em;
|
||||
}
|
||||
137
bower_components/leaflet-search/dist/leaflet-search.src.css
vendored
Normal file
137
bower_components/leaflet-search/dist/leaflet-search.src.css
vendored
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
/*
|
||||
* Leaflet Search Control v1.4.7 - 2014-01-04
|
||||
*
|
||||
* Copyright 2014 Stefano Cudini
|
||||
* stefano.cudini@gmail.com
|
||||
* http://labs.easyblog.it/
|
||||
*
|
||||
* Licensed under the MIT license.
|
||||
*
|
||||
* Demo:
|
||||
* http://labs.easyblog.it/maps/leaflet-search/
|
||||
*
|
||||
* Source:
|
||||
* git@github.com:stefanocudini/leaflet-search.git
|
||||
*
|
||||
*/
|
||||
|
||||
.leaflet-container .leaflet-control-search {
|
||||
position:relative;
|
||||
float:left;
|
||||
background:#fff;
|
||||
color:#1978cf;
|
||||
-moz-border-radius: 4px;
|
||||
-webkit-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
background-color: rgba(255, 255, 255, 0.8);
|
||||
z-index:1000;
|
||||
box-shadow: 0 1px 7px rgba(0,0,0,0.65);
|
||||
margin-left: 10px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
.leaflet-control-search.search-exp {/*expanded*/
|
||||
box-shadow: 0 1px 7px #999;
|
||||
background: #fff;
|
||||
}
|
||||
.leaflet-control-search .search-input {
|
||||
display:block;
|
||||
float:left;
|
||||
background: #fff;
|
||||
border:1px solid #666;
|
||||
border-radius:2px;
|
||||
height:18px;
|
||||
padding:0 18px 0 2px;
|
||||
margin:3px 0 3px 3px;
|
||||
}
|
||||
.leaflet-control-search.search-load .search-input {
|
||||
background: url('../images/loader.gif') no-repeat center right #fff;
|
||||
}
|
||||
.leaflet-control-search.search-load .search-cancel {
|
||||
visibility:hidden;
|
||||
}
|
||||
.leaflet-control-search .search-cancel {
|
||||
display:block;
|
||||
width:22px;
|
||||
height:18px;
|
||||
position:absolute;
|
||||
right:22px;
|
||||
margin:3px 0;
|
||||
background: url('../images/search-icon.png') no-repeat 0 -46px;
|
||||
text-decoration:none;
|
||||
filter: alpha(opacity=80);
|
||||
opacity: 0.8;
|
||||
}
|
||||
.leaflet-control-search .search-cancel:hover {
|
||||
filter: alpha(opacity=100);
|
||||
opacity: 1;
|
||||
}
|
||||
.leaflet-control-search .search-cancel span {
|
||||
display:none;/* comment for cancel button imageless */
|
||||
font-size:18px;
|
||||
line-height:20px;
|
||||
color:#ccc;
|
||||
font-weight:bold;
|
||||
}
|
||||
.leaflet-control-search .search-cancel:hover span {
|
||||
color:#aaa;
|
||||
}
|
||||
.leaflet-control-search .search-button {
|
||||
display:block;
|
||||
float:left;
|
||||
width:26px;
|
||||
height:26px;
|
||||
background: url('../images/search-icon.png') no-repeat 2px 2px;
|
||||
border-radius:4px;
|
||||
}
|
||||
.leaflet-control-search .search-button:hover {
|
||||
background: url('../images/search-icon.png') no-repeat 2px -22px;
|
||||
}
|
||||
.leaflet-control-search .search-tooltip {
|
||||
position:absolute;
|
||||
top:100%;
|
||||
left:0;
|
||||
float:left;
|
||||
min-width:80px;
|
||||
max-height:106px;/*(.search-tip height * 5)*/
|
||||
box-shadow: 0 0 8px rgba(0,0,0,0.4);
|
||||
-webkit-border-radius: 5px;
|
||||
-webkit-border-top-left-radius: 0;
|
||||
-moz-border-radius: 5px;
|
||||
-moz-border-radius-topleft: 0;
|
||||
border-radius: 5px;
|
||||
border-top-left-radius: 0;
|
||||
background-color: rgba(0, 0, 0, 0.25);
|
||||
z-index:1010;
|
||||
overflow-y:auto;
|
||||
overflow-x:hidden;
|
||||
}
|
||||
.leaflet-control-search .search-tip {
|
||||
font-size:.85em;
|
||||
margin:2px;
|
||||
padding:2px;
|
||||
display:block;
|
||||
color:black;
|
||||
background: #ddd;
|
||||
border-radius:.25em;
|
||||
text-decoration:none;
|
||||
white-space:nowrap;
|
||||
font-size:.85em;
|
||||
vertical-align:center;
|
||||
}
|
||||
.leaflet-control-search .search-tip-select,
|
||||
.leaflet-control-search .search-tip:hover,
|
||||
.leaflet-control-search .search-button:hover {
|
||||
background-color: #fff;
|
||||
}
|
||||
.leaflet-control-search .search-alert {
|
||||
cursor:pointer;
|
||||
clear:both;
|
||||
font-size:.75em;
|
||||
margin-bottom:5px;
|
||||
padding:0 .25em;
|
||||
color:#e00;
|
||||
font-weight:bold;
|
||||
border-radius:.25em;
|
||||
}
|
||||
|
||||
|
||||
855
bower_components/leaflet-search/dist/leaflet-search.src.js
vendored
Normal file
855
bower_components/leaflet-search/dist/leaflet-search.src.js
vendored
Normal file
|
|
@ -0,0 +1,855 @@
|
|||
/*
|
||||
* Leaflet Search Control v1.4.7 - 2014-01-04
|
||||
*
|
||||
* Copyright 2014 Stefano Cudini
|
||||
* stefano.cudini@gmail.com
|
||||
* http://labs.easyblog.it/
|
||||
*
|
||||
* Licensed under the MIT license.
|
||||
*
|
||||
* Demo:
|
||||
* http://labs.easyblog.it/maps/leaflet-search/
|
||||
*
|
||||
* Source:
|
||||
* git@github.com:stefanocudini/leaflet-search.git
|
||||
*
|
||||
*/
|
||||
|
||||
(function() {
|
||||
|
||||
L.Control.Search = L.Control.extend({
|
||||
includes: L.Mixin.Events,
|
||||
//
|
||||
// Name Data passed Description
|
||||
//
|
||||
//Managed Events:
|
||||
// search_locationfound {latlng, title} 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
|
||||
//
|
||||
options: {
|
||||
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"
|
||||
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
|
||||
initial: true, //search elements only by initial text
|
||||
autoType: true, //complete input with first suggested result and select this filled-in text.
|
||||
delayType: 400, //delay while typing for show tooltip
|
||||
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
|
||||
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
|
||||
animateLocation: true, //animate a circle over location found
|
||||
circleLocation: true, //draw a circle in location found
|
||||
markerLocation: false, //draw a marker in location found
|
||||
zoom: null, //zoom after pan to location found, default: map.getZoom()
|
||||
text: 'Search...', //placeholder value
|
||||
textCancel: 'Cancel', //title in cancel button
|
||||
textErr: 'Location not found', //error message
|
||||
position: 'topleft'
|
||||
//TODO add option collapsed, like control.layers
|
||||
},
|
||||
//FIXME option condition problem {autoCollapse: true, markerLocation: true} not show location
|
||||
//FIXME option condition problem {autoCollapse: false }
|
||||
|
||||
initialize: function(options) {
|
||||
L.Util.setOptions(this, options || {});
|
||||
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; //useful for disable autoType temporarily in delete/backspace keydown
|
||||
this._countertips = 0; //number of tips items
|
||||
this._recordsCache = {}; //key,value table! that store locations! format: key,latlng
|
||||
},
|
||||
|
||||
onAdd: function (map) {
|
||||
this._map = map;
|
||||
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');
|
||||
|
||||
if(this.options.circleLocation || this.options.markerLocation)
|
||||
this._markerLoc = new SearchMarker([0,0], {marker: this.options.markerLocation});//see below
|
||||
|
||||
this.setLayer( this._layer );
|
||||
map.on({
|
||||
// 'layeradd': this._onLayerAddRemove,
|
||||
// 'layerremove': this._onLayerAddRemove
|
||||
'resize':this._handleAutoresize()
|
||||
}, this);
|
||||
return this._container;
|
||||
},
|
||||
|
||||
onRemove: function(map) {
|
||||
this._recordsCache = {};
|
||||
// map.off({
|
||||
// 'layeradd': this._onLayerAddRemove,
|
||||
// 'layerremove': this._onLayerAddRemove
|
||||
// }, this);
|
||||
},
|
||||
|
||||
// _onLayerAddRemove: function(e) {
|
||||
// //console.info('_onLayerAddRemove');
|
||||
// //without this, run setLayer also for each Markers!! to optimize!
|
||||
// if(e.layer instanceof L.LayerGroup)
|
||||
// if( L.stamp(e.layer) != L.stamp(this._layer) )
|
||||
// this.setLayer(e.layer);
|
||||
// },
|
||||
|
||||
setLayer: function(layer) { //set search layer at runtime
|
||||
//this.options.layer = layer; //setting this, run only this._recordsFromLayer()
|
||||
this._layer = layer;
|
||||
this._layer.addTo(this._map);
|
||||
if(this._markerLoc)
|
||||
this._layer.addLayer(this._markerLoc);
|
||||
return this;
|
||||
},
|
||||
|
||||
showAlert: function(text) {
|
||||
text = text || this.options.textErr;
|
||||
this._alert.style.display = 'block';
|
||||
this._alert.innerHTML = text;
|
||||
clearTimeout(this.timerAlert);
|
||||
var that = this;
|
||||
this.timerAlert = setTimeout(function() {
|
||||
that.hideAlert();
|
||||
},this.options.autoCollapseTime);
|
||||
return this;
|
||||
},
|
||||
|
||||
hideAlert: function() {
|
||||
this._alert.style.display = 'none';
|
||||
return this;
|
||||
},
|
||||
|
||||
cancel: function() {
|
||||
this._input.value = '';
|
||||
this._handleKeypress({keyCode:8});//simulate backspace keypress
|
||||
this._input.size = this._inputMinSize;
|
||||
this._input.focus();
|
||||
this._cancel.style.display = 'none';
|
||||
return this;
|
||||
},
|
||||
|
||||
expand: function() {
|
||||
this._input.style.display = 'block';
|
||||
L.DomUtil.addClass(this._container, 'search-exp');
|
||||
this._input.focus();
|
||||
this._map.on('dragstart', this.collapse, this);
|
||||
return this;
|
||||
},
|
||||
|
||||
collapse: function() {
|
||||
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);
|
||||
this.fire('search_collapsed');
|
||||
return this;
|
||||
},
|
||||
|
||||
collapseDelayed: function() { //collapse after delay, used on_input blur
|
||||
if (!this.options.autoCollapse) return this;
|
||||
var that = this;
|
||||
clearTimeout(this.timerCollapse);
|
||||
this.timerCollapse = setTimeout(function() {
|
||||
that.collapse();
|
||||
}, this.options.autoCollapseTime);
|
||||
return this;
|
||||
},
|
||||
|
||||
collapseDelayedStop: function() {
|
||||
clearTimeout(this.timerCollapse);
|
||||
return this;
|
||||
},
|
||||
|
||||
////start DOM creations
|
||||
_createAlert: function(className) {
|
||||
var alert = L.DomUtil.create('div', className, this._container);
|
||||
alert.style.display = 'none';
|
||||
|
||||
L.DomEvent
|
||||
.on(alert, 'click', L.DomEvent.stop, this)
|
||||
.on(alert, 'click', this.hideAlert, this);
|
||||
|
||||
return alert;
|
||||
},
|
||||
|
||||
_createInput: function (text, className) {
|
||||
var input = L.DomUtil.create('input', className, this._container);
|
||||
input.type = 'text';
|
||||
input.size = this._inputMinSize;
|
||||
input.value = '';
|
||||
input.autocomplete = 'off';
|
||||
input.placeholder = text;
|
||||
input.style.display = 'none';
|
||||
|
||||
L.DomEvent
|
||||
.disableClickPropagation(input)
|
||||
.on(input, 'keyup', this._handleKeypress, this)
|
||||
.on(input, 'keydown', this._handleAutoresize, this)
|
||||
.on(input, 'blur', this.collapseDelayed, this)
|
||||
.on(input, 'focus', this.collapseDelayedStop, this);
|
||||
|
||||
return input;
|
||||
},
|
||||
|
||||
_createCancel: function (title, className) {
|
||||
var cancel = L.DomUtil.create('a', className, this._container);
|
||||
cancel.href = '#';
|
||||
cancel.title = title;
|
||||
cancel.style.display = 'none';
|
||||
cancel.innerHTML = "<span>⊗</span>";//imageless(see css)
|
||||
|
||||
L.DomEvent
|
||||
.on(cancel, 'click', L.DomEvent.stop, this)
|
||||
.on(cancel, 'click', this.cancel, this);
|
||||
|
||||
return cancel;
|
||||
},
|
||||
|
||||
_createButton: function (title, className) {
|
||||
var button = L.DomUtil.create('a', className, this._container);
|
||||
button.href = '#';
|
||||
button.title = title;
|
||||
|
||||
L.DomEvent
|
||||
.on(button, 'click', L.DomEvent.stop, this)
|
||||
.on(button, 'click', this._handleSubmit, this)
|
||||
.on(button, 'focus', this.collapseDelayedStop, this)
|
||||
.on(button, 'blur', this.collapseDelayed, this);
|
||||
|
||||
return button;
|
||||
},
|
||||
|
||||
_createTooltip: function(className) {
|
||||
var tool = L.DomUtil.create('div', className, this._container);
|
||||
tool.style.display = 'none';
|
||||
|
||||
var that = this;
|
||||
L.DomEvent
|
||||
.disableClickPropagation(tool)
|
||||
.on(tool, 'blur', this.collapseDelayed, this)
|
||||
.on(tool, 'mousewheel', function(e) {
|
||||
that.collapseDelayedStop();
|
||||
L.DomEvent.stopPropagation(e);//disable zoom map
|
||||
}, this)
|
||||
.on(tool, 'mouseover', function(e) {
|
||||
that.collapseDelayedStop();
|
||||
}, this);
|
||||
return tool;
|
||||
},
|
||||
|
||||
_createTip: function(text, val) {//val is object in recordCache, usually is Latlng
|
||||
var tip;
|
||||
|
||||
if(this.options.callTip)
|
||||
{
|
||||
tip = this.options.callTip(text,val); //custom tip node or html string
|
||||
if(typeof tip === 'string')
|
||||
{
|
||||
var tmpNode = L.DomUtil.create('div');
|
||||
tmpNode.innerHTML = tip;
|
||||
tip = tmpNode.firstChild;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tip = L.DomUtil.create('a', '');
|
||||
tip.href = '#';
|
||||
tip.innerHTML = text;
|
||||
}
|
||||
|
||||
L.DomUtil.addClass(tip, 'search-tip');
|
||||
tip._text = text; //value replaced in this._input and used by _autoType
|
||||
|
||||
L.DomEvent
|
||||
.disableClickPropagation(tip)
|
||||
.on(tip, 'click', L.DomEvent.stop, this)
|
||||
.on(tip, 'click', function(e) {
|
||||
this._input.value = text;
|
||||
this._handleAutoresize();
|
||||
this._input.focus();
|
||||
this._hideTooltip();
|
||||
if(this.options.tipAutoSubmit)//go to location at once
|
||||
this._handleSubmit();
|
||||
}, this);
|
||||
|
||||
return tip;
|
||||
},
|
||||
|
||||
//////end DOM creations
|
||||
|
||||
_filterRecords: function(text) { //Filter this._recordsCache case insensitive and much more..
|
||||
|
||||
var regFilter = new RegExp("^[.]$|[\[\]|()*]",'g'), //remove . * | ( ) ] [
|
||||
I, regSearch,
|
||||
frecords = {};
|
||||
|
||||
text = text.replace(regFilter,''); //sanitize text
|
||||
I = this.options.initial ? '^' : ''; //search only initial text
|
||||
//TODO add option for case sesitive search, also showLocation
|
||||
regSearch = new RegExp(I + text,'i');
|
||||
|
||||
//TODO use .filter or .map
|
||||
for(var key in this._recordsCache)
|
||||
if( regSearch.test(key) )
|
||||
frecords[key]= this._recordsCache[key];
|
||||
|
||||
return frecords;
|
||||
},
|
||||
|
||||
showTooltip: function() {
|
||||
var filteredRecords, newTip;
|
||||
|
||||
this._countertips = 0;
|
||||
|
||||
//FIXME problem with jsonp/ajax when remote filter has different behavior of this._filterRecords
|
||||
if(this.options.layer)
|
||||
filteredRecords = this._filterRecords( this._input.value );
|
||||
else
|
||||
filteredRecords = this._recordsCache;
|
||||
|
||||
this._tooltip.innerHTML = '';
|
||||
this._tooltip.currentSelection = -1; //inizialized for _handleArrowSelect()
|
||||
|
||||
for(var key in filteredRecords)//fill tooltip
|
||||
{
|
||||
if(++this._countertips == this.options.tooltipLimit) break;
|
||||
|
||||
newTip = this._createTip(key, filteredRecords[key] );
|
||||
|
||||
this._tooltip.appendChild(newTip);
|
||||
}
|
||||
|
||||
if(this._countertips > 0)
|
||||
{
|
||||
this._tooltip.style.display = 'block';
|
||||
if(this._autoTypeTmp)
|
||||
this._autoType();
|
||||
this._autoTypeTmp = this.options.autoType;//reset default value
|
||||
}
|
||||
else
|
||||
this._hideTooltip();
|
||||
|
||||
this._tooltip.scrollTop = 0;
|
||||
return this._countertips;
|
||||
},
|
||||
|
||||
_hideTooltip: function() {
|
||||
this._tooltip.style.display = 'none';
|
||||
this._tooltip.innerHTML = '';
|
||||
return 0;
|
||||
},
|
||||
|
||||
_defaultFilterJSON: function(json) { //default callback for filter data
|
||||
var jsonret = {},
|
||||
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] ] );
|
||||
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");
|
||||
return jsonret;
|
||||
},
|
||||
|
||||
_recordsFromJsonp: function(text, callAfter) { //extract searched records from remote jsonp service
|
||||
//TODO remove script node after call run
|
||||
var that = this;
|
||||
L.Control.Search.callJsonp = function(data) { //jsonp callback
|
||||
var fdata = that._filterJSON(data);//_filterJSON defined in inizialize...
|
||||
callAfter(fdata);
|
||||
}
|
||||
var script = L.DomUtil.create('script','search-jsonp', document.getElementsByTagName('body')[0] ),
|
||||
url = L.Util.template(this.options.url+'&'+this.options.jsonpParam+'=L.Control.Search.callJsonp', {s: text}); //parsing url
|
||||
//rnd = '&_='+Math.floor(Math.random()*10000);
|
||||
//TODO add rnd param or randomize callback name! in recordsFromJsonp
|
||||
script.type = 'text/javascript';
|
||||
script.src = url;
|
||||
return this;
|
||||
//may be return {abort: function() { script.parentNode.removeChild(script); } };
|
||||
},
|
||||
|
||||
_recordsFromAjax: function(text, callAfter) { //Ajax request
|
||||
if (window.XMLHttpRequest === undefined) {
|
||||
window.XMLHttpRequest = function() {
|
||||
try { return new ActiveXObject("Microsoft.XMLHTTP.6.0"); }
|
||||
catch (e1) {
|
||||
try { return new ActiveXObject("Microsoft.XMLHTTP.3.0"); }
|
||||
catch (e2) { throw new Error("XMLHttpRequest is not supported"); }
|
||||
}
|
||||
};
|
||||
}
|
||||
var request = new XMLHttpRequest(),
|
||||
url = L.Util.template(this.options.url, {s: text}), //parsing url
|
||||
//rnd = '&_='+Math.floor(Math.random()*10000);
|
||||
//TODO add rnd param or randomize callback name! in recordsFromAjax
|
||||
response = {};
|
||||
|
||||
request.open("GET", url);
|
||||
var that = this;
|
||||
request.onreadystatechange = function() {
|
||||
if(request.readyState === 4 && request.status === 200) {
|
||||
response = JSON.parse(request.responseText);
|
||||
var fdata = that._filterJSON(response);//_filterJSON defined in inizialize...
|
||||
callAfter(fdata);
|
||||
}
|
||||
};
|
||||
request.send();
|
||||
return this;
|
||||
},
|
||||
|
||||
_recordsFromLayer: function() { //return table: key,value from layer
|
||||
var retRecords = {},
|
||||
propName = this.options.propertyName,
|
||||
loc;
|
||||
|
||||
this._layer.eachLayer(function(layer) {
|
||||
|
||||
if(layer instanceof SearchMarker) return;
|
||||
|
||||
if(layer instanceof L.Marker)
|
||||
{
|
||||
if(layer.options.hasOwnProperty(propName))
|
||||
{
|
||||
loc = layer.getLatLng();
|
||||
loc.layer = layer;
|
||||
retRecords[ layer.options[propName] ] = loc;
|
||||
|
||||
}else if(layer.feature.properties.hasOwnProperty(propName)){
|
||||
|
||||
loc = layer.getLatLng();
|
||||
loc.layer = layer;
|
||||
retRecords[ layer.feature.properties[propName] ] = loc;
|
||||
|
||||
}else{
|
||||
console.log("propertyName '"+propName+"' not found in marker", layer);
|
||||
}
|
||||
}
|
||||
else if(layer.hasOwnProperty('feature'))//GeoJSON layer
|
||||
{
|
||||
if(layer.feature.properties.hasOwnProperty(propName))
|
||||
{
|
||||
loc = layer.getBounds().getCenter();
|
||||
loc.layer = layer;
|
||||
retRecords[ layer.feature.properties[propName] ] = loc;
|
||||
}
|
||||
else
|
||||
console.log("propertyName '"+propName+"' not found in feature", layer);
|
||||
}
|
||||
|
||||
},this);
|
||||
|
||||
return retRecords;
|
||||
},
|
||||
|
||||
_autoType: function() {
|
||||
|
||||
//TODO implements autype without selection(useful for mobile device)
|
||||
|
||||
var start = this._input.value.length,
|
||||
firstRecord = this._tooltip.firstChild._text,
|
||||
end = firstRecord.length;
|
||||
|
||||
if (firstRecord.indexOf(this._input.value) === 0) { // If prefix match
|
||||
this._input.value = firstRecord;
|
||||
this._handleAutoresize();
|
||||
|
||||
if (this._input.createTextRange) {
|
||||
var selRange = this._input.createTextRange();
|
||||
selRange.collapse(true);
|
||||
selRange.moveStart('character', start);
|
||||
selRange.moveEnd('character', end);
|
||||
selRange.select();
|
||||
}
|
||||
else if(this._input.setSelectionRange) {
|
||||
this._input.setSelectionRange(start, end);
|
||||
}
|
||||
else if(this._input.selectionStart) {
|
||||
this._input.selectionStart = start;
|
||||
this._input.selectionEnd = end;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_hideAutoType: function() { // deselect text:
|
||||
|
||||
var sel;
|
||||
if ((sel = this._input.selection) && sel.empty) {
|
||||
sel.empty();
|
||||
}
|
||||
else if (this._input.createTextRange) {
|
||||
sel = this._input.createTextRange();
|
||||
sel.collapse(true);
|
||||
var end = this._input.value.length;
|
||||
sel.moveStart('character', end);
|
||||
sel.moveEnd('character', end);
|
||||
sel.select();
|
||||
}
|
||||
else {
|
||||
if (this._input.getSelection) {
|
||||
this._input.getSelection().removeAllRanges();
|
||||
}
|
||||
this._input.selectionStart = this._input.selectionEnd;
|
||||
}
|
||||
},
|
||||
|
||||
_handleKeypress: function (e) { //run _input keyup event
|
||||
|
||||
switch(e.keyCode)
|
||||
{
|
||||
case 27: //Esc
|
||||
this.collapse();
|
||||
break;
|
||||
case 13: //Enter
|
||||
if(this._countertips == 1)
|
||||
this._handleArrowSelect(1);
|
||||
this._handleSubmit(); //do search
|
||||
break;
|
||||
case 38://Up
|
||||
this._handleArrowSelect(-1);
|
||||
break;
|
||||
case 40://Down
|
||||
this._handleArrowSelect(1);
|
||||
break;
|
||||
case 37://Left
|
||||
case 39://Right
|
||||
case 16://Shift
|
||||
case 17://Ctrl
|
||||
//case 32://Space
|
||||
break;
|
||||
case 8://backspace
|
||||
case 46://delete
|
||||
this._autoTypeTmp = false;//disable temporarily autoType
|
||||
break;
|
||||
default://All keys
|
||||
|
||||
if(this._input.value.length)
|
||||
this._cancel.style.display = 'block';
|
||||
else
|
||||
this._cancel.style.display = 'none';
|
||||
|
||||
if(this._input.value.length >= this.options.minLength)
|
||||
{
|
||||
var that = this;
|
||||
clearTimeout(this.timerKeypress); //cancel last search request while type in
|
||||
this.timerKeypress = setTimeout(function() { //delay before request, for limit jsonp/ajax request
|
||||
|
||||
that._fillRecordsCache();
|
||||
|
||||
}, this.options.delayType);
|
||||
}
|
||||
else
|
||||
this._hideTooltip();
|
||||
}
|
||||
},
|
||||
|
||||
_fillRecordsCache: function() {
|
||||
//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
|
||||
|
||||
var inputText = this._input.value,
|
||||
that;
|
||||
|
||||
L.DomUtil.addClass(this._container, 'search-load');
|
||||
|
||||
if(this.options.callData) //CUSTOM SEARCH CALLBACK(USUALLY FOR AJAX SEARCHING)
|
||||
{
|
||||
that = this;
|
||||
this.options.callData(inputText, function(jsonraw) {
|
||||
|
||||
that._recordsCache = that._filterJSON(jsonraw);
|
||||
|
||||
that.showTooltip();
|
||||
|
||||
L.DomUtil.removeClass(that._container, 'search-load');
|
||||
});
|
||||
}
|
||||
else if(this.options.url) //JSONP/AJAX REQUEST
|
||||
{
|
||||
if(this.options.jsonpParam)
|
||||
{
|
||||
that = this;
|
||||
this._recordsFromJsonp(inputText, function(data) {// is async request then it need callback
|
||||
that._recordsCache = data;
|
||||
that.showTooltip();
|
||||
L.DomUtil.removeClass(that._container, 'search-load');
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
that = this;
|
||||
this._recordsFromAjax(inputText, function(data) {// is async request then it need callback
|
||||
that._recordsCache = data;
|
||||
that.showTooltip();
|
||||
L.DomUtil.removeClass(that._container, 'search-load');
|
||||
});
|
||||
}
|
||||
}
|
||||
else if(this.options.layer) //SEARCH ELEMENTS IN PRELOADED LAYER
|
||||
{
|
||||
this._recordsCache = this._recordsFromLayer(); //fill table key,value from markers into layer
|
||||
this.showTooltip();
|
||||
L.DomUtil.removeClass(this._container, 'search-load');
|
||||
}
|
||||
},
|
||||
|
||||
_handleAutoresize: function() { //autoresize this._input
|
||||
//TODO refact _handleAutoresize now is not accurate
|
||||
if (this._input.style.maxWidth != this._map._container.offsetWidth) //If maxWidth isn't the same as when first set, reset to current Map width
|
||||
this._input.style.maxWidth = L.DomUtil.getStyle(this._map._container, 'width');
|
||||
|
||||
if(this.options.autoResize && (this._container.offsetWidth + 45 < this._map._container.offsetWidth))
|
||||
this._input.size = this._input.value.length<this._inputMinSize ? this._inputMinSize : this._input.value.length;
|
||||
},
|
||||
|
||||
_handleArrowSelect: function(velocity) {
|
||||
|
||||
var searchTips = this._tooltip.hasChildNodes() ? this._tooltip.childNodes : [];
|
||||
|
||||
for (i=0; i<searchTips.length; i++)
|
||||
L.DomUtil.removeClass(searchTips[i], 'search-tip-select');
|
||||
|
||||
if ((velocity == 1 ) && (this._tooltip.currentSelection >= (searchTips.length - 1))) {// If at end of list.
|
||||
L.DomUtil.addClass(searchTips[this._tooltip.currentSelection], 'search-tip-select');
|
||||
}
|
||||
else if ((velocity == -1 ) && (this._tooltip.currentSelection <= 0)) { // Going back up to the search box.
|
||||
this._tooltip.currentSelection = -1;
|
||||
}
|
||||
else if (this._tooltip.style.display != 'none') { // regular up/down
|
||||
this._tooltip.currentSelection += velocity;
|
||||
|
||||
L.DomUtil.addClass(searchTips[this._tooltip.currentSelection], 'search-tip-select');
|
||||
|
||||
this._input.value = searchTips[this._tooltip.currentSelection]._text;
|
||||
|
||||
// scroll:
|
||||
var tipOffsetTop = searchTips[this._tooltip.currentSelection].offsetTop;
|
||||
|
||||
if (tipOffsetTop + searchTips[this._tooltip.currentSelection].clientHeight >= this._tooltip.scrollTop + this._tooltip.clientHeight) {
|
||||
this._tooltip.scrollTop = tipOffsetTop - this._tooltip.clientHeight + searchTips[this._tooltip.currentSelection].clientHeight;
|
||||
}
|
||||
else if (tipOffsetTop <= this._tooltip.scrollTop) {
|
||||
this._tooltip.scrollTop = tipOffsetTop;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_handleSubmit: function() { //button and tooltip click and enter submit
|
||||
|
||||
this._hideAutoType();
|
||||
|
||||
this.hideAlert();
|
||||
this._hideTooltip();
|
||||
|
||||
if(this._input.style.display == 'none') //on first click show _input only
|
||||
this.expand();
|
||||
else
|
||||
{
|
||||
if(this._input.value === '') //hide _input only
|
||||
this.collapse();
|
||||
else
|
||||
{
|
||||
var loc = this._getLocation(this._input.value);
|
||||
|
||||
if(loc===false)
|
||||
this.showAlert();
|
||||
else
|
||||
{
|
||||
this.showLocation(loc, this._input.value);
|
||||
this.fire('search_locationfound', {
|
||||
latlng: loc,
|
||||
text: this._input.value,
|
||||
layer: loc.layer ? loc.layer : null
|
||||
});
|
||||
}
|
||||
//this.collapse();
|
||||
//FIXME if collapse in _handleSubmit hide _markerLoc!
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_getLocation: function(key) { //extract latlng from _recordsCache
|
||||
|
||||
if( this._recordsCache.hasOwnProperty(key) )
|
||||
return this._recordsCache[key];//then after use .loc attribute
|
||||
else
|
||||
return false;
|
||||
},
|
||||
|
||||
showLocation: function(latlng, title) { //set location on map from _recordsCache
|
||||
|
||||
if(this.options.zoom)
|
||||
this._map.setView(latlng, this.options.zoom);
|
||||
else
|
||||
this._map.panTo(latlng);
|
||||
|
||||
if(this._markerLoc)
|
||||
{
|
||||
this._markerLoc.setLatLng(latlng); //show circle/marker in location found
|
||||
this._markerLoc.setTitle(title);
|
||||
this._markerLoc.show();
|
||||
if(this.options.animateLocation)
|
||||
this._markerLoc.animate();
|
||||
//TODO showLocation: start animation after setView or panTo, maybe with map.on('moveend')...
|
||||
}
|
||||
|
||||
//FIXME autoCollapse option hide this._markerLoc before that visualized!!
|
||||
if(this.options.autoCollapse)
|
||||
this.collapse();
|
||||
return this;
|
||||
}
|
||||
});
|
||||
|
||||
var SearchMarker = L.Marker.extend({
|
||||
|
||||
includes: L.Mixin.Events,
|
||||
|
||||
options: {
|
||||
radius: 10,
|
||||
weight: 3,
|
||||
color: '#e03',
|
||||
stroke: true,
|
||||
fill: false,
|
||||
title: '',
|
||||
//TODO add custom icon!
|
||||
marker: false //show icon optional, show only circleLoc
|
||||
},
|
||||
|
||||
initialize: function (latlng, options) {
|
||||
L.setOptions(this, options);
|
||||
L.Marker.prototype.initialize.call(this, latlng, options);
|
||||
this._circleLoc = new L.CircleMarker(latlng, this.options);
|
||||
//TODO add inner circle
|
||||
},
|
||||
|
||||
onAdd: function (map) {
|
||||
L.Marker.prototype.onAdd.call(this, map);
|
||||
map.addLayer(this._circleLoc);
|
||||
this.hide();
|
||||
},
|
||||
|
||||
onRemove: function (map) {
|
||||
L.Marker.prototype.onRemove.call(this, map);
|
||||
map.removeLayer(this._circleLoc);
|
||||
},
|
||||
|
||||
setLatLng: function (latlng) {
|
||||
L.Marker.prototype.setLatLng.call(this, latlng);
|
||||
this._circleLoc.setLatLng(latlng);
|
||||
return this;
|
||||
},
|
||||
|
||||
setTitle: function(title) {
|
||||
title = title || '';
|
||||
this.options.title = title;
|
||||
if(this._icon)
|
||||
this._icon.title = title;
|
||||
return this;
|
||||
},
|
||||
|
||||
show: function() {
|
||||
if(this.options.marker)
|
||||
{
|
||||
if(this._icon)
|
||||
this._icon.style.display = 'block';
|
||||
if(this._shadow)
|
||||
this._shadow.style.display = 'block';
|
||||
//this._bringToFront();
|
||||
}
|
||||
if(this._circleLoc)
|
||||
{
|
||||
this._circleLoc.setStyle({fill: this.options.fill, stroke: this.options.stroke});
|
||||
//this._circleLoc.bringToFront();
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
hide: function() {
|
||||
if(this._icon)
|
||||
this._icon.style.display = 'none';
|
||||
if(this._shadow)
|
||||
this._shadow.style.display = 'none';
|
||||
if(this._circleLoc)
|
||||
this._circleLoc.setStyle({fill: false, stroke: false});
|
||||
return this;
|
||||
},
|
||||
|
||||
animate: function() {
|
||||
//TODO refact animate() more smooth! like this: http://goo.gl/DDlRs
|
||||
var circle = this._circleLoc,
|
||||
tInt = 200, //time interval
|
||||
ss = 10, //frames
|
||||
mr = parseInt(circle._radius/ss),
|
||||
oldrad = this.options.radius,
|
||||
newrad = circle._radius * 2.5,
|
||||
acc = 0;
|
||||
|
||||
circle._timerAnimLoc = setInterval(function() {
|
||||
acc += 0.5;
|
||||
mr += acc; //adding acceleration
|
||||
newrad -= mr;
|
||||
|
||||
circle.setRadius(newrad);
|
||||
|
||||
if(newrad<oldrad)
|
||||
{
|
||||
clearInterval(circle._timerAnimLoc);
|
||||
circle.setRadius(oldrad);//reset radius
|
||||
//if(typeof afterAnimCall == 'function')
|
||||
//afterAnimCall();
|
||||
//TODO use create event 'animateEnd' in SearchMarker
|
||||
}
|
||||
}, tInt);
|
||||
|
||||
return this;
|
||||
}
|
||||
});
|
||||
|
||||
L.Map.addInitHook(function () {
|
||||
if (this.options.searchControl) {
|
||||
this.searchControl = L.control.search(this.options.searchControl);
|
||||
this.addControl(this.searchControl);
|
||||
}
|
||||
});
|
||||
|
||||
L.control.search = function (options) {
|
||||
return new L.Control.Search(options);
|
||||
};
|
||||
|
||||
}).call(this);
|
||||
|
||||
BIN
bower_components/leaflet-search/images/back.png
vendored
Normal file
BIN
bower_components/leaflet-search/images/back.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 115 KiB |
BIN
bower_components/leaflet-search/images/loader.gif
vendored
Normal file
BIN
bower_components/leaflet-search/images/loader.gif
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.8 KiB |
BIN
bower_components/leaflet-search/images/search-icon-mobile.png
vendored
Normal file
BIN
bower_components/leaflet-search/images/search-icon-mobile.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.9 KiB |
BIN
bower_components/leaflet-search/images/search-icon.png
vendored
Normal file
BIN
bower_components/leaflet-search/images/search-icon.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.7 KiB |
102
bower_components/leaflet-search/index.html
vendored
Normal file
102
bower_components/leaflet-search/index.html
vendored
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>Leaflet.Control.Search</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<link rel="stylesheet" href="style.css" />
|
||||
</head>
|
||||
|
||||
<body id="home">
|
||||
|
||||
<h2>Leaflet.Control.Search</h2>
|
||||
|
||||
<div id="desc">
|
||||
A Leaflet Control for search markers/features location by attribute<br />
|
||||
and much more.
|
||||
<div style="position:absolute;top:0;right:-120px">
|
||||
<iframe src="http://ghbtns.com/github-btn.html?user=stefanocudini&repo=leaflet-search&type=watch&count=true" allowtransparency="true" frameborder="0" scrolling="0" width="104px" height="20px"></iframe>
|
||||
</div>
|
||||
<br />
|
||||
Other useful stuff for <a href="http://labs.easyblog.it/maps/">Web Mapping...</a>
|
||||
</div>
|
||||
|
||||
<div style="clear:both"></div>
|
||||
|
||||
<div class="contents">
|
||||
<h4>Features</h4>
|
||||
<ul id="ff">
|
||||
<li>Autocomplete</li>
|
||||
<li>No require external Ajax libs</li>
|
||||
<li>Retrieve data locations by Ajax/Jsonp</li>
|
||||
<li>Pre-filtering data from Ajax/Jsonp</li>
|
||||
<li>Complete fields remapping for remote Jsonp service</li>
|
||||
<li>Data source callback support</li>
|
||||
<li>Localization placeholder and text alert</li>
|
||||
<li>Autozoom on location founded</li>
|
||||
<li>Autoresize textbox</li>
|
||||
<li>Customize tooltip menu</li>
|
||||
<li>Many options to customize the behavior</li>
|
||||
<li>Support search in features collection</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="contents">
|
||||
<h4>Examples</h4>
|
||||
<ul id="examples">
|
||||
<li><a href="examples/simple.html">Simple</a></li>
|
||||
<li><a href="examples/geojson-layer.html">GeoJSON features</a></li>
|
||||
<li><a href="examples/ajax.html">Ajax</a></li>
|
||||
<li><a href="examples/jsonp.html">Jsonp</a></li>
|
||||
<li><a href="examples/ajax-jquery.html">Ajax by jQuery</a></li>
|
||||
<li><a href="examples/jsonp-filtered.html">Jsonp Filtered</a></li>
|
||||
<li><a href="examples/ajax-bulk.html">Bulk data</a></li>
|
||||
<li><a href="examples/custom-tip.html">Custom Tip</a></li>
|
||||
<li><a href="examples/google-geocoding.html">GeoCode Search - Google Geocoding API</a></li>
|
||||
<li><a href="examples/nominatim.html">GeoCode Search - OSM Nominatim API</a></li>
|
||||
<li><a href="examples/cloudmade.html">GeoCode Search - Cloudmade API</a></li>
|
||||
<li><a href="examples/mobile.html">Mobile styled</a></li>
|
||||
<li><a href="examples/twitter.html">Twitter API</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="contents">
|
||||
<h4>Code repositories</h4>
|
||||
<a target="_blank" href="https://github.com/stefanocudini/leaflet-search">Github.com</a>
|
||||
<br />
|
||||
<a target="_blank" href="https://bitbucket.org/zakis_/leaflet-search">Bitbucket.org</a>
|
||||
<br />
|
||||
<a target="_blank" href="https://npmjs.org/package/leaflet-search">Node Packaged Module</a>
|
||||
<br />
|
||||
<a target="_blank" href="https://atmosphere.meteor.com/package/leaflet-search">Atmosphere Meteor JS</a>
|
||||
<br />
|
||||
|
||||
<h4>Website</h4>
|
||||
<a href="http://labs.easyblog.it/maps/leaflet-search/">labs.easyblog.it/maps/leaflet-search</a>
|
||||
<br />
|
||||
|
||||
<h4>Download</h4>
|
||||
<ul>
|
||||
<li><a href="https://github.com/stefanocudini/leaflet-search/archive/master.zip">Dev Pack (.zip)</a></li>
|
||||
<li><a href="dist/leaflet-search.src.js">Source Code (.js)</a></li>
|
||||
<li><a href="dist/leaflet-search.min.js">Compressed (.min.js)</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div id="copy"><a href="http://labs.easyblog.it/">Labs</a> • <a rel="author" href="http://labs.easyblog.it/stefano-cudini/">Stefano Cudini</a></div>
|
||||
|
||||
<a href="https://github.com/stefanocudini/leaflet-search"><img id="ribbon" src="https://s3.amazonaws.com/github/ribbons/forkme_right_darkblue_121621.png" alt="Fork me on GitHub"></a>
|
||||
|
||||
<div style="clear:both;font-size:.85em;margin-bottom:1em">
|
||||
<b>For questions and bugs</b> I recommend you to <a href="https://github.com/stefanocudini/leaflet-search/issues">create New Issue</a> on Github repository.</strong><br />
|
||||
Or to obtain a fast response consult <a href="https://groups.google.com/forum/?hl=it&fromgroups=#!forum/leaflet-js">Official Leaflet community forum</a>.<br />
|
||||
<br />
|
||||
This is a micro discussion area for methods of implementation.<br />
|
||||
</div>
|
||||
|
||||
<div id="comments">
|
||||
<div id="disqus_thread"></div>
|
||||
</div>
|
||||
<script>var disqus_shortname = 'easyblog-it'</script>
|
||||
|
||||
<script type="text/javascript" src="/labs-common.js"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
11
bower_components/leaflet-search/package.js
vendored
Normal file
11
bower_components/leaflet-search/package.js
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
Package.describe({
|
||||
summary: "Leaflet Control Search"
|
||||
});
|
||||
|
||||
Package.on_use(function (api, where) {
|
||||
api.add_files('dist/leaflet-search.min.js', 'client');
|
||||
api.add_files('dist/leaflet-search.min.css', 'client');
|
||||
api.add_files('images/search-icon.png', 'client');
|
||||
api.add_files('images/loader.gif', 'client');
|
||||
//TODO server-side searching...
|
||||
});
|
||||
34
bower_components/leaflet-search/package.json
vendored
Normal file
34
bower_components/leaflet-search/package.json
vendored
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
{
|
||||
"name": "leaflet-search",
|
||||
"version": "1.4.7",
|
||||
"description": "Leaflet Control for searching markers/features by attribute on map or remote searching in jsonp/ajax",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git@github.com:stefanocudini/leaflet-search.git"
|
||||
},
|
||||
"homepage": "http://labs.easyblog.it/maps/leaflet-search/",
|
||||
"author": {
|
||||
"name": "Stefano Cudini",
|
||||
"email": "stefano.cudini@gmail.com",
|
||||
"url": "http://labs.easyblog.it/"
|
||||
},
|
||||
"license": "MIT",
|
||||
"keywords": [
|
||||
"gis",
|
||||
"map",
|
||||
"leaflet"
|
||||
],
|
||||
"dependencies": {
|
||||
"leaflet": "*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"grunt": "~0.4.2",
|
||||
"grunt-contrib-uglify": "~0.2.7",
|
||||
"grunt-contrib-concat": "~0.3.0",
|
||||
"grunt-contrib-clean": "~0.5.0",
|
||||
"grunt-contrib-cssmin": "~0.7.0",
|
||||
"grunt-contrib-jshint": "~0.7.2",
|
||||
"grunt-contrib-watch": "~0.5.3",
|
||||
"grunt-todos": "~0.2.0"
|
||||
}
|
||||
}
|
||||
8
bower_components/leaflet-search/smart.json
vendored
Normal file
8
bower_components/leaflet-search/smart.json
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"name": "leaflet-search",
|
||||
"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 <stefano.cudini@gmail.com>",
|
||||
"version": "1.4.7",
|
||||
"git": "https://github.com/stefanocudini/leaflet-search.git"
|
||||
}
|
||||
121
bower_components/leaflet-search/src/leaflet-search.css
vendored
Normal file
121
bower_components/leaflet-search/src/leaflet-search.css
vendored
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
|
||||
.leaflet-container .leaflet-control-search {
|
||||
position:relative;
|
||||
float:left;
|
||||
background:#fff;
|
||||
color:#1978cf;
|
||||
-moz-border-radius: 4px;
|
||||
-webkit-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
background-color: rgba(255, 255, 255, 0.8);
|
||||
z-index:1000;
|
||||
box-shadow: 0 1px 7px rgba(0,0,0,0.65);
|
||||
margin-left: 10px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
.leaflet-control-search.search-exp {/*expanded*/
|
||||
box-shadow: 0 1px 7px #999;
|
||||
background: #fff;
|
||||
}
|
||||
.leaflet-control-search .search-input {
|
||||
display:block;
|
||||
float:left;
|
||||
background: #fff;
|
||||
border:1px solid #666;
|
||||
border-radius:2px;
|
||||
height:18px;
|
||||
padding:0 18px 0 2px;
|
||||
margin:3px 0 3px 3px;
|
||||
}
|
||||
.leaflet-control-search.search-load .search-input {
|
||||
background: url('../images/loader.gif') no-repeat center right #fff;
|
||||
}
|
||||
.leaflet-control-search.search-load .search-cancel {
|
||||
visibility:hidden;
|
||||
}
|
||||
.leaflet-control-search .search-cancel {
|
||||
display:block;
|
||||
width:22px;
|
||||
height:18px;
|
||||
position:absolute;
|
||||
right:22px;
|
||||
margin:3px 0;
|
||||
background: url('../images/search-icon.png') no-repeat 0 -46px;
|
||||
text-decoration:none;
|
||||
filter: alpha(opacity=80);
|
||||
opacity: 0.8;
|
||||
}
|
||||
.leaflet-control-search .search-cancel:hover {
|
||||
filter: alpha(opacity=100);
|
||||
opacity: 1;
|
||||
}
|
||||
.leaflet-control-search .search-cancel span {
|
||||
display:none;/* comment for cancel button imageless */
|
||||
font-size:18px;
|
||||
line-height:20px;
|
||||
color:#ccc;
|
||||
font-weight:bold;
|
||||
}
|
||||
.leaflet-control-search .search-cancel:hover span {
|
||||
color:#aaa;
|
||||
}
|
||||
.leaflet-control-search .search-button {
|
||||
display:block;
|
||||
float:left;
|
||||
width:26px;
|
||||
height:26px;
|
||||
background: url('../images/search-icon.png') no-repeat 2px 2px;
|
||||
border-radius:4px;
|
||||
}
|
||||
.leaflet-control-search .search-button:hover {
|
||||
background: url('../images/search-icon.png') no-repeat 2px -22px;
|
||||
}
|
||||
.leaflet-control-search .search-tooltip {
|
||||
position:absolute;
|
||||
top:100%;
|
||||
left:0;
|
||||
float:left;
|
||||
min-width:80px;
|
||||
max-height:106px;/*(.search-tip height * 5)*/
|
||||
box-shadow: 0 0 8px rgba(0,0,0,0.4);
|
||||
-webkit-border-radius: 5px;
|
||||
-webkit-border-top-left-radius: 0;
|
||||
-moz-border-radius: 5px;
|
||||
-moz-border-radius-topleft: 0;
|
||||
border-radius: 5px;
|
||||
border-top-left-radius: 0;
|
||||
background-color: rgba(0, 0, 0, 0.25);
|
||||
z-index:1010;
|
||||
overflow-y:auto;
|
||||
overflow-x:hidden;
|
||||
}
|
||||
.leaflet-control-search .search-tip {
|
||||
font-size:.85em;
|
||||
margin:2px;
|
||||
padding:2px;
|
||||
display:block;
|
||||
color:black;
|
||||
background: #ddd;
|
||||
border-radius:.25em;
|
||||
text-decoration:none;
|
||||
white-space:nowrap;
|
||||
font-size:.85em;
|
||||
vertical-align:center;
|
||||
}
|
||||
.leaflet-control-search .search-tip-select,
|
||||
.leaflet-control-search .search-tip:hover,
|
||||
.leaflet-control-search .search-button:hover {
|
||||
background-color: #fff;
|
||||
}
|
||||
.leaflet-control-search .search-alert {
|
||||
cursor:pointer;
|
||||
clear:both;
|
||||
font-size:.75em;
|
||||
margin-bottom:5px;
|
||||
padding:0 .25em;
|
||||
color:#e00;
|
||||
font-weight:bold;
|
||||
border-radius:.25em;
|
||||
}
|
||||
|
||||
|
||||
839
bower_components/leaflet-search/src/leaflet-search.js
vendored
Normal file
839
bower_components/leaflet-search/src/leaflet-search.js
vendored
Normal file
|
|
@ -0,0 +1,839 @@
|
|||
|
||||
(function() {
|
||||
|
||||
L.Control.Search = L.Control.extend({
|
||||
includes: L.Mixin.Events,
|
||||
//
|
||||
// Name Data passed Description
|
||||
//
|
||||
//Managed Events:
|
||||
// search_locationfound {latlng, title} 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
|
||||
//
|
||||
options: {
|
||||
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"
|
||||
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
|
||||
initial: true, //search elements only by initial text
|
||||
autoType: true, //complete input with first suggested result and select this filled-in text.
|
||||
delayType: 400, //delay while typing for show tooltip
|
||||
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
|
||||
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
|
||||
animateLocation: true, //animate a circle over location found
|
||||
circleLocation: true, //draw a circle in location found
|
||||
markerLocation: false, //draw a marker in location found
|
||||
zoom: null, //zoom after pan to location found, default: map.getZoom()
|
||||
text: 'Search...', //placeholder value
|
||||
textCancel: 'Cancel', //title in cancel button
|
||||
textErr: 'Location not found', //error message
|
||||
position: 'topleft'
|
||||
//TODO add option collapsed, like control.layers
|
||||
},
|
||||
//FIXME option condition problem {autoCollapse: true, markerLocation: true} not show location
|
||||
//FIXME option condition problem {autoCollapse: false }
|
||||
|
||||
initialize: function(options) {
|
||||
L.Util.setOptions(this, options || {});
|
||||
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; //useful for disable autoType temporarily in delete/backspace keydown
|
||||
this._countertips = 0; //number of tips items
|
||||
this._recordsCache = {}; //key,value table! that store locations! format: key,latlng
|
||||
},
|
||||
|
||||
onAdd: function (map) {
|
||||
this._map = map;
|
||||
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');
|
||||
|
||||
if(this.options.circleLocation || this.options.markerLocation)
|
||||
this._markerLoc = new SearchMarker([0,0], {marker: this.options.markerLocation});//see below
|
||||
|
||||
this.setLayer( this._layer );
|
||||
map.on({
|
||||
// 'layeradd': this._onLayerAddRemove,
|
||||
// 'layerremove': this._onLayerAddRemove
|
||||
'resize':this._handleAutoresize()
|
||||
}, this);
|
||||
return this._container;
|
||||
},
|
||||
|
||||
onRemove: function(map) {
|
||||
this._recordsCache = {};
|
||||
// map.off({
|
||||
// 'layeradd': this._onLayerAddRemove,
|
||||
// 'layerremove': this._onLayerAddRemove
|
||||
// }, this);
|
||||
},
|
||||
|
||||
// _onLayerAddRemove: function(e) {
|
||||
// //console.info('_onLayerAddRemove');
|
||||
// //without this, run setLayer also for each Markers!! to optimize!
|
||||
// if(e.layer instanceof L.LayerGroup)
|
||||
// if( L.stamp(e.layer) != L.stamp(this._layer) )
|
||||
// this.setLayer(e.layer);
|
||||
// },
|
||||
|
||||
setLayer: function(layer) { //set search layer at runtime
|
||||
//this.options.layer = layer; //setting this, run only this._recordsFromLayer()
|
||||
this._layer = layer;
|
||||
this._layer.addTo(this._map);
|
||||
if(this._markerLoc)
|
||||
this._layer.addLayer(this._markerLoc);
|
||||
return this;
|
||||
},
|
||||
|
||||
showAlert: function(text) {
|
||||
text = text || this.options.textErr;
|
||||
this._alert.style.display = 'block';
|
||||
this._alert.innerHTML = text;
|
||||
clearTimeout(this.timerAlert);
|
||||
var that = this;
|
||||
this.timerAlert = setTimeout(function() {
|
||||
that.hideAlert();
|
||||
},this.options.autoCollapseTime);
|
||||
return this;
|
||||
},
|
||||
|
||||
hideAlert: function() {
|
||||
this._alert.style.display = 'none';
|
||||
return this;
|
||||
},
|
||||
|
||||
cancel: function() {
|
||||
this._input.value = '';
|
||||
this._handleKeypress({keyCode:8});//simulate backspace keypress
|
||||
this._input.size = this._inputMinSize;
|
||||
this._input.focus();
|
||||
this._cancel.style.display = 'none';
|
||||
return this;
|
||||
},
|
||||
|
||||
expand: function() {
|
||||
this._input.style.display = 'block';
|
||||
L.DomUtil.addClass(this._container, 'search-exp');
|
||||
this._input.focus();
|
||||
this._map.on('dragstart', this.collapse, this);
|
||||
return this;
|
||||
},
|
||||
|
||||
collapse: function() {
|
||||
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);
|
||||
this.fire('search_collapsed');
|
||||
return this;
|
||||
},
|
||||
|
||||
collapseDelayed: function() { //collapse after delay, used on_input blur
|
||||
if (!this.options.autoCollapse) return this;
|
||||
var that = this;
|
||||
clearTimeout(this.timerCollapse);
|
||||
this.timerCollapse = setTimeout(function() {
|
||||
that.collapse();
|
||||
}, this.options.autoCollapseTime);
|
||||
return this;
|
||||
},
|
||||
|
||||
collapseDelayedStop: function() {
|
||||
clearTimeout(this.timerCollapse);
|
||||
return this;
|
||||
},
|
||||
|
||||
////start DOM creations
|
||||
_createAlert: function(className) {
|
||||
var alert = L.DomUtil.create('div', className, this._container);
|
||||
alert.style.display = 'none';
|
||||
|
||||
L.DomEvent
|
||||
.on(alert, 'click', L.DomEvent.stop, this)
|
||||
.on(alert, 'click', this.hideAlert, this);
|
||||
|
||||
return alert;
|
||||
},
|
||||
|
||||
_createInput: function (text, className) {
|
||||
var input = L.DomUtil.create('input', className, this._container);
|
||||
input.type = 'text';
|
||||
input.size = this._inputMinSize;
|
||||
input.value = '';
|
||||
input.autocomplete = 'off';
|
||||
input.placeholder = text;
|
||||
input.style.display = 'none';
|
||||
|
||||
L.DomEvent
|
||||
.disableClickPropagation(input)
|
||||
.on(input, 'keyup', this._handleKeypress, this)
|
||||
.on(input, 'keydown', this._handleAutoresize, this)
|
||||
.on(input, 'blur', this.collapseDelayed, this)
|
||||
.on(input, 'focus', this.collapseDelayedStop, this);
|
||||
|
||||
return input;
|
||||
},
|
||||
|
||||
_createCancel: function (title, className) {
|
||||
var cancel = L.DomUtil.create('a', className, this._container);
|
||||
cancel.href = '#';
|
||||
cancel.title = title;
|
||||
cancel.style.display = 'none';
|
||||
cancel.innerHTML = "<span>⊗</span>";//imageless(see css)
|
||||
|
||||
L.DomEvent
|
||||
.on(cancel, 'click', L.DomEvent.stop, this)
|
||||
.on(cancel, 'click', this.cancel, this);
|
||||
|
||||
return cancel;
|
||||
},
|
||||
|
||||
_createButton: function (title, className) {
|
||||
var button = L.DomUtil.create('a', className, this._container);
|
||||
button.href = '#';
|
||||
button.title = title;
|
||||
|
||||
L.DomEvent
|
||||
.on(button, 'click', L.DomEvent.stop, this)
|
||||
.on(button, 'click', this._handleSubmit, this)
|
||||
.on(button, 'focus', this.collapseDelayedStop, this)
|
||||
.on(button, 'blur', this.collapseDelayed, this);
|
||||
|
||||
return button;
|
||||
},
|
||||
|
||||
_createTooltip: function(className) {
|
||||
var tool = L.DomUtil.create('div', className, this._container);
|
||||
tool.style.display = 'none';
|
||||
|
||||
var that = this;
|
||||
L.DomEvent
|
||||
.disableClickPropagation(tool)
|
||||
.on(tool, 'blur', this.collapseDelayed, this)
|
||||
.on(tool, 'mousewheel', function(e) {
|
||||
that.collapseDelayedStop();
|
||||
L.DomEvent.stopPropagation(e);//disable zoom map
|
||||
}, this)
|
||||
.on(tool, 'mouseover', function(e) {
|
||||
that.collapseDelayedStop();
|
||||
}, this);
|
||||
return tool;
|
||||
},
|
||||
|
||||
_createTip: function(text, val) {//val is object in recordCache, usually is Latlng
|
||||
var tip;
|
||||
|
||||
if(this.options.callTip)
|
||||
{
|
||||
tip = this.options.callTip(text,val); //custom tip node or html string
|
||||
if(typeof tip === 'string')
|
||||
{
|
||||
var tmpNode = L.DomUtil.create('div');
|
||||
tmpNode.innerHTML = tip;
|
||||
tip = tmpNode.firstChild;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tip = L.DomUtil.create('a', '');
|
||||
tip.href = '#';
|
||||
tip.innerHTML = text;
|
||||
}
|
||||
|
||||
L.DomUtil.addClass(tip, 'search-tip');
|
||||
tip._text = text; //value replaced in this._input and used by _autoType
|
||||
|
||||
L.DomEvent
|
||||
.disableClickPropagation(tip)
|
||||
.on(tip, 'click', L.DomEvent.stop, this)
|
||||
.on(tip, 'click', function(e) {
|
||||
this._input.value = text;
|
||||
this._handleAutoresize();
|
||||
this._input.focus();
|
||||
this._hideTooltip();
|
||||
if(this.options.tipAutoSubmit)//go to location at once
|
||||
this._handleSubmit();
|
||||
}, this);
|
||||
|
||||
return tip;
|
||||
},
|
||||
|
||||
//////end DOM creations
|
||||
|
||||
_filterRecords: function(text) { //Filter this._recordsCache case insensitive and much more..
|
||||
|
||||
var regFilter = new RegExp("^[.]$|[\[\]|()*]",'g'), //remove . * | ( ) ] [
|
||||
I, regSearch,
|
||||
frecords = {};
|
||||
|
||||
text = text.replace(regFilter,''); //sanitize text
|
||||
I = this.options.initial ? '^' : ''; //search only initial text
|
||||
//TODO add option for case sesitive search, also showLocation
|
||||
regSearch = new RegExp(I + text,'i');
|
||||
|
||||
//TODO use .filter or .map
|
||||
for(var key in this._recordsCache)
|
||||
if( regSearch.test(key) )
|
||||
frecords[key]= this._recordsCache[key];
|
||||
|
||||
return frecords;
|
||||
},
|
||||
|
||||
showTooltip: function() {
|
||||
var filteredRecords, newTip;
|
||||
|
||||
this._countertips = 0;
|
||||
|
||||
//FIXME problem with jsonp/ajax when remote filter has different behavior of this._filterRecords
|
||||
if(this.options.layer)
|
||||
filteredRecords = this._filterRecords( this._input.value );
|
||||
else
|
||||
filteredRecords = this._recordsCache;
|
||||
|
||||
this._tooltip.innerHTML = '';
|
||||
this._tooltip.currentSelection = -1; //inizialized for _handleArrowSelect()
|
||||
|
||||
for(var key in filteredRecords)//fill tooltip
|
||||
{
|
||||
if(++this._countertips == this.options.tooltipLimit) break;
|
||||
|
||||
newTip = this._createTip(key, filteredRecords[key] );
|
||||
|
||||
this._tooltip.appendChild(newTip);
|
||||
}
|
||||
|
||||
if(this._countertips > 0)
|
||||
{
|
||||
this._tooltip.style.display = 'block';
|
||||
if(this._autoTypeTmp)
|
||||
this._autoType();
|
||||
this._autoTypeTmp = this.options.autoType;//reset default value
|
||||
}
|
||||
else
|
||||
this._hideTooltip();
|
||||
|
||||
this._tooltip.scrollTop = 0;
|
||||
return this._countertips;
|
||||
},
|
||||
|
||||
_hideTooltip: function() {
|
||||
this._tooltip.style.display = 'none';
|
||||
this._tooltip.innerHTML = '';
|
||||
return 0;
|
||||
},
|
||||
|
||||
_defaultFilterJSON: function(json) { //default callback for filter data
|
||||
var jsonret = {},
|
||||
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] ] );
|
||||
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");
|
||||
return jsonret;
|
||||
},
|
||||
|
||||
_recordsFromJsonp: function(text, callAfter) { //extract searched records from remote jsonp service
|
||||
//TODO remove script node after call run
|
||||
var that = this;
|
||||
L.Control.Search.callJsonp = function(data) { //jsonp callback
|
||||
var fdata = that._filterJSON(data);//_filterJSON defined in inizialize...
|
||||
callAfter(fdata);
|
||||
}
|
||||
var script = L.DomUtil.create('script','search-jsonp', document.getElementsByTagName('body')[0] ),
|
||||
url = L.Util.template(this.options.url+'&'+this.options.jsonpParam+'=L.Control.Search.callJsonp', {s: text}); //parsing url
|
||||
//rnd = '&_='+Math.floor(Math.random()*10000);
|
||||
//TODO add rnd param or randomize callback name! in recordsFromJsonp
|
||||
script.type = 'text/javascript';
|
||||
script.src = url;
|
||||
return this;
|
||||
//may be return {abort: function() { script.parentNode.removeChild(script); } };
|
||||
},
|
||||
|
||||
_recordsFromAjax: function(text, callAfter) { //Ajax request
|
||||
if (window.XMLHttpRequest === undefined) {
|
||||
window.XMLHttpRequest = function() {
|
||||
try { return new ActiveXObject("Microsoft.XMLHTTP.6.0"); }
|
||||
catch (e1) {
|
||||
try { return new ActiveXObject("Microsoft.XMLHTTP.3.0"); }
|
||||
catch (e2) { throw new Error("XMLHttpRequest is not supported"); }
|
||||
}
|
||||
};
|
||||
}
|
||||
var request = new XMLHttpRequest(),
|
||||
url = L.Util.template(this.options.url, {s: text}), //parsing url
|
||||
//rnd = '&_='+Math.floor(Math.random()*10000);
|
||||
//TODO add rnd param or randomize callback name! in recordsFromAjax
|
||||
response = {};
|
||||
|
||||
request.open("GET", url);
|
||||
var that = this;
|
||||
request.onreadystatechange = function() {
|
||||
if(request.readyState === 4 && request.status === 200) {
|
||||
response = JSON.parse(request.responseText);
|
||||
var fdata = that._filterJSON(response);//_filterJSON defined in inizialize...
|
||||
callAfter(fdata);
|
||||
}
|
||||
};
|
||||
request.send();
|
||||
return this;
|
||||
},
|
||||
|
||||
_recordsFromLayer: function() { //return table: key,value from layer
|
||||
var retRecords = {},
|
||||
propName = this.options.propertyName,
|
||||
loc;
|
||||
|
||||
this._layer.eachLayer(function(layer) {
|
||||
|
||||
if(layer instanceof SearchMarker) return;
|
||||
|
||||
if(layer instanceof L.Marker)
|
||||
{
|
||||
if(layer.options.hasOwnProperty(propName))
|
||||
{
|
||||
loc = layer.getLatLng();
|
||||
loc.layer = layer;
|
||||
retRecords[ layer.options[propName] ] = loc;
|
||||
|
||||
}else if(layer.feature.properties.hasOwnProperty(propName)){
|
||||
|
||||
loc = layer.getLatLng();
|
||||
loc.layer = layer;
|
||||
retRecords[ layer.feature.properties[propName] ] = loc;
|
||||
|
||||
}else{
|
||||
console.log("propertyName '"+propName+"' not found in marker", layer);
|
||||
}
|
||||
}
|
||||
else if(layer.hasOwnProperty('feature'))//GeoJSON layer
|
||||
{
|
||||
if(layer.feature.properties.hasOwnProperty(propName))
|
||||
{
|
||||
loc = layer.getBounds().getCenter();
|
||||
loc.layer = layer;
|
||||
retRecords[ layer.feature.properties[propName] ] = loc;
|
||||
}
|
||||
else
|
||||
console.log("propertyName '"+propName+"' not found in feature", layer);
|
||||
}
|
||||
|
||||
},this);
|
||||
|
||||
return retRecords;
|
||||
},
|
||||
|
||||
_autoType: function() {
|
||||
|
||||
//TODO implements autype without selection(useful for mobile device)
|
||||
|
||||
var start = this._input.value.length,
|
||||
firstRecord = this._tooltip.firstChild._text,
|
||||
end = firstRecord.length;
|
||||
|
||||
if (firstRecord.indexOf(this._input.value) === 0) { // If prefix match
|
||||
this._input.value = firstRecord;
|
||||
this._handleAutoresize();
|
||||
|
||||
if (this._input.createTextRange) {
|
||||
var selRange = this._input.createTextRange();
|
||||
selRange.collapse(true);
|
||||
selRange.moveStart('character', start);
|
||||
selRange.moveEnd('character', end);
|
||||
selRange.select();
|
||||
}
|
||||
else if(this._input.setSelectionRange) {
|
||||
this._input.setSelectionRange(start, end);
|
||||
}
|
||||
else if(this._input.selectionStart) {
|
||||
this._input.selectionStart = start;
|
||||
this._input.selectionEnd = end;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_hideAutoType: function() { // deselect text:
|
||||
|
||||
var sel;
|
||||
if ((sel = this._input.selection) && sel.empty) {
|
||||
sel.empty();
|
||||
}
|
||||
else if (this._input.createTextRange) {
|
||||
sel = this._input.createTextRange();
|
||||
sel.collapse(true);
|
||||
var end = this._input.value.length;
|
||||
sel.moveStart('character', end);
|
||||
sel.moveEnd('character', end);
|
||||
sel.select();
|
||||
}
|
||||
else {
|
||||
if (this._input.getSelection) {
|
||||
this._input.getSelection().removeAllRanges();
|
||||
}
|
||||
this._input.selectionStart = this._input.selectionEnd;
|
||||
}
|
||||
},
|
||||
|
||||
_handleKeypress: function (e) { //run _input keyup event
|
||||
|
||||
switch(e.keyCode)
|
||||
{
|
||||
case 27: //Esc
|
||||
this.collapse();
|
||||
break;
|
||||
case 13: //Enter
|
||||
if(this._countertips == 1)
|
||||
this._handleArrowSelect(1);
|
||||
this._handleSubmit(); //do search
|
||||
break;
|
||||
case 38://Up
|
||||
this._handleArrowSelect(-1);
|
||||
break;
|
||||
case 40://Down
|
||||
this._handleArrowSelect(1);
|
||||
break;
|
||||
case 37://Left
|
||||
case 39://Right
|
||||
case 16://Shift
|
||||
case 17://Ctrl
|
||||
//case 32://Space
|
||||
break;
|
||||
case 8://backspace
|
||||
case 46://delete
|
||||
this._autoTypeTmp = false;//disable temporarily autoType
|
||||
break;
|
||||
default://All keys
|
||||
|
||||
if(this._input.value.length)
|
||||
this._cancel.style.display = 'block';
|
||||
else
|
||||
this._cancel.style.display = 'none';
|
||||
|
||||
if(this._input.value.length >= this.options.minLength)
|
||||
{
|
||||
var that = this;
|
||||
clearTimeout(this.timerKeypress); //cancel last search request while type in
|
||||
this.timerKeypress = setTimeout(function() { //delay before request, for limit jsonp/ajax request
|
||||
|
||||
that._fillRecordsCache();
|
||||
|
||||
}, this.options.delayType);
|
||||
}
|
||||
else
|
||||
this._hideTooltip();
|
||||
}
|
||||
},
|
||||
|
||||
_fillRecordsCache: function() {
|
||||
//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
|
||||
|
||||
var inputText = this._input.value,
|
||||
that;
|
||||
|
||||
L.DomUtil.addClass(this._container, 'search-load');
|
||||
|
||||
if(this.options.callData) //CUSTOM SEARCH CALLBACK(USUALLY FOR AJAX SEARCHING)
|
||||
{
|
||||
that = this;
|
||||
this.options.callData(inputText, function(jsonraw) {
|
||||
|
||||
that._recordsCache = that._filterJSON(jsonraw);
|
||||
|
||||
that.showTooltip();
|
||||
|
||||
L.DomUtil.removeClass(that._container, 'search-load');
|
||||
});
|
||||
}
|
||||
else if(this.options.url) //JSONP/AJAX REQUEST
|
||||
{
|
||||
if(this.options.jsonpParam)
|
||||
{
|
||||
that = this;
|
||||
this._recordsFromJsonp(inputText, function(data) {// is async request then it need callback
|
||||
that._recordsCache = data;
|
||||
that.showTooltip();
|
||||
L.DomUtil.removeClass(that._container, 'search-load');
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
that = this;
|
||||
this._recordsFromAjax(inputText, function(data) {// is async request then it need callback
|
||||
that._recordsCache = data;
|
||||
that.showTooltip();
|
||||
L.DomUtil.removeClass(that._container, 'search-load');
|
||||
});
|
||||
}
|
||||
}
|
||||
else if(this.options.layer) //SEARCH ELEMENTS IN PRELOADED LAYER
|
||||
{
|
||||
this._recordsCache = this._recordsFromLayer(); //fill table key,value from markers into layer
|
||||
this.showTooltip();
|
||||
L.DomUtil.removeClass(this._container, 'search-load');
|
||||
}
|
||||
},
|
||||
|
||||
_handleAutoresize: function() { //autoresize this._input
|
||||
//TODO refact _handleAutoresize now is not accurate
|
||||
if (this._input.style.maxWidth != this._map._container.offsetWidth) //If maxWidth isn't the same as when first set, reset to current Map width
|
||||
this._input.style.maxWidth = L.DomUtil.getStyle(this._map._container, 'width');
|
||||
|
||||
if(this.options.autoResize && (this._container.offsetWidth + 45 < this._map._container.offsetWidth))
|
||||
this._input.size = this._input.value.length<this._inputMinSize ? this._inputMinSize : this._input.value.length;
|
||||
},
|
||||
|
||||
_handleArrowSelect: function(velocity) {
|
||||
|
||||
var searchTips = this._tooltip.hasChildNodes() ? this._tooltip.childNodes : [];
|
||||
|
||||
for (i=0; i<searchTips.length; i++)
|
||||
L.DomUtil.removeClass(searchTips[i], 'search-tip-select');
|
||||
|
||||
if ((velocity == 1 ) && (this._tooltip.currentSelection >= (searchTips.length - 1))) {// If at end of list.
|
||||
L.DomUtil.addClass(searchTips[this._tooltip.currentSelection], 'search-tip-select');
|
||||
}
|
||||
else if ((velocity == -1 ) && (this._tooltip.currentSelection <= 0)) { // Going back up to the search box.
|
||||
this._tooltip.currentSelection = -1;
|
||||
}
|
||||
else if (this._tooltip.style.display != 'none') { // regular up/down
|
||||
this._tooltip.currentSelection += velocity;
|
||||
|
||||
L.DomUtil.addClass(searchTips[this._tooltip.currentSelection], 'search-tip-select');
|
||||
|
||||
this._input.value = searchTips[this._tooltip.currentSelection]._text;
|
||||
|
||||
// scroll:
|
||||
var tipOffsetTop = searchTips[this._tooltip.currentSelection].offsetTop;
|
||||
|
||||
if (tipOffsetTop + searchTips[this._tooltip.currentSelection].clientHeight >= this._tooltip.scrollTop + this._tooltip.clientHeight) {
|
||||
this._tooltip.scrollTop = tipOffsetTop - this._tooltip.clientHeight + searchTips[this._tooltip.currentSelection].clientHeight;
|
||||
}
|
||||
else if (tipOffsetTop <= this._tooltip.scrollTop) {
|
||||
this._tooltip.scrollTop = tipOffsetTop;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_handleSubmit: function() { //button and tooltip click and enter submit
|
||||
|
||||
this._hideAutoType();
|
||||
|
||||
this.hideAlert();
|
||||
this._hideTooltip();
|
||||
|
||||
if(this._input.style.display == 'none') //on first click show _input only
|
||||
this.expand();
|
||||
else
|
||||
{
|
||||
if(this._input.value === '') //hide _input only
|
||||
this.collapse();
|
||||
else
|
||||
{
|
||||
var loc = this._getLocation(this._input.value);
|
||||
|
||||
if(loc===false)
|
||||
this.showAlert();
|
||||
else
|
||||
{
|
||||
this.showLocation(loc, this._input.value);
|
||||
this.fire('search_locationfound', {
|
||||
latlng: loc,
|
||||
text: this._input.value,
|
||||
layer: loc.layer ? loc.layer : null
|
||||
});
|
||||
}
|
||||
//this.collapse();
|
||||
//FIXME if collapse in _handleSubmit hide _markerLoc!
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_getLocation: function(key) { //extract latlng from _recordsCache
|
||||
|
||||
if( this._recordsCache.hasOwnProperty(key) )
|
||||
return this._recordsCache[key];//then after use .loc attribute
|
||||
else
|
||||
return false;
|
||||
},
|
||||
|
||||
showLocation: function(latlng, title) { //set location on map from _recordsCache
|
||||
|
||||
if(this.options.zoom)
|
||||
this._map.setView(latlng, this.options.zoom);
|
||||
else
|
||||
this._map.panTo(latlng);
|
||||
|
||||
if(this._markerLoc)
|
||||
{
|
||||
this._markerLoc.setLatLng(latlng); //show circle/marker in location found
|
||||
this._markerLoc.setTitle(title);
|
||||
this._markerLoc.show();
|
||||
if(this.options.animateLocation)
|
||||
this._markerLoc.animate();
|
||||
//TODO showLocation: start animation after setView or panTo, maybe with map.on('moveend')...
|
||||
}
|
||||
|
||||
//FIXME autoCollapse option hide this._markerLoc before that visualized!!
|
||||
if(this.options.autoCollapse)
|
||||
this.collapse();
|
||||
return this;
|
||||
}
|
||||
});
|
||||
|
||||
var SearchMarker = L.Marker.extend({
|
||||
|
||||
includes: L.Mixin.Events,
|
||||
|
||||
options: {
|
||||
radius: 10,
|
||||
weight: 3,
|
||||
color: '#e03',
|
||||
stroke: true,
|
||||
fill: false,
|
||||
title: '',
|
||||
//TODO add custom icon!
|
||||
marker: false //show icon optional, show only circleLoc
|
||||
},
|
||||
|
||||
initialize: function (latlng, options) {
|
||||
L.setOptions(this, options);
|
||||
L.Marker.prototype.initialize.call(this, latlng, options);
|
||||
this._circleLoc = new L.CircleMarker(latlng, this.options);
|
||||
//TODO add inner circle
|
||||
},
|
||||
|
||||
onAdd: function (map) {
|
||||
L.Marker.prototype.onAdd.call(this, map);
|
||||
map.addLayer(this._circleLoc);
|
||||
this.hide();
|
||||
},
|
||||
|
||||
onRemove: function (map) {
|
||||
L.Marker.prototype.onRemove.call(this, map);
|
||||
map.removeLayer(this._circleLoc);
|
||||
},
|
||||
|
||||
setLatLng: function (latlng) {
|
||||
L.Marker.prototype.setLatLng.call(this, latlng);
|
||||
this._circleLoc.setLatLng(latlng);
|
||||
return this;
|
||||
},
|
||||
|
||||
setTitle: function(title) {
|
||||
title = title || '';
|
||||
this.options.title = title;
|
||||
if(this._icon)
|
||||
this._icon.title = title;
|
||||
return this;
|
||||
},
|
||||
|
||||
show: function() {
|
||||
if(this.options.marker)
|
||||
{
|
||||
if(this._icon)
|
||||
this._icon.style.display = 'block';
|
||||
if(this._shadow)
|
||||
this._shadow.style.display = 'block';
|
||||
//this._bringToFront();
|
||||
}
|
||||
if(this._circleLoc)
|
||||
{
|
||||
this._circleLoc.setStyle({fill: this.options.fill, stroke: this.options.stroke});
|
||||
//this._circleLoc.bringToFront();
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
hide: function() {
|
||||
if(this._icon)
|
||||
this._icon.style.display = 'none';
|
||||
if(this._shadow)
|
||||
this._shadow.style.display = 'none';
|
||||
if(this._circleLoc)
|
||||
this._circleLoc.setStyle({fill: false, stroke: false});
|
||||
return this;
|
||||
},
|
||||
|
||||
animate: function() {
|
||||
//TODO refact animate() more smooth! like this: http://goo.gl/DDlRs
|
||||
var circle = this._circleLoc,
|
||||
tInt = 200, //time interval
|
||||
ss = 10, //frames
|
||||
mr = parseInt(circle._radius/ss),
|
||||
oldrad = this.options.radius,
|
||||
newrad = circle._radius * 2.5,
|
||||
acc = 0;
|
||||
|
||||
circle._timerAnimLoc = setInterval(function() {
|
||||
acc += 0.5;
|
||||
mr += acc; //adding acceleration
|
||||
newrad -= mr;
|
||||
|
||||
circle.setRadius(newrad);
|
||||
|
||||
if(newrad<oldrad)
|
||||
{
|
||||
clearInterval(circle._timerAnimLoc);
|
||||
circle.setRadius(oldrad);//reset radius
|
||||
//if(typeof afterAnimCall == 'function')
|
||||
//afterAnimCall();
|
||||
//TODO use create event 'animateEnd' in SearchMarker
|
||||
}
|
||||
}, tInt);
|
||||
|
||||
return this;
|
||||
}
|
||||
});
|
||||
|
||||
L.Map.addInitHook(function () {
|
||||
if (this.options.searchControl) {
|
||||
this.searchControl = L.control.search(this.options.searchControl);
|
||||
this.addControl(this.searchControl);
|
||||
}
|
||||
});
|
||||
|
||||
L.control.search = function (options) {
|
||||
return new L.Control.Search(options);
|
||||
};
|
||||
|
||||
}).call(this);
|
||||
|
||||
67
bower_components/leaflet-search/src/leaflet-search.mobile.css
vendored
Normal file
67
bower_components/leaflet-search/src/leaflet-search.mobile.css
vendored
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
|
||||
/* SEARCH */
|
||||
.leaflet-control.leaflet-control-search {
|
||||
z-index:2000;
|
||||
}
|
||||
.leaflet-control-search .search-input {
|
||||
display:block;
|
||||
float:left;
|
||||
background: #fff;
|
||||
border:1px solid #666;
|
||||
border-radius:2px;
|
||||
height:24px;
|
||||
font-size:1.25em;
|
||||
padding:0 .125em;
|
||||
margin:3px;
|
||||
padding-right:30px;
|
||||
}
|
||||
.leaflet-control-search .search-button:hover,
|
||||
.leaflet-control-search .search-button {
|
||||
background-image: url('../images/search-icon-mobile.png');
|
||||
-webkit-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
background-position: 1px 1px;
|
||||
width:32px;
|
||||
height:32px;
|
||||
}
|
||||
.leaflet-control-search.search-load .search-input {
|
||||
background: url('../images/loader.gif') no-repeat center right #fff;
|
||||
}
|
||||
.leaflet-control-search .search-cancel {
|
||||
background-image: url('../images/search-icon-mobile.png');
|
||||
-webkit-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
background-position: 0px -62px;
|
||||
width:26px;
|
||||
height:26px;
|
||||
right:34px;
|
||||
margin:3px;
|
||||
}
|
||||
.leaflet-control-search .search-tooltip {
|
||||
max-height:142px;/*(.search-tip height * 5)*/
|
||||
}
|
||||
.leaflet-control-search .search-tip {
|
||||
font-size:1em;
|
||||
margin:2px;
|
||||
padding:2px;
|
||||
display:block;
|
||||
color:black;
|
||||
background: rgba(255,255,255,0.8);
|
||||
border-radius:.25em;
|
||||
text-decoration:none;
|
||||
white-space:nowrap;
|
||||
vertical-align:center;
|
||||
}
|
||||
.leaflet-control-search .search-tip .climbo-icon-mini {
|
||||
float:right;
|
||||
display:block;
|
||||
white-space:nowrap;
|
||||
}
|
||||
.leaflet-control-search .search-button:hover,
|
||||
.leaflet-control-search .search-tip-select,
|
||||
.leaflet-control-search .search-tip:hover {
|
||||
background-color: #fff;
|
||||
}
|
||||
.leaflet-control-search .search-alert {
|
||||
font-size:1.2em;
|
||||
}
|
||||
97
bower_components/leaflet-search/style.css
vendored
Normal file
97
bower_components/leaflet-search/style.css
vendored
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
body {
|
||||
background:#b5d0d0;
|
||||
color:#285585;
|
||||
font-family:Arial;
|
||||
}
|
||||
body#home {
|
||||
background:url('images/back.png') no-repeat top left #b5d0d0;
|
||||
margin-left:150px;
|
||||
}
|
||||
|
||||
a {
|
||||
color:#1978cf;
|
||||
}
|
||||
a:hover {
|
||||
color:#fff;
|
||||
}
|
||||
h2, h3, h4 {
|
||||
white-space:nowrap;
|
||||
margin:1em 0 0 0;
|
||||
}
|
||||
h3 a,
|
||||
h3 a:hover {
|
||||
text-decoration:none;
|
||||
}
|
||||
#desc {
|
||||
float: left;
|
||||
margin-bottom: 1em;
|
||||
position: relative;
|
||||
white-space:nowrap;
|
||||
font-size:1em;
|
||||
}
|
||||
#map {
|
||||
border-radius:.125em;
|
||||
border:2px solid #1978cf;
|
||||
box-shadow: 0 0 8px #999;
|
||||
float:left;
|
||||
width:600px;
|
||||
height:400px;
|
||||
}
|
||||
ul {
|
||||
font-size:.85em;
|
||||
margin:0;
|
||||
padding:0;
|
||||
}
|
||||
li {
|
||||
margin:0 0 2px 18px;
|
||||
}
|
||||
#post-it {
|
||||
width:9em;
|
||||
height:9em;
|
||||
margin-left:2em;
|
||||
padding:1em;
|
||||
float:left;
|
||||
background:#fbf5bf;
|
||||
border:1px solid #c6bb58;
|
||||
box-shadow: 2px 2px 6px #999;
|
||||
color:#666;
|
||||
}
|
||||
#copy {
|
||||
position:fixed;
|
||||
z-index:1000;
|
||||
right:150px;
|
||||
top:-8px;
|
||||
font-size:.85em;
|
||||
padding:8px 8px 2px 8px;
|
||||
background: #323b44;
|
||||
border: 2px solid #737c85;
|
||||
border-radius:.7em;
|
||||
opacity: 0.9;
|
||||
box-shadow:0 0 8px #5f7182;
|
||||
color:#eee
|
||||
}
|
||||
#copy a {
|
||||
color:#ccc;
|
||||
text-decoration:none
|
||||
}
|
||||
#copy a:hover {
|
||||
color:#fff
|
||||
}
|
||||
#ribbon {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
border: 0;
|
||||
filter: alpha(opacity=80);
|
||||
-khtml-opacity: .8;
|
||||
-moz-opacity: .8;
|
||||
opacity: .8;
|
||||
}
|
||||
.contents {
|
||||
float:left;
|
||||
margin:0 2em 2em 0;
|
||||
}
|
||||
#comments {
|
||||
clear:both;
|
||||
}
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue