Commit a0fba7c83e7e5f480f33c9dc67bf92cea899a837
1 parent
1131cb0d
Exists in
master
and in
1 other branch
david
Showing
4 changed files
with
164 additions
and
121 deletions
Show diff stats
index.html
| 1 | -<!DOCTYPE html> | 1 | +<!DOCTYPE html> |
| 2 | <html lang="en" dir="ltr" ng-app="batmanDelivers" id="html"> | 2 | <html lang="en" dir="ltr" ng-app="batmanDelivers" id="html"> |
| 3 | - | ||
| 4 | <head> | 3 | <head> |
| 5 | <meta charset="utf-8"> | 4 | <meta charset="utf-8"> |
| 6 | <meta name="viewport" content="initial-scale=1.0"> | 5 | <meta name="viewport" content="initial-scale=1.0"> |
| @@ -9,27 +8,25 @@ | @@ -9,27 +8,25 @@ | ||
| 9 | <link rel="stylesheet" href="./bower_components/angular-ui-select/dist/select.css"> | 8 | <link rel="stylesheet" href="./bower_components/angular-ui-select/dist/select.css"> |
| 10 | <link rel="stylesheet" href="./bower_components/bootstrap/dist/css/bootstrap.css"> | 9 | <link rel="stylesheet" href="./bower_components/bootstrap/dist/css/bootstrap.css"> |
| 11 | </head> | 10 | </head> |
| 12 | - | ||
| 13 | <body ng-controller="myCtrl"> | 11 | <body ng-controller="myCtrl"> |
| 14 | <div class="container-fluid"> | 12 | <div class="container-fluid"> |
| 15 | <div class="left"> | 13 | <div class="left"> |
| 16 | <form> | 14 | <form> |
| 17 | - | ||
| 18 | <div class="" ng-repeat="stop in stops"> | 15 | <div class="" ng-repeat="stop in stops"> |
| 19 | <div address-search placeholder="Enter Pickup" model="stop" order="{{$index}}" lbl="($first)? 'Pickup':($last)?'Drop':'Via'"></div> | 16 | <div address-search placeholder="Enter Pickup" model="stop" order="{{$index}}" lbl="($first)? 'Pickup':($last)?'Drop':'Via'"></div> |
| 20 | </div> | 17 | </div> |
| 21 | </form> | 18 | </form> |
| 19 | + | ||
| 22 | </div> | 20 | </div> |
| 23 | <div class="map"> | 21 | <div class="map"> |
| 24 | <div id="map-div"></div> | 22 | <div id="map-div"></div> |
| 25 | </div> | 23 | </div> |
| 26 | </div> | 24 | </div> |
| 25 | + <script src="./bower_components/angular/angular.js" charset="utf-8"></script> | ||
| 26 | + <script src="./bower_components/angular-sanitize/angular-sanitize.js" charset="utf-8"></script> | ||
| 27 | + <script src="./bower_components/angular-ui-select/dist/select.js" charset="utf-8"></script> | ||
| 28 | + <script src="./src/js/app.js" charset="utf-8"></script> | ||
| 29 | + <script src="./src/js/directives/address-search/directive.js" charset="utf-8"></script> | ||
| 30 | + <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyB4fiyAw8BEs35uf2U48jEicFrRtqgD5aQ&libraries=weather,visualization,places,drawing,geometry&sensor=false&language=en&v=3.13"></script> | ||
| 27 | </body> | 31 | </body> |
| 28 | -<script src="./bower_components/angular/angular.js" charset="utf-8"></script> | ||
| 29 | -<script src="./bower_components/angular-sanitize/angular-sanitize.js" charset="utf-8"></script> | ||
| 30 | -<script src="./bower_components/angular-ui-select/dist/select.js" charset="utf-8"></script> | ||
| 31 | -<script src="./src/js/app.js" charset="utf-8"></script> | ||
| 32 | -<script src="./src/js/directives/address-search/directive.js" charset="utf-8"></script> | ||
| 33 | -<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyAPYatPrCcmNcVdAO_MF0YhO3c1mgdLvuQ"></script> | ||
| 34 | - | ||
| 35 | </html> | 32 | </html> |
src/js/app.js
| @@ -5,16 +5,18 @@ var app = angular.module('batmanDelivers', ['ngSanitize', 'ui.select']); | @@ -5,16 +5,18 @@ var app = angular.module('batmanDelivers', ['ngSanitize', 'ui.select']); | ||
| 5 | //Controller | 5 | //Controller |
| 6 | /////////// | 6 | /////////// |
| 7 | 7 | ||
| 8 | -app.controller('myCtrl', function($scope, $http, $timeout) { | 8 | +app.controller('myCtrl', function($scope, $http, $timeout, $rootScope) { |
| 9 | 9 | ||
| 10 | var initializing = true; | 10 | var initializing = true; |
| 11 | + | ||
| 12 | + | ||
| 11 | var map = null; | 13 | var map = null; |
| 12 | var waypoints = []; | 14 | var waypoints = []; |
| 13 | var markers = []; | 15 | var markers = []; |
| 14 | var route = null; | 16 | var route = null; |
| 15 | var map = null; | 17 | var map = null; |
| 16 | var marker = null; | 18 | var marker = null; |
| 17 | - var markers = []; | 19 | + |
| 18 | var myLatLng = { lat: 0, lng: 0 }; | 20 | var myLatLng = { lat: 0, lng: 0 }; |
| 19 | var directionsService = new google.maps.DirectionsService; | 21 | var directionsService = new google.maps.DirectionsService; |
| 20 | var directionsDisplay = new google.maps.DirectionsRenderer({ | 22 | var directionsDisplay = new google.maps.DirectionsRenderer({ |
| @@ -22,6 +24,8 @@ app.controller('myCtrl', function($scope, $http, $timeout) { | @@ -22,6 +24,8 @@ app.controller('myCtrl', function($scope, $http, $timeout) { | ||
| 22 | strokeColor: "#d8d8d8" | 24 | strokeColor: "#d8d8d8" |
| 23 | } | 25 | } |
| 24 | }); | 26 | }); |
| 27 | + | ||
| 28 | + | ||
| 25 | var end; | 29 | var end; |
| 26 | var marked; | 30 | var marked; |
| 27 | var valid = true; | 31 | var valid = true; |
| @@ -29,73 +33,104 @@ app.controller('myCtrl', function($scope, $http, $timeout) { | @@ -29,73 +33,104 @@ app.controller('myCtrl', function($scope, $http, $timeout) { | ||
| 29 | 33 | ||
| 30 | $scope.stops = [{ | 34 | $scope.stops = [{ |
| 31 | "Description": "Start typing to search...", | 35 | "Description": "Start typing to search...", |
| 32 | - "changed": false | 36 | + "changed": false, |
| 37 | + valid: false, | ||
| 38 | + id: 1 | ||
| 33 | 39 | ||
| 34 | }, { | 40 | }, { |
| 35 | "Description": "Start typing to search...", | 41 | "Description": "Start typing to search...", |
| 36 | - "changed": false | ||
| 37 | - | 42 | + "changed": false, |
| 43 | + valid: false, | ||
| 44 | + id: 2 | ||
| 38 | }] | 45 | }] |
| 39 | 46 | ||
| 40 | - $scope.$watchCollection('stops', function () { | ||
| 41 | - | ||
| 42 | - if (initializing) { | ||
| 43 | - $timeout(function() { initializing = false; }); | ||
| 44 | - } else { | ||
| 45 | - if ($scope.stops[$scope.stops.length -1].Description != "Start typing to search...") { | ||
| 46 | - $scope.stops.forEach(function(stop, i){ | ||
| 47 | - if (stop.Description != "Start typing to search...") { | ||
| 48 | - valid = true; | ||
| 49 | - } else { | ||
| 50 | - valid = false; | ||
| 51 | - } | ||
| 52 | - }) | ||
| 53 | - } else { | ||
| 54 | - valid = false; | ||
| 55 | - } | ||
| 56 | 47 | ||
| 57 | - $scope.stops.forEach(function(stop, i){ | ||
| 58 | - if (stop.Description != "Start typing to search..." && stop.changed == false) { | ||
| 59 | - if (i != 0 && i != $scope.stops.length-1) { | ||
| 60 | - drawMarker(stop.Latitude, stop.Longitude); | ||
| 61 | - waypoints.push({ | ||
| 62 | - location: stop.Description, | ||
| 63 | - stopover: true | ||
| 64 | - }); | ||
| 65 | - } else { | ||
| 66 | - drawMarker(stop.Latitude, stop.Longitude); | 48 | + $scope.$on('StopChanged', function () { |
| 49 | + var validstops = $scope.stops.filter(function (x) { return x.valid; }); | ||
| 50 | + | ||
| 51 | + if (validstops.length == 1) { | ||
| 52 | + map.panTo(validstops[0].$marker.getPosition()); | ||
| 53 | + } else if (validstops.length > 1) { | ||
| 54 | + var bounds = new google.maps.LatLngBounds(); | ||
| 55 | + | ||
| 56 | + for (var i = 0; i < validstops.length; i++) { | ||
| 57 | + bounds.extend(validstops[i].$marker.getPosition()); | ||
| 67 | } | 58 | } |
| 68 | - } | ||
| 69 | - }) | ||
| 70 | 59 | ||
| 71 | - if (valid == true) { | ||
| 72 | - calculateAndDisplayRoute($scope.stops[0].Description, $scope.stops[$scope.stops.length - 1].Description); | 60 | + map.fitBounds(bounds, 100); |
| 73 | } | 61 | } |
| 74 | - } | ||
| 75 | 62 | ||
| 76 | - }, true); | ||
| 77 | 63 | ||
| 78 | - function calculateAndDisplayRoute(start, end) { | 64 | + if (validstops.length == $scope.stops.length) { |
| 65 | + var waypoints = []; | ||
| 66 | + if ($scope.stops.length > 2) { | ||
| 67 | + waypoints = $scope.stops.slice(1, $scope.stops.length - 2); | ||
| 68 | + } | ||
| 69 | + calculateAndDisplayRoute($scope.stops[0], $scope.stops[$scope.stops.length - 1], waypoints); | ||
| 70 | + } | ||
| 71 | + }); | ||
| 72 | + | ||
| 73 | + | ||
| 74 | + //$scope.$watch('stops', function () { | ||
| 75 | + // if (initializing) { | ||
| 76 | + // $timeout(function() { initializing = false; }); | ||
| 77 | + // } else { | ||
| 78 | + // if ($scope.stops[$scope.stops.length -1].Description != "Start typing to search...") { | ||
| 79 | + // $scope.stops.forEach(function(stop, i){ | ||
| 80 | + // if (stop.Description != "Start typing to search...") { | ||
| 81 | + // valid = true; | ||
| 82 | + // } else { | ||
| 83 | + // valid = false; | ||
| 84 | + // } | ||
| 85 | + // }) | ||
| 86 | + // } else { | ||
| 87 | + // valid = false; | ||
| 88 | + // } | ||
| 89 | + | ||
| 90 | + // $scope.stops.forEach(function(stop, i){ | ||
| 91 | + // if (stop.Description != "Start typing to search..." && stop.changed == false) { | ||
| 92 | + // if (i != 0 && i != $scope.stops.length-1) { | ||
| 93 | + // drawMarker(stop.Latitude, stop.Longitude); | ||
| 94 | + // waypoints.push({ | ||
| 95 | + // location: stop.Description, | ||
| 96 | + // stopover: true | ||
| 97 | + // }); | ||
| 98 | + // } else { | ||
| 99 | + // drawMarker(stop.Latitude, stop.Longitude); | ||
| 100 | + // } | ||
| 101 | + // } | ||
| 102 | + // }) | ||
| 103 | + | ||
| 104 | + // if (valid == true) { | ||
| 105 | + // calculateAndDisplayRoute($scope.stops[0].Description, $scope.stops[$scope.stops.length - 1].Description); | ||
| 106 | + // } | ||
| 107 | + // } | ||
| 108 | + | ||
| 109 | + //}, true); | ||
| 110 | + | ||
| 111 | + function calculateAndDisplayRoute(start, end, waypoints) { | ||
| 79 | directionsService.route({ | 112 | directionsService.route({ |
| 80 | - origin: start, | ||
| 81 | - destination: end, | ||
| 82 | - waypoints: waypoints, | 113 | + origin: start.$marker.getPosition(), |
| 114 | + destination: end.$marker.getPosition(), | ||
| 115 | + waypoints: waypoints.map(function (x) { return x.$marker.getPosition(); }), | ||
| 83 | travelMode: 'DRIVING', | 116 | travelMode: 'DRIVING', |
| 84 | provideRouteAlternatives: false | 117 | provideRouteAlternatives: false |
| 85 | }, function(response, status) { | 118 | }, function(response, status) { |
| 86 | if (status === 'OK') { | 119 | if (status === 'OK') { |
| 87 | directionsDisplay.setDirections(response); | 120 | directionsDisplay.setDirections(response); |
| 88 | - directionsDisplay.setOptions( { suppressMarkers: true } ); | ||
| 89 | - pinA = new google.maps.Marker({ | ||
| 90 | - position: start, | ||
| 91 | - map: map, | ||
| 92 | - icon: '.././includes/images/c1.png' | ||
| 93 | - }), | ||
| 94 | - pinB = new google.maps.Marker({ | ||
| 95 | - position: end, | ||
| 96 | - map: map, | ||
| 97 | - icon: '.././includes/images/c1.png' | ||
| 98 | - }); | 121 | + directionsDisplay.setOptions({ suppressMarkers: true }); |
| 122 | + | ||
| 123 | + var arrayOfPoints = response.routes[0].overview_path; | ||
| 124 | + var marker = new google.maps.Marker({ | ||
| 125 | + map: map, | ||
| 126 | + position: arrayOfPoints[0] | ||
| 127 | + }); | ||
| 128 | + | ||
| 129 | + var counter = 1; | ||
| 130 | + setInterval(function () { | ||
| 131 | + marker.setPosition(arrayOfPoints[counter]); | ||
| 132 | + counter++; | ||
| 133 | + }, 500); | ||
| 99 | } else { | 134 | } else { |
| 100 | console.log("Need more Stops", start, end, waypoints) | 135 | console.log("Need more Stops", start, end, waypoints) |
| 101 | } | 136 | } |
| @@ -113,6 +148,7 @@ app.controller('myCtrl', function($scope, $http, $timeout) { | @@ -113,6 +148,7 @@ app.controller('myCtrl', function($scope, $http, $timeout) { | ||
| 113 | } | 148 | } |
| 114 | 149 | ||
| 115 | function drawMarker(lat, lng) { | 150 | function drawMarker(lat, lng) { |
| 151 | + return; | ||
| 116 | var marker = new google.maps.Marker({ | 152 | var marker = new google.maps.Marker({ |
| 117 | position: {lat: lat, lng: lng}, | 153 | position: {lat: lat, lng: lng}, |
| 118 | icon: '.././includes/images/c1.png', | 154 | icon: '.././includes/images/c1.png', |
| @@ -281,6 +317,7 @@ app.controller('myCtrl', function($scope, $http, $timeout) { | @@ -281,6 +317,7 @@ app.controller('myCtrl', function($scope, $http, $timeout) { | ||
| 281 | ] | 317 | ] |
| 282 | }); | 318 | }); |
| 283 | directionsDisplay.setMap(map); | 319 | directionsDisplay.setMap(map); |
| 320 | + $rootScope.map = map; | ||
| 284 | } | 321 | } |
| 285 | }); | 322 | }); |
| 286 | 323 |
src/js/directives/address-search/directive.js
| 1 | -(function(angular) { | 1 | +(function (angular) { |
| 2 | var app = angular.module('batmanDelivers'); | 2 | var app = angular.module('batmanDelivers'); |
| 3 | app.directive("addressSearch", addressSearch); | 3 | app.directive("addressSearch", addressSearch); |
| 4 | - addressSearch.$inject = ['$parse', '$rootScope', '$http', '$timeout', '$sce'] | 4 | + addressSearch.$inject = ['$parse', '$rootScope', '$http', '$timeout', '$sce', '$rootScope'] |
| 5 | 5 | ||
| 6 | - function addressSearch($parse, $rootScope, $http, $timeout, $sce) { | 6 | + function addressSearch($parse, $rootScope, $http, $timeout, $sce, $rootScope) { |
| 7 | return { | 7 | return { |
| 8 | templateUrl: '/src/js/directives/address-search/partial.html', | 8 | templateUrl: '/src/js/directives/address-search/partial.html', |
| 9 | - replace: true, //study | ||
| 10 | - transclude: true, //study | ||
| 11 | - link: function(scope, elm, attrs) { | ||
| 12 | - | 9 | + scope: { |
| 10 | + address: '=model' | ||
| 11 | + }, | ||
| 12 | + link: function (scope, elm, attrs) { | ||
| 13 | scope.placeholder = attrs["placeholder"]; | 13 | scope.placeholder = attrs["placeholder"]; |
| 14 | - scope.address = $parse(attrs['model'])(scope); | 14 | + scope.selected = { |
| 15 | + address: null | ||
| 16 | + }; | ||
| 17 | + | ||
| 15 | scope.order = $parse(attrs['order'])(scope); | 18 | scope.order = $parse(attrs['order'])(scope); |
| 16 | scope.lbl = $parse(attrs['lbl'])(scope); | 19 | scope.lbl = $parse(attrs['lbl'])(scope); |
| 17 | 20 | ||
| 21 | + var autocompleteService = new google.maps.places.AutocompleteService(); | ||
| 22 | + var placesService = new google.maps.places.PlacesService($rootScope.map); | ||
| 18 | 23 | ||
| 19 | - | ||
| 20 | - scope.request = function(value){ | ||
| 21 | - if (value && value.length > 3) { | ||
| 22 | - $http({ | ||
| 23 | - dataType: 'jsonp', | ||
| 24 | - method: "GET", | ||
| 25 | - url: "https://maps.googleapis.com/maps/api/place/autocomplete/json?input=" + value + "&key=AIzaSyAPYatPrCcmNcVdAO_MF0YhO3c1mgdLvuQ" | ||
| 26 | - }).then(function mySuccess(response) { | ||
| 27 | - scope.addresses = response.data.predictions; | ||
| 28 | - }, function myError(response) { | ||
| 29 | - scope.error = response.statusText; | ||
| 30 | - }); | ||
| 31 | - } | 24 | + scope.request = function (value) { |
| 25 | + if (value && value.length > 3) { | ||
| 26 | + autocompleteService.getPlacePredictions({ | ||
| 27 | + input: value | ||
| 28 | + }, function (results) { | ||
| 29 | + scope.addresses = results; | ||
| 30 | + scope.$apply(); | ||
| 31 | + }); | ||
| 32 | + } | ||
| 32 | } | 33 | } |
| 33 | 34 | ||
| 34 | - scope.selectAddress = function(place) { | ||
| 35 | - $http({ | ||
| 36 | - method: "GET", | ||
| 37 | - url: "https://maps.googleapis.com/maps/api/place/details/json?placeid=" + place.place_id + "&fields=geometry,adr_address,address_component,formatted_address&key=AIzaSyAPYatPrCcmNcVdAO_MF0YhO3c1mgdLvuQ" | ||
| 38 | - }).then(function mySuccess(response) { | ||
| 39 | - scope.result = response.data.result; | 35 | + scope.$watch('selected.address', function (newvalue) { |
| 36 | + if (newvalue && newvalue.place_id) { | ||
| 37 | + placesService.getDetails({ | ||
| 38 | + placeId: newvalue.place_id | ||
| 39 | + }, function (result) { | ||
| 40 | + scope.result = result; | ||
| 41 | + scope.address.AddressLine1 = scope.result.address_components[1].long_name; | ||
| 42 | + scope.address.AddressLine2 = scope.result.address_components[2].long_name; | ||
| 43 | + scope.address.City = scope.result.address_components[3].long_name; | ||
| 44 | + scope.address.PostCode = scope.result.address_components[0].long_name; | ||
| 45 | + scope.address.Latitude = scope.result.geometry.location.lat(); | ||
| 46 | + scope.address.Longitude = scope.result.geometry.location.lng(); | ||
| 47 | + scope.address.Description = newvalue.description; | ||
| 48 | + scope.address.changed = false; | ||
| 49 | + scope.address.valid = true; | ||
| 40 | 50 | ||
| 41 | - scope.stops[scope.order] = { | ||
| 42 | - AddressLine1: scope.result.address_components[1].long_name, | ||
| 43 | - AddressLine2: scope.result.address_components[2].long_name, | ||
| 44 | - City: scope.result.address_components[3].long_name, | ||
| 45 | - PostCode: scope.result.address_components[0].long_name, | ||
| 46 | - Latitude: scope.result.geometry.location.lat, | ||
| 47 | - Longitude: scope.result.geometry.location.lng, | ||
| 48 | - Description: place.description, | ||
| 49 | - changed: false | ||
| 50 | - } | ||
| 51 | 51 | ||
| 52 | - }, function myError(response) { | ||
| 53 | - scope.error = response.statusText; | ||
| 54 | - }); | ||
| 55 | - } | 52 | + if (!scope.address.$marker) { |
| 53 | + scope.address.$marker = new google.maps.Marker({ | ||
| 54 | + map: $rootScope.map, | ||
| 55 | + position: scope.result.geometry.location, | ||
| 56 | + icon: '.././includes/images/c1.png' | ||
| 57 | + }); | ||
| 58 | + } else { | ||
| 59 | + scope.address.$marker.setPosition({ lat: scope.result.geometry.location.lat(), lng: scope.result.geometry.location.lng() }); | ||
| 60 | + } | ||
| 61 | + scope.$apply(); | ||
| 62 | + scope.$emit('StopChanged'); | ||
| 63 | + }); | ||
| 64 | + } | ||
| 65 | + }); | ||
| 56 | 66 | ||
| 57 | - scope.addStop = function(){ | ||
| 58 | - scope.stops.push({ | ||
| 59 | - Description: "Start typing to search..." | ||
| 60 | - }) | 67 | + scope.addStop = function () { |
| 68 | + scope.stops.push({ | ||
| 69 | + Description: "Start typing to search..." | ||
| 70 | + }) | ||
| 61 | } | 71 | } |
| 62 | - scope.removeStop = function(index){ | ||
| 63 | - scope.stops.splice(index, 1); | 72 | + scope.removeStop = function (index) { |
| 73 | + scope.stops.splice(index, 1); | ||
| 64 | } | 74 | } |
| 65 | } | 75 | } |
| 66 | } | 76 | } |
src/js/directives/address-search/partial.html
| 1 | <div class="search-box"> | 1 | <div class="search-box"> |
| 2 | <p class="lbl" ng-bind="lbl"></p> | 2 | <p class="lbl" ng-bind="lbl"></p> |
| 3 | <div class="ui-select-container"> | 3 | <div class="ui-select-container"> |
| 4 | - <ui-select ng-model="address" class="control"> | ||
| 5 | - <ui-select-match> | ||
| 6 | - <p class="desc">{{$select.selected.Description}}</p> | ||
| 7 | - </ui-select-match> | ||
| 8 | - <ui-select-choices repeat="address in addresses" refresh="request($select.search)" refresh-delay="300" ng-click="selectAddress(address)"> | ||
| 9 | - {{address.description}} | ||
| 10 | - </ui-select-choices> | ||
| 11 | - </ui-select> | ||
| 12 | - <span class="add-stop" ng-click="addStop()">add</span> | ||
| 13 | - <span class="remove-stop" ng-click="removeStop($index)">remove</span> | ||
| 14 | - | 4 | + <ui-select ng-model="selected.address" class="control"> |
| 5 | + <ui-select-match> | ||
| 6 | + <p class="desc">{{$select.selected.description}}</p> | ||
| 7 | + </ui-select-match> | ||
| 8 | + <ui-select-choices repeat="a in addresses" refresh="request($select.search)" refresh-delay="300"> | ||
| 9 | + {{a.description}} | ||
| 10 | + </ui-select-choices> | ||
| 11 | + </ui-select> | ||
| 12 | + <span class="add-stop" ng-click="addStop()">add</span> | ||
| 13 | + <span class="remove-stop" ng-click="removeStop($index)">remove</span> | ||
| 15 | </div> | 14 | </div> |
| 16 | </div> | 15 | </div> |