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 | 2 | <html lang="en" dir="ltr" ng-app="batmanDelivers" id="html"> |
| 3 | - | |
| 4 | 3 | <head> |
| 5 | 4 | <meta charset="utf-8"> |
| 6 | 5 | <meta name="viewport" content="initial-scale=1.0"> |
| ... | ... | @@ -9,27 +8,25 @@ |
| 9 | 8 | <link rel="stylesheet" href="./bower_components/angular-ui-select/dist/select.css"> |
| 10 | 9 | <link rel="stylesheet" href="./bower_components/bootstrap/dist/css/bootstrap.css"> |
| 11 | 10 | </head> |
| 12 | - | |
| 13 | 11 | <body ng-controller="myCtrl"> |
| 14 | 12 | <div class="container-fluid"> |
| 15 | 13 | <div class="left"> |
| 16 | 14 | <form> |
| 17 | - | |
| 18 | 15 | <div class="" ng-repeat="stop in stops"> |
| 19 | 16 | <div address-search placeholder="Enter Pickup" model="stop" order="{{$index}}" lbl="($first)? 'Pickup':($last)?'Drop':'Via'"></div> |
| 20 | 17 | </div> |
| 21 | 18 | </form> |
| 19 | + | |
| 22 | 20 | </div> |
| 23 | 21 | <div class="map"> |
| 24 | 22 | <div id="map-div"></div> |
| 25 | 23 | </div> |
| 26 | 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 | 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 | 32 | </html> | ... | ... |
src/js/app.js
| ... | ... | @@ -5,16 +5,18 @@ var app = angular.module('batmanDelivers', ['ngSanitize', 'ui.select']); |
| 5 | 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 | 10 | var initializing = true; |
| 11 | + | |
| 12 | + | |
| 11 | 13 | var map = null; |
| 12 | 14 | var waypoints = []; |
| 13 | 15 | var markers = []; |
| 14 | 16 | var route = null; |
| 15 | 17 | var map = null; |
| 16 | 18 | var marker = null; |
| 17 | - var markers = []; | |
| 19 | + | |
| 18 | 20 | var myLatLng = { lat: 0, lng: 0 }; |
| 19 | 21 | var directionsService = new google.maps.DirectionsService; |
| 20 | 22 | var directionsDisplay = new google.maps.DirectionsRenderer({ |
| ... | ... | @@ -22,6 +24,8 @@ app.controller('myCtrl', function($scope, $http, $timeout) { |
| 22 | 24 | strokeColor: "#d8d8d8" |
| 23 | 25 | } |
| 24 | 26 | }); |
| 27 | + | |
| 28 | + | |
| 25 | 29 | var end; |
| 26 | 30 | var marked; |
| 27 | 31 | var valid = true; |
| ... | ... | @@ -29,73 +33,104 @@ app.controller('myCtrl', function($scope, $http, $timeout) { |
| 29 | 33 | |
| 30 | 34 | $scope.stops = [{ |
| 31 | 35 | "Description": "Start typing to search...", |
| 32 | - "changed": false | |
| 36 | + "changed": false, | |
| 37 | + valid: false, | |
| 38 | + id: 1 | |
| 33 | 39 | |
| 34 | 40 | }, { |
| 35 | 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 | 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 | 116 | travelMode: 'DRIVING', |
| 84 | 117 | provideRouteAlternatives: false |
| 85 | 118 | }, function(response, status) { |
| 86 | 119 | if (status === 'OK') { |
| 87 | 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 | 134 | } else { |
| 100 | 135 | console.log("Need more Stops", start, end, waypoints) |
| 101 | 136 | } |
| ... | ... | @@ -113,6 +148,7 @@ app.controller('myCtrl', function($scope, $http, $timeout) { |
| 113 | 148 | } |
| 114 | 149 | |
| 115 | 150 | function drawMarker(lat, lng) { |
| 151 | + return; | |
| 116 | 152 | var marker = new google.maps.Marker({ |
| 117 | 153 | position: {lat: lat, lng: lng}, |
| 118 | 154 | icon: '.././includes/images/c1.png', |
| ... | ... | @@ -281,6 +317,7 @@ app.controller('myCtrl', function($scope, $http, $timeout) { |
| 281 | 317 | ] |
| 282 | 318 | }); |
| 283 | 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 | 2 | var app = angular.module('batmanDelivers'); |
| 3 | 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 | 7 | return { |
| 8 | 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 | 13 | scope.placeholder = attrs["placeholder"]; |
| 14 | - scope.address = $parse(attrs['model'])(scope); | |
| 14 | + scope.selected = { | |
| 15 | + address: null | |
| 16 | + }; | |
| 17 | + | |
| 15 | 18 | scope.order = $parse(attrs['order'])(scope); |
| 16 | 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 | 1 | <div class="search-box"> |
| 2 | 2 | <p class="lbl" ng-bind="lbl"></p> |
| 3 | 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 | 14 | </div> |
| 16 | 15 | </div> | ... | ... |