From 02ac641e5f52bc36ce14f67fb7c594ef20c3826e Mon Sep 17 00:00:00 2001 From: David Molineus Date: Sat, 10 Jan 2015 12:55:48 +0100 Subject: [PATCH] Extract libraries to an separate extension. --- assets/control-geocoder/Control.Geocoder.css | 140 + assets/control-geocoder/Control.Geocoder.js | 735 ++ assets/control-geocoder/LICENSE | 23 + assets/control-geocoder/README.md | 156 + assets/control-geocoder/images/geocoder.png | Bin 0 -> 466 bytes assets/control-geocoder/images/throbber.gif | Bin 0 -> 4831 bytes assets/control-geocoder/package.json | 26 + assets/leaflet-ajax/README.md | 75 + assets/leaflet-ajax/leaflet.ajax.js | 740 ++ assets/leaflet-ajax/leaflet.ajax.min.js | 1 + assets/leaflet-ajax/license.md | 7 + assets/leaflet-ajax/package.json | 29 + assets/leaflet-loading/CONTRIBUTING.md | 19 + assets/leaflet-loading/Control.Loading.css | 23 + assets/leaflet-loading/Control.Loading.js | 262 + assets/leaflet-loading/LICENSE | 19 + assets/leaflet-loading/README.md | 83 + assets/leaflet-loading/bower.json | 27 + assets/leaflet-loading/loading.gif | Bin 0 -> 1840 bytes assets/leaflet/images/layers-2x.png | Bin 0 -> 2898 bytes assets/leaflet/images/layers.png | Bin 0 -> 1502 bytes assets/leaflet/images/marker-icon-2x.png | Bin 0 -> 4033 bytes assets/leaflet/images/marker-icon.png | Bin 0 -> 1747 bytes assets/leaflet/images/marker-shadow.png | Bin 0 -> 797 bytes assets/leaflet/leaflet-src.js | 9180 ++++++++++++++++++ assets/leaflet/leaflet.css | 478 + assets/leaflet/leaflet.js | 9 + composer.json | 35 + module/config/autload.ini | 2 + module/config/config.php | 63 + 30 files changed, 12132 insertions(+) create mode 100644 assets/control-geocoder/Control.Geocoder.css create mode 100644 assets/control-geocoder/Control.Geocoder.js create mode 100644 assets/control-geocoder/LICENSE create mode 100644 assets/control-geocoder/README.md create mode 100644 assets/control-geocoder/images/geocoder.png create mode 100644 assets/control-geocoder/images/throbber.gif create mode 100644 assets/control-geocoder/package.json create mode 100644 assets/leaflet-ajax/README.md create mode 100644 assets/leaflet-ajax/leaflet.ajax.js create mode 100644 assets/leaflet-ajax/leaflet.ajax.min.js create mode 100644 assets/leaflet-ajax/license.md create mode 100644 assets/leaflet-ajax/package.json create mode 100644 assets/leaflet-loading/CONTRIBUTING.md create mode 100644 assets/leaflet-loading/Control.Loading.css create mode 100644 assets/leaflet-loading/Control.Loading.js create mode 100644 assets/leaflet-loading/LICENSE create mode 100644 assets/leaflet-loading/README.md create mode 100644 assets/leaflet-loading/bower.json create mode 100644 assets/leaflet-loading/loading.gif create mode 100644 assets/leaflet/images/layers-2x.png create mode 100644 assets/leaflet/images/layers.png create mode 100644 assets/leaflet/images/marker-icon-2x.png create mode 100644 assets/leaflet/images/marker-icon.png create mode 100644 assets/leaflet/images/marker-shadow.png create mode 100644 assets/leaflet/leaflet-src.js create mode 100644 assets/leaflet/leaflet.css create mode 100644 assets/leaflet/leaflet.js create mode 100644 composer.json create mode 100644 module/config/autload.ini create mode 100644 module/config/config.php diff --git a/assets/control-geocoder/Control.Geocoder.css b/assets/control-geocoder/Control.Geocoder.css new file mode 100644 index 0000000..407f8f0 --- /dev/null +++ b/assets/control-geocoder/Control.Geocoder.css @@ -0,0 +1,140 @@ +.leaflet-control-geocoder { + background: white; + box-shadow: 0 1px 7px rgba(0,0,0,0.65); + -webkit-border-radius: 4px; + border-radius: 4px; + line-height: 26px; + overflow: hidden; +} + +.leaflet-touch .leaflet-control-geocoder { + box-shadow: none; + border: 2px solid rgba(0,0,0,0.2); + background-clip: padding-box; + line-height: 30px; +} + +.leaflet-control-geocoder-form { + display: inline; +} + +.leaflet-control-geocoder-form input, .leaflet-control-geocoder-form ul, .leaflet-control-geocoder-error { + border: 0; + color: transparent; + background: white; +} + +.leaflet-control-geocoder-form input { + font-size: 16px; + width: 0; + transition: width 0.125s ease-in; +} + +.leaflet-touch .leaflet-control-geocoder-form input { + font-size: 22px; +} + +.leaflet-control-geocoder-icon { + width: 26px; + height: 26px; + background-image: url('images/geocoder.png'); + background-repeat: no-repeat; + background-position: center; + float: right; + cursor: pointer; +} + +.leaflet-touch .leaflet-control-geocoder-icon { + margin-top: 2px; + width: 30px; +} + +.leaflet-control-geocoder-throbber .leaflet-control-geocoder-icon { + background-image: url('images/throbber.gif'); +} + +.leaflet-control-geocoder-expanded input, .leaflet-control-geocoder-error { + width: 226px; + margin: 0 0 0 4px; + padding: 0 0 0 4px; + vertical-align: middle; + color: #000; +} + +.leaflet-control-geocoder-form input:focus { + outline: none; +} + +.leaflet-control-geocoder-form button { + display: none; +} + +.leaflet-control-geocoder-form-no-error { + display: none; +} + +.leaflet-control-geocoder-error { + margin-top: 8px; + display: block; + color: #444; +} + +ul.leaflet-control-geocoder-alternatives { + width: 260px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + list-style: none; + padding: 0; + transition: height 0.125s ease-in; +} + +.leaflet-control-geocoder-alternatives-minimized { + width: 0 !important; + height: 0; + overflow: hidden; + margin: 0; + padding: 0; +} + +.leaflet-control-geocoder-alternatives li { + width: 100%; + overflow: hidden; + text-overflow: ellipsis; + border-bottom: 1px solid #eee; + padding: 0; +} + + +.leaflet-control-geocoder-alternatives li:last-child { + border-bottom: none; +} + +.leaflet-control-geocoder-alternatives a { + display: block; + text-decoration: none; + color: black; + padding: 6px 8px 16px 6px; + font-size: 14px; + line-height: 1; + font-weight: bold; +} + +.leaflet-touch .leaflet-control-geocoder-alternatives a { + font-size: 18px; +} + +.leaflet-control-geocoder-alternatives a:hover, .leaflet-control-geocoder-selected { + background-color: #ddd; +} + +.leaflet-control-geocoder-address-detail { + font-size: 12px; + font-weight: normal; +} + +.leaflet-control-geocoder-address-context { + color: #666; + font-size: 12px; + font-weight: lighter; +} diff --git a/assets/control-geocoder/Control.Geocoder.js b/assets/control-geocoder/Control.Geocoder.js new file mode 100644 index 0000000..58b8e83 --- /dev/null +++ b/assets/control-geocoder/Control.Geocoder.js @@ -0,0 +1,735 @@ +(function (factory) { + // Packaging/modules magic dance + var L; + if (typeof define === 'function' && define.amd) { + // AMD + define(['leaflet'], factory); + } else if (typeof module !== 'undefined') { + // Node/CommonJS + L = require('leaflet'); + module.exports = factory(L); + } else { + // Browser globals + if (typeof window.L === 'undefined') + throw 'Leaflet must be loaded first'; + factory(window.L); + } +}(function (L) { + 'use strict'; + L.Control.Geocoder = L.Control.extend({ + options: { + showResultIcons: false, + collapsed: true, + expand: 'click', + position: 'topright', + placeholder: 'Search...', + errorMessage: 'Nothing found.' + }, + + _callbackId: 0, + + initialize: function (options) { + L.Util.setOptions(this, options); + if (!this.options.geocoder) { + this.options.geocoder = new L.Control.Geocoder.Nominatim(); + } + }, + + onAdd: function (map) { + var className = 'leaflet-control-geocoder', + container = L.DomUtil.create('div', className), + icon = L.DomUtil.create('div', 'leaflet-control-geocoder-icon', container), + form = this._form = L.DomUtil.create('form', className + '-form', container), + input; + + this._map = map; + this._container = container; + input = this._input = L.DomUtil.create('input'); + input.type = 'text'; + input.placeholder = this.options.placeholder; + + L.DomEvent.addListener(input, 'keydown', this._keydown, this); + //L.DomEvent.addListener(input, 'onpaste', this._clearResults, this); + //L.DomEvent.addListener(input, 'oninput', this._clearResults, this); + + this._errorElement = document.createElement('div'); + this._errorElement.className = className + '-form-no-error'; + this._errorElement.innerHTML = this.options.errorMessage; + + this._alts = L.DomUtil.create('ul', className + '-alternatives leaflet-control-geocoder-alternatives-minimized'); + + form.appendChild(input); + form.appendChild(this._errorElement); + container.appendChild(this._alts); + + L.DomEvent.addListener(form, 'submit', this._geocode, this); + + if (this.options.collapsed) { + if (this.options.expand === 'click') { + L.DomEvent.addListener(icon, 'click', function(e) { + // TODO: touch + if (e.button === 0 && e.detail !== 2) { + this._toggle(); + } + }, this); + } else { + L.DomEvent.addListener(icon, 'mouseover', this._expand, this); + L.DomEvent.addListener(icon, 'mouseout', this._collapse, this); + this._map.on('movestart', this._collapse, this); + } + } else { + this._expand(); + } + + L.DomEvent.disableClickPropagation(container); + + return container; + }, + + _geocodeResult: function (results) { + L.DomUtil.removeClass(this._container, 'leaflet-control-geocoder-throbber'); + if (results.length === 1) { + this._geocodeResultSelected(results[0]); + } else if (results.length > 0) { + this._alts.innerHTML = ''; + this._results = results; + L.DomUtil.removeClass(this._alts, 'leaflet-control-geocoder-alternatives-minimized'); + for (var i = 0; i < results.length; i++) { + this._alts.appendChild(this._createAlt(results[i], i)); + } + } else { + L.DomUtil.addClass(this._errorElement, 'leaflet-control-geocoder-error'); + } + }, + + markGeocode: function(result) { + this._map.fitBounds(result.bbox); + + if (this._geocodeMarker) { + this._map.removeLayer(this._geocodeMarker); + } + + this._geocodeMarker = new L.Marker(result.center) + .bindPopup(result.html || result.name) + .addTo(this._map) + .openPopup(); + + return this; + }, + + _geocode: function(event) { + L.DomEvent.preventDefault(event); + + L.DomUtil.addClass(this._container, 'leaflet-control-geocoder-throbber'); + this._clearResults(); + this.options.geocoder.geocode(this._input.value, this._geocodeResult, this); + + return false; + }, + + _geocodeResultSelected: function(result) { + if (this.options.collapsed) { + this._collapse(); + } else { + this._clearResults(); + } + this.markGeocode(result); + }, + + _toggle: function() { + if (this._container.className.indexOf('leaflet-control-geocoder-expanded') >= 0) { + this._collapse(); + } else { + this._expand(); + } + }, + + _expand: function () { + L.DomUtil.addClass(this._container, 'leaflet-control-geocoder-expanded'); + this._input.select(); + }, + + _collapse: function () { + this._container.className = this._container.className.replace(' leaflet-control-geocoder-expanded', ''); + L.DomUtil.addClass(this._alts, 'leaflet-control-geocoder-alternatives-minimized'); + L.DomUtil.removeClass(this._errorElement, 'leaflet-control-geocoder-error'); + }, + + _clearResults: function () { + L.DomUtil.addClass(this._alts, 'leaflet-control-geocoder-alternatives-minimized'); + this._selection = null; + L.DomUtil.removeClass(this._errorElement, 'leaflet-control-geocoder-error'); + }, + + _createAlt: function(result, index) { + var li = document.createElement('li'), + a = L.DomUtil.create('a', '', li), + icon = this.options.showResultIcons && result.icon ? L.DomUtil.create('img', '', a) : null, + text = result.html ? undefined : document.createTextNode(result.name); + + if (icon) { + icon.src = result.icon; + } + + a.href = '#'; + a.setAttribute('data-result-index', index); + + if (result.html) { + a.innerHTML = result.html; + } else { + a.appendChild(text); + } + + L.DomEvent.addListener(li, 'click', function clickHandler(e) { + L.DomEvent.preventDefault(e); + this._geocodeResultSelected(result); + }, this); + + return li; + }, + + _keydown: function(e) { + var _this = this, + select = function select(dir) { + if (_this._selection) { + L.DomUtil.removeClass(_this._selection.firstChild, 'leaflet-control-geocoder-selected'); + _this._selection = _this._selection[dir > 0 ? 'nextSibling' : 'previousSibling']; + } + if (!_this._selection) { + _this._selection = _this._alts[dir > 0 ? 'firstChild' : 'lastChild']; + } + + if (_this._selection) { + L.DomUtil.addClass(_this._selection.firstChild, 'leaflet-control-geocoder-selected'); + } + }; + + switch (e.keyCode) { + // Escape + case 27: + if (this.options.collapsed) { + this._collapse(); + } + break; + // Up + case 38: + select(-1); + L.DomEvent.preventDefault(e); + break; + // Up + case 40: + select(1); + L.DomEvent.preventDefault(e); + break; + // Enter + case 13: + if (this._selection) { + var index = parseInt(this._selection.firstChild.getAttribute('data-result-index'), 10); + this._geocodeResultSelected(this._results[index]); + this._clearResults(); + L.DomEvent.preventDefault(e); + } + } + return true; + } + }); + + L.Control.geocoder = function(id, options) { + return new L.Control.Geocoder(id, options); + }; + + L.Control.Geocoder.callbackId = 0; + L.Control.Geocoder.jsonp = function(url, params, callback, context, jsonpParam) { + var callbackId = '_l_geocoder_' + (L.Control.Geocoder.callbackId++); + params[jsonpParam || 'callback'] = callbackId; + window[callbackId] = L.Util.bind(callback, context); + var script = document.createElement('script'); + script.type = 'text/javascript'; + script.src = url + L.Util.getParamString(params); + script.id = callbackId; + document.getElementsByTagName('head')[0].appendChild(script); + }; + L.Control.Geocoder.getJSON = function(url, params, callback) { + var xmlHttp = new XMLHttpRequest(); + xmlHttp.open( "GET", url + L.Util.getParamString(params), true); + xmlHttp.send(null); + xmlHttp.onreadystatechange = function () { + if (xmlHttp.readyState != 4) return; + if (xmlHttp.status != 200 && req.status != 304) return; + callback(JSON.parse(xmlHttp.response)); + }; + }; + + L.Control.Geocoder.template = function (str, data, htmlEscape) { + return str.replace(/\{ *([\w_]+) *\}/g, function (str, key) { + var value = data[key]; + if (value === undefined) { + value = ''; + } else if (typeof value === 'function') { + value = value(data); + } + return L.Control.Geocoder.htmlEscape(value); + }); + }; + + // Adapted from handlebars.js + // https://github.com/wycats/handlebars.js/ + L.Control.Geocoder.htmlEscape = (function() { + var badChars = /[&<>"'`]/g; + var possible = /[&<>"'`]/; + var escape = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + '\'': ''', + '`': '`' + }; + + function escapeChar(chr) { + return escape[chr]; + } + + return function(string) { + if (string == null) { + return ''; + } else if (!string) { + return string + ''; + } + + // Force a string conversion as this will be done by the append regardless and + // the regex test will do this transparently behind the scenes, causing issues if + // an object's to string has escaped characters in it. + string = '' + string; + + if (!possible.test(string)) { + return string; + } + return string.replace(badChars, escapeChar); + }; + })(); + + L.Control.Geocoder.Nominatim = L.Class.extend({ + options: { + serviceUrl: '//nominatim.openstreetmap.org/', + geocodingQueryParams: {}, + reverseQueryParams: {}, + htmlTemplate: function(r) { + var a = r.address, + parts = []; + if (a.road || a.building) { + parts.push('{building} {road} {house_number}'); + } + + if (a.city || a.town || a.village) { + parts.push('{postcode} {city}{town}{village}'); + } + + if (a.state || a.country) { + parts.push('{state} {country}'); + } + + return L.Control.Geocoder.template(parts.join('
'), a, true); + } + }, + + initialize: function(options) { + L.Util.setOptions(this, options); + }, + + geocode: function(query, cb, context) { + L.Control.Geocoder.jsonp(this.options.serviceUrl + 'search/', L.extend({ + q: query, + limit: 5, + format: 'json', + addressdetails: 1 + }, this.options.geocodingQueryParams), + function(data) { + var results = []; + for (var i = data.length - 1; i >= 0; i--) { + var bbox = data[i].boundingbox; + for (var j = 0; j < 4; j++) bbox[j] = parseFloat(bbox[j]); + results[i] = { + icon: data[i].icon, + name: data[i].display_name, + html: this.options.htmlTemplate ? + this.options.htmlTemplate(data[i]) + : undefined, + bbox: L.latLngBounds([bbox[0], bbox[2]], [bbox[1], bbox[3]]), + center: L.latLng(data[i].lat, data[i].lon), + properties: data[i] + }; + } + cb.call(context, results); + }, this, 'json_callback'); + }, + + reverse: function(location, scale, cb, context) { + L.Control.Geocoder.jsonp(this.options.serviceUrl + 'reverse/', L.extend({ + lat: location.lat, + lon: location.lng, + zoom: Math.round(Math.log(scale / 256) / Math.log(2)), + addressdetails: 1, + format: 'json' + }, this.options.reverseQueryParams), function(data) { + var result = [], + loc; + + if (data && data.lat && data.lon) { + loc = L.latLng(data.lat, data.lon); + result.push({ + name: data.display_name, + html: this.options.htmlTemplate ? + this.options.htmlTemplate(data) + : undefined, + center: loc, + bounds: L.latLngBounds(loc, loc), + properties: data + }); + } + + cb.call(context, result); + }, this, 'json_callback'); + } + }); + + L.Control.Geocoder.nominatim = function(options) { + return new L.Control.Geocoder.Nominatim(options); + }; + + L.Control.Geocoder.Bing = L.Class.extend({ + initialize: function(key) { + this.key = key; + }, + + geocode : function (query, cb, context) { + L.Control.Geocoder.jsonp('//dev.virtualearth.net/REST/v1/Locations', { + query: query, + key : this.key + }, function(data) { + var results = []; + for (var i = data.resourceSets[0].resources.length - 1; i >= 0; i--) { + var resource = data.resourceSets[0].resources[i], + bbox = resource.bbox; + results[i] = { + name: resource.name, + bbox: L.latLngBounds([bbox[0], bbox[1]], [bbox[2], bbox[3]]), + center: L.latLng(resource.point.coordinates) + }; + } + cb.call(context, results); + }, this, 'jsonp'); + }, + + reverse: function(location, scale, cb, context) { + L.Control.Geocoder.jsonp('//dev.virtualearth.net/REST/v1/Locations/' + location.lat + ',' + location.lng, { + key : this.key + }, function(data) { + var results = []; + for (var i = data.resourceSets[0].resources.length - 1; i >= 0; i--) { + var resource = data.resourceSets[0].resources[i], + bbox = resource.bbox; + results[i] = { + name: resource.name, + bbox: L.latLngBounds([bbox[0], bbox[1]], [bbox[2], bbox[3]]), + center: L.latLng(resource.point.coordinates) + }; + } + cb.call(context, results); + }, this, 'jsonp'); + } + }); + + L.Control.Geocoder.bing = function(key) { + return new L.Control.Geocoder.Bing(key); + }; + + L.Control.Geocoder.RaveGeo = L.Class.extend({ + options: { + querySuffix: '', + deepSearch: true, + wordBased: false + }, + + jsonp: function(params, callback, context) { + var callbackId = '_l_geocoder_' + (L.Control.Geocoder.callbackId++), + paramParts = []; + params.prepend = callbackId + '('; + params.append = ')'; + for (var p in params) { + paramParts.push(p + '=' + escape(params[p])); + } + + window[callbackId] = L.Util.bind(callback, context); + var script = document.createElement('script'); + script.type = 'text/javascript'; + script.src = this._serviceUrl + '?' + paramParts.join('&'); + script.id = callbackId; + document.getElementsByTagName('head')[0].appendChild(script); + }, + + initialize: function(serviceUrl, scheme, options) { + L.Util.setOptions(this, options); + + this._serviceUrl = serviceUrl; + this._scheme = scheme; + }, + + geocode: function(query, cb, context) { + L.Control.Geocoder.jsonp(this._serviceUrl, { + address: query + this.options.querySuffix, + scheme: this._scheme, + outputFormat: 'jsonp', + deepSearch: this.options.deepSearch, + wordBased: this.options.wordBased + }, function(data) { + var results = []; + for (var i = data.length - 1; i >= 0; i--) { + var r = data[i], + c = L.latLng(r.y, r.x); + results[i] = { + name: r.address, + bbox: L.latLngBounds([c]), + center: c + }; + } + cb.call(context, results); + }, this); + } + }); + + L.Control.Geocoder.raveGeo = function(serviceUrl, scheme, options) { + return new L.Control.Geocoder.RaveGeo(serviceUrl, scheme, options); + }; + + L.Control.Geocoder.MapQuest = L.Class.extend({ + initialize: function(key) { + // MapQuest seems to provide URI encoded API keys, + // so to avoid encoding them twice, we decode them here + this._key = decodeURIComponent(key); + }, + + _formatName: function() { + var r = [], + i; + for (i = 0; i < arguments.length; i++) { + if (arguments[i]) { + r.push(arguments[i]); + } + } + + return r.join(', '); + }, + + geocode: function(query, cb, context) { + L.Control.Geocoder.jsonp('//www.mapquestapi.com/geocoding/v1/address', { + key: this._key, + location: query, + limit: 5, + outFormat: 'json' + }, function(data) { + var results = [], + loc, + latLng; + if (data.results && data.results[0].locations) { + for (var i = data.results[0].locations.length - 1; i >= 0; i--) { + loc = data.results[0].locations[i]; + latLng = L.latLng(loc.latLng); + results[i] = { + name: this._formatName(loc.street, loc.adminArea4, loc.adminArea3, loc.adminArea1), + bbox: L.latLngBounds(latLng, latLng), + center: latLng + }; + } + } + + cb.call(context, results); + }, this); + }, + + reverse: function(location, scale, cb, context) { + L.Control.Geocoder.jsonp('//www.mapquestapi.com/geocoding/v1/reverse', { + key: this._key, + location: location.lat + ',' + location.lng, + outputFormat: 'json' + }, function(data) { + var results = [], + loc, + latLng; + if (data.results && data.results[0].locations) { + for (var i = data.results[0].locations.length - 1; i >= 0; i--) { + loc = data.results[0].locations[i]; + latLng = L.latLng(loc.latLng); + results[i] = { + name: this._formatName(loc.street, loc.adminArea4, loc.adminArea3, loc.adminArea1), + bbox: L.latLngBounds(latLng, latLng), + center: latLng + }; + } + } + + cb.call(context, results); + }, this); + } + }); + + L.Control.Geocoder.mapQuest = function(key) { + return new L.Control.Geocoder.MapQuest(key); + }; + + L.Control.Geocoder.Mapbox = L.Class.extend({ + options: { + service_url: 'https://api.tiles.mapbox.com/v4/geocode/mapbox.places-v1/' + }, + + initialize: function(access_token) { + this._access_token = access_token; + }, + + geocode: function(query, cb, context) { + L.Control.Geocoder.getJSON(this.options.service_url + encodeURIComponent(query) + '.json', { + access_token: this._access_token, + }, function(data) { + var results = [], + loc, + latLng, + latLngBounds; + if (data.features && data.features.length) { + for (var i = 0; i <= data.features.length - 1; i++) { + loc = data.features[i]; + latLng = L.latLng(loc.center.reverse()); + if(loc.hasOwnProperty('bbox')) + { + latLngBounds = L.latLngBounds(L.latLng(loc.bbox.slice(0, 2).reverse()), L.latLng(loc.bbox.slice(2, 4).reverse())); + } + else + { + latLngBounds = L.latLngBounds(latLng, latLng); + } + results[i] = { + name: loc.place_name, + bbox: latLngBounds, + center: latLng + }; + } + } + + cb.call(context, results); + }); + }, + + reverse: function(location, scale, cb, context) { + L.Control.Geocoder.getJSON(this.options.service_url + encodeURIComponent(location.lng) + ',' + encodeURIComponent(location.lat) + '.json', { + access_token: this._access_token, + }, function(data) { + var results = [], + loc, + latLng, + latLngBounds; + if (data.features && data.features.length) { + for (var i = 0; i <= data.features.length - 1; i++) { + loc = data.features[i]; + latLng = L.latLng(loc.center.reverse()); + if(loc.hasOwnProperty('bbox')) + { + latLngBounds = L.latLngBounds(L.latLng(loc.bbox.slice(0, 2).reverse()), L.latLng(loc.bbox.slice(2, 4).reverse())); + } + else + { + latLngBounds = L.latLngBounds(latLng, latLng); + } + results[i] = { + name: loc.place_name, + bbox: latLngBounds, + center: latLng + }; + } + } + + cb.call(context, results); + }); + } + }); + + L.Control.Geocoder.mapbox = function(access_token) { + return new L.Control.Geocoder.Mapbox(access_token); + }; + + L.Control.Geocoder.Google = L.Class.extend({ + options: { + service_url: 'https://maps.googleapis.com/maps/api/geocode/json' + }, + + initialize: function(key) { + this._key = key; + }, + + geocode: function(query, cb, context) { + var params = { + address: query, + }; + if(this._key && this._key.length) + { + params['key'] = this._key + } + + L.Control.Geocoder.getJSON(this.options.service_url, params, function(data) { + var results = [], + loc, + latLng, + latLngBounds; + if (data.results && data.results.length) { + for (var i = 0; i <= data.results.length - 1; i++) { + loc = data.results[i]; + latLng = L.latLng(loc.geometry.location); + latLngBounds = L.latLngBounds(L.latLng(loc.geometry.viewport.northeast), L.latLng(loc.geometry.viewport.southwest)); + results[i] = { + name: loc.formatted_address, + bbox: latLngBounds, + center: latLng + }; + } + } + + cb.call(context, results); + }); + }, + + reverse: function(location, scale, cb, context) { + var params = { + latlng: encodeURIComponent(location.lat) + ',' + encodeURIComponent(location.lng) + }; + if(this._key && this._key.length) + { + params['key'] = this._key + } + L.Control.Geocoder.getJSON(this.options.service_url, params, function(data) { + var results = [], + loc, + latLng, + latLngBounds; + if (data.results && data.results.length) { + for (var i = 0; i <= data.results.length - 1; i++) { + loc = data.results[i]; + latLng = L.latLng(loc.geometry.location); + latLngBounds = L.latLngBounds(L.latLng(loc.geometry.viewport.northeast), L.latLng(loc.geometry.viewport.southwest)); + results[i] = { + name: loc.formatted_address, + bbox: latLngBounds, + center: latLng + }; + } + } + + cb.call(context, results); + }); + } + }); + + L.Control.Geocoder.google = function(key) { + return new L.Control.Geocoder.Google(key); + }; + return L.Control.Geocoder; +})); diff --git a/assets/control-geocoder/LICENSE b/assets/control-geocoder/LICENSE new file mode 100644 index 0000000..cbfe31f --- /dev/null +++ b/assets/control-geocoder/LICENSE @@ -0,0 +1,23 @@ +Copyright (c) 2012 sa3m (https://github.com/sa3m) +Copyright (c) 2013 Per Liedman +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are +permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of + conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, this list + of conditions and the following disclaimer in the documentation and/or other materials + provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR +TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/assets/control-geocoder/README.md b/assets/control-geocoder/README.md new file mode 100644 index 0000000..f2b100f --- /dev/null +++ b/assets/control-geocoder/README.md @@ -0,0 +1,156 @@ +## A few words on diversity in tech + +I need to take some of your time. I can't believe we let shit like [the Kathy Sierra incident](http://www.wired.com/2014/10/trolls-will-always-win/) or [what happened to Brianna Wu](https://twitter.com/Spacekatgal/status/520739878993420290) happen over and over again. I can't believe we, the open source community, let [sexist, misogynous shit happen over and over again](http://geekfeminism.wikia.com/wiki/Timeline_of_incidents). + +I strongly believe that it is my — and your — duty to make the open source community, as well as the tech community at large, a community where everyone feel welcome and is accepted. At the very minimum, that means making sure the community and its forums both _are_ safe, and are perceived as safe. It means being friendly and inclusive, even when you disagree with people. It means not shrugging of discussions about sexism and inclusiveness with [handwaving about censorship and free speech](https://josm.openstreetmap.de/ticket/10568). For a more elaborate document on what that means, [the NPM Code of Conduct](http://www.npmjs.com/policies/conduct) is a good start, [Geek Feminism's resources for allies](http://geekfeminism.wikia.com/wiki/Resources_for_allies) contains much more. + +While I can't force anyone to do anything, if you happen to disagree with this, I ask of you not to use any of the open source I have published. Nor am I interested in contributions from people who can't accept or act respectfully towards other humans regardless of gender identity, sexual orientation, disability, ethnicity, religion, age, physical appearance, body size, race, or similar personal characteristics. If you think feminism, anti-racism or the LGBT movement is somehow wrong, disturbing or irrelevant, I ask you to go elsewhere to find software. + +Leaflet Control Geocoder [![NPM version](https://badge.fury.io/js/leaflet-control-geocoder.png)](http://badge.fury.io/js/leaflet-control-geocoder) +============================= + +A simple geocoder for [Leaflet](http://leafletjs.com/) that by default uses [OSM](http://www.openstreetmap.org/)/[Nominatim](http://wiki.openstreetmap.org/wiki/Nominatim). + +The plugin supports many different data providers: + +* [OSM](http://www.openstreetmap.org/)/[Nominatim](http://wiki.openstreetmap.org/wiki/Nominatim) +* [Bing Locations API](http://msdn.microsoft.com/en-us/library/ff701715.aspx) +* [Google Geocoding API](https://developers.google.com/maps/documentation/geocoding/) +* [Mapbox Geocoding](https://www.mapbox.com/developers/api/geocoding/) +* [MapQuest Geocoding API](http://developer.mapquest.com/web/products/dev-services/geocoding-ws) +* [RaveGeo](http://www2.idevio.com/ravegeo-server.html) + +The plugin can easily be extended to support other providers. + +See the [Leaflet Control Geocoder Demo](http://perliedman.github.com/leaflet-control-geocoder/). + +# Usage + +Load the CSS and Javascript: + +```HTML + + +``` + +Add the control to a map instance: + +```javascript +var map = L.map('map').setView([0, 0], 2); +L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', { + attribution: '© OpenStreetMap contributors' +}).addTo(map); +L.Control.geocoder().addTo(map); +``` + +# Customizing + +By default, when a geocoding result is found, the control will center the map on it and place +a marker at its location. This can be customized by overwriting the control's ```markGeocode``` +function, to perform any action desired. + +For example: + +```javascript +var geocoder = L.Control.geocoder().addTo(map); + +geocoder.markGeocode = function(result) { + var bbox = result.bbox; + L.polygon([ + bbox.getSouthEast(), + bbox.getNorthEast(), + bbox.getNorthWest(), + bbox.getSouthWest() + ]).addTo(map); +}; +``` + +This will add a polygon representing the result's boundingbox when a result is selected. + +# API + +## L.Control.Geocoder + +This is the geocoder control. It works like any other Leaflet control, and is added to the map. + +### Constructor + +```js +L.Control.Geocoder(options) +``` + +### Options + +| Option | Type | Default | Description | +| --------------- | ---------------- | ----------------- | ----------- | +| collapsed | Boolean | true | Collapse control unless hovered/clicked | +| position | String | "topright" | Control [position](http://leafletjs.com/reference.html#control-positions) | +| placeholder | String | "Search..." | Placeholder text for text input +| errorMessage | String | "Nothing found." | Message when no result found / geocoding error occurs | +| geocoder | IGeocoder | new L.Control.Geocoder.Nominatim() | Object to perform the actual geocoding queries | +| showResultIcons | Boolean | false | Show icons for geocoding results (if available); supported by Nominatim | + +### Methods + +| Method | Returns | Description | +| ------------------------------------- | ------------------- | ----------------- | +| markGeocode( result) | this | Marks a geocoding result on the map | + +## L.Control.Geocoder.Nominatim + +Uses [Nominatim](http://wiki.openstreetmap.org/wiki/Nominatim) to respond to geocoding queries. This is the default +geocoding service used by the control, unless otherwise specified in the options. Implements ```IGeocoder```. + +Unless using your own Nominatim installation, please refer to the [Nominatim usage policy](http://wiki.openstreetmap.org/wiki/Nominatim_usage_policy). + +### Constructor + +```js +L.Control.Geocoder.Nominatim(options) +``` + +## Options + +| Option | Type | Default | Description | +| --------------- | ---------------- | ----------------- | ----------- | +| serviceUrl | String | "http://nominatim.openstreetmap.org/" | URL of the service | +| geocodingQueryParams | Object | {} | Additional URL parameters (strings) that will be added to geocoding requests; can be used to restrict results to a specific country for example, by providing the [`countrycodes`](http://wiki.openstreetmap.org/wiki/Nominatim#Parameters) parameter to Nominatim | +| reverseQueryParams | Object | {} | Additional URL parameters (strings) that will be added to reverse geocoding requests | +| htmlTemplate | function | special | A function that takes an GeocodingResult as argument and returns an HTML formatted string that represents the result. Default function breaks up address in parts from most to least specific, in attempt to increase readability compared to Nominatim's naming + +## L.Control.Geocoder.Bing + +Uses [Bing Locations API](http://msdn.microsoft.com/en-us/library/ff701715.aspx) to respond to geocoding queries. Implements ```IGeocoder```. + +Note that you need an API key to use this service. + +### Constructor + +``` +L.Control.Geocoder.Bing( key) +``` + +## IGeocoder + +An interface implemented to respond to geocoding queries. + +### Methods + +| Method | Returns | Description | +| ------------------------------------- | ------------------- | ----------------- | +| geocode( query, callback, context) | GeocodingResult[] | Performs a geocoding query and returns the results to the callback in the provided context | +| reverse( location, scale, callback, context) | GeocodingResult[] | Performs a reverse geocoding query and returns the results to the callback in the provided context | + +## GeocodingResult + +An object that represents a result from a geocoding query. + +### Properties + +| Property | Type | Description | +| ---------- | ---------------- | ------------------------------------- | +| name | String | Name of found location | +| bounds | L.LatLngBounds | The bounds of the location | +| center | L.LatLng | The center coordinate of the location | +| icon | String | URL for icon representing result; optional | +| html | String | (optional) HTML formatted representation of the name | diff --git a/assets/control-geocoder/images/geocoder.png b/assets/control-geocoder/images/geocoder.png new file mode 100644 index 0000000000000000000000000000000000000000..246bbe7687f485cdd72e599e8ebba0dc6a41752a GIT binary patch literal 466 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", + "license": "BSD-2-Clause", + "bugs": { + "url": "https://github.com/perliedman/leaflet-control-geocoder/issues" + }, + "dependencies": { + "leaflet": "~0.7.2" + } +} diff --git a/assets/leaflet-ajax/README.md b/assets/leaflet-ajax/README.md new file mode 100644 index 0000000..ab0c8f2 --- /dev/null +++ b/assets/leaflet-ajax/README.md @@ -0,0 +1,75 @@ +leaflet-ajax +=========== + +Allows you to call JSON via an Ajax call with a jsonp fallback. + +```javascript +var geojsonLayer = new L.GeoJSON.AJAX("geojson.json"); +``` +for jsonp add the option "dataType" and set it to "jsonp" +``` javascript +var geojsonLayer = L.geoJson.ajax("http:webhost.fake/geojson.jsonp",{dataType:"jsonp"}); +``` +Note that data starts to download when the layer is created NOT when it’s added to the map in order to get a head start. + +You may pass either a url string or an array of url strings if you want to download multiple things (handy +if your downloading data from an ESRI based thing which will have separate line, point, and poly features). + +As you see you can also use lower case methods without creating new objects + +For weirder jsonp you can set "callbackParam" for if you need to change the name of the callback parameter to something besides "callback", e.g. [Mapquest Nominative Open](http://open.mapquestapi.com/nominatim/) uses "json_callback" instead of "callback". + +If you want to use `eval` to parse JSON in older browsers you need to pass an option `evil` set to something truthy. + +If you want to be able to load stuff from the file system (with appropriate custom flags set) set local to true. + +Gives off three events `data:loading`, `data:progress` and `data:loaded`. + +- `data:loading` fires before we start downloading things, note if the constructor is given a url it won't wait to be added to the map +to start downloading the data, but it does do an async wait so you have time to add a listener to it (and so [leaflet.spin](https://github.com/makinacorpus/Leaflet.Spin) will work with it). +- `data:progress` is called each time a file is downloaded and passes the downloaded geojson as event data. +- `data:loaded` is called when all files have downloaded, this is mainly different from `data:progress` when you are downloading multiple things. + +You can also add a middleware function which is called after you download the data but before you add it to leaflet: + +```javascript +var geojsonLayer = L.geoJson.ajax("route/to/esri.json",{ + middleware:function(data){ + return esri2geoOrSomething(json); + } + }); +``` + +addUrl does not clear the current layers but adds to the current one, e.g.: + +```javascript +var geojsonLayer = L.geoJson.ajax("data.json"); +geojsonLayer.addUrl("data2.json");//we now have 2 layers +geojsonLayer.refresh();//redownload the most recent layer +geojsonLayer.refresh("new1.json");//add a new layer replacing whatever is there +``` + +last but now least we can refilter layers without re adding them + +```javascript +var geojsonLayer = L.geoJson.ajax("data.json"); +geojsonLayer.refilter(function(feature){ + return feature.properties.key === values; +}); +``` + +Behind the scenes are two new classes L.Util.ajax = function (url) for same origin requests and L.Util.jsonp = function (url,options) cross origin ones. Both return promises, which have an additional abort method that will abort the ajax request. + +```js +L.Util.ajax("url/same/origin.xml").then(function(data){ + doStuff(data); +}); +//or +L.Util.jsonp("http://www.dif.ori/gin").then(function(data){ + doStuff(data); +}); +``` + +In related news `L.Util.Promise` is now a constructor for a promise, it takes one argument, a resolver function. + +Some of the jsonp code inspired by/taken from [this interesting looking plugin](https://github.com/stefanocudini/leaflet-search) that I have failed to make heads nor tails of (the plugin, not the jsonp code) diff --git a/assets/leaflet-ajax/leaflet.ajax.js b/assets/leaflet-ajax/leaflet.ajax.js new file mode 100644 index 0000000..9914f7e --- /dev/null +++ b/assets/leaflet-ajax/leaflet.ajax.js @@ -0,0 +1,740 @@ +;(function(){ + +/** + * Require the given path. + * + * @param {String} path + * @return {Object} exports + * @api public + */ + +function require(path, parent, orig) { + var resolved = require.resolve(path); + + // lookup failed + if (null == resolved) { + orig = orig || path; + parent = parent || 'root'; + var err = new Error('Failed to require "' + orig + '" from "' + parent + '"'); + err.path = orig; + err.parent = parent; + err.require = true; + throw err; + } + + var module = require.modules[resolved]; + + // perform real require() + // by invoking the module's + // registered function + if (!module.exports) { + module.exports = {}; + module.client = module.component = true; + module.call(this, module.exports, require.relative(resolved), module); + } + + return module.exports; +} + +/** + * Registered modules. + */ + +require.modules = {}; + +/** + * Registered aliases. + */ + +require.aliases = {}; + +/** + * Resolve `path`. + * + * Lookup: + * + * - PATH/index.js + * - PATH.js + * - PATH + * + * @param {String} path + * @return {String} path or null + * @api private + */ + +require.resolve = function(path) { + if (path.charAt(0) === '/') path = path.slice(1); + + var paths = [ + path, + path + '.js', + path + '.json', + path + '/index.js', + path + '/index.json' + ]; + + for (var i = 0; i < paths.length; i++) { + var path = paths[i]; + if (require.modules.hasOwnProperty(path)) return path; + if (require.aliases.hasOwnProperty(path)) return require.aliases[path]; + } +}; + +/** + * Normalize `path` relative to the current path. + * + * @param {String} curr + * @param {String} path + * @return {String} + * @api private + */ + +require.normalize = function(curr, path) { + var segs = []; + + if ('.' != path.charAt(0)) return path; + + curr = curr.split('/'); + path = path.split('/'); + + for (var i = 0; i < path.length; ++i) { + if ('..' == path[i]) { + curr.pop(); + } else if ('.' != path[i] && '' != path[i]) { + segs.push(path[i]); + } + } + + return curr.concat(segs).join('/'); +}; + +/** + * Register module at `path` with callback `definition`. + * + * @param {String} path + * @param {Function} definition + * @api private + */ + +require.register = function(path, definition) { + require.modules[path] = definition; +}; + +/** + * Alias a module definition. + * + * @param {String} from + * @param {String} to + * @api private + */ + +require.alias = function(from, to) { + if (!require.modules.hasOwnProperty(from)) { + throw new Error('Failed to alias "' + from + '", it does not exist'); + } + require.aliases[to] = from; +}; + +/** + * Return a require function relative to the `parent` path. + * + * @param {String} parent + * @return {Function} + * @api private + */ + +require.relative = function(parent) { + var p = require.normalize(parent, '..'); + + /** + * lastIndexOf helper. + */ + + function lastIndexOf(arr, obj) { + var i = arr.length; + while (i--) { + if (arr[i] === obj) return i; + } + return -1; + } + + /** + * The relative require() itself. + */ + + function localRequire(path) { + var resolved = localRequire.resolve(path); + return require(resolved, parent, path); + } + + /** + * Resolve relative to the parent. + */ + + localRequire.resolve = function(path) { + var c = path.charAt(0); + if ('/' == c) return path.slice(1); + if ('.' == c) return require.normalize(p, path); + + // resolve deps by returning + // the dep in the nearest "deps" + // directory + var segs = parent.split('/'); + var i = lastIndexOf(segs, 'deps') + 1; + if (!i) i = 0; + path = segs.slice(0, i + 1).join('/') + '/deps/' + path; + return path; + }; + + /** + * Check if module is defined at `path`. + */ + + localRequire.exists = function(path) { + return require.modules.hasOwnProperty(localRequire.resolve(path)); + }; + + return localRequire; +}; +require.register("calvinmetcalf-setImmediate/lib/index.js", function(exports, require, module){ +"use strict"; +var types = [ + require("./nextTick"), + require("./mutation"), + require("./postMessage"), + require("./messageChannel"), + require("./stateChange"), + require("./timeout") +]; +var handlerQueue = []; + +function drainQueue() { + var i = 0, + task, + innerQueue = handlerQueue; + handlerQueue = []; + /*jslint boss: true */ + while (task = innerQueue[i++]) { + task(); + } +} +var nextTick; +types.some(function (obj) { + var t = obj.test(); + if (t) { + nextTick = obj.install(drainQueue); + } + return t; +}); +var retFunc = function (task) { + var len, args; + if (arguments.length > 1 && typeof task === "function") { + args = Array.prototype.slice.call(arguments, 1); + args.unshift(undefined); + task = task.bind.apply(task, args); + } + if ((len = handlerQueue.push(task)) === 1) { + nextTick(drainQueue); + } + return len; +}; +retFunc.clear = function (n) { + if (n <= handlerQueue.length) { + handlerQueue[n - 1] = function () {}; + } + return this; +}; +module.exports = retFunc; + +}); +require.register("calvinmetcalf-setImmediate/lib/nextTick.js", function(exports, require, module){ +"use strict"; +exports.test = function () { + // Don't get fooled by e.g. browserify environments. + return typeof process === "object" && Object.prototype.toString.call(process) === "[object process]"; +}; + +exports.install = function () { + return process.nextTick; +}; +}); +require.register("calvinmetcalf-setImmediate/lib/postMessage.js", function(exports, require, module){ +"use strict"; +var globe = require("./global"); +exports.test = function () { + // The test against `importScripts` prevents this implementation from being installed inside a web worker, + // where `global.postMessage` means something completely different and can"t be used for this purpose. + + if (!globe.postMessage || globe.importScripts) { + return false; + } + + var postMessageIsAsynchronous = true; + var oldOnMessage = globe.onmessage; + globe.onmessage = function () { + postMessageIsAsynchronous = false; + }; + globe.postMessage("", "*"); + globe.onmessage = oldOnMessage; + + return postMessageIsAsynchronous; +}; + +exports.install = function (func) { + var codeWord = "com.calvinmetcalf.setImmediate" + Math.random(); + function globalMessage(event) { + if (event.source === globe && event.data === codeWord) { + func(); + } + } + if (globe.addEventListener) { + globe.addEventListener("message", globalMessage, false); + } else { + globe.attachEvent("onmessage", globalMessage); + } + return function () { + globe.postMessage(codeWord, "*"); + }; +}; +}); +require.register("calvinmetcalf-setImmediate/lib/messageChannel.js", function(exports, require, module){ +"use strict"; +var globe = require("./global"); +exports.test = function () { + return !!globe.MessageChannel; +}; + +exports.install = function (func) { + var channel = new globe.MessageChannel(); + channel.port1.onmessage = func; + return function () { + channel.port2.postMessage(0); + }; +}; +}); +require.register("calvinmetcalf-setImmediate/lib/stateChange.js", function(exports, require, module){ +"use strict"; +var globe = require("./global"); +exports.test = function () { + return "document" in globe && "onreadystatechange" in globe.document.createElement("script"); +}; + +exports.install = function (handle) { + return function () { + + // Create a