Google Place Search using SearchBox - Restrict for UK only - google-maps-api-3

I am using google place SearchBox ( not AutoComplete ) for place search. My objective is I want to restrict the search for a particular country (UK).
I know the same thing can be achieved easily by using AutoComplete. But I can't use this because my map will populate on enter key as well as against a search button.
I am using code to select the first option on search button click.
I have tried with google.maps.LatLngBounds but that only sets the priority of result, not restricting anything.
Html:
<ul class="list-unstyled search-branch">
<li>Search branches:</li>
<li><input type="text" placeholder="City, town or postcode" id="txtbranch" value="Eurochange" />
<input type="button" class="button gold" id="getbranch" value="Search" />
<div style="clear:both;"></div>
<div class="error-message-summary" id="locationnotfound" style="padding: 0;top:-30px; position:relative; font-size:16px;display:none">
No search results found.
</div>
</li>
</ul>
js:
var input = document.getElementById('txtbranch');
var defaultBounds = new google.maps.LatLngBounds(
new google.maps.LatLng(-33.8902, 151.1759),
new google.maps.LatLng(-33.8474, 1512631)
);
var options = {
bounds: defaultBounds
}
var searchBox = new google.maps.places.SearchBox(input, {
bounds: defaultBounds
});
$('#getbranch').click(function () {
var input = document.getElementById('txtbranch');
if (BranchAddressSelector.val() == "") {
return;
}
google.maps.event.trigger(input, 'focus');
google.maps.event.trigger(input, 'keydown', { keyCode: 13 });
return false;
})
searchBox.addListener('places_changed', function () {
var places = searchBox.getPlaces()[0];
if (typeof (places) === "undefined") {
locationNotFoundSelector.css("display", "block");
return false;
}
if (BranchAddressSelector.val() == "") {
return false;
}
var address = places.formatted_address;
if (typeof (address) === "undefined") {
locationNotFoundSelector.css("display", "block");
return false;
}
var latitude = places.geometry.location.lat();
var longitude = places.geometry.location.lng();
$.ajax({
type: "GET",
url: BranchLocatorUrl.GetBranches,
data: { Latitude: latitude, longitude: longitude },
success: function (data) {
if (data.length > 0) {
markers = data;
LoadMap(0, 0);
BranchListSelector.html(CreateSearchHtml(markers));
goToByScroll("dvMap");
BranchListSelector.css("display", "none");
paginationSelector.css("display", "none");
$('.map-distance').css("display", "block");
locationNotFoundSelector.css("display", "none");
var show_per_page = 6;
var number_of_items = BranchListSelector.children('.BranchItem').size();
var number_of_pages = Math.ceil(number_of_items / show_per_page);
totalPages = number_of_pages;
$('#current_page').val(0);
$('#show_per_page').val(show_per_page);
var navigation_html = '<a class="previous_link" style="color: #007ea0;" href="javascript:previous();">Prev</a> ';
var current_link = 0;
while (number_of_pages > current_link) {
navigation_html += '<a class="page_link" style="color: #007ea0;" href="javascript:go_to_page(' + current_link + ')" longdesc="' + current_link + '">' + (current_link + 1) + '</a> ';
current_link++;
}
navigation_html += '<a class="next_link" style="color: #007ea0;" href="javascript:next();"> Next</a>';
$('#page_navigation').html(navigation_html).css("float", "right").css("display", "none");
$('#page_navigation .page_link:first').addClass('active_page');
BranchListSelector.children('.BranchItem').css('display', 'none');
BranchListSelector.children('.BranchItem').slice(0, show_per_page).css('display', 'block');
BranchListSelector.css("display", "block");
// paginationSelector.css("display", "block");
$('.map-distance').css("display", "none");
$('#moreBranch').css("display", "block");
}
else {
alert("Data not found.");
}
},
error: function (e) {
alert("Some Problem occurs.Try after some time");
return;
}
});
});

Related

How to add google map and other charts in the gridstack widget using knockout.js

I am using Gridstack with Knockout.js. I am using http://troolee.github.io/gridstack.js/demo/knockout.html to create Gridstack widgets. I added a Google map in one of these widgets. The map appears with a scroll bar. Also, I need to have some kind of heading, as it is in its present state. The main problem is that the dimension of the map is fixed and when I resize the widget, the map does not fit in the widget automatically. Here is my full code:
ko.components.register('dashboard-grid', {
viewModel: {
createViewModel: function (controller, componentInfo) {
var ViewModel = function (controller, componentInfo) {
var grid = null;
this.widgets = controller.widgets;
this.id = controller.id;
this.afterAddWidget = function (items) {
if (grid == null) {
grid = $(componentInfo.element).find('.grid-stack').gridstack({
auto: false,
animate: true
}).data('gridstack');
}
var item = _.find(items, function (i) { return i.nodeType == 1 });
grid.addWidget(item);
ko.utils.domNodeDisposal.addDisposeCallback(item, function () {
grid.removeWidget(item);
});
};
};
return new ViewModel(controller, componentInfo);
}
},
template:
[
'<div class="grid-stack" data-bind="foreach: {data: widgets, afterRender: afterAddWidget}">',
' <div class="grid-stack-item" data-bind="attr: {\'data-gs-x\': $data.x, \'data-gs-y\': $data.y, \'data-gs-width\': $data.width, \'data-gs-height\': $data.height, \'data-gs-auto-position\': $data.auto_position}">',
' <div class="grid-stack-item-content" >',
' <header style="background-color: green;"> ',
' <button data-bind="click: $root.deleteWidget">Delete me</button><br>',
' <label><strong data-bind="text: $root.ids"></strong></label>',
' </header>',
' <div data-bind="attr: {id: $root.ids}">',
' </div>',
' </div>',
' </div>',
'</div> '
].join('')
});
$(function () {
var ids;
var Controller = function () {
var self = this;
this.widgets = ko.observableArray([]);
this.id = ko.observable("google-map");
this.ids = "";
this.addNewWidget = function () {
this.ids = this.id(); // this.ids is used to give id to div elements
this.widgets.push({
x: 0,
y: 0,
width:4,
height:5,
auto_position: true,
});
// calling method to draw map
createWidget(this.ids);
return false;
};
this.deleteWidget = function (item) {
self.widgets.remove(item);
return false;
};
};
ko.applyBindings(new Controller());
});
function createWidget(id) {
var dataArray, latitude, longitude, speed;
// Load the Visualization API and the corechart package.
try {
google.charts.load('current', {'packages':['map', 'gauge']});
// Set a callback to run when the Google Visualization API is loaded.
google.charts.setOnLoadCallback(drawChart);
}
catch ( err ) {
//console.log(err);
}
function drawChart() {
latitude = Number(12.93213);
longitude = Number(77.695185);
var mapOptions = {
showTooltip: true,
showInfoWindow: true,
zoomLevel: 16, // range: 0-21 for "roadmap" map type
mapType: 'roadmap',
enableScrollWheel: true,
draggable: false,
};
var coordinates = "Latitude : " + latitude + "\nLongitude : "+ longitude;
var mapData = google.visualization.arrayToDataTable([
['Lat', 'Long', 'Name'],
[latitude, longitude, coordinates]
] );
try {
//var chart = new google.visualization.Gauge(document.getElementById('gauge'));
var map = new google.visualization.Map(document.getElementById(id));
map.draw(mapData, mapOptions);
}
catch (err) {
console.log(err);
}
} // drawChart() ends here
} // createWidgets() ends here

How to to Get Places (e.g Gas Stations) along Route Between Origin and Destination in Google Maps API

Can you please let me know if it is possible to get list of all places for example Gas Stations along Route Between Origin and Destination in Google Maps API? Here is a link that I am trying to list all Gas Stations or Rest areas ( or any of Google Maps API Supported Place Types)between two points ans based on a Direction supported route.
and this my code so far:
var directionsDisplay;
var directionsService = new google.maps.DirectionsService();
var map;
var haight = new google.maps.LatLng(49.216364,-122.811897);
var oceanBeach = new google.maps.LatLng(50.131446,-119.506838);
function initialize() {
directionsDisplay = new google.maps.DirectionsRenderer();
var mapOptions = {
zoom: 14,
mapTypeId: google.maps.MapTypeId.ROADMAP,
center: haight
}
map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
directionsDisplay.setMap(map);
calcRoute();
}
function calcRoute() {
var request = {
origin: haight,
destination: oceanBeach,
travelMode: google.maps.TravelMode.DRIVING
};
directionsService.route(request, function(response, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsDisplay.setDirections(response);
}
});
}
google.maps.event.addDomListener(window, 'load', initialize);
Edited Part:
// Make the directions request
directionService.route(request, function(result, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsRenderer.setDirections(result);
// Box around the overview path of the first route
var path = result.routes[0].overview_path;
var boxes = routeBoxer.box(path, distance);
drawBoxes(boxes);
} else {
alert("Directions query failed: " + status);
}
for (var i = 0; i < boxes.length; i++) {
var bounds = box[i];
// Perform search over this bounds
}
});
}
Use the RouteBoxer to get an array of google.maps.LatLngBounds objects that cover the route.
for each of those bounds use the Places library to search for the places.
Note that there are query limits and quotas on the places requests, so for long routes this may not be practical.
example
(however, looking at how the results are grouped, it looks like the places service is searching around the center of the bounds, rather than in the bounds, but it might be good enough for your needs).
code snippet:
var map = null;
var boxpolys = null;
var directions = null;
var routeBoxer = null;
var distance = null; // km
var service = null;
var gmarkers = [];
var boxes = null;
var infowindow = new google.maps.InfoWindow();
function initialize() {
// Default the map view to the continental U.S.
var mapOptions = {
center: new google.maps.LatLng(40, -80.5),
mapTypeId: google.maps.MapTypeId.ROADMAP,
zoom: 8
};
map = new google.maps.Map(document.getElementById("map"), mapOptions);
service = new google.maps.places.PlacesService(map);
routeBoxer = new RouteBoxer();
directionService = new google.maps.DirectionsService();
directionsRenderer = new google.maps.DirectionsRenderer({
map: map
});
// If there are any parameters at eh end of the URL, they will be in location.search
// looking something like "?marker=3"
// skip the first character, we are not interested in the "?"
var query = location.search.substring(1);
// split the rest at each "&" character to give a list of "argname=value" pairs
var pairs = query.split("&");
for (var i = 0; i < pairs.length; i++) {
// break each pair at the first "=" to obtain the argname and value
var pos = pairs[i].indexOf("=");
var argname = pairs[i].substring(0, pos).toLowerCase();
var value = pairs[i].substring(pos + 1).toLowerCase();
// process each possible argname - use unescape() if theres any chance of spaces
if (argname == "to") {
document.getElementById('to').value = unescape(value);
}
if (argname == "from") {
document.getElementById('from').value = unescape(value);
}
if (argname == "dist") {
document.getElementById('distance').value = parseFloat(value);
}
if (argname == "type") {
document.getElementById('type').value = unescape(value);
}
if (argname == "keyword") {
document.getElementById('keyword').value = unescape(value);
}
if (argname == "name") {
document.getElementById('name').value = unescape(value);
}
if (argname == "submit") {
route();
}
}
}
function route() {
// Clear any previous route boxes from the map
clearBoxes();
// Convert the distance to box around the route from miles to km
distance = parseFloat(document.getElementById("distance").value) * 1.609344;
var request = {
origin: document.getElementById("from").value,
destination: document.getElementById("to").value,
travelMode: google.maps.DirectionsTravelMode.DRIVING
}
// Make the directions request
directionService.route(request, function(result, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsRenderer.setDirections(result);
// Box around the overview path of the first route
var path = result.routes[0].overview_path;
boxes = routeBoxer.box(path, distance);
// alert(boxes.length);
drawBoxes();
findPlaces(0);
} else {
alert("Directions query failed: " + status);
}
});
}
// Draw the array of boxes as polylines on the map
function drawBoxes() {
boxpolys = new Array(boxes.length);
for (var i = 0; i < boxes.length; i++) {
boxpolys[i] = new google.maps.Rectangle({
bounds: boxes[i],
fillOpacity: 0,
strokeOpacity: 1.0,
strokeColor: '#000000',
strokeWeight: 1,
map: map
});
}
}
function findPlaces(searchIndex) {
var type = document.getElementById('type').value;
var keyword = document.getElementById('keyword').value;
var name = document.getElementById('name').value;
var request = {
bounds: boxes[searchIndex],
};
if (!!type && (type != "")) {
if (type.indexOf(',') > 0)
request.types = type.split(',');
else
request.types = [type];
}
if (!!keyword && (keyword != "")) request.keyword = keyword;
if (!!name && (name != "")) request.name = name;
service.nearbySearch(request, function(results, status) {
if (status == google.maps.places.PlacesServiceStatus.OK) {
document.getElementById('side_bar').innerHTML += "bounds[" + searchIndex + "] returns " + results.length + " results<br>"
for (var i = 0, result; result = results[i]; i++) {
var marker = createMarker(result);
}
} else {
document.getElementById('side_bar').innerHTML += "bounds[" + searchIndex + "] returns 0 results<br> status=" + status + "<br>";
}
if (status != google.maps.places.PlacesServiceStatus.OVER_QUERY_LIMIT) {
searchIndex++;
if (searchIndex < boxes.length)
findPlaces(searchIndex);
} else { // delay 1 second and try again
setTimeout("findPlaces(" + searchIndex + ")", 1000);
}
});
}
// Clear boxes currently on the map
function clearBoxes() {
if (boxpolys != null) {
for (var i = 0; i < boxpolys.length; i++) {
boxpolys[i].setMap(null);
}
}
boxpolys = null;
}
function createMarker(place) {
var placeLoc = place.geometry.location;
if (place.icon) {
var image = new google.maps.MarkerImage(
place.icon, new google.maps.Size(71, 71),
new google.maps.Point(0, 0), new google.maps.Point(17, 34),
new google.maps.Size(25, 25));
} else var image = {
url: "https://maps.gstatic.com/intl/en_us/mapfiles/markers2/measle.png",
size: new google.maps.Size(7, 7),
anchor: new google.maps.Point(3.5, 3.5)
};
var marker = new google.maps.Marker({
map: map,
icon: image,
position: place.geometry.location
});
var request = {
reference: place.reference
};
google.maps.event.addListener(marker, 'click', function() {
service.getDetails(request, function(place, status) {
if (status == google.maps.places.PlacesServiceStatus.OK) {
var contentStr = '<h5>' + place.name + '</h5><p>' + place.formatted_address;
if (!!place.formatted_phone_number) contentStr += '<br>' + place.formatted_phone_number;
if (!!place.website) contentStr += '<br><a target="_blank" href="' + place.website + '">' + place.website + '</a>';
contentStr += '<br>' + place.types + '</p>';
infowindow.setContent(contentStr);
infowindow.open(map, marker);
} else {
var contentStr = "<h5>No Result, status=" + status + "</h5>";
infowindow.setContent(contentStr);
infowindow.open(map, marker);
}
});
});
gmarkers.push(marker);
if (!place.name) place.name = "result " + gmarkers.length;
var side_bar_html = "<a href='javascript:google.maps.event.trigger(gmarkers[" + parseInt(gmarkers.length - 1) + "],\"click\");'>" + place.name + "</a><br>";
document.getElementById('side_bar').innerHTML += side_bar_html;
}
google.maps.event.addDomListener(window, 'load', initialize);
html,
body,
#map_canvas {
margin: 0;
padding: 0;
height: 100%;
}
<script src="https://maps.googleapis.com/maps/api/js?libraries=places&key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk"></script>
<script src="https://cdn.jsdelivr.net/gh/denissellu/routeboxer#master/src/RouteBoxer.js" type="text/javascript"></script>
<table border="1">
<tr>
<td valign="top">
<div id="map" style="width: 600px; height: 500px;"></div>
</td>
<td>
<div id="side_bar" style="width:200px; height: 600px; overflow: auto"></div>
</td>
</tr>
</table>
Box within at least
<input type="text" id="distance" value="3" size="2">miles of the route from
<input type="text" id="from" value="denver" />to
<input type="text" id="to" value="oklahoma city, OK" />
<input type="submit" onclick="route()" />
<br>
<label>type</label>
<input type="text" id="type" value="gas_station" />
<label>keyword</label>
<input type="text" id="keyword" value="" />
<label>name</label>
<input type="text" id="name" value="" />
<div id="towns"></div>

Breeze.js query does not update knockout view

I am querying data via breeze.js which works fine the first time. The second time the view isn't updated.
html
<a id="linkQDate">Order by Newest</a>
<a id="linkQScore">Order by Score</a>
<div id="questionWrapper">
<ul data-bind="foreach: results">
<li>
<strong><span data-bind="text: Score"></span></strong>
<span data-bind="text: Titel"></span>
</li>
</ul>
</DIV>
js
$(document).ready(function () {
var manager = new breeze.EntityManager('/breeze/dbentities');
var isApplied = false;
var dmodel;
$("#linkQDate").click(function () {
var query = breeze.EntityQuery.from("Questions").orderBy("Date");
manager.executeQuery(query).then(querySucceeded);
function querySucceeded(data) {
dmodel = data;
if (!isApplied) {
ko.applyBindings(dmodel, $("#questionWrapper")[0]);
isApplied = true;
}
}
});
$("#linkQScore").click(function () {
var query = breeze.EntityQuery.from("Questions").orderBy("Score");
manager.executeQuery(query).then(querySucceeded);
function querySucceeded(data) {
dmodel = data;
if (!isApplied) {
ko.applyBindings(dmodel, $("#questionWrapper")[0]);
isApplied = true;
}
}
});
});
If you just using plain JS objects it will not work. Because it does not know when underlying data changes. Use mapping plugin for this to work:
$(document).ready(function () {
var manager = new breeze.EntityManager('/breeze/dbentities');
var isApplied = false;
var dmodel;
function querySucceeded(data) {
if (!isApplied) {
dmodel = ko.mapping.fromJS(data);
ko.applyBindings(dmodel, $("#questionWrapper")[0]);
isApplied = true;
} else {
ko.mapping.fromJS(data, dmodel);
}
}
$("#linkQDate").click(function () {
var query = breeze.EntityQuery.from("Questions").orderBy("Date");
manager.executeQuery(query).then(querySucceeded);
});
$("#linkQScore").click(function () {
var query = breeze.EntityQuery.from("Questions").orderBy("Score");
});
});
Working code from Tomas without mappings. It is much faster:
$(document).ready(function () {
var manager = new breeze.EntityManager('/breeze/dbentities');
var isApplied = false;
var dmodel = { results: ko.observableArray() };
function queryFailed(data) {
console.log(data);
}
function querySucceeded(data) {
if (!isApplied) {
for (var i = 0; i < data.results.length; i++) {
dmodel.results.push(data.results[i]);
}
ko.applyBindings(dmodel, $("#questionWrapper")[0]);
isApplied = true;
} else {
dmodel.results.removeAll();
for (var i = 0; i < data.results.length; i++) {
dmodel.results.push(data.results[i]);
}
}
}
$("#linkQDate").click(function () {
var query = breeze.EntityQuery.from("Questions").orderBy("Date");
manager.executeQuery(query).then(querySucceeded).fail(queryFailed);;
});
$("#linkQScore").click(function () {
var query = breeze.EntityQuery.from("Questions").orderBy("Score");
manager.executeQuery(query).then(querySucceeded).fail(queryFailed);;
});
});

Best way to load css for partial views loaded using ajax

I'm working on my application that creates tabs dynamically and fills them with partial views using ajax.
My question is: how to load css for this views? What's the best way to do it? I mean I can't load the css file on the partial view (no head) or could i?
Some code: the tabManager (a partial view loaded on the main page):
<script>
var tabTemplate = "<li class='#{color}'><a id='#{id}'href='#{href}'>#{label}</a> <span class='ui-icon ui-icon-close' role='presentation'>Remove Tab</span></li>"; // base format for the tabs
$(document).ready(function () {
var tabs = $("#tabs").tabs(); // apply jQuery ui to tabs
$("a.menuButton").click(function () {
var urlContent = $(this).data("direction");
var label = $(this).data("label");
var idTab = $(this).data("id");
var color = $(this).data("color");
var exist = false;
var counter = 0;
$('#tabs ul li a').each(function (i) { // tab already exist o no hay que crear una tabla?
counter = counter + 1; // index counter
if (this.id == "#" + idTab) { // Tab already exist?
exist = true;
$("#tabs").tabs("option", "active", counter - 1); //activate existing element
}
});
if (idTab == "-1") { // is a clickable element?
exist = true;
}
if (exist == false) { // create new tab
addTab(idTab, label, color); // basic tab
getTabContent(idTab, urlContent); // content for new tab
var lastTab = $('#tabs >ul >li').size() - 1; // get count of tabs
$("#tabs").tabs("option", "active", lastTab); // select last created tab
}
});
function getTabContent(idT, urlC) { // ajax call to partial view
$.ajax({
url: urlC,
type: 'GET',
async: false,
success: function (result) {
$("#"+idT).html(result);
}
});
};
function addTab(idT, labT, color) { //create new tab
var label = labT,
id = idT,
li = $(tabTemplate.replace(/#\{href\}/g, "#" + id).replace(/#\{label\}/g, label).replace(/#\{id\}/g, "#" + id).replace(/#\{color\}/g, color)),
tabContentHtml = "Cargando...";
tabs.find(".ui-tabs-nav").append(li);
tabs.append("<div id='" + id + "'><p>" + tabContentHtml + "</p></div>");
tabs.tabs("refresh");
}
// close icon: removing the tab on click
tabs.delegate("span.ui-icon-close", "click", function () {
var panelId = $(this).closest("li").remove().attr("aria-controls");
$("#" + panelId).remove();
tabs.tabs("refresh");
});
tabs.bind("keyup", function (event) {
if (event.altKey && event.keyCode === $.ui.keyCode.BACKSPACE) {
var panelId = tabs.find(".ui-tabs-active").remove().attr("aria-controls");
$("#" + panelId).remove();
tabs.tabs("refresh");
}
});
});
</script>
<div id=tabs>
<ul>
</ul>
A button example:
<li><a class="menuButton" href="#" title="Permisos" data-id="tab3" data-direction="Permiso/_Administrar" data-label="Label" data-color="blue"><img src="#Res_icons.More">Permisos</a><li>
i found my answer here: http://dean.resplace.net/blog/2012/09/jquery-load-css-with-ajax-all-browsers/
the code:
<script type="text/javascript">
$(document).ready(function () {
$("head").append("<link href='...' rel='stylesheet'>");
});
</script>

How to find places along the route using google map api? [duplicate]

Can you please let me know if it is possible to get list of all places for example Gas Stations along Route Between Origin and Destination in Google Maps API? Here is a link that I am trying to list all Gas Stations or Rest areas ( or any of Google Maps API Supported Place Types)between two points ans based on a Direction supported route.
and this my code so far:
var directionsDisplay;
var directionsService = new google.maps.DirectionsService();
var map;
var haight = new google.maps.LatLng(49.216364,-122.811897);
var oceanBeach = new google.maps.LatLng(50.131446,-119.506838);
function initialize() {
directionsDisplay = new google.maps.DirectionsRenderer();
var mapOptions = {
zoom: 14,
mapTypeId: google.maps.MapTypeId.ROADMAP,
center: haight
}
map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
directionsDisplay.setMap(map);
calcRoute();
}
function calcRoute() {
var request = {
origin: haight,
destination: oceanBeach,
travelMode: google.maps.TravelMode.DRIVING
};
directionsService.route(request, function(response, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsDisplay.setDirections(response);
}
});
}
google.maps.event.addDomListener(window, 'load', initialize);
Edited Part:
// Make the directions request
directionService.route(request, function(result, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsRenderer.setDirections(result);
// Box around the overview path of the first route
var path = result.routes[0].overview_path;
var boxes = routeBoxer.box(path, distance);
drawBoxes(boxes);
} else {
alert("Directions query failed: " + status);
}
for (var i = 0; i < boxes.length; i++) {
var bounds = box[i];
// Perform search over this bounds
}
});
}
Use the RouteBoxer to get an array of google.maps.LatLngBounds objects that cover the route.
for each of those bounds use the Places library to search for the places.
Note that there are query limits and quotas on the places requests, so for long routes this may not be practical.
example
(however, looking at how the results are grouped, it looks like the places service is searching around the center of the bounds, rather than in the bounds, but it might be good enough for your needs).
code snippet:
var map = null;
var boxpolys = null;
var directions = null;
var routeBoxer = null;
var distance = null; // km
var service = null;
var gmarkers = [];
var boxes = null;
var infowindow = new google.maps.InfoWindow();
function initialize() {
// Default the map view to the continental U.S.
var mapOptions = {
center: new google.maps.LatLng(40, -80.5),
mapTypeId: google.maps.MapTypeId.ROADMAP,
zoom: 8
};
map = new google.maps.Map(document.getElementById("map"), mapOptions);
service = new google.maps.places.PlacesService(map);
routeBoxer = new RouteBoxer();
directionService = new google.maps.DirectionsService();
directionsRenderer = new google.maps.DirectionsRenderer({
map: map
});
// If there are any parameters at eh end of the URL, they will be in location.search
// looking something like "?marker=3"
// skip the first character, we are not interested in the "?"
var query = location.search.substring(1);
// split the rest at each "&" character to give a list of "argname=value" pairs
var pairs = query.split("&");
for (var i = 0; i < pairs.length; i++) {
// break each pair at the first "=" to obtain the argname and value
var pos = pairs[i].indexOf("=");
var argname = pairs[i].substring(0, pos).toLowerCase();
var value = pairs[i].substring(pos + 1).toLowerCase();
// process each possible argname - use unescape() if theres any chance of spaces
if (argname == "to") {
document.getElementById('to').value = unescape(value);
}
if (argname == "from") {
document.getElementById('from').value = unescape(value);
}
if (argname == "dist") {
document.getElementById('distance').value = parseFloat(value);
}
if (argname == "type") {
document.getElementById('type').value = unescape(value);
}
if (argname == "keyword") {
document.getElementById('keyword').value = unescape(value);
}
if (argname == "name") {
document.getElementById('name').value = unescape(value);
}
if (argname == "submit") {
route();
}
}
}
function route() {
// Clear any previous route boxes from the map
clearBoxes();
// Convert the distance to box around the route from miles to km
distance = parseFloat(document.getElementById("distance").value) * 1.609344;
var request = {
origin: document.getElementById("from").value,
destination: document.getElementById("to").value,
travelMode: google.maps.DirectionsTravelMode.DRIVING
}
// Make the directions request
directionService.route(request, function(result, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsRenderer.setDirections(result);
// Box around the overview path of the first route
var path = result.routes[0].overview_path;
boxes = routeBoxer.box(path, distance);
// alert(boxes.length);
drawBoxes();
findPlaces(0);
} else {
alert("Directions query failed: " + status);
}
});
}
// Draw the array of boxes as polylines on the map
function drawBoxes() {
boxpolys = new Array(boxes.length);
for (var i = 0; i < boxes.length; i++) {
boxpolys[i] = new google.maps.Rectangle({
bounds: boxes[i],
fillOpacity: 0,
strokeOpacity: 1.0,
strokeColor: '#000000',
strokeWeight: 1,
map: map
});
}
}
function findPlaces(searchIndex) {
var type = document.getElementById('type').value;
var keyword = document.getElementById('keyword').value;
var name = document.getElementById('name').value;
var request = {
bounds: boxes[searchIndex],
};
if (!!type && (type != "")) {
if (type.indexOf(',') > 0)
request.types = type.split(',');
else
request.types = [type];
}
if (!!keyword && (keyword != "")) request.keyword = keyword;
if (!!name && (name != "")) request.name = name;
service.nearbySearch(request, function(results, status) {
if (status == google.maps.places.PlacesServiceStatus.OK) {
document.getElementById('side_bar').innerHTML += "bounds[" + searchIndex + "] returns " + results.length + " results<br>"
for (var i = 0, result; result = results[i]; i++) {
var marker = createMarker(result);
}
} else {
document.getElementById('side_bar').innerHTML += "bounds[" + searchIndex + "] returns 0 results<br> status=" + status + "<br>";
}
if (status != google.maps.places.PlacesServiceStatus.OVER_QUERY_LIMIT) {
searchIndex++;
if (searchIndex < boxes.length)
findPlaces(searchIndex);
} else { // delay 1 second and try again
setTimeout("findPlaces(" + searchIndex + ")", 1000);
}
});
}
// Clear boxes currently on the map
function clearBoxes() {
if (boxpolys != null) {
for (var i = 0; i < boxpolys.length; i++) {
boxpolys[i].setMap(null);
}
}
boxpolys = null;
}
function createMarker(place) {
var placeLoc = place.geometry.location;
if (place.icon) {
var image = new google.maps.MarkerImage(
place.icon, new google.maps.Size(71, 71),
new google.maps.Point(0, 0), new google.maps.Point(17, 34),
new google.maps.Size(25, 25));
} else var image = {
url: "https://maps.gstatic.com/intl/en_us/mapfiles/markers2/measle.png",
size: new google.maps.Size(7, 7),
anchor: new google.maps.Point(3.5, 3.5)
};
var marker = new google.maps.Marker({
map: map,
icon: image,
position: place.geometry.location
});
var request = {
reference: place.reference
};
google.maps.event.addListener(marker, 'click', function() {
service.getDetails(request, function(place, status) {
if (status == google.maps.places.PlacesServiceStatus.OK) {
var contentStr = '<h5>' + place.name + '</h5><p>' + place.formatted_address;
if (!!place.formatted_phone_number) contentStr += '<br>' + place.formatted_phone_number;
if (!!place.website) contentStr += '<br><a target="_blank" href="' + place.website + '">' + place.website + '</a>';
contentStr += '<br>' + place.types + '</p>';
infowindow.setContent(contentStr);
infowindow.open(map, marker);
} else {
var contentStr = "<h5>No Result, status=" + status + "</h5>";
infowindow.setContent(contentStr);
infowindow.open(map, marker);
}
});
});
gmarkers.push(marker);
if (!place.name) place.name = "result " + gmarkers.length;
var side_bar_html = "<a href='javascript:google.maps.event.trigger(gmarkers[" + parseInt(gmarkers.length - 1) + "],\"click\");'>" + place.name + "</a><br>";
document.getElementById('side_bar').innerHTML += side_bar_html;
}
google.maps.event.addDomListener(window, 'load', initialize);
html,
body,
#map_canvas {
margin: 0;
padding: 0;
height: 100%;
}
<script src="https://maps.googleapis.com/maps/api/js?libraries=places&key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk"></script>
<script src="https://cdn.jsdelivr.net/gh/denissellu/routeboxer#master/src/RouteBoxer.js" type="text/javascript"></script>
<table border="1">
<tr>
<td valign="top">
<div id="map" style="width: 600px; height: 500px;"></div>
</td>
<td>
<div id="side_bar" style="width:200px; height: 600px; overflow: auto"></div>
</td>
</tr>
</table>
Box within at least
<input type="text" id="distance" value="3" size="2">miles of the route from
<input type="text" id="from" value="denver" />to
<input type="text" id="to" value="oklahoma city, OK" />
<input type="submit" onclick="route()" />
<br>
<label>type</label>
<input type="text" id="type" value="gas_station" />
<label>keyword</label>
<input type="text" id="keyword" value="" />
<label>name</label>
<input type="text" id="name" value="" />
<div id="towns"></div>

Resources