diff --git a/appinfo/application.php b/appinfo/application.php index bd596b2..f6ce0b7 100644 --- a/appinfo/application.php +++ b/appinfo/application.php @@ -18,6 +18,7 @@ use \OCA\Maps\Db\DeviceMapper; use \OCA\Maps\Db\LocationMapper; use \OCA\Maps\Db\FavoriteMapper; +use \OCA\Maps\Db\ApiKeyMapper; use \OCA\Maps\Controller\PageController; use \OCA\Maps\Controller\LocationController; use \OCA\Maps\Controller\FavoriteController; @@ -41,7 +42,8 @@ public function __construct (array $urlParams=array()) { $c->query('Request'), $c->query('UserId'), $c->query('CacheManager'), - $c->query('DeviceMapper') + $c->query('DeviceMapper'), + $c->query('ApiKeyMapper') ); }); $container->registerService('LocationController', function($c) { @@ -89,6 +91,12 @@ public function __construct (array $urlParams=array()) { $server->getDb() ); }); + $container->registerService('ApiKeyMapper', function($c) use ($server) { + /** @var SimpleContainer $c */ + return new ApiKeyMapper( + $server->getDb() + ); + }); } diff --git a/appinfo/database.xml b/appinfo/database.xml index 11b1fbf..43e91df 100644 --- a/appinfo/database.xml +++ b/appinfo/database.xml @@ -173,4 +173,27 @@ + + *dbprefix*maps_apikeys + + + id + integer + 0 + true + 1 + 41 + + + user_id + text + 64 + + + api_key + text + 64 + + +
diff --git a/appinfo/routes.php b/appinfo/routes.php index bc9da3b..85c64fb 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -38,5 +38,9 @@ array('name' => 'favorite#get_favorites', 'url' => '/api/1.0/favorite/getFavorites', 'verb' => 'POST'), array('name' => 'favorite#remove_favorite', 'url' => '/api/1.0/favorite/removeFromFavorites', 'verb' => 'POST'), array('name' => 'favorite#update_favorite', 'url' => '/api/1.0/favorite/updateFavorite', 'verb' => 'POST'), + array('name' => 'favorite#get_favorites_by_name', 'url' => '/api/1.0/favorite/getFavoritesByName', 'verb' => 'POST'), + + array('name' => 'apikey#get_key', 'url' => '/api/1.0/apikey/getKey', 'verb' => 'POST'), + array('name' => 'apikey#add_key', 'url' => '/api/1.0/apikey/addKey', 'verb' => 'POST'), ))); diff --git a/controller/apikeycontroller.php b/controller/apikeycontroller.php new file mode 100644 index 0000000..df5e3f6 --- /dev/null +++ b/controller/apikeycontroller.php @@ -0,0 +1,103 @@ + + * @copyright Vinzenz Rosenkranz 2015 + */ + +namespace OCA\Maps\Controller; + +use OCA\Maps\Db\ApiKey; +use OCA\Maps\Db\ApiKeyMapper; +use \OCP\IRequest; +use \OCP\AppFramework\Http\JSONResponse; +use \OCP\AppFramework\ApiController; + + +class ApiKeyController extends ApiController { + + private $userId; + private $apiKeyMapper; + + public function __construct($appName, IRequest $request, ApiKeyMapper $apiKeyMapper, $userId) { + parent::__construct($appName, $request); + $this->apiKeyMapper = $apiKeyMapper; + $this->userId = $userId; + } + + /** + * @NoAdminRequired + * + * @param $key string + * @param $id int + * @return JSONResponse + */ + public function updateKey($key, $id) { + + $apikey = new ApiKey(); + $apikey->setId($id); + $apikey->setApiKey($key); + + /* Only save apiKey if it exists in db */ + try { + $this->apiKeyMapper->find($id); + return new JSONResponse($this->apiKeyMapper->update($apikey)); + } catch(\OCP\AppFramework\Db\DoesNotExistException $e) { + return new JSONResponse([ + 'error' => $e->getMessage() + ]); + } + } + + /** + * @NoAdminRequired + * + * @param $key string + * @return JSONResponse + */ + public function addKey($key){ + $apikey = new ApiKey(); + $apikey->setApiKey($key); + $apikey->setUserId($this->userId); + + /* @var $apikey ApiKey */ + $apikey = $this->apiKeyMapper->insert($apikey); + + $response = array('id'=> $apikey->getId()); + return new JSONResponse($response); + } + + /** + * @NoAdminRequired + * + * @return JSONResponse + */ + public function getKey(){ + $apikey = new ApiKey(); + try { + $apikey = $this->apiKeyMapper->findByUser($this->userId); + } catch(\OCP\AppFramework\Db\DoesNotExistException $e) { + $apikey->setUserId($this->userId); + } + return new JSONResponse($apikey); + } + + /** + * @NoAdminRequired + * + * @param $id int + * @return JSONResponse + */ + public function removeApiKey($id){ + $apikey = $this->apiKeyMapper->find($id); + if($apikey->userId == $this->userId) { + $this->apiKeyMapper->delete($apikey); + } + return new JSONResponse(); + } + +} diff --git a/controller/favoritecontroller.php b/controller/favoritecontroller.php index 0d736e7..ba34c6d 100644 --- a/controller/favoritecontroller.php +++ b/controller/favoritecontroller.php @@ -86,6 +86,18 @@ public function getFavorites(){ return new JSONResponse($favorites); } + /** + * @NoAdminRequired + * + * @param $name string + * + * @return JSONResponse + */ + public function getFavoritesByName($name){ + $favorites = $this->favoriteMapper->findByName($name); + return new JSONResponse($favorites); + } + /** * @NoAdminRequired * diff --git a/controller/pagecontroller.php b/controller/pagecontroller.php index 13ec0ea..5b201aa 100644 --- a/controller/pagecontroller.php +++ b/controller/pagecontroller.php @@ -11,7 +11,9 @@ namespace OCA\Maps\Controller; +use \OCA\Maps\Db\ApiKey; use \OCA\Maps\Db\DeviceMapper; +use \OCA\Maps\Db\ApiKeyMapper; use \OCP\IRequest; use \OCP\AppFramework\Http\TemplateResponse; use \OCP\AppFramework\Controller; @@ -22,13 +24,16 @@ class PageController extends Controller { private $userId; private $cacheManager; private $deviceMapper; + private $apiKeyMapper; public function __construct($appName, IRequest $request, $userId, CacheManager $cacheManager, - DeviceMapper $deviceMapper) { + DeviceMapper $deviceMapper, + ApiKeyMapper $apiKeyMapper) { parent::__construct($appName, $request); $this -> userId = $userId; $this -> cacheManager = $cacheManager; $this -> deviceMapper = $deviceMapper; + $this -> apiKeyMapper = $apiKeyMapper; } /** @@ -52,10 +57,25 @@ public function index() { // marker icons $csp->addAllowedImageDomain('https://api.tiles.mapbox.com'); // inline images - $csp->addAllowedScriptDomain('data:'); $csp->addAllowedImageDomain('data:'); //overpasslayer api $csp->addAllowedConnectDomain('http://overpass-api.de/api/interpreter?'); + $tmpkey = new ApiKey(); + try { + $tmpkey = $this->apiKeyMapper->findByUser($this->userId); + } catch(\OCP\AppFramework\Db\DoesNotExistException $e) { + $tmpkey->setUserId($this->userId); + } + if($tmpkey->apiKey != null && strlen($tmpkey->apiKey) > 0) { + // mapzen geocoder + $csp->addAllowedConnectDomain('http://search.mapzen.com/v1/search?'); + $csp->addAllowedConnectDomain('http://search.mapzen.com/v1/reverse?'); + } else { + // nominatim geocoder + $csp->addAllowedScriptDomain('http://nominatim.openstreetmap.org/search?q=*'); + $csp->addAllowedScriptDomain('http://nominatim.openstreetmap.org/reverse'); + $csp->addAllowedConnectDomain('http://router.project-osrm.org'); + } $response->setContentSecurityPolicy($csp); } return $response; @@ -106,7 +126,7 @@ public function search() { $kw = $this -> params('search'); $bbox = $this -> params('bbox'); $response = array('contacts'=>array(),'nodes'=>array(),'addresses'=>array()); - + $contacts = $cm -> search($kw, array('FN', 'ADR')); foreach ($contacts as $r) { $data = array(); @@ -126,7 +146,7 @@ public function search() { } } //$response['addresses'] = (array)($this->doAdresslookup($kw)); - + return $response; } @@ -139,9 +159,9 @@ public function geodecode(){ $lat = $this->params('lat'); $lng = $this->params('lng'); $zoom = $this->params('zoom'); - + $hash = md5($lat.','.$lng.'@'.$zoom); - + $checkCache = $this -> checkGeoCache($hash); if(!$checkCache){ $url = 'http://nominatim.openstreetmap.org/reverse/?format=json&email=brantje@gmail.com&lat='.$lat.'&lng='. $lng.'&zoom=67108864'; @@ -154,7 +174,7 @@ public function geodecode(){ } echo $response; die(); - } + } /** * Simply method that posts back the payload of the request * @NoAdminRequired @@ -217,7 +237,7 @@ private function getURL($url, $userAgent = true) { $ch = curl_init(); curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); curl_setopt($ch, CURLOPT_HEADER, 0); - curl_setopt($ch, CURLOPT_TIMEOUT, 900); + curl_setopt($ch, CURLOPT_TIMEOUT, 900); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); if ($userAgent) { curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.2) Gecko/20090729 Firefox/3.5.2 GTB5'); diff --git a/css/leaflet/Control.Geocoder.css b/css/leaflet/Control.Geocoder.css new file mode 100644 index 0000000..ddc78ae --- /dev/null +++ b/css/leaflet/Control.Geocoder.css @@ -0,0 +1,104 @@ +.leaflet-control-geocoder { + background: white; +} + +.leaflet-control-geocoder a, .leaflet-control-geocoder .leaflet-control-geocoder-icon { + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; + border-bottom: none; + display: inline-block; +} + +.leaflet-control-geocoder .leaflet-control-geocoder-alternatives a { + width: inherit; + height: inherit; + line-height: inherit; +} + +.leaflet-control-geocoder a:hover, .leaflet-control-geocoder .leaflet-control-geocoder-icon:hover { + border-bottom: none; + display: inline-block; +} + +.leaflet-control-geocoder-form { + display: none; + vertical-align: middle; +} +.leaflet-control-geocoder-expanded .leaflet-control-geocoder-form { + display: inline-block; +} +.leaflet-control-geocoder-form input { + font-size: 120%; + border: 0; + background-color: transparent; + width: 246px; +} +.leaflet-control-geocoder-icon { + background-image: url(images/geocoder.png); + background-repeat: no-repeat; + background-position: center; +} +.leaflet-control-geocoder-throbber .leaflet-control-geocoder-icon { + background-image: url(images/throbber.gif); +} + +.leaflet-control-geocoder-form-no-error { + display: none; +} + +.leaflet-control-geocoder-form input:focus { + outline: none; +} + +.leaflet-control-geocoder-form button { + display: none; +} +.leaflet-control-geocoder-error { + margin-top: 8px; + margin-left: 8px; + display: block; + color: #444; +} +.leaflet-control-geocoder-alternatives { + display: block; + width: 272px; + list-style: none; + padding: 0; + margin: 0; +} + +.leaflet-control-geocoder-alternatives-minimized { + display: none; + height: 0; +} +.leaflet-control-geocoder-alternatives li { + white-space: nowrap; + display: block; + overflow: hidden; + padding: 5px 8px; + text-overflow: ellipsis; + border-bottom: 1px solid #ccc; + cursor: pointer; +} + +.leaflet-control-geocoder-alternatives li a, .leaflet-control-geocoder-alternatives li a:hover { + width: inherit; + height: inherit; + line-height: inherit; + background: inherit; + border-radius: inherit; + text-align: left; +} + +.leaflet-control-geocoder-alternatives li:last-child { + border-bottom: none; +} +.leaflet-control-geocoder-alternatives li:hover, .leaflet-control-geocoder-selected { + background-color: #f5f5f5; +} +.leaflet-control-geocoder-address-detail { + +} +.leaflet-control-geocoder-address-context { + color: #666; +} diff --git a/css/leaflet/images/geocoder.png b/css/leaflet/images/geocoder.png new file mode 100644 index 0000000..d82a017 Binary files /dev/null and b/css/leaflet/images/geocoder.png differ diff --git a/css/leaflet/images/throbber.gif b/css/leaflet/images/throbber.gif new file mode 100644 index 0000000..c0c52a0 Binary files /dev/null and b/css/leaflet/images/throbber.gif differ diff --git a/css/leaflet/leaflet-routing-machine.css b/css/leaflet/leaflet-routing-machine.css index 3f55305..f513955 100644 --- a/css/leaflet/leaflet-routing-machine.css +++ b/css/leaflet/leaflet-routing-machine.css @@ -1,114 +1,258 @@ -.leaflet-routing-container { - width:240px; - padding-top: 4px; - transition: margin-right 0.2s ease; -} - -.leaflet-control-container .leaflet-routing-container-hide { - margin-right: -340px; -} - -.leaflet-routing-container h2 { - font-size: 14px; -} - -.leaflet-routing-container h3 { - font-size: 12px; - font-weight: normal; -} -.leaflet-marker-icon-wrapper{ - position: absolute; -} -.leaflet-routing-alt, .leaflet-routing-geocoders { - padding: 6px; - margin-top: 2px; - margin-bottom: 6px; - border-bottom: 1px solid #ccc; - max-height: 320px; - overflow-y: auto; - transition: all 0.2s ease; -} - -.leaflet-bar .leaflet-routing-alt:last-child { - border-bottom: none; -} - -.leaflet-routing-alt-minimized { - color: #888; - max-height: 64px; - overflow: hidden; - cursor: pointer; -} - -.leaflet-routing-alt table { - border-collapse: collapse; -} - -.leaflet-routing-alt tr:hover { - background-color: #eee; - cursor: pointer; -} - -.leaflet-routing-alt::-webkit-scrollbar { - width: 8px; -} - -.leaflet-routing-alt::-webkit-scrollbar-track { - border-radius: 2px; - background-color: #eee; -} - -.leaflet-routing-alt::-webkit-scrollbar-thumb { - border-radius: 2px; - background-color: #888; -} - -.leaflet-routing-geocoders input { - width: 192px; - padding: 4px; - border: 1px solid #ccc; -} - -.leaflet-routing-geocoders button { - font: bold 18px 'Lucida Console', Monaco, monospace; - border: 1px solid #ccc; - border-radius: 4px; - background-color: white; - margin: 0 6px; - float: right; - cursor: pointer; - transition: background-color 0.2s ease; -} - -.leaflet-routing-geocoders button:hover { - background-color: #eee; -} - -.leaflet-routing-geocoder-result { - position: absolute; - max-height: 0; - overflow: hidden; - transition: all 0.5s ease; - z-index: 60; -} - -.leaflet-routing-geocoder-result table { - width: 100%; - border: 1px solid #ccc; - border-radius: 0 0 4px 4px; - background-color: white; - cursor: pointer; -} - -.leaflet-routing-geocoder-result-open { - max-height: 800px; -} - -.leaflet-routing-geocoder-selected, .leaflet-routing-geocoder-result tr:hover { - background-color: #eee; -} - -.leaflet-routing-geocoder-no-results { - font-style: italic; - color: #888; -} \ No newline at end of file +.leaflet-routing-container, .leaflet-routing-error { + width: 320px; + background-color: white; + padding-top: 4px; + transition: all 0.2s ease; + box-sizing: border-box; +} + +.leaflet-control-container .leaflet-routing-container-hide { + width: 32px; + height: 32px; +} + +.leaflet-routing-container h2 { + font-size: 14px; +} + +.leaflet-routing-container h3 { + font-size: 12px; + font-weight: normal; +} + +.leaflet-routing-collapsible .leaflet-routing-geocoders { + margin-top: 20px; +} + +.leaflet-routing-alt, .leaflet-routing-geocoders, .leaflet-routing-error { + padding: 6px; + margin-top: 2px; + margin-bottom: 6px; + border-bottom: 1px solid #ccc; + max-height: 320px; + overflow-y: auto; + transition: all 0.2s ease; +} + +.leaflet-control-container .leaflet-routing-container-hide .leaflet-routing-alt, +.leaflet-control-container .leaflet-routing-container-hide .leaflet-routing-geocoders { + display: none; +} + +.leaflet-bar .leaflet-routing-alt:last-child { + border-bottom: none; +} + +.leaflet-routing-alt-minimized { + color: #888; + max-height: 64px; + overflow: hidden; + cursor: pointer; +} + +.leaflet-routing-alt table { + border-collapse: collapse; +} + +.leaflet-routing-alt tr:hover { + background-color: #eee; + cursor: pointer; +} + +.leaflet-routing-alt::-webkit-scrollbar { + width: 8px; +} + +.leaflet-routing-alt::-webkit-scrollbar-track { + border-radius: 2px; + background-color: #eee; +} + +.leaflet-routing-alt::-webkit-scrollbar-thumb { + border-radius: 2px; + background-color: #888; +} + +.leaflet-routing-icon { + background-image: url('leaflet.routing.icons.png'); + -webkit-background-size: 240px 20px; + background-size: 240px 20px; + background-repeat: no-repeat; + margin: 0; + content: ''; + display: inline-block; + vertical-align: top; + width: 20px; + height: 20px; +} + +.leaflet-routing-icon-continue { background-position: 0 0; } +.leaflet-routing-icon-sharp-right { background-position: -20px 0; } +.leaflet-routing-icon-turn-right { background-position: -40px 0; } +.leaflet-routing-icon-bear-right { background-position: -60px 0; } +.leaflet-routing-icon-u-turn { background-position: -80px 0; } +.leaflet-routing-icon-sharp-left { background-position: -100px 0; } +.leaflet-routing-icon-turn-left { background-position: -120px 0; } +.leaflet-routing-icon-bear-left { background-position: -140px 0; } +.leaflet-routing-icon-depart { background-position: -160px 0; } +.leaflet-routing-icon-enter-roundabout { background-position: -180px 0; } +.leaflet-routing-icon-arrive { background-position: -200px 0; } +.leaflet-routing-icon-via { background-position: -220px 0; } + +.leaflet-routing-geocoders div { + padding: 4px 0px 4px 0px; +} + +.leaflet-routing-geocoders input { + width: 303px; + width: calc(100% - 4px); + line-height: 1.67; + border: 1px solid #ccc; +} + +.leaflet-routing-geocoders button { + font: bold 18px 'Lucida Console', Monaco, monospace; + border: 1px solid #ccc; + border-radius: 4px; + background-color: white; + margin: 0; + margin-right: 3px; + float: right; + cursor: pointer; + transition: background-color 0.2s ease; +} + +.leaflet-routing-add-waypoint:after { + content: '+'; +} + +.leaflet-routing-reverse-waypoints:after { + font-weight: normal; + content: '\21c5'; +} + +.leaflet-routing-geocoders button:hover { + background-color: #eee; +} + +.leaflet-routing-geocoders input,.leaflet-routing-remove-waypoint,.leaflet-routing-geocoder { + position: relative; +} + +.leaflet-routing-geocoder-result { + font: 12px/1.5 "Helvetica Neue", Arial, Helvetica, sans-serif; + position: absolute; + max-height: 0; + overflow: hidden; + transition: all 0.5s ease; + z-index: 1000; /* Arbitrary, but try to be above "most" things. */ +} + +.leaflet-routing-geocoder-result table { + width: 100%; + border: 1px solid #ccc; + border-radius: 0 0 4px 4px; + background-color: white; + cursor: pointer; +} + +.leaflet-routing-geocoder-result-open { + max-height: 800px; +} + +.leaflet-routing-geocoder-selected, .leaflet-routing-geocoder-result tr:hover { + background-color: #eee; +} + +.leaflet-routing-geocoder-no-results { + font-style: italic; + color: #888; +} + +.leaflet-routing-remove-waypoint { + background-color: transparent; + display: inline-block; + vertical-align: middle; + cursor: pointer; +} + +.leaflet-routing-remove-waypoint:after { + position: absolute; + display: block; + width: 15px; + height: 1px; + z-index: 1; + right: 1px; + top: 4px; + bottom: 0; + margin: auto; + padding: 2px; + font-size: 18px; + font-weight: bold; + content: "\00d7"; + text-align: center; + cursor: pointer; + color: #ccc; + background: white; + padding-bottom: 16px; + margin-top: -16px; + padding-right: 4px; + line-height: 1; +} + +.leaflet-routing-remove-waypoint:hover { + color: black; +} + +.leaflet-routing-instruction-distance { + width: 48px; +} + +.leaflet-routing-collapse-btn { + position: absolute; + top: 0; + right: 6px; + font-size: 24px; + color: #ccc; + font-weight: bold; +} + +.leaflet-routing-collapse-btn:after { + content: '\00d7'; +} + +.leaflet-routing-container-hide .leaflet-routing-collapse-btn { + position: relative; + left: 4px; + top: 4px; + display: block; + width: 26px; + height: 23px; + background-image: url('routing-icon.png'); +} + +.leaflet-routing-container-hide .leaflet-routing-collapse-btn:after { + content: none; +} + +.leaflet-top .leaflet-routing-container.leaflet-routing-container-hide { + margin-top: 10px !important; +} +.leaflet-right .leaflet-routing-container.leaflet-routing-container-hide { + margin-right: 10px !important; +} +.leaflet-bottom .leaflet-routing-container.leaflet-routing-container-hide { + margin-bottom: 10px !important; +} +.leaflet-left .leaflet-routing-container.leaflet-routing-container-hide { + margin-left: 10px !important; +} + +@media only screen and (max-width: 640px) { + .leaflet-routing-container { + margin: 0 !important; + padding: 0 !important; + width: 100%; + height: 100%; + } +} diff --git a/css/leaflet/leaflet.routing.icons.png b/css/leaflet/leaflet.routing.icons.png new file mode 100644 index 0000000..2566467 Binary files /dev/null and b/css/leaflet/leaflet.routing.icons.png differ diff --git a/css/leaflet/leaflet.routing.icons.svg b/css/leaflet/leaflet.routing.icons.svg new file mode 100644 index 0000000..a544746 --- /dev/null +++ b/css/leaflet/leaflet.routing.icons.svg @@ -0,0 +1,239 @@ + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + A + + + + B + + + V + ia + + diff --git a/css/leaflet/routing-icon.png b/css/leaflet/routing-icon.png new file mode 100644 index 0000000..3f4b80b Binary files /dev/null and b/css/leaflet/routing-icon.png differ diff --git a/css/style.css b/css/style.css index c20a78d..b9eff6e 100644 --- a/css/style.css +++ b/css/style.css @@ -42,6 +42,40 @@ div.olControlZoom a { filter: alpha(opacity=80); } +div#search { + position: absolute; + top: 3px; + left: 50px; + z-index: 1; +} + +div.geocoder-container { + display: block; +} + +input.geocoder { + width: 210px; +} + +ul.geocoder-list { + background: white; + width: 400px; + font-size: 10px; + position: absolute; +} + +li.geocoder-list-item { + padding: 5px; +} + +li.geocoder-list-item:hover { + background: #ddd; +} + +button#geocoder-button { + background: white; +} + input#search { width: 180px; margin: 10px 10px; diff --git a/db/apikey.php b/db/apikey.php new file mode 100644 index 0000000..838e02c --- /dev/null +++ b/db/apikey.php @@ -0,0 +1,15 @@ +findEntity($sql, [$id]); + } + + /** + * @param string $uid + * @throws \OCP\AppFramework\Db\DoesNotExistException if not found + * @return ApiKey + */ + public function findByUser($uid) { + $sql = 'SELECT * FROM `*PREFIX*maps_apikeys` '. + 'WHERE `user_id` = ?'; + return $this->findEntity($sql, [$uid]); + } + + /** + * @param int $limit + * @param int $offset + * @return ApiKey[] + */ + public function findAll($limit=null, $offset=null) { + $sql = 'SELECT * FROM `*PREFIX*maps_apikeys`'; + return $this->findEntities($sql, $limit, $offset); + } +} diff --git a/db/favoritemapper.php b/db/favoritemapper.php index 90fc007..947a786 100644 --- a/db/favoritemapper.php +++ b/db/favoritemapper.php @@ -22,6 +22,16 @@ public function find($id) { return $this->findEntity($sql, [$id]); } + /** + * @param string $name + * @return Favorite[] + */ + public function findByName($name) { + $sql = 'SELECT * FROM `*PREFIX*maps_favorites` '. + 'WHERE `name` ILIKE ?'; + return $this->findEntities($sql, ['%' . addcslashes($name, '\\_%') . '%']); + } + /** * @param string $userId * @param string $from diff --git a/js/3rdparty/leaflet/lib/Control.Geocoder.js b/js/3rdparty/leaflet/lib/Control.Geocoder.js index fdd8792..e3f0ca1 100644 --- a/js/3rdparty/leaflet/lib/Control.Geocoder.js +++ b/js/3rdparty/leaflet/lib/Control.Geocoder.js @@ -1,22 +1,10 @@ -(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({ +(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o' + - (this.options.showResultIcons && result.icon ? - '' : - '') + - result.name + ''; - L.DomEvent.addListener(li, 'click', function clickHandler() { - this._geocodeResultSelected(result); - }, this); + var li = L.DomUtil.create('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), + clickHandler = function clickHandler(e) { + L.DomEvent.preventDefault(e); + this._geocodeResultSelected(result); + }; + + if (icon) { + icon.src = result.icon; + } + + li.setAttribute('data-result-index', index); + + if (result.html) { + a.innerHTML = result.html; + } else { + a.appendChild(text); + } + + L.DomEvent.addListener(li, 'click', clickHandler, this); return li; }, _keydown: function(e) { var _this = this, - select = function select(dir) { + select = function select(dir) { if (_this._selection) { - L.DomUtil.removeClass(_this._selection.firstChild, 'leaflet-control-geocoder-selected'); + L.DomUtil.removeClass(_this._selection, 'leaflet-control-geocoder-selected'); _this._selection = _this._selection[dir > 0 ? 'nextSibling' : 'previousSibling']; } if (!_this._selection) { @@ -185,11 +191,17 @@ } if (_this._selection) { - L.DomUtil.addClass(_this._selection.firstChild, 'leaflet-control-geocoder-selected'); + L.DomUtil.addClass(_this._selection, 'leaflet-control-geocoder-selected'); } }; switch (e.keyCode) { + // Escape + case 27: + if (this.options.collapsed) { + this._collapse(); + } + break; // Up case 38: select(-1); @@ -203,7 +215,7 @@ // Enter case 13: if (this._selection) { - var index = parseInt(this._selection.firstChild.getAttribute('data-result-index'), 10); + var index = parseInt(this._selection.getAttribute('data-result-index'), 10); this._geocodeResultSelected(this._results[index]); this._clearResults(); L.DomEvent.preventDefault(e); @@ -211,27 +223,452 @@ } return true; } - }); + }), + factory: function(options) { + return new L.Control.Geocoder(options); + } +}; - L.Control.geocoder = function(id, options) { - return new L.Control.Geocoder(id, options); - }; +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"./geocoders/nominatim":7}],2:[function(require,module,exports){ +(function (global){ +var L = (typeof window !== "undefined" ? window['L'] : typeof global !== "undefined" ? global['L'] : null), + Util = require('../util'); - 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); - }; +module.exports = { + "class": L.Class.extend({ + initialize: function(key) { + this.key = key; + }, + + geocode : function (query, cb, context) { + Util.jsonp('//dev.virtualearth.net/REST/v1/Locations', { + query: query, + key : this.key + }, function(data) { + var results = []; + if( data.resourceSets.length > 0 ){ + 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) { + Util.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'); + } + }), + + factory: function(key) { + return new L.Control.Geocoder.Bing(key); + } +}; + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"../util":11}],3:[function(require,module,exports){ +(function (global){ +var L = (typeof window !== "undefined" ? window['L'] : typeof global !== "undefined" ? global['L'] : null), + Util = require('../util'); + +module.exports = { + "class": L.Class.extend({ + options: { + serviceUrl: 'https://maps.googleapis.com/maps/api/geocode/json', + geocodingQueryParams: {}, + reverseQueryParams: {} + }, + + initialize: function(key, options) { + this._key = key; + L.setOptions(this, options); + // Backwards compatibility + this.options.serviceUrl = this.options.service_url || this.options.serviceUrl; + }, + + geocode: function(query, cb, context) { + var params = { + address: query + }; + + if (this._key && this._key.length) { + params.key = this._key; + } + + params = L.Util.extend(params, this.options.geocodingQueryParams); + + Util.getJSON(this.options.serviceUrl, 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, + properties: loc.address_components + }; + } + } + + cb.call(context, results); + }); + }, + + reverse: function(location, scale, cb, context) { + var params = { + latlng: encodeURIComponent(location.lat) + ',' + encodeURIComponent(location.lng) + }; + params = L.Util.extend(params, this.options.reverseQueryParams); + if (this._key && this._key.length) { + params.key = this._key; + } + + Util.getJSON(this.options.serviceUrl, 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, + properties: loc.address_components + }; + } + } + + cb.call(context, results); + }); + } + }), + + factory: function(key, options) { + return new L.Control.Geocoder.Google(key, options); + } +}; + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"../util":11}],4:[function(require,module,exports){ +(function (global){ +var L = (typeof window !== "undefined" ? window['L'] : typeof global !== "undefined" ? global['L'] : null), + Util = require('../util'); + +module.exports = { + "class": L.Class.extend({ + options: { + serviceUrl: 'https://api.tiles.mapbox.com/v4/geocode/mapbox.places-v1/' + }, + + initialize: function(accessToken, options) { + L.setOptions(this, options); + this._accessToken = accessToken; + }, + + geocode: function(query, cb, context) { + Util.getJSON(this.options.serviceUrl + encodeURIComponent(query) + '.json', { + access_token: this._accessToken + }, 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); + }); + }, + + suggest: function(query, cb, context) { + return this.geocode(query, cb, context); + }, + + reverse: function(location, scale, cb, context) { + Util.getJSON(this.options.serviceUrl + encodeURIComponent(location.lng) + ',' + encodeURIComponent(location.lat) + '.json', { + access_token: this._accessToken + }, 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); + }); + } + }), + + factory: function(accessToken, options) { + return new L.Control.Geocoder.Mapbox(accessToken, options); + } +}; + + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"../util":11}],5:[function(require,module,exports){ +(function (global){ +var L = (typeof window !== "undefined" ? window['L'] : typeof global !== "undefined" ? global['L'] : null), + Util = require('../util'); + +module.exports = { + "class": L.Class.extend({ + options: { + serviceUrl: '//www.mapquestapi.com/geocoding/v1' + }, + + initialize: function(key, options) { + // MapQuest seems to provide URI encoded API keys, + // so to avoid encoding them twice, we decode them here + this._key = decodeURIComponent(key); + + L.Util.setOptions(this, options); + }, + + _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) { + Util.jsonp(this.options.serviceUrl + '/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); + }, - L.Control.Geocoder.Nominatim = L.Class.extend({ + reverse: function(location, scale, cb, context) { + Util.jsonp(this.options.serviceUrl + '/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); + } + }), + + factory: function(key, options) { + return new L.Control.Geocoder.MapQuest(key, options); + } +}; + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"../util":11}],6:[function(require,module,exports){ +(function (global){ +var L = (typeof window !== "undefined" ? window['L'] : typeof global !== "undefined" ? global['L'] : null), + Util = require('../util'); + +module.exports = { + "class": L.Class.extend({ options: { - serviceUrl: OC.generateUrl('apps/maps/router?url=http://nominatim.openstreetmap.org/') + serviceUrl: '//search.mapzen.com/v1', + geocodingQueryParams: {}, + reverseQueryParams: {} + }, + + initialize: function(apiKey, options) { + L.Util.setOptions(this, options); + this._apiKey = apiKey; + this._lastSuggest = 0; + }, + + geocode: function(query, cb, context) { + var _this = this; + Util.getJSON(this.options.serviceUrl + "/search", L.extend({ + 'api_key': this._apiKey, + 'text': query + }, this.options.geocodingQueryParams), function(data) { + cb.call(context, _this._parseResults(data, "bbox")); + }); + }, + + suggest: function(query, cb, context) { + var _this = this; + Util.getJSON(this.options.serviceUrl + "/autocomplete", L.extend({ + 'api_key': this._apiKey, + 'text': query + }, this.options.geocodingQueryParams), function(data) { + if (data.geocoding.timestamp > this._lastSuggest) { + this._lastSuggest = data.geocoding.timestamp; + cb.call(context, _this._parseResults(data, "bbox")); + } + }); + }, + + reverse: function(location, scale, cb, context) { + var _this = this; + Util.getJSON(this.options.serviceUrl + "/reverse", L.extend({ + 'api_key': this._apiKey, + 'point.lat': location.lat, + 'point.lon': location.lng + }, this.options.reverseQueryParams), function(data) { + cb.call(context, _this._parseResults(data, "bounds")); + }); + }, + + _parseResults: function(data, bboxname) { + var results = []; + L.geoJson(data, { + pointToLayer: function (feature, latlng) { + return L.circleMarker(latlng); + }, + onEachFeature: function(feature, layer) { + var result = {}; + result['name'] = layer.feature.properties.label; + result[bboxname] = layer.getBounds(); + result['center'] = result[bboxname].getCenter(); + result['properties'] = layer.feature.properties; + results.push(result); + } + }); + return results; + } + }), + + factory: function(apiKey, options) { + return new L.Control.Geocoder.Mapzen(apiKey, options); + } +}; + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"../util":11}],7:[function(require,module,exports){ +(function (global){ +var L = (typeof window !== "undefined" ? window['L'] : typeof global !== "undefined" ? global['L'] : null), + Util = require('../util'); + +module.exports = { + "class": 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 Util.template(parts.join('
'), a, true); + } }, initialize: function(options) { @@ -239,11 +676,13 @@ }, geocode: function(query, cb, context) { - L.Control.Geocoder.jsonp(this.options.serviceUrl + 'search/', { + Util.jsonp(this.options.serviceUrl + 'search', L.extend({ q: query, limit: 5, - format: 'json' - }, function(data) { + 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; @@ -251,9 +690,12 @@ 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((bbox[0] + bbox[1]) / 2, (bbox[2] + bbox[3]) / 2), - originalObject: data + center: L.latLng(data[i].lat, data[i].lon), + properties: data[i] }; } cb.call(context, results); @@ -261,133 +703,334 @@ }, reverse: function(location, scale, cb, context) { - L.Control.Geocoder.jsonp(this.options.serviceUrl + 'reverse/', { + Util.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' - }, function(data) { - var loc = L.latLng(data.lat, data.lon); - cb.call(context, [{ - name: data.display_name, - center: loc, - bounds: L.latLngBounds(loc, loc), - originalObject: data - }]); + }, 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) { + factory: function(options) { return new L.Control.Geocoder.Nominatim(options); - }; + } +}; - L.Control.Geocoder.Bing = L.Class.extend({ - initialize: function(key) { - this.key = key; +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"../util":11}],8:[function(require,module,exports){ +(function (global){ +var L = (typeof window !== "undefined" ? window['L'] : typeof global !== "undefined" ? global['L'] : null), + Util = require('../util'); + +module.exports = { + "class": L.Class.extend({ + options: { + serviceUrl: '//photon.komoot.de/api/', + reverseUrl: '//photon.komoot.de/reverse/', + nameProperties: [ + 'name', + 'street', + 'suburb', + 'hamlet', + 'town', + 'city', + 'state', + 'country' + ] }, - geocode : function (query, cb, context) { - L.Control.Geocoder.jsonp(OC.generateUrl('apps/maps/router?url=http://dev.virtualearth.net/REST/v1/Locations'), { - query: query, - key : this.key + initialize: function(options) { + L.setOptions(this, options); + }, + + geocode: function(query, cb, context) { + var params = L.extend({ + q: query + }, this.options.geocodingQueryParams); + + Util.getJSON(this.options.serviceUrl, params, L.bind(function(data) { + cb.call(context, this._decodeFeatures(data)); + }, this)); + }, + + suggest: function(query, cb, context) { + return this.geocode(query, cb, context); + }, + + reverse: function(latLng, scale, cb, context) { + var params = L.extend({ + lat: latLng.lat, + lon: latLng.lng + }, this.options.geocodingQueryParams); + + Util.getJSON(this.options.reverseUrl, params, L.bind(function(data) { + cb.call(context, this._decodeFeatures(data)); + }, this)); + }, + + _decodeFeatures: function(data) { + var results = [], + i, + f, + c, + latLng, + extent, + bbox; + + if (data && data.features) { + for (i = 0; i < data.features.length; i++) { + f = data.features[i]; + c = f.geometry.coordinates; + latLng = L.latLng(c[1], c[0]); + extent = f.properties.extent; + + if (extent) { + bbox = L.latLngBounds([extent[1], extent[0]], [extent[3], extent[2]]); + } else { + bbox = L.latLngBounds(latLng, latLng); + } + + results.push({ + name: this._deocodeFeatureName(f), + center: latLng, + bbox: bbox, + properties: f.properties + }); + } + } + + return results; + }, + + _deocodeFeatureName: function(f) { + var j, + name; + for (j = 0; !name && j < this.options.nameProperties.length; j++) { + name = f.properties[this.options.nameProperties[j]]; + } + + return name; + } + }), + + factory: function(options) { + return new L.Control.Geocoder.Photon(options); + } +}; + + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"../util":11}],9:[function(require,module,exports){ +(function (global){ +var L = (typeof window !== "undefined" ? window['L'] : typeof global !== "undefined" ? global['L'] : null), + Util = require('../util'); + +module.exports = { + "class": L.Class.extend({ + options: { + serviceUrl: 'http://api.what3words.com/' + }, + + initialize: function(accessToken) { + this._accessToken = accessToken; + }, + + geocode: function(query, cb, context) { + //get three words and make a dot based string + Util.getJSON(this.options.serviceUrl +'w3w', { + key: this._accessToken, + string: query.split(/\s+/).join('.') }, 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) + var results = [], loc, latLng, latLngBounds; + if (data.position && data.position.length) { + loc = data.words; + latLng = L.latLng(data.position[0],data.position[1]); + latLngBounds = L.latLngBounds(latLng, latLng); + results[0] = { + name: loc.join('.'), + bbox: latLngBounds, + center: latLng }; } + cb.call(context, results); - }, this, 'jsonp'); + }); + }, + + suggest: function(query, cb, context) { + return this.geocode(query, cb, context); }, reverse: function(location, scale, cb, context) { - L.Control.Geocoder.jsonp(OC.generateUrl('apps/maps/router?url=http://dev.virtualearth.net/REST/v1/Locations/' + location.lat + ',' + location.lng), { - key : this.key + Util.getJSON(this.options.serviceUrl +'position', { + key: this._accessToken, + position: [location.lat,location.lng].join(',') }, 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) + var results = [],loc,latLng,latLngBounds; + if (data.position && data.position.length) { + loc = data.words; + latLng = L.latLng(data.position[0],data.position[1]); + latLngBounds = L.latLngBounds(latLng, latLng); + results[0] = { + name: loc.join('.'), + bbox: latLngBounds, + center: latLng }; } cb.call(context, results); - }, this, 'jsonp'); + }); } - }); + }), - L.Control.Geocoder.bing = function(key) { - return new L.Control.Geocoder.Bing(key); - }; + factory: function(accessToken) { + return new L.Control.Geocoder.What3Words(accessToken); + } +}; - 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])); - } +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"../util":11}],10:[function(require,module,exports){ +(function (global){ +var L = (typeof window !== "undefined" ? window['L'] : typeof global !== "undefined" ? global['L'] : null), + Control = require('./control'), + Nominatim = require('./geocoders/nominatim'), + Bing = require('./geocoders/bing'), + MapQuest = require('./geocoders/mapquest'), + Mapbox = require('./geocoders/mapbox'), + What3Words = require('./geocoders/what3words'), + Google = require('./geocoders/google'), + Photon = require('./geocoders/photon'), + Mapzen = require('./geocoders/mapzen'); - 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); - }, +module.exports = L.Util.extend(Control["class"], { + Nominatim: Nominatim["class"], + nominatim: Nominatim.factory, + Bing: Bing["class"], + bing: Bing.factory, + MapQuest: MapQuest["class"], + mapQuest: MapQuest.factory, + Mapbox: Mapbox["class"], + mapbox: Mapbox.factory, + What3Words: What3Words["class"], + what3words: What3Words.factory, + Google: Google["class"], + google: Google.factory, + Photon: Photon["class"], + photon: Photon.factory, + Mapzen: Mapzen["class"], + mapzen: Mapzen.factory +}); - initialize: function(serviceUrl, scheme, options) { - L.Util.setOptions(this, options); +L.Util.extend(L.Control, { + Geocoder: module.exports, + geocoder: Control.factory +}); - this._serviceUrl = serviceUrl; - this._scheme = scheme; - }, +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"./control":1,"./geocoders/bing":2,"./geocoders/google":3,"./geocoders/mapbox":4,"./geocoders/mapquest":5,"./geocoders/mapzen":6,"./geocoders/nominatim":7,"./geocoders/photon":8,"./geocoders/what3words":9}],11:[function(require,module,exports){ +(function (global){ +var L = (typeof window !== "undefined" ? window['L'] : typeof global !== "undefined" ? global['L'] : null), + lastCallbackId = 0, + htmlEscape = (function() { + // Adapted from handlebars.js + // https://github.com/wycats/handlebars.js/ + var badChars = /[&<>"'`]/g; + var possible = /[&<>"'`]/; + var escape = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + '\'': ''', + '`': '`' + }; - 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); + function escapeChar(chr) { + return escape[chr]; } - }); - L.Control.Geocoder.raveGeo = function(serviceUrl, scheme, options) { - return new L.Control.Geocoder.RaveGeo(serviceUrl, scheme, options); - }; + 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); + }; + })(); + +module.exports = { + jsonp: function(url, params, callback, context, jsonpParam) { + var callbackId = '_l_geocoder_' + (lastCallbackId++); + 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); + }, + + getJSON: function(url, params, callback) { + var xmlHttp = new XMLHttpRequest(); + xmlHttp.onreadystatechange = function () { + if (xmlHttp.readyState !== 4){ + return; + } + if (xmlHttp.status !== 200 && xmlHttp.status !== 304){ + callback(''); + return; + } + callback(JSON.parse(xmlHttp.response)); + }; + xmlHttp.open('GET', url + L.Util.getParamString(params), true); + xmlHttp.setRequestHeader('Accept', 'application/json'); + xmlHttp.send(null); + }, + + template: function (str, data) { + 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 htmlEscape(value); + }); + }, + + htmlEscape: htmlEscape +}; +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{}]},{},[10]); - return L.Control.Geocoder; -})); \ No newline at end of file diff --git a/js/3rdparty/leaflet/plugins/leaflet-routing-machine.min.js b/js/3rdparty/leaflet/plugins/leaflet-routing-machine.min.js index c3c22a6..e3817dd 100644 --- a/js/3rdparty/leaflet/plugins/leaflet-routing-machine.min.js +++ b/js/3rdparty/leaflet/plugins/leaflet-routing-machine.min.js @@ -1,1394 +1,4 @@ -// Packaging/modules magic dance. This code is inserted before all other -// code when the dist is built. -(function (factory) { - 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) { -(function() { - 'use strict'; - - L.Routing = L.Routing || {}; - - L.Routing.Autocomplete = L.Class.extend({ - options: { - timeout: 500, - blurTimeout: 100, - noResultsMessage: 'No results found.' - }, - - initialize: function(elem, callback, context, options) { - L.setOptions(this, options); - - this._elem = elem; - this._resultFn = options.resultFn ? L.Util.bind(options.resultFn, options.resultContext) : null; - this._autocomplete = options.autocompleteFn ? L.Util.bind(options.autocompleteFn, options.autocompleteContext) : null; - this._selectFn = L.Util.bind(callback, context); - this._container = L.DomUtil.create('div', 'leaflet-routing-geocoder-result'); - this._resultTable = L.DomUtil.create('table', '', this._container); - - // TODO: looks a bit like a kludge to register same for input and keypress - - // browsers supporting both will get duplicate events; just registering - // input will not catch enter, though. - L.DomEvent.addListener(this._elem, 'input', this._keyPressed, this); - L.DomEvent.addListener(this._elem, 'keypress', this._keyPressed, this); - L.DomEvent.addListener(this._elem, 'keydown', this._keyDown, this); - L.DomEvent.addListener(this._elem, 'blur', function(e) { - if (this._isOpen) { - //this.close(); - } - else - { - if($(e.srcElement).val()==''){ - $(e.srcElement).attr('completiontype','local'); - } - } - }, this); - }, - - close: function() { - L.DomUtil.removeClass(this._container, 'leaflet-routing-geocoder-result-open'); - this._isOpen = false; - }, - - _open: function() { - var sibling = this._elem.nextSibling; - if (!this._container.parentElement) { - if (sibling) { - this._elem.parentElement.insertBefore(this._container, sibling); - } else { - this._elem.parentElement.appendChild(this._container); - } - this._container.style.left = this._elem.offsetLeft + 'px'; - this._container.style.top = (this._elem.offsetTop + this._elem.offsetHeight) + 'px'; - this._container.style.width = 'auto'; - } - - L.DomUtil.addClass(this._container, 'leaflet-routing-geocoder-result-open'); - this._isOpen = true; - }, - - _setResults: function(results) { - var i, - tr, - td, - text; - - delete this._selection; - this._results = results; - - while (this._resultTable.firstChild) { - this._resultTable.removeChild(this._resultTable.firstChild); - } - - for (i = 0; i < results.length; i++) { - tr = L.DomUtil.create('tr', '', this._resultTable); - tr.setAttribute('data-result-index', i); - td = L.DomUtil.create('td', '', tr); - text = document.createTextNode(results[i].name); - td.appendChild(text); - // mousedown + click because: - // http://stackoverflow.com/questions/10652852/jquery-fire-click-before-blur-event - L.DomEvent.addListener(td, 'mousedown', L.DomEvent.preventDefault); - L.DomEvent.addListener(td, 'click', this._resultSelected(results[i]), this); - } - - if (!i) { - tr = L.DomUtil.create('tr', '', this._resultTable); - td = L.DomUtil.create('td', 'leaflet-routing-geocoder-no-results', tr); - td.innerHTML = this.options.noResultsMessage; - } - - this._open(); - - if (results.length > 0) { - // Select the first entry - this._select(1); - } - }, - - _resultSelected: function(r) { - $(this._elem).attr('completed','true'); - return L.bind(function() { - this.close(); - this._elem.value = r.name; - this._lastCompletedText = r.name; - this._selectFn(r); - }, this); - }, - keyPressTimeout: 0, - _keyPressed: function(e) { - var index; - - if($(e.srcElement).attr('completionType')!="OSM") return; - - if(e.target.value==''){ - this._unselect; - this.close(); - $(e.target).attr('completiontype','local'); - return; - } - if (this._isOpen && e.keyCode === 13 && this._selection) { - index = parseInt(this._selection.getAttribute('data-result-index'), 10); - this._resultSelected(this._results[index])(); - L.DomEvent.preventDefault(e); - return; - } - clearTimeout(this.keyPressTimeout); - var _this = this; - this.keyPressTimeout = setTimeout(function(){ _this._complete(_this._resultFn, true)} ,500) - if (e.keyCode === 13) { - this._complete(this._resultFn, true); - return; - } - else - { - $(e.srcElement).removeAttr('completed'); - } - - if (this._autocomplete && document.activeElement === this._elem) { - if (this._timer) { - clearTimeout(this._timer); - } - this._timer = setTimeout(L.Util.bind(function() { this._complete(this._autocomplete); }, this), - this.options.timeout); - return; - } - - - }, - - _select: function(dir) { - var sel = this._selection; - if (sel) { - L.DomUtil.removeClass(sel.firstChild, 'leaflet-routing-geocoder-selected'); - sel = sel[dir > 0 ? 'nextSibling' : 'previousSibling']; - } - if (!sel) { - sel = this._resultTable[dir > 0 ? 'firstChild' : 'lastChild']; - } - - if (sel) { - L.DomUtil.addClass(sel.firstChild, 'leaflet-routing-geocoder-selected'); - this._selection = sel; - } - }, - - _unselect: function() { - if (this._selection) { - L.DomUtil.removeClass(this._selection.firstChild, 'leaflet-routing-geocoder-selected'); - } - delete this._selection; - }, - - _keyDown: function(e) { - if (this._isOpen) { - switch (e.keyCode) { - // Up - case 38: - this._select(-1); - L.DomEvent.preventDefault(e); - return; - // Down - case 40: - this._select(1); - L.DomEvent.preventDefault(e); - return; - } - } - }, - - _complete: function(completeFn, trySelect) { - var v = this._elem.value; - function completeResults(results) { - this._lastCompletedText = v; - //if (trySelect && results.length === 1) { - //this._resultSelected(results[0])(); - //} else { - this._setResults(results); - //} - } - - if (!v) { - return; - } - - if (v !== this._lastCompletedText) { - completeFn(v, completeResults, this); - } else if (trySelect) { - completeResults.call(this, this._results); - } - } - }); -})(); -(function() { - 'use strict'; - - // Ignore camelcase naming for this file, since OSRM's API uses - // underscores. - /* jshint camelcase: false */ - - L.Routing = L.Routing || {}; - - L.Routing._jsonpCallbackId = 0; - L.Routing._jsonp = function(url, callback, context, jsonpParam) { - var callbackId = '_l_routing_machine_' + (L.Routing._jsonpCallbackId++), - script; - url += '&' + jsonpParam + '=' + callbackId; - window[callbackId] = L.Util.bind(callback, context); - script = document.createElement('script'); - script.type = 'text/javascript'; - script.src = url; - script.id = callbackId; - console.log(url); - document.getElementsByTagName('head')[0].appendChild(script); - }; - - L.Routing.OSRM = L.Class.extend({ - // - options: { - serviceUrl:OC.generateUrl('apps/maps/router?url=http://router.project-osrm.org/viaroute'), - geometryPrecision: 6 - }, - - initialize: function(options) { - L.Util.setOptions(this, options); - this._hints = { - locations: {} - }; - }, - - route: function(waypoints, callback, context) { - var url = this._buildRouteUrl(waypoints); - - L.Routing._jsonp(url, function(data) { - this._routeDone(data, waypoints, callback, context); - }, this, 'jsonp'); - - return this; - }, - - _routeDone: function(response, waypoints, callback, context) { - context = context || callback; - if (response.status !== 0) { - callback.call(context, { - status: response.status, - message: response.message - }); - return; - } - - var alts = [{ - name: response.route_name.join(', '), - coordinates: this._decode(response.route_geometry, this.options.geometryPrecision), - instructions: this._convertInstructions(response.route_instructions), - summary: this._convertSummary(response.route_summary), - waypoints: response.via_points - }], - i; - - if (response.alternative_geometries) { - for (i = 0; i < response.alternative_geometries.length; i++) { - alts.push({ - name: response.alternative_names[i].join(', '), - coordinates: this._decode(response.alternative_geometries[i], this.options.geometryPrecision), - instructions: this._convertInstructions(response.alternative_instructions[i]), - summary: this._convertSummary(response.alternative_summaries[i]), - waypoints: response.via_points - }); - } - } - - this._saveHintData(response, waypoints); - callback.call(context, null, alts); - }, - - _buildRouteUrl: function(waypoints) { - var locs = [], - locationKey, - hint; - - for (var i = 0; i < waypoints.length; i++) { - locationKey = this._locationKey(waypoints[i].latLng); - locs.push('loc=' + locationKey); - - hint = this._hints.locations[locationKey]; - if (hint) { - locs.push('hint=' + hint); - } - } - - return this.options.serviceUrl + '?' + - 'instructions=true&' + - locs.join('&') + - (this._hints.checksum !== undefined ? '&checksum=' + this._hints.checksum : ''); - }, - - _locationKey: function(location) { - return location.lat + ',' + location.lng; - }, - - _saveHintData: function(route, waypoints) { - var hintData = route.hint_data, - loc; - this._hints = { - checksum: hintData.checksum, - locations: {} - }; - for (var i = hintData.locations.length - 1; i >= 0; i--) { - loc = waypoints[i].latLng; - this._hints.locations[this._locationKey(loc)] = hintData.locations[i]; - } - }, - - // Adapted from - // https://github.com/DennisSchiefer/Project-OSRM-Web/blob/develop/WebContent/routing/OSRM.RoutingGeometry.js - _decode: function(encoded, precision) { - var len = encoded.length, - index=0, - lat=0, - lng = 0, - array = []; - - precision = Math.pow(10, -precision); - - while (index < len) { - var b, - shift = 0, - result = 0; - do { - b = encoded.charCodeAt(index++) - 63; - result |= (b & 0x1f) << shift; - shift += 5; - } while (b >= 0x20); - var dlat = ((result & 1) ? ~(result >> 1) : (result >> 1)); - lat += dlat; - shift = 0; - result = 0; - do { - b = encoded.charCodeAt(index++) - 63; - result |= (b & 0x1f) << shift; - shift += 5; - } while (b >= 0x20); - var dlng = ((result & 1) ? ~(result >> 1) : (result >> 1)); - lng += dlng; - //array.push( {lat: lat * precision, lng: lng * precision} ); - array.push( [lat * precision, lng * precision] ); - } - return array; - }, - - _convertSummary: function(osrmSummary) { - return { - totalDistance: osrmSummary.total_distance, - totalTime: osrmSummary.total_time - }; - }, - - _convertInstructions: function(osrmInstructions) { - var result = [], - i, - instr, - type, - driveDir; - - for (i = 0; i < osrmInstructions.length; i++) { - instr = osrmInstructions[i]; - type = this._drivingDirectionType(instr[0]); - driveDir = instr[0].split('-'); - if (type) { - result.push({ - type: type, - distance: instr[2], - time: instr[4], - road: instr[1], - direction: instr[6], - exit: driveDir.length > 1 ? driveDir[1] : undefined, - index: instr[3] - }); - } - } - - return result; - }, - - _drivingDirectionType: function(d) { - switch (parseInt(d, 10)) { - case 1: - return 'Straight'; - case 2: - return 'SlightRight'; - case 3: - return 'Right'; - case 4: - return 'SharpRight'; - case 5: - return 'TurnAround'; - case 6: - return 'SharpLeft'; - case 7: - return 'Left'; - case 8: - return 'SlightRight'; - case 9: - return 'WaypointReached'; - case 10: - // TODO: "Head on" - // https://github.com/DennisOSRM/Project-OSRM/blob/master/DataStructures/TurnInstructions.h#L48 - return 'Straight'; - case 11: - case 12: - return 'Roundabout'; - case 15: - return 'DestinationReached'; - default: - return null; - } - } - }); - - L.Routing.osrm = function(options) { - return new L.Routing.OSRM(options); - }; -})(); -(function() { - 'use strict'; - - L.Routing = L.Routing || {}; - - L.Routing.Line = L.Class.extend({ - includes: L.Mixin.Events, - - options: { - styles: [ - {color: 'black', opacity: 0.15, weight: 7}, - {color: 'white', opacity: 0.8, weight: 2}, - {color: 'blue', opacity: 1, weight: 2} - ], - addWaypoints: true - }, - - initialize: function(route, options) { - L.Util.setOptions(this, options); - this._route = route; - - this._wpIndices = this._findWaypointIndices(); - }, - - addTo: function(map) { - map.addLayer(this); - return this; - }, - - onAdd: function(map) { - var geom = this._route.coordinates, - i, - pl; - - this._map = map; - this._layers = []; - for (i = 0; i < this.options.styles.length; i++) { - pl = L.polyline(geom, this.options.styles[i]) - .addTo(map); - if (this.options.addWaypoints) { - pl.on('mousedown', this._onLineTouched, this); - } - this._layers.push(pl); - } - }, - - onRemove: function(map) { - var i; - for (i = 0; i < this._layers.length; i++) { - map.removeLayer(this._layers[i]); - } - - delete this._map; - }, - - getBounds: function() { - return L.latLngBounds(this._route.coordinates); - }, - - _findWaypointIndices: function() { - var wps = this._route.waypoints, - indices = [], - i; - for (i = 0; i < wps.length; i++) { - indices.push(this._findClosestRoutePoint(L.latLng(wps[i]))); - } - - return indices; - }, - - _findClosestRoutePoint: function(latlng) { - var minDist = Number.MAX_VALUE, - minIndex, - i, - d; - - for (i = this._route.coordinates.length - 1; i >= 0 ; i--) { - // TODO: maybe do this in pixel space instead? - d = latlng.distanceTo(this._route.coordinates[i]); - if (d < minDist) { - minIndex = i; - minDist = d; - } - } - - return minIndex; - }, - - _findNearestWpBefore: function(i) { - var j = this._wpIndices.length - 1; - while (j >= 0 && this._wpIndices[j] > i) { - j--; - } - - return j; - }, - - _onLineTouched: function(e) { - var afterIndex = this._findNearestWpBefore(this._findClosestRoutePoint(e.latlng)); - this.fire('linetouched', { - afterIndex: afterIndex, - latlng: e.latlng - }); - }, - }); - - L.Routing.line = function(route, options) { - return new L.Routing.Line(route, options); - }; -})(); -(function() { - 'use strict'; - - L.Routing = L.Routing || {}; - - L.Routing.Itinerary = L.Control.extend({ - includes: L.Mixin.Events, - - options: { - units: 'metric', - pointMarkerStyle: { - radius: 5, - color: '#03f', - fillColor: 'white', - opacity: 1, - fillOpacity: 0.7 - }, - summaryTemplate: '

{name}

{distance}, {time}

', - distanceTemplate: '{value} {unit}', - timeTemplate: '{time}', - unitNames: { - meters: 'm', - kilometers: 'km', - yards: 'yd', - miles: 'mi', - hours: 'h', - minutes: 'm�n', - seconds: 's' - }, - containerClassName: '', - alternativeClassName: '', - minimizedClassName: '', - itineraryClassName: '', - roundingSensitivity: 1, - show: true - }, - - initialize: function(options) { - L.setOptions(this, options); - }, - - onAdd: function() { - this._container = L.DomUtil.create('div', 'leaflet-routing-container' + - (!this.options.show ? 'leaflet-routing-container-hide' : '') + - this.options.containerClassName); - L.DomEvent.disableClickPropagation(this._container); - L.DomEvent.addListener(this._container, 'mousewheel', function(e) { - L.DomEvent.stopPropagation(e); - }); - return this._container; - }, - - onRemove: function() { - }, - - setAlternatives: function(routes) { - var i, - alt, - altDiv; - - this._clearAlts(); - - this._routes = routes; - - for (i = 0; i < this._routes.length; i++) { - alt = this._routes[i]; - altDiv = this._createAlternative(alt, i); - this._container.appendChild(altDiv); - this._altElements.push(altDiv); - } - - this.fire('routeselected', {route: this._routes[0]}); - - - return this; - }, - - show: function() { - L.DomUtil.removeClass(this._container, 'leaflet-routing-container-hide'); - }, - - hide: function() { - L.DomUtil.addClass(this._container, 'leaflet-routing-container-hide'); - }, - - _createAlternative: function(alt, i) { - var altDiv = L.DomUtil.create('div', 'leaflet-routing-alt ' + - this.options.alternativeClassName + - (i > 0 ? ' leaflet-routing-alt-minimized ' + this.options.minimizedClassName : '')); - altDiv.innerHTML = L.Util.template(this.options.summaryTemplate, { - name: alt.name, - distance: this._formatDistance(alt.summary.totalDistance), - time: this._formatTime(alt.summary.totalTime) - }); - L.DomEvent.addListener(altDiv, 'click', this._onAltClicked, this); - - altDiv.appendChild(this._createItineraryTable(alt)); - return altDiv; - }, - - _clearAlts: function() { - var i, - alt; - // TODO: this is really inelegant - for (i = 0; this._container && i < this._container.children.length; i++) { - alt = this._container.children[i]; - if (L.DomUtil.hasClass(alt, 'leaflet-routing-alt')) { - this._container.removeChild(alt); - i--; - } - } - - this._altElements = []; - }, - - _createItineraryTable: function(r) { - var table = L.DomUtil.create('table', this.options.itineraryClassName), - body = L.DomUtil.create('tbody', '', table), - i, - instr, - row, - row2, - td; - - for (i = 0; i < r.instructions.length; i++) { - instr = r.instructions[i]; - row = L.DomUtil.create('tr', '', body); - td = L.DomUtil.create('td', '', row); - td.appendChild(document.createTextNode(this._instruction(instr, i))); - - row2 = L.DomUtil.create('tr', '', body); - td = L.DomUtil.create('td', '', row2); - td.appendChild(document.createTextNode(this._formatDistance(instr.distance))); - - - this._addRowListeners(row, r.coordinates[instr.index]); - this._addRowListeners(row2, r.coordinates[instr.index]); - } - - return table; - }, - - _addRowListeners: function(row, coordinate) { - var _this = this, - marker; - L.DomEvent.addListener(row, 'mouseover', function() { - marker = L.circleMarker(coordinate, - _this.options.pointMarkerStyle).addTo(_this._map); - }); - L.DomEvent.addListener(row, 'mouseout', function() { - if (marker) { - _this._map.removeLayer(marker); - marker = null; - } - }); - L.DomEvent.addListener(row, 'click', function(e) { - _this._map.panTo(coordinate); - L.DomEvent.stopPropagation(e); - }); - }, - - _onAltClicked: function(e) { - var altElem, - j, - n, - isCurrentSelection, - classFn; - - altElem = e.target || window.event.srcElement; - while (!L.DomUtil.hasClass(altElem, 'leaflet-routing-alt')) { - altElem = altElem.parentElement; - } - - if (L.DomUtil.hasClass(altElem, 'leaflet-routing-alt-minimized')) { - for (j = 0; j < this._altElements.length; j++) { - n = this._altElements[j]; - isCurrentSelection = altElem === n; - classFn = isCurrentSelection ? 'removeClass' : 'addClass'; - L.DomUtil[classFn](n, 'leaflet-routing-alt-minimized'); - if (this.options.minimizedClassName) { - L.DomUtil[classFn](n, this.options.minimizedClassName); - } - - if (isCurrentSelection) { - // TODO: don't fire if the currently active is clicked - this.fire('routeselected', {route: this._routes[j]}); - } - } - } - - L.DomEvent.stop(e); - }, - - _formatDistance: function(d /* Number (meters) */) { - var un = this.options.unitNames, - v, - data; - - if (this.options.units === 'imperial') { - d = d / 1.609344; - if (d >= 1000) { - data = { - value: (this._round(d) / 1000), - unit: un.miles - }; - } else { - data = { - value: this._round(d / 1.760), - unit: un.yards - }; - } - } else { - v = this._round(d); - data = { - value: v >= 1000 ? (v / 1000) : v, - unit: v >= 1000 ? un.kilometers : un.meters - }; - } - - return L.Util.template(this.options.distanceTemplate, data); - }, - - _round: function(d) { - var pow10 = Math.pow(10, (Math.floor(d / this.options.roundingSensitivity) + '').length - 1), - r = Math.floor(d / pow10), - p = (r > 5) ? pow10 : pow10 / 2; - - return Math.round(d / p) * p; - }, - - _formatTime: function(t /* Number (seconds) */) { - if (t > 86400) { - return Math.round(t / 3600) + ' h'; - } else if (t > 3600) { - return Math.floor(t / 3600) + ' h ' + - Math.round((t % 3600) / 60) + ' min'; - } else if (t > 300) { - return Math.round(t / 60) + ' min'; - } else if (t > 60) { - return Math.floor(t / 60) + ' min ' + - (t % 60) + ' s'; - } else { - return t + ' s'; - } - }, - - _instruction: function(instr, i) { - if (instr.type !== undefined) { - return L.Util.template(this._getInstructionTemplate(instr, i), - L.extend({exit: this._formatOrder(instr.exit), dir: this._dir[instr.direction]}, - instr)); - } else { - return instr.text; - } - }, - - _getInstructionTemplate: function(instr, i) { - switch (instr.type) { - case 'Straight': - return (i === 0 ? 'Head' : 'Continue') + ' {dir}' + (instr.road ? ' on {road}' : ''); - case 'SlightRight': - return 'Slight right' + (instr.road ? ' onto {road}' : ''); - case 'Right': - return 'Right' + (instr.road ? ' onto {road}' : ''); - case 'SharpRight': - return 'Sharp right' + (instr.road ? ' onto {road}' : ''); - case 'TurnAround': - return 'Turn around'; - case 'SharpLeft': - return 'Sharp left' + (instr.road ? ' onto {road}' : ''); - case 'Left': - return 'Left' + (instr.road ? ' onto {road}' : ''); - case 'SlightLeft': - return 'Slight left' + (instr.road ? ' onto {road}' : ''); - case 'WaypointReached': - return 'Waypoint reached'; - case 'Roundabout': - return 'Take the {exit} exit in the roundabout'; - case 'DestinationReached': - return 'Destination reached'; - } - }, - - _formatOrder: function(n) { - var i = n % 10 - 1, - suffix = ['st', 'nd', 'rd']; - - return suffix[i] ? n + suffix[i] : n + 'th'; - }, - - _dir: { - N: 'north', - NE: 'northeast', - E: 'east', - SE: 'southeast', - S: 'south', - SW: 'southwest', - W: 'west', - NW: 'northwest' - } - }); - - L.Routing.Itinerary._instructions = { - }; - - L.Routing.itinerary = function(router) { - return new L.Routing.Itinerary(router); - }; -})(); -(function() { - 'use strict'; - - var Waypoint = L.Class.extend({ - initialize: function(latLng, name) { - this.latLng = latLng; - this.name = name; - } - }); - - L.Routing = L.Routing || {}; - - L.Routing.Plan = L.Class.extend({ - includes: L.Mixin.Events, - - options: { - dragStyles: [ - {color: 'black', opacity: 0.15, weight: 7}, - {color: 'white', opacity: 0.8, weight: 4}, - {color: 'orange', opacity: 1, weight: 2, dashArray: '7,12'} - ], - draggableWaypoints: true, - addWaypoints: true, - maxGeocoderTolerance: 200, - autocompleteOptions: {}, - geocodersClassName: '', - geocoderPlaceholder: function(i, numberWaypoints) { - return i === 0 ? - 'Search' : - (i < numberWaypoints - 1 ? - 'Via ' + i : - 'End'); - }, - geocoderClass: function(i) { - return 'geocoder-'+i; - } - }, - - initialize: function(waypoints, options) { - L.Util.setOptions(this, options); - this._waypoints = []; - this.setWaypoints(waypoints); - }, - - isReady: function() { - var i; - for (i = 0; i < this._waypoints.length; i++) { - if (!this._waypoints[i].latLng) { - return false; - } - } - - return true; - }, - - getWaypoints: function() { - var i, - wps = []; - - for (i = 0; i < this._waypoints.length; i++) { - wps.push(this._waypoints[i]); - } - - return wps; - }, - - setWaypoints: function(waypoints) { - var args = [0, this._waypoints.length].concat(waypoints); - this.spliceWaypoints.apply(this, args); - return this; - }, - - spliceWaypoints: function() { - var args = [arguments[0], arguments[1]], - i, - wp; - - for (i = 2; i < arguments.length; i++) { - args.push(arguments[i] && arguments[i].hasOwnProperty('latLng') ? arguments[i] : new Waypoint(arguments[i])); - } - - [].splice.apply(this._waypoints, args); - - while (this._waypoints.length < 2) { - wp = new Waypoint(); - this._waypoints.push(wp); - args.push(wp); - } - - this._updateMarkers(); - this._fireChanged.apply(this, args); - }, - - onAdd: function(map) { - this._map = map; - this._updateMarkers(); - }, - - onRemove: function() { - var i; - this._removeMarkers(); - - if (this._newWp) { - for (i = 0; i < this._newWp.lines.length; i++) { - this._map.removeLayer(this._newWp.lines[i]); - } - } - - delete this._map; - }, - - createGeocoders: function() { - var container = L.DomUtil.create('div', 'leaflet-routing-geocoders ' + this.options.geocodersClassName), - waypoints = this._waypoints, - i, - geocoderElem, - clRoute, - addWpBtn; - - this._geocoderContainer = container; - this._geocoderElems = []; - - for (i = 0; i < waypoints.length; i++) { - geocoderElem = this._createGeocoder(i); - container.appendChild(geocoderElem); - this._geocoderElems.push(geocoderElem); - } - - addWpBtn = L.DomUtil.create('button', '', container); - addWpBtn.setAttribute('type', 'button'); - addWpBtn.className = 'addwaypoint'; - addWpBtn.innerHTML = '+'; - clRoute = L.DomUtil.create('button', '', container); - clRoute.setAttribute('type', 'button'); - clRoute.className = 'clearroute icon-close'; - clRoute.style.display = 'none'; - clRoute.innerHTML = 'Clear route'; - if (this.options.addWaypoints) { - L.DomEvent.addListener(addWpBtn, 'click', function() { - if(!$('.geocoder-1').is(':visible')){ - $('.geocoder-1').show(); - $('.geocoder-0').attr('OSM'); - } - else - { - this.spliceWaypoints(waypoints.length, 0, null); - } - }, this); - } else { - addWpBtn.style.display = 'none'; - } - - this.on('waypointsspliced', this._updateGeocoders); - - return container; - }, - - _createGeocoder: function(i) { - var geocoderElem = L.DomUtil.create('input', ''), - wp = this._waypoints[i]; - geocoderElem.setAttribute('placeholder', this.options.geocoderPlaceholder(i, this._waypoints.length)); - geocoderElem.setAttribute('completionType', 'OSM'); - geocoderElem.className = this.options.geocoderClass(i, this._waypoints.length); - - this._updateWaypointName(i, geocoderElem); - // This has to be here, or geocoder's value will not be properly - // initialized. - // TODO: look into why and make _updateWaypointName fix this. - geocoderElem.value = wp.name; - - L.DomEvent.addListener(geocoderElem, 'click', function() { - this.select(); - }, geocoderElem); - - new L.Routing.Autocomplete(geocoderElem, function(r) { - geocoderElem.value = r.name; - wp.name = r.name; - wp.latLng = r.center; - this._updateMarkers(); - this._fireChanged(); - }, this, L.extend({ - resultFn: this.options.geocoder.geocode, - resultContext: this.options.geocoder, - autocompleteFn: this.options.geocoder.suggest, - autocompleteContext: this.options.geocoder - }, this.options.autocompleteOptions)); - - return geocoderElem; - }, - - _updateGeocoders: function(e) { - var newElems = [], - i, - geocoderElem, - beforeElem; - - // Determine where to insert geocoders for new waypoints - if (e.index >= this._geocoderElems.length) { - // lastChild is the "add new wp" button - beforeElem = this._geocoderContainer.lastChild; - } else { - beforeElem = this._geocoderElems[e.index]; - } - - // Insert new geocoders for new waypoints - for (i = 0; i < e.added.length; i++) { - geocoderElem = this._createGeocoder(e.index + i); - this._geocoderContainer.insertBefore(geocoderElem, beforeElem); - newElems.push(geocoderElem); - } - //newElems.reverse(); - - for (i = e.index; i < e.index + e.nRemoved; i++) { - this._geocoderContainer.removeChild(this._geocoderElems[i]); - } - - newElems.splice(0, 0, e.index, e.nRemoved); - [].splice.apply(this._geocoderElems, newElems); - - for (i = 0; i < this._geocoderElems.length; i++) { - this._geocoderElems[i].placeholder = this.options.geocoderPlaceholder(i, this._waypoints.length); - this._geocoderElems[i].className = this.options.geocoderClass(i, this._waypoints.length); - } - }, - - _updateGeocoder: function(i, geocoderElem) { - var wp = this._waypoints[i], - value = wp && wp.name ? wp.name : ''; - geocoderElem.value = value; - }, - - _updateWaypointName: function(i, geocoderElem, force) { - var wp = this._waypoints[i]; - - wp.name = wp.name || ''; - - if (wp.latLng && (force || !wp.name)) { - if (this.options.geocoder && this.options.geocoder.reverse) { - this.options.geocoder.reverse(wp.latLng, 67108864 /* zoom 18 */, function(rs) { - if (rs.length > 0 && rs[0].center.distanceTo(wp.latLng) < this.options.maxGeocoderTolerance) { - wp.name = rs[0].name; - } else { - wp.name = ''; - } - this._updateGeocoder(i, geocoderElem); - }, this); - } else { - wp.name = ''; - } - - this._updateGeocoder(i, geocoderElem); - } - - }, - - _removeMarkers: function() { - var i; - if (this._markers) { - for (i = 0; i < this._markers.length; i++) { - if (this._markers[i]) { - this._map.removeLayer(this._markers[i]); - } - } - } - this._markers = []; - }, - - _updateMarkers: function() { - var i, - icon, - m; - - if (!this._map) { - return; - } - - this._removeMarkers(); - - for (i = 0; i < this._waypoints.length; i++) { - if (this._waypoints[i].latLng) { - icon = (typeof(this.options.waypointIcon) === 'function') ? - this.options.waypointIcon(i, this._waypoints[i].name, this._waypoints.length) : - this.options.waypointIcon; - m = this._createMarker(icon, i); - if (this.options.draggableWaypoints) { - this._hookWaypointEvents(m, i); - } - } else { - m = null; - } - this._markers.push(m); - } - }, - - _createMarker: function(icon, i) { - var options = { - draggable: true - }; - if (icon) { - options.icon = icon; - } - var marker = L.marker(this._waypoints[i].latLng, options); - toolKit.addMarker(marker,'',Maps.showPopup) - return marker - }, - - _fireChanged: function() { - this.fire('waypointschanged', {waypoints: this.getWaypoints()}); - - if (arguments.length >= 2) { - this.fire('waypointsspliced', { - index: Array.prototype.shift.call(arguments), - nRemoved: Array.prototype.shift.call(arguments), - added: arguments - }); - } - }, - - _hookWaypointEvents: function(m, i) { - m.on('dragstart', function(e) { - this.fire('waypointdragstart', this._createWaypointEvent(i, e)); - }, this); - m.on('drag', function(e) { - this.fire('waypointdrag', this._createWaypointEvent(i, e)); - }, this); - m.on('dragend', function(e) { - this.fire('waypointdragend', this._createWaypointEvent(i, e)); - this._waypoints[i].latLng = e.target.getLatLng(); - this._waypoints[i].name = ''; - this._updateWaypointName(i, this._geocoderElems[i], true); - this._fireChanged(); - }, this); - }, - - _createWaypointEvent: function(i, e) { - return {index: i, latlng: e.target.getLatLng()}; - }, - - dragNewWaypoint: function(e) { - var i; - this._newWp = { - afterIndex: e.afterIndex, - marker: L.marker(e.latlng).addTo(this._map), - lines: [] - }; - - for (i = 0; i < this.options.dragStyles.length; i++) { - this._newWp.lines.push(L.polyline([ - this._waypoints[e.afterIndex].latLng, - e.latlng, - this._waypoints[e.afterIndex + 1].latLng - ], this.options.dragStyles[i]).addTo(this._map)); - } - - this._markers.splice(e.afterIndex + 1, 0, this._newWp.marker); - this._map.on('mousemove', this._onDragNewWp, this); - this._map.on('mouseup', this._onWpRelease, this); - }, - - _onDragNewWp: function(e) { - var i; - this._newWp.marker.setLatLng(e.latlng); - for (i = 0; i < this._newWp.lines.length; i++) { - this._newWp.lines[i].spliceLatLngs(1, 1, e.latlng); - } - }, - - _onWpRelease: function(e) { - var i; - this._map.off('mouseup', this._onWpRelease, this); - this._map.off('mousemove', this._onDragNewWp, this); - for (i = 0; i < this._newWp.lines.length; i++) { - this._map.removeLayer(this._newWp.lines[i]); - } - this.spliceWaypoints(this._newWp.afterIndex + 1, 0, e.latlng); - delete this._newWp; - } - }); - - L.Routing.plan = function(waypoints, options) { - return new L.Routing.Plan(waypoints, options); - }; -})(); -(function() { - 'use strict'; - - L.Routing.Control = L.Routing.Itinerary.extend({ - options: { - fitSelectedRoutes: true - }, - - initialize: function(options) { - L.Util.setOptions(this, options); - - this._router = this.options.router || new L.Routing.OSRM(); - this._plan = this.options.plan || L.Routing.plan(undefined, { geocoder: this.options.geocoder }); - if (this.options.geocoder) { - this._plan.options.geocoder = this.options.geocoder; - } - if (this.options.waypoints) { - this._plan.setWaypoints(this.options.waypoints); - } - - L.Routing.Itinerary.prototype.initialize.call(this, options); - - this.on('routeselected', this._routeSelected, this); - this._plan.on('waypointschanged', function(e) { - this._route(); - this.fire('waypointschanged', {waypoints: e.waypoints}); - }, this); - - this._route(); - }, - - onAdd: function(map) { - var container = L.Routing.Itinerary.prototype.onAdd.call(this, map); - - this._map = map; - this._map.addLayer(this._plan); - - if (this.options.geocoder) { - container.insertBefore(this._plan.createGeocoders(), container.firstChild); - } - - return container; - }, - - onRemove: function(map) { - if (this._line) { - map.removeLayer(this._line); - } - map.removeLayer(this._plan); - return L.Routing.Itinerary.prototype.onRemove.call(this, map); - }, - - getWaypoints: function() { - return this._plan.getWaypoints(); - }, - - setWaypoints: function(waypoints) { - if(waypoints.length==0) $('.clearroute').hide(); - this._plan.setWaypoints(waypoints); - return this; - }, - - spliceWaypoints: function() { - var removed = this._plan.spliceWaypoints.apply(this._plan, arguments); - return removed; - }, - - getPlan: function() { - return this._plan; - }, - - _routeSelected: function(e) { - var route = e.route; - this._clearLine(); - - this._line = L.Routing.line(route, this.options.lineOptions); - this._line.addTo(this._map); - this._hookEvents(this._line); - - if (this.options.fitSelectedRoutes) { - this._map.fitBounds(this._line.getBounds()); - } - }, - - _hookEvents: function(l) { - l.on('linetouched', function(e) { - this._plan.dragNewWaypoint(e); - }, this); - }, - - _route: function() { - var wps; - - this._clearLine(); - this._clearAlts(); - - if (this._plan.isReady()) { - wps = this._plan.getWaypoints(); - this.fire('routingstart', {waypoints: wps}); - this._router.route(wps, function(err, routes) { - if (err) { - this.fire('routingerror', {error: err}); - return; - } - this.fire('routesfound', {waypoints: wps, routes: routes}); - $('.clearroute').show(); - this.setAlternatives(routes); - - }, this); - } - }, - - _clearLine: function() { - if (this._line) { - this._map.removeLayer(this._line); - delete this._line; - } - } - }); - - L.Routing.control = function(options) { - return new L.Routing.Control(options); - }; -})(); - return L.Routing; -})); -// Packaging/modules magic dance end. This code is inserted after all other -// code when the dist is built. \ No newline at end of file +/*! leaflet-routing-machine - v2.6.1 - 2016-01-07 */ + +!function(a){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=a();else if("function"==typeof define&&define.amd)define([],a);else{var b;b="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,(b.L||(b.L={})).Routing=a()}}(function(){return function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);var j=new Error("Cannot find module '"+g+"'");throw j.code="MODULE_NOT_FOUND",j}var k=c[g]={exports:{}};b[g][0].call(k.exports,function(a){var c=b[g][1][a];return e(c?c:a)},k,k.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g=200&&300>a||304===a}function e(){void 0===h.status||d(h.status)?b.call(h,null,h):b.call(h,h,null)}var f=!1;if("undefined"==typeof window.XMLHttpRequest)return b(Error("Browser not supported"));if("undefined"==typeof c){var g=a.match(/^\s*https?:\/\/[^\/]*/);c=g&&g[0]!==location.protocol+"//"+location.domain+(location.port?":"+location.port:"")}var h=new window.XMLHttpRequest;if(c&&!("withCredentials"in h)){h=new window.XDomainRequest;var i=b;b=function(){if(f)i.apply(this,arguments);else{var a=this,b=arguments;setTimeout(function(){i.apply(a,b)},0)}}}return"onload"in h?h.onload=e:h.onreadystatechange=function(){4===h.readyState&&e()},h.onerror=function(a){b.call(this,a||!0,null),b=function(){}},h.onprogress=function(){},h.ontimeout=function(a){b.call(this,a,null),b=function(){}},h.onabort=function(a){b.call(this,a,null),b=function(){}},h.open("GET",a,!0),h.send(null),f=!0,h}"undefined"!=typeof b&&(b.exports=d)},{}],2:[function(a,b,c){function d(a,b){a=Math.round(a*b),a<<=1,0>a&&(a=~a);for(var c="";a>=32;)c+=String.fromCharCode((32|31&a)+63),a>>=5;return c+=String.fromCharCode(a+63)}var e={};e.decode=function(a,b){for(var c,d,e=0,f=0,g=0,h=[],i=0,j=0,k=null,l=Math.pow(10,b||5);e=32);c=1&j?~(j>>1):j>>1,i=j=0;do k=a.charCodeAt(e++)-63,j|=(31&k)<=32);d=1&j?~(j>>1):j>>1,f+=c,g+=d,h.push([f/l,g/l])}return h},e.encode=function(a,b){if(!a.length)return"";for(var c=Math.pow(10,b||5),e=d(a[0][0],c)+d(a[0][1],c),f=1;f0&&this._select(1)},_createClickListener:function(a){var b=this._resultSelected(a);return L.bind(function(){this._elem.blur(),b()},this)},_resultSelected:function(a){return L.bind(function(){this.close(),this._elem.value=a.name,this._lastCompletedText=a.name,this._selectFn(a)},this)},_keyPressed:function(a){var b;return this._isOpen&&13===a.keyCode&&this._selection?(b=parseInt(this._selection.getAttribute("data-result-index"),10),this._resultSelected(this._results[b])(),void L.DomEvent.preventDefault(a)):13===a.keyCode?void this._complete(this._resultFn,!0):this._autocomplete&&document.activeElement===this._elem?(this._timer&&clearTimeout(this._timer),void(this._timer=setTimeout(L.Util.bind(function(){this._complete(this._autocomplete)},this),this.options.timeout))):void this._unselect()},_select:function(a){var b=this._selection;b&&(L.DomUtil.removeClass(b.firstChild,"leaflet-routing-geocoder-selected"),b=b[a>0?"nextSibling":"previousSibling"]),b||(b=this._resultTable[a>0?"firstChild":"lastChild"]),b&&(L.DomUtil.addClass(b.firstChild,"leaflet-routing-geocoder-selected"),this._selection=b)},_unselect:function(){this._selection&&L.DomUtil.removeClass(this._selection.firstChild,"leaflet-routing-geocoder-selected"),delete this._selection},_keyDown:function(a){if(this._isOpen)switch(a.keyCode){case 27:return this.close(),void L.DomEvent.preventDefault(a);case 38:return this._select(-1),void L.DomEvent.preventDefault(a);case 40:return this._select(1),void L.DomEvent.preventDefault(a)}},_complete:function(a,b){function c(a){this._lastCompletedText=d,b&&1===a.length?this._resultSelected(a[0])():this._setResults(a)}var d=this._elem.value;d&&(d!==this._lastCompletedText?a(d,c,this):b&&c.call(this,this._results))}})}()},{}],4:[function(a,b,c){(function(c){!function(){"use strict";var d="undefined"!=typeof window?window.L:"undefined"!=typeof c?c.L:null;d.Routing=d.Routing||{},d.extend(d.Routing,a("./L.Routing.Itinerary")),d.extend(d.Routing,a("./L.Routing.Line")),d.extend(d.Routing,a("./L.Routing.Plan")),d.extend(d.Routing,a("./L.Routing.OSRM")),d.extend(d.Routing,a("./L.Routing.ErrorControl")),d.Routing.Control=d.Routing.Itinerary.extend({options:{fitSelectedRoutes:"smart",routeLine:function(a,b){return d.Routing.line(a,b)},autoRoute:!0,routeWhileDragging:!1,routeDragInterval:500,waypointMode:"connect",useZoomParameter:!1,showAlternatives:!1},initialize:function(a){d.Util.setOptions(this,a),this._router=this.options.router||new d.Routing.OSRM(a),this._plan=this.options.plan||d.Routing.plan(this.options.waypoints,a),this._requestCount=0,d.Routing.Itinerary.prototype.initialize.call(this,a),this.on("routeselected",this._routeSelected,this),this._plan.on("waypointschanged",this._onWaypointsChanged,this),a.routeWhileDragging&&this._setupRouteDragging(),this.options.autoRoute&&this.route()},onAdd:function(a){var b=d.Routing.Itinerary.prototype.onAdd.call(this,a);return this._map=a,this._map.addLayer(this._plan),this.options.useZoomParameter&&this._map.on("zoomend",function(){this.route({callback:d.bind(this._updateLineCallback,this)})},this),this._plan.options.geocoder&&b.insertBefore(this._plan.createGeocoders(),b.firstChild),b},onRemove:function(a){return this._line&&a.removeLayer(this._line),a.removeLayer(this._plan),d.Routing.Itinerary.prototype.onRemove.call(this,a)},getWaypoints:function(){return this._plan.getWaypoints()},setWaypoints:function(a){return this._plan.setWaypoints(a),this},spliceWaypoints:function(){var a=this._plan.spliceWaypoints.apply(this._plan,arguments);return a},getPlan:function(){return this._plan},getRouter:function(){return this._router},_routeSelected:function(a){var b=a.route,c=this.options.showAlternatives&&a.alternatives,d=this.options.fitSelectedRoutes,e="smart"===d&&!this._waypointsVisible()||"smart"!==d&&d;this._updateLines({route:b,alternatives:c}),e&&this._map.fitBounds(this._line.getBounds()),"snap"===this.options.waypointMode&&(this._plan.off("waypointschanged",this._onWaypointsChanged,this),this.setWaypoints(b.waypoints),this._plan.on("waypointschanged",this._onWaypointsChanged,this))},_waypointsVisible:function(){var a,b,c,e,f,g=this.getWaypoints();try{for(a=this._map.getSize(),e=0;ea.x/5||c.y>a.y/5)&&this._waypointsInViewport()}catch(h){return!1}},_waypointsInViewport:function(){var a,b,c=this.getWaypoints();try{a=this._map.getBounds()}catch(d){return!1}for(b=0;b
"+a.message+"
=b,j=i?function(a){return a}:d.bind(this._round,this);return"imperial"===this.options.units?(e=a/.9144,f=e>=1e3?{value:j(a/1609.344,b),unit:h.miles}:{value:j(e,b),unit:h.yards}):(c=j(a,b),f={value:c>=1e3?c/1e3:c,unit:c>=1e3?h.kilometers:h.meters}),i&&(g=Math.pow(10,-b),f.value=Math.round(f.value*g)/g),d.Util.template(this.options.distanceTemplate,f)},_round:function(a,b){var c=b||this.options.roundingSensitivity,d=Math.pow(10,(Math.floor(a/c)+"").length-1),e=Math.floor(a/d),f=e>5?d:d/2;return Math.round(a/f)*f},formatTime:function(a){return a>86400?Math.round(a/3600)+" h":a>3600?Math.floor(a/3600)+" h "+Math.round(a%3600/60)+" min":a>300?Math.round(a/60)+" min":a>60?Math.floor(a/60)+" min"+(a%60!==0?" "+a%60+" s":""):a+" s"},formatInstruction:function(a,b){return void 0===a.text?d.Util.template(this._getInstructionTemplate(a,b),d.extend({exitStr:a.exit?d.Routing.Localization[this.options.language].formatOrder(a.exit):"",dir:d.Routing.Localization[this.options.language].directions[a.direction]},a)):a.text},getIconName:function(a,b){switch(a.type){case"Straight":return 0===b?"depart":"continue";case"SlightRight":return"bear-right";case"Right":return"turn-right";case"SharpRight":return"sharp-right";case"TurnAround":return"u-turn";case"SharpLeft":return"sharp-left";case"Left":return"turn-left";case"SlightLeft":return"bear-left";case"WaypointReached":return"via";case"Roundabout":return"enter-roundabout";case"DestinationReached":return"arrive"}},_getInstructionTemplate:function(a,b){var c="Straight"===a.type?0===b?"Head":"Continue":a.type,e=d.Routing.Localization[this.options.language].instructions[c];return e[0]+(e.length>1&&a.road?e[1]:"")}}),b.exports=d.Routing}()}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"./L.Routing.Localization":11}],7:[function(a,b,c){(function(c){!function(){"use strict";function d(a){a.setSelectionRange?a.setSelectionRange(0,9999):a.select()}var e="undefined"!=typeof window?window.L:"undefined"!=typeof c?c.L:null;e.Routing=e.Routing||{},e.extend(e.Routing,a("./L.Routing.Autocomplete")),e.Routing.GeocoderElement=e.Class.extend({includes:e.Mixin.Events,options:{createGeocoder:function(a,b,c){var d=e.DomUtil.create("div","leaflet-routing-geocoder"),f=e.DomUtil.create("input","",d),g=c.addWaypoints?e.DomUtil.create("span","leaflet-routing-remove-waypoint",d):void 0;return f.disabled=!c.addWaypoints,{container:d,input:f,closeButton:g}},geocoderPlaceholder:function(a,b,c){var d=e.Routing.Localization[c.options.language].ui;return 0===a?d.startPlaceholder:b-1>a?e.Util.template(d.viaPlaceholder,{viaNumber:a}):d.endPlaceholder},geocoderClass:function(){return""},waypointNameFallback:function(a){var b=a.lat<0?"S":"N",c=a.lng<0?"W":"E",d=(Math.round(1e4*Math.abs(a.lat))/1e4).toString(),e=(Math.round(1e4*Math.abs(a.lng))/1e4).toString();return b+d+", "+c+e},maxGeocoderTolerance:200,autocompleteOptions:{},language:"en"},initialize:function(a,b,c,f){e.setOptions(this,f);var g=this.options.createGeocoder(b,c,this.options),h=g.closeButton,i=g.input;i.setAttribute("placeholder",this.options.geocoderPlaceholder(b,c,this)),i.className=this.options.geocoderClass(b,c),this._element=g,this._waypoint=a,this.update(),i.value=a.name,e.DomEvent.addListener(i,"click",function(){d(this)},i),h&&e.DomEvent.addListener(h,"click",function(){this.fire("delete",{waypoint:this._waypoint})},this),new e.Routing.Autocomplete(i,function(b){i.value=b.name,a.name=b.name,a.latLng=b.center,this.fire("geocoded",{waypoint:a,value:b})},this,e.extend({resultFn:this.options.geocoder.geocode,resultContext:this.options.geocoder,autocompleteFn:this.options.geocoder.suggest,autocompleteContext:this.options.geocoder},this.options.autocompleteOptions))},getContainer:function(){return this._element.container},setValue:function(a){this._element.input.value=a},update:function(a){var b,c=this._waypoint;c.name=c.name||"",!c.latLng||!a&&c.name||(b=this.options.waypointNameFallback(c.latLng),this.options.geocoder&&this.options.geocoder.reverse?this.options.geocoder.reverse(c.latLng,67108864,function(a){a.length>0&&a[0].center.distanceTo(c.latLng){name}

{distance}, {time}

",timeTemplate:"{time}",containerClassName:"",alternativeClassName:"",minimizedClassName:"",itineraryClassName:"",totalDistanceRoundingSensitivity:-1,show:!0,collapsible:void 0,collapseBtn:function(a){var b=d.DomUtil.create("span",a.options.collapseBtnClass);d.DomEvent.on(b,"click",a._toggle,a),a._container.insertBefore(b,a._container.firstChild)},collapseBtnClass:"leaflet-routing-collapse-btn"},initialize:function(a){d.setOptions(this,a),this._formatter=this.options.formatter||new d.Routing.Formatter(this.options),this._itineraryBuilder=this.options.itineraryBuilder||new d.Routing.ItineraryBuilder({containerClassName:this.options.itineraryClassName})},onAdd:function(a){var b=this.options.collapsible;return b=b||void 0===b&&a.getSize().x<=640,this._container=d.DomUtil.create("div","leaflet-routing-container leaflet-bar "+(this.options.show?"":"leaflet-routing-container-hide ")+(b?"leaflet-routing-collapsible ":"")+this.options.containerClassName),this._altContainer=this.createAlternativesContainer(),this._container.appendChild(this._altContainer),d.DomEvent.disableClickPropagation(this._container),d.DomEvent.addListener(this._container,"mousewheel",function(a){d.DomEvent.stopPropagation(a)}),b&&this.options.collapseBtn(this),this._container},onRemove:function(){},createAlternativesContainer:function(){return d.DomUtil.create("div","leaflet-routing-alternatives-container")},setAlternatives:function(a){var b,c,d;for(this._clearAlts(),this._routes=a,b=0;b0?" leaflet-routing-alt-minimized "+this.options.minimizedClassName:"")),e=this.options.summaryTemplate,f=d.extend({name:a.name,distance:this._formatter.formatDistance(a.summary.totalDistance,this.options.totalDistanceRoundingSensitivity),time:this._formatter.formatTime(a.summary.totalTime)},a);return c.innerHTML="function"==typeof e?e(f):d.Util.template(e,f),d.DomEvent.addListener(c,"click",this._onAltClicked,this),this.on("routeselected",this._selectAlt,this),c.appendChild(this._createItineraryContainer(a)),c},_clearAlts:function(){for(var a=this._altContainer;a&&a.firstChild;)a.removeChild(a.firstChild);this._altElements=[]},_createItineraryContainer:function(a){var b,c,d,e,f,g,h=this._itineraryBuilder.createContainer(),i=this._itineraryBuilder.createStepsContainer();for(h.appendChild(i),b=0;b=0;c--)d=a.distanceTo(this._route.coordinates[c]),e>d&&(b=c,e=d);return b},_extendToWaypoints:function(){var a,b,d,e=this._route.inputWaypoints,f=this._getWaypointIndices();for(a=0;athis.options.missingRouteTolerance&&this._addSegment([b,d],this.options.missingRouteStyles)},_addSegment:function(a,b,d){var e,f;for(e=0;e=0&&b[c]>a;)c--;return c},_onLineTouched:function(a){var b=this._findNearestWpBefore(this._findClosestRoutePoint(a.latlng));this.fire("linetouched",{afterIndex:b,latlng:a.latlng})},_getWaypointIndices:function(){return this._wpIndices||(this._wpIndices=this._route.waypointIndices||this._findWaypointIndices()),this._wpIndices}}),c.Routing.line=function(a,b){return new c.Routing.Line(a,b)},b.exports=c.Routing}()}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],11:[function(a,b,c){!function(){"use strict";L.Routing=L.Routing||{},L.Routing.Localization={en:{directions:{N:"north",NE:"northeast",E:"east",SE:"southeast",S:"south",SW:"southwest",W:"west",NW:"northwest"},instructions:{Head:["Head {dir}"," on {road}"],Continue:["Continue {dir}"," on {road}"],SlightRight:["Slight right"," onto {road}"],Right:["Right"," onto {road}"],SharpRight:["Sharp right"," onto {road}"],TurnAround:["Turn around"],SharpLeft:["Sharp left"," onto {road}"],Left:["Left"," onto {road}"],SlightLeft:["Slight left"," onto {road}"],WaypointReached:["Waypoint reached"],Roundabout:["Take the {exitStr} exit in the roundabout"," onto {road}"],DestinationReached:["Destination reached"]},formatOrder:function(a){var b=a%10-1,c=["st","nd","rd"];return c[b]?a+c[b]:a+"th"},ui:{startPlaceholder:"Start",viaPlaceholder:"Via {viaNumber}",endPlaceholder:"End"}},de:{directions:{N:"Norden",NE:"Nordosten",E:"Osten",SE:"Südosten",S:"Süden",SW:"Südwesten",W:"Westen",NW:"Nordwesten"},instructions:{Head:["Richtung {dir}"," auf {road}"],Continue:["Geradeaus Richtung {dir}"," auf {road}"],SlightRight:["Leicht rechts abbiegen"," auf {road}"],Right:["Rechts abbiegen"," auf {road}"],SharpRight:["Scharf rechts abbiegen"," auf {road}"],TurnAround:["Wenden"],SharpLeft:["Scharf links abbiegen"," auf {road}"],Left:["Links abbiegen"," auf {road}"],SlightLeft:["Leicht links abbiegen"," auf {road}"],WaypointReached:["Zwischenhalt erreicht"],Roundabout:["Nehmen Sie die {exitStr} Ausfahrt im Kreisverkehr"," auf {road}"],DestinationReached:["Sie haben ihr Ziel erreicht"]},formatOrder:function(a){return a+"."},ui:{startPlaceholder:"Start",viaPlaceholder:"Via {viaNumber}",endPlaceholder:"Ziel"}},sv:{directions:{N:"norr",NE:"nordost",E:"öst",SE:"sydost",S:"syd",SW:"sydväst",W:"väst",NW:"nordväst"},instructions:{Head:["Åk åt {dir}"," på {road}"],Continue:["Fortsätt {dir}"," på {road}"],SlightRight:["Svagt höger"," på {road}"],Right:["Sväng höger"," på {road}"],SharpRight:["Skarpt höger"," på {road}"],TurnAround:["Vänd"],SharpLeft:["Skarpt vänster"," på {road}"],Left:["Sväng vänster"," på {road}"],SlightLeft:["Svagt vänster"," på {road}"],WaypointReached:["Viapunkt nådd"],Roundabout:["Tag {exitStr} avfarten i rondellen"," till {road}"],DestinationReached:["Framme vid resans mål"]},formatOrder:function(a){return["första","andra","tredje","fjärde","femte","sjätte","sjunde","åttonde","nionde","tionde"][a-1]},ui:{startPlaceholder:"Från",viaPlaceholder:"Via {viaNumber}",endPlaceholder:"Till"}},sp:{directions:{N:"norte",NE:"noreste",E:"este",SE:"sureste",S:"sur",SW:"suroeste",W:"oeste",NW:"noroeste"},instructions:{Head:["Derecho {dir}"," sobre {road}"],Continue:["Continuar {dir}"," en {road}"],SlightRight:["Leve giro a la derecha"," sobre {road}"],Right:["Derecha"," sobre {road}"],SharpRight:["Giro pronunciado a la derecha"," sobre {road}"],TurnAround:["Dar vuelta"],SharpLeft:["Giro pronunciado a la izquierda"," sobre {road}"],Left:["Izquierda"," en {road}"],SlightLeft:["Leve giro a la izquierda"," en {road}"],WaypointReached:["Llegó a un punto del camino"],Roundabout:["Tomar {exitStr} salida en la rotonda"," en {road}"],DestinationReached:["Llegada a destino"]},formatOrder:function(a){return a+"º"},ui:{startPlaceholder:"Inicio",viaPlaceholder:"Via {viaNumber}",endPlaceholder:"Destino"}},nl:{directions:{N:"noordelijke",NE:"noordoostelijke",E:"oostelijke",SE:"zuidoostelijke",S:"zuidelijke",SW:"zuidewestelijke",W:"westelijke",NW:"noordwestelijke"},instructions:{Head:["Vertrek in {dir} richting"," de {road} op"],Continue:["Ga in {dir} richting"," de {road} op"],SlightRight:["Volg de weg naar rechts"," de {road} op"],Right:["Ga rechtsaf"," de {road} op"],SharpRight:["Ga scherpe bocht naar rechts"," de {road} op"],TurnAround:["Keer om"],SharpLeft:["Ga scherpe bocht naar links"," de {road} op"],Left:["Ga linksaf"," de {road} op"],SlightLeft:["Volg de weg naar links"," de {road} op"],WaypointReached:["Aangekomen bij tussenpunt"],Roundabout:["Neem de {exitStr} afslag op de rotonde"," de {road} op"],DestinationReached:["Aangekomen op eindpunt"]},formatOrder:function(a){return 1===a||a>=20?a+"ste":a+"de"},ui:{startPlaceholder:"Vertrekpunt",viaPlaceholder:"Via {viaNumber}",endPlaceholder:"Bestemming"}},fr:{directions:{N:"nord",NE:"nord-est",E:"est",SE:"sud-est",S:"sud",SW:"sud-ouest",W:"ouest",NW:"nord-ouest"},instructions:{Head:["Tout droit au {dir}"," sur {road}"],Continue:["Continuer au {dir}"," sur {road}"],SlightRight:["Légèrement à droite"," sur {road}"],Right:["A droite"," sur {road}"],SharpRight:["Complètement à droite"," sur {road}"],TurnAround:["Faire demi-tour"],SharpLeft:["Complètement à gauche"," sur {road}"],Left:["A gauche"," sur {road}"],SlightLeft:["Légèrement à gauche"," sur {road}"],WaypointReached:["Point d'étape atteint"],Roundabout:["Au rond-point, prenez la {exitStr} sortie"," sur {road}"],DestinationReached:["Destination atteinte"]},formatOrder:function(a){return a+"º"},ui:{startPlaceholder:"Départ",viaPlaceholder:"Intermédiaire {viaNumber}",endPlaceholder:"Arrivée"}},it:{directions:{N:"nord",NE:"nord-est",E:"est",SE:"sud-est",S:"sud",SW:"sud-ovest",W:"ovest",NW:"nord-ovest"},instructions:{Head:["Dritto verso {dir}"," su {road}"],Continue:["Continuare verso {dir}"," su {road}"],SlightRight:["Mantenere la destra"," su {road}"], +Right:["A destra"," su {road}"],SharpRight:["Strettamente a destra"," su {road}"],TurnAround:["Fare inversione di marcia"],SharpLeft:["Strettamente a sinistra"," su {road}"],Left:["A sinistra"," sur {road}"],SlightLeft:["Mantenere la sinistra"," su {road}"],WaypointReached:["Punto di passaggio raggiunto"],Roundabout:["Alla rotonda, prendere la {exitStr} uscita"],DestinationReached:["Destinazione raggiunta"]},formatOrder:function(a){return a+"º"},ui:{startPlaceholder:"Partenza",viaPlaceholder:"Intermedia {viaNumber}",endPlaceholder:"Destinazione"}},pt:{directions:{N:"norte",NE:"nordeste",E:"leste",SE:"sudeste",S:"sul",SW:"sudoeste",W:"oeste",NW:"noroeste"},instructions:{Head:["Siga {dir}"," na {road}"],Continue:["Continue {dir}"," na {road}"],SlightRight:["Curva ligeira a direita"," na {road}"],Right:["Curva a direita"," na {road}"],SharpRight:["Curva fechada a direita"," na {road}"],TurnAround:["Retorne"],SharpLeft:["Curva fechada a esquerda"," na {road}"],Left:["Curva a esquerda"," na {road}"],SlightLeft:["Curva ligueira a esquerda"," na {road}"],WaypointReached:["Ponto de interesse atingido"],Roundabout:["Pegue a {exitStr} saída na rotatória"," na {road}"],DestinationReached:["Destino atingido"]},formatOrder:function(a){return a+"º"},ui:{startPlaceholder:"Origem",viaPlaceholder:"Intermédio {viaNumber}",endPlaceholder:"Destino"}}},b.exports=L.Routing}()},{}],12:[function(a,b,c){(function(c){!function(){"use strict";var d="undefined"!=typeof window?window.L:"undefined"!=typeof c?c.L:null,e=a("corslite"),f=a("polyline");d.Routing=d.Routing||{},d.extend(d.Routing,a("./L.Routing.Waypoint")),d.Routing.OSRM=d.Class.extend({options:{serviceUrl:"//router.project-osrm.org/viaroute",timeout:3e4,routingOptions:{}},initialize:function(a){d.Util.setOptions(this,a),this._hints={locations:{}}},route:function(a,b,c,f){var g,h,i,j,k=!1,l=[];for(g=this.buildRouteUrl(a,d.extend({},this.options.routingOptions,f)),h=setTimeout(function(){k=!0,b.call(c||b,{status:-1,message:"OSRM request timed out."})},this.options.timeout),j=0;j=0;b--)e[b]=d.latLng(c[b]);return e},_toWaypoints:function(a,b){var c,e=[];for(c=0;c=0;d--)c=b[d].latLng,this._hints.locations[this._locationKey(c)]=a.locations[d]},_convertSummary:function(a){return{totalDistance:a.total_distance,totalTime:a.total_time}},_convertInstructions:function(a){var b,c,d,e,f=[];for(b=0;b1?e[1]:void 0,index:c[3]});return f},_drivingDirectionType:function(a){switch(parseInt(a,10)){case 1:return"Straight";case 2:return"SlightRight";case 3:return"Right";case 4:return"SharpRight";case 5:return"TurnAround";case 6:return"SharpLeft";case 7:return"Left";case 8:return"SlightLeft";case 9:return"WaypointReached";case 10:return"Straight";case 11:case 12:return"Roundabout";case 15:return"DestinationReached";default:return null}},_clampIndices:function(a,b){var c,d=b.length-1;for(c=0;c0||this._waypoints.length>2?this.spliceWaypoints(a,1):this.spliceWaypoints(a,1,new d.Routing.Waypoint)},this).on("geocoded",function(b){this._updateMarkers(),this._fireChanged(),this._focusGeocoder(a+1),this.fire("waypointgeocoded",{waypointIndex:a,waypoint:b.waypoint})},this).on("reversegeocoded",function(b){this.fire("waypointgeocoded",{waypointIndex:a,waypoint:b.waypoint})},this),b},_updateGeocoders:function(){var a,b,c=[];for(a=0;a=0;a--)b=this._createGeocoder(a),this._geocoderContainer.insertBefore(b.getContainer(),this._geocoderContainer.firstChild),c.push(b);this._geocoderElems=c.reverse()},_removeMarkers:function(){var a;if(this._markers)for(a=0;a=2&&this.fire("waypointsspliced",{index:Array.prototype.shift.call(arguments),nRemoved:Array.prototype.shift.call(arguments),added:arguments})},_hookWaypointEvents:function(a,b,c){var e,f,g=function(a){return c?a.latlng:a.target.getLatLng()},h=d.bind(function(a){this.fire("waypointdragstart",{index:b,latlng:g(a)})},this),i=d.bind(function(a){this._waypoints[b].latLng=g(a),this.fire("waypointdrag",{index:b,latlng:g(a)})},this),j=d.bind(function(a){this._waypoints[b].latLng=g(a),this._waypoints[b].name="",this._geocoderElems&&this._geocoderElems[b].update(!0),this.fire("waypointdragend",{index:b,latlng:g(a)}),this._fireChanged()},this);c?(e=d.bind(function(a){this._markers[b].setLatLng(a.latlng),i(a)},this),f=d.bind(function(a){this._map.dragging.enable(),this._map.off("mouseup",f),this._map.off("mousemove",e),j(a)},this),this._map.dragging.disable(),this._map.on("mousemove",e),this._map.on("mouseup",f),h({latlng:this._waypoints[b].latLng})):(a.on("dragstart",h),a.on("drag",i),a.on("dragend",j))},dragNewWaypoint:function(a){var b=a.afterIndex+1;this.options.routeWhileDragging?(this.spliceWaypoints(b,0,a.latlng),this._hookWaypointEvents(this._markers[b],b,!0)):this._dragNewWaypoint(b,a.latlng)},_dragNewWaypoint:function(a,b){var c,e=new d.Routing.Waypoint(b),f=this._waypoints[a-1],g=this._waypoints[a],h=this.options.createMarker(a,e,this._waypoints.length+1),i=[],j=d.bind(function(a){var b;for(h&&h.setLatLng(a.latlng),b=0;b'; } }) - var houseNo = (result.originalObject.address.house_number) ? result.originalObject.address.house_number : ''; - popupHtml += result.originalObject.address.road + ' ' + houseNo + '
'; - popupHtml += result.originalObject.address.town + ', ' + result.originalObject.address.state + ', ' + result.originalObject.address.country; + var houseNo = (address.house_number) ? address.house_number : ''; + popupHtml += address.road + ' ' + houseNo + '
'; + popupHtml += address.town + ', ' + address.state + ', ' + address.country; toolKit.addMarker(Maps.droppedPin, popupHtml, true); }, 50); @@ -139,7 +158,8 @@ Array.prototype.unique = function() { zoom : oldZoom, zoomControl : false, layers : [mapQuest] - }); + }), + map.options.minZoom = 3; var hash = new L.Hash(map); /*var baseMaps = { @@ -170,18 +190,19 @@ Array.prototype.unique = function() { }); routing = L.Routing.control({ waypoints : [], - geocoder : L.Control.Geocoder.nominatim(), - plan : L.Routing.plan(null, { - waypointIcon : function(i) { - return new L.Icon.Label.Default({ - labelText : String.fromCharCode(65 + i) - }); - } - }) + //geocoder : geocoder, + routeWhileDragging: true, + fitSelectedRoutes: true, + show: false }).addTo(map); - $(".leaflet-routing-geocoders").appendTo("#searchContainer"); - $(".leaflet-routing-container").appendTo("#searchContainer"); - $('.geocoder-0').attr('completiontype', 'local'); + + routing.getPlan().on('waypointschanged', function(e) { + geocodeSearch.waypointsChanged(e); + }) + + apiKey = ''; + + geocodeSearch.addGeocoder(); // properly style as input field //$('#searchContainer').find('input').attr('type', 'text'); @@ -192,6 +213,16 @@ Array.prototype.unique = function() { Maps.displayPoiIcons(zoom); }) + $.post(OC.generateUrl('/apps/maps/api/1.0/apikey/getKey'), null, function(data){ + if(data.id != null && data.apiKey != null) { + apiKey = data.apiKey; + document.getElementById('apiKey').value = apiKey; + geocoder = L.Control.Geocoder.mapzen(apiKey); + } else { + geocoder = L.Control.Geocoder.nominatim(); + } + }); + map.on('mousedown', function(e) { Maps.mouseDowntime = new Date().getTime(); }); @@ -204,14 +235,10 @@ Array.prototype.unique = function() { if (Maps.droppedPin) { map.removeLayer(Maps.droppedPin); Maps.droppedPin = false; - if ($('.geocoder-0').attr('completiontype') === 'local' && ($('.geocoder-0').val() == '')) { - $('.geocoder-0').val(''); - } } if (/*(curTime - Maps.mouseDowntime) > 200 && */Maps.dragging === false) {//200 = 2 seconds addGeocodeMarker(e.latlng); } - }); map.on("dragstart", function() { @@ -220,18 +247,6 @@ Array.prototype.unique = function() { map.on("dragend zoomend", function(e) { Maps.saveCurrentLocation(e); Maps.dragging = false; - var searchInput = $('.geocoder-0') - if (searchInput.attr('completiontype') == 'local' && searchInput.val() != '') { - var data = { - search : searchInput.val(), - bbox : map.getBounds().toBBoxString() - } - clearTimeout(searchTimeout); - searchTimeout = setTimeout(function() { - console.log('Get new results'); - mapSearch.getSearchResults(data, mapSearch.showResultsOnMap); - }, 500); - } }) $(document).on('click', '.toggle-children', function(e) { @@ -432,6 +447,16 @@ Array.prototype.unique = function() { minDate : -900 }); + $(document).on('click', '#setApiKey', function(e) { + var value = document.getElementById('apiKey').value; + if(value.length == 0) return; + var formData = { + key : value + }; + $.post(OC.generateUrl('/apps/maps/api/1.0/apikey/addKey'), formData, function(data){ + }); + }); + $(document).on('click', '.deviceHistory', function(e) { var isVisible = $(this).parent().find('i').length; var dId = $(this).parent().attr('data-deviceId'); @@ -473,30 +498,6 @@ Array.prototype.unique = function() { /* searchItems = []*/ searchTimeout = 0; - $(document).on('keyup blur', '.geocoder-0', function(e) { - if ($(this).attr('completiontype') != 'local') - return; - - var data = { - search : $(this).val(), - bbox : map.getBounds().toBBoxString() - } - clearTimeout(searchTimeout); - if ($(this).val() == '') { - mapSearch.clearSearchResults(); - mapSearch._ids = []; - } - if (e.keyCode != 13) { - searchTimeout = setTimeout(function() { - - }, 1000) - } else { - mapSearch.clearSearchResults(); - mapSearch._ids = []; - mapSearch.getSearchResults(data, mapSearch.showResultsOnMap); - } - - }); /** * setDestination on click */ @@ -511,18 +512,18 @@ Array.prototype.unique = function() { $(document).on('click', '.setDestination', function() { var latlng = $(this).attr('data-latlng'); - routing.setWaypoints([]) var end = latlng.split(','); end[0] = end[0] * 1; end[1] = end[1] * 1; //map.removeLayer(routing); - routing.setWaypoints([L.latLng(currentlocation[0], currentlocation[1]), L.latLng(end[0], end[1])]); + routing.setWaypoints([ + L.Routing.waypoint(L.latLng(currentlocation[0], currentlocation[1]), ""), + L.Routing.waypoint(L.latLng(end[0], end[1]), "") + ]); - $('.geocoder-1').show(); map.closePopup(); }); - /** * Clear route */ @@ -555,6 +556,249 @@ Array.prototype.unique = function() { } } + geocodeSearch = { + results : [], + waypoints : [], + markers : [], + apiKeySet : function() { + return apiKey != null && apiKey.length > 0; + }, + addGeocoder : function() { + var geocoderInputs = document.getElementsByClassName('geocoder'); + var elems = 0; + if(geocoderInputs != null) elems = geocoderInputs.length; + if(elems == 7) return;//only allow 5 via points + var timeoutId; + var searchCont = document.getElementById('search'); + var geocoderDiv = document.createElement('div'); + geocoderDiv.className = 'geocoder-container'; + var input = document.createElement('input'); + input.type = 'text'; + input.className = 'geocoder not-geocoded'; + var debounceTimeout = 500; + if(!geocodeSearch.apiKeySet()) debounceTimeout = 1000; + input.addEventListener('input', debounce(function() { + geocodeSearch.performGeocode(input) + }, debounceTimeout)); + input.addEventListener('blur', geocodeSearch.clearResults(input)); + var list = document.createElement('ul'); + list.className = 'geocoder-list'; + list.style.display = 'none'; + + var btn = document.createElement('button'); + + if(elems == 0) { + geocoderDiv.id = 'geocoder-container-start'; + input.id = 'geocoder-start'; + list.id = 'geocoder-results-start'; + input.placeholder = 'Start address'; + + btn.className = 'icon-add geocoder-button'; + btn.id = 'geocoder-add'; + btn.addEventListener('click', function() { + geocodeSearch.addGeocoder(); + }); + + geocoderDiv.appendChild(input); + geocoderDiv.appendChild(list); + geocoderDiv.appendChild(btn); + searchCont.appendChild(geocoderDiv); + } else if(elems == 1) { + geocoderDiv.id = 'geocoder-container-end'; + input.id = 'geocoder-end'; + list.id = 'geocoder-results-end'; + input.placeholder = 'End address'; + + btn.className = 'icon-close geocoder-button'; + btn.id = 'geocoder-remove-end'; + btn.addEventListener('click', function() { + geocodeSearch.removeGeocoder(geocoderDiv); + }); + + geocoderDiv.appendChild(input); + geocoderDiv.appendChild(list); + geocoderDiv.appendChild(btn); + searchCont.appendChild(geocoderDiv); + } else { + var id = elems - 2; + geocoderDiv.id = 'geocoder-container-' + id; + input.id = 'geocoder-' + id; + list.id = 'geocoder-results-' + id; + input.placeholder = 'Via address '/* + (id+1)*/; + + btn.className = 'icon-close geocoder-button'; + btn.id = 'geocoder-remove-' + id; + btn.addEventListener('click', function() { + geocodeSearch.removeGeocoder(geocoderDiv); + }); + + var children = searchCont.childNodes; + var childLength = children.length; + geocoderDiv.appendChild(input); + geocoderDiv.appendChild(list); + geocoderDiv.appendChild(btn); + searchCont.insertBefore(geocoderDiv, children[childLength-1]); + } + }, + removeGeocoder : function(div) { + var geocoderInputs = document.getElementsByClassName('geocoder'); + var elems = 0; + if(geocoderInputs != null) elems = geocoderInputs.length; + var isGeocoded = div.getElementsByClassName('is-geocoded'); + if(isGeocoded.length > 0) { + geocodeSearch.removeMarker(isGeocoded[0].id) + } + //alert(div.getElementById('geocoder-end').toSource()) + if(div.id == 'geocoder-container-end') { + var children = div.parentElement.childNodes; + var childLength = children.length; + var newEndDiv = children[childLength-2]; + var newInput = newEndDiv.getElementsByClassName('geocoder')[0]; + var newList = newEndDiv.getElementsByClassName('geocoder-list')[0]; + var newButton = newEndDiv.getElementsByClassName('geocoder-button')[0]; + newEndDiv.id = 'geocoder-container-end'; + newInput.id = 'geocoder-end'; + newList.id = 'geocoder-results-end'; + if(document.getElementsByClassName('geocoder').length - 1 > 1) { + newInput.placeholder = 'End address'; + } + newButton.id = 'geocoder-remove-end'; + } + div.parentElement.removeChild(div); + }, + removeMarker : function(id) { + var remIndex = -1; + for(var i=0; i= 0) { + geocodeSearch.markers.splice(remIndex, 1); + geocodeSearch.computeRoute(); + } + }, + clearResults : function(input) { + geocodeSearch.results = []; + var idParts = input.id.split('-'); + var id = idParts[0] + '-results-' + idParts[1]; + var list = document.getElementById(id); + if(list == null) return; + list.innerHTML = ''; + list.style.display = 'none'; + }, + performGeocode : function(input) { + var query = input.value; + geocodeSearch.clearResults(input); + input.className = input.className.replace('is-geocoded', 'not-geocoded'); + geocodeSearch.removeMarker(input.id); + if(query.length < 3) return; + geocoder.geocode(query, function(data) { + geocodeSearch.addResults(data); + var formData = { + name : query + }; + $.post(OC.generateUrl('/apps/maps/api/1.0/favorite/getFavoritesByName'), formData, function(data){ + $.each(data, function(index, content) { + content.center = L.latLng(content.lat, content.lng); + content.bbox = null; + content.type = 'favorite'; + geocodeSearch.addResults(data); + }); + geocodeSearch.displayResults(input); + }); + }, null); + //TODO search for contacts + }, + addResults : function(searchResults) { + $.each(searchResults, function(index, cont) { + geocodeSearch.results.push(cont); + }) + }, + displayResults : function(input) { + var idParts = input.id.split('-'); + var id = idParts[0] + '-results-' + idParts[1]; + var list = document.getElementById(id); + $.each(geocodeSearch.results, function(index, content) { + var li = document.createElement('li'); + li.appendChild(document.createTextNode(content.name)); + li.setAttribute('id', 'entry-' + index); + var className = 'geocoder-list-item'; + if(content.type == 'favorite') className += ' icon-starred'; + li.setAttribute('class', className); + li.addEventListener('click', function() { + input.className = input.className.replace('not-geocoded', 'is-geocoded'); + var marker = L.marker(content.center); + geocodeSearch.markers.push([[input.id], [marker]]); + toolKit.addMarker(marker, content.name); + var points = document.getElementsByClassName('is-geocoded'); + if(points.length < 2 && content.bbox != null) { + map.fitBounds(content.bbox); + }; + input.value = content.name; + geocodeSearch.clearResults(input); + geocodeSearch.computeRoute(); + }); + list.appendChild(li); + }, null); + list.style.display = 'block'; + }, + computeRoute : function() { + geocodeSearch.waypoints = []; + var points = document.getElementsByClassName('is-geocoded'); + if(points.length < 2) return; + $.each(points, function(i) { + var id = $(this).attr('id'); + var val = $(this).val(); + for(var i=0; i= 1000) distance = parseFloat(distance/1000).toFixed(1) + 'km'; + else distance += 'm'; + time = Math.ceil(time / 60); // time as minutes + var hours = Math.floor(time / 60); + var minutes = time % 60; + alert('Route ' + name + ' is ' + distance + ' long and takes about ' + hours + ':' + minutes); + }); + }, + waypointsChanged : function(e) { + var wps = e.waypoints; + var wpscount = wps.length; + var inputcount = document.getElementById('search').childNodes.length; + while(wpscount > inputcount) { + geocodeSearch.addGeocoder(); + inputcount++; + } + var inputContainers = document.getElementById('search').childNodes; + $.each(wps, function(idx, wp) { + var name = wp.name; + if(name == null || name == '') { + geocoder.reverse(wp.latLng, 67108864, function(data) { + var input = inputContainers[idx].getElementsByClassName('geocoder')[0]; + data = data[0]; + input.value = data.name; + wp.name = data.name; + wp.latLng = data.center; + }); + } + }); + } + }, + mapSearch = { searchItems : [], _ids : [], @@ -658,6 +902,7 @@ Array.prototype.unique = function() { Maps = { addressbooks : [], + addresses : [], tempArr : [], tempCounter : 0, tempTotal : 0, @@ -770,6 +1015,38 @@ Array.prototype.unique = function() { } Maps.addressbooks.push(book); }) + //Load addresses in array + $.each(Maps.addressbooks, function(ai) { + $.get(OC.generateUrl('/apps/contacts/addressbook/' + this.backend + '/' + this.id + '/contacts'), function(r) { + $.each(r.contacts, function(ci) { + var name = this.data.FN[0].value; + var adr = {}; + var orgAdr = {}; + if(this.data.ADR){ + for(var i=0; i< this.data.ADR.length; i++){ + var currAddr = this.data.ADR[i].value; + //remove empty cells (didn't work with delete or any other function...thus: ugly code + for (var j=currAddr.length-1; j>=0; j--) { + if (currAddr[j] === null || currAddr[j] === undefined || currAddr[j] === "") { + currAddr.splice(j,1); + } + } + adr[i] = currAddr.toString().replace(/,/g, ", "); + orgAdr[i] = this.data.ADR[i].value; + } + + } + if(!adr[0]) return true; + var addr = { + 'name': name, + 'add': adr, + 'orgAdd': orgAdr + }; + Maps.addresses.push(addr); + }); + }); + }); + //end Maps.loadContacts(); }) }, @@ -1017,7 +1294,7 @@ Array.prototype.unique = function() { return false; }, _popupMouseOut: function(e) { - if(marker == null) return false; + if(marker == null || marker._popup == null) return false; L.DomEvent.off(marker._popup, 'mouseout', this._popupMouseOut, this); var tgt = e.toElement || e.relatedTarget; if (this._getParent(tgt, 'leaflet-popup')) return true; diff --git a/templates/main.php b/templates/main.php index 63cee4e..81ae9a4 100644 --- a/templates/main.php +++ b/templates/main.php @@ -7,7 +7,6 @@ \OCP\Util::addScript('maps', '3rdparty/overpass/OverPassLayer'); \OCP\Util::addScript('maps', '3rdparty/leaflet/plugins/leaflet-routing-machine.min'); -\OCP\Util::addScript('maps', '3rdparty/leaflet/lib/Control.Geocoder'); \OCP\Util::addScript('maps', '3rdparty/leaflet/lib/leaflet.iconlabel'); \OCP\Util::addScript('maps', '3rdparty/leaflet/plugins/leaflet-hash'); @@ -27,10 +26,13 @@ \OCP\Util::addScript('maps', '3rdparty/binaryajax-lib'); \OCP\Util::addScript('maps', '3rdparty/exif'); +\OCP\Util::addScript('maps', '3rdparty/leaflet/lib/Control.Geocoder'); + \OCP\Util::addStyle('maps', 'leaflet/leaflet'); \OCP\Util::addStyle('maps', 'leaflet/leaflet-compass.min'); \OCP\Util::addStyle('maps', 'leaflet/leaflet-routing-machine'); +\OCP\Util::addStyle('maps', 'leaflet/Control.Geocoder'); \OCP\Util::addStyle('maps', 'style'); \OCP\Util::addStyle('maps', 'font-awesome.min'); @@ -76,12 +78,17 @@
Location tracking settings +

Mapzen API key

+

+ +

-
+