How can I make my WebRTC is working properly - webrtc

Now I am building a video call site with WebRTC. But it recognize camera and ask to allow camera.
When I allow camera it shows nothing.
I will write down my code here.
<body onload="init()">
<div class="row">
<div class="col-8">
<form action="#">
<h5>Current Room ID: <span id="curr_room_id"></span><br/></h5>
<input id="new_room_id" name="room" type="text" placeholder="Enter a room id to connect..." style="padding: 5px"/>
<input type="submit" id="connect" value="Connect" />
</form>
<input id="call" type="submit" value="Call" disabled="true"/>
<input id="end" type="submit" value="End Call"disabled="true"/>
</div>
<div class="col-4" id="google_translate_element"></div>
</div>
<h1>local</h1>
<video id="local_video" width="400px" style="border: 1px solid black;"></video>
<h1>remote</h1>
<video id="remote_video" width="400px" style="border: 1px solid black;"></video>
<script src="/socket.io/socket.io.js"></script>
<script src="../scripts/video-client.js"></script>
<script src="../scripts/video-room.js"></script>
<script>
function init() {
console.log("document loaded");
call.removeAttribute("disabled");
call.addEventListener("click", function(){
createPeerConnection();
call.setAttribute("disabled", true);
end.removeAttribute("disabled");
});
end.addEventListener("click", function() {
// change rooms
end.setAttribute("disabled", true);
call.removeAttribute("disabled");
});
}
</script>
</body>
I think it is because of not showing video stream to webview. But i didn't find nothing. Please tell me.
And here is video-client.js
console.log("loaded");
var socket = io();
var local = document.getElementById("local_video");
var remote = document.getElementById("remote_video");
var call = document.getElementById("call");
var end = document.getElementById("end");
var room_id = document.getElementById("curr_room_id");
var localStream = null, remoteStream = null;
var config = {'iceServers' : [{'url' : 'stun:stun.l.google.com:19302'}]};
var pc;
/////////////////////////////////
function createPeerConnection() {
try {
pc = new RTCPeerConnection(config);
pc.onicecandidate = handleIceCandidate;
pc.onaddstream = handleRemoteStreamAdded;
pc.onremovestream = handleRemoteStreamRemoved;
pc.onnegotiationneeded = handleNegotiationNeeded;
getUserMedia(displayLocalVideo);
pc.addStream(localStream);
console.log("Created RTCPeerConnection");
} catch (e) {
console.log("Failed to create PeerConnection: " + e.message);
return;
}
}
function handleIceCandidate(event) {
console.log("handleIceCandidate event: " + event);
if(event.candidate) {
sendMessage(JSON.stringify({'candidate': evt.candidate}));
} else {
consolel.log("End of ice candidates");
}
}
function handleRemoteStreamAdded(event) {
console.log("Remote stream added");
displayRemoteVideo(event.stream);
call.setAttribute("disabled", true);
end.removeAttribute("disabled");
}
function handleRemoteStreamRemoved(event) {
console.log("Remote stream removed: " + event);
end.setAttribute("disabled", true);
call.removeAttribute("disabled");
local.src = "";
remote.src = "";
}
function handleNegotiationNeeded() {
pc.createOffer(localDescCreated, logError);
}
function localDescCreated(desc) {
pc.setLocalDescription(desc, function() {
sendMessage(JSON.stringify({'sdp': pc.localDescription}));
}, logError);
}
call.onclick(function(){
createPeerConnection();
});
/////////////////////////////////
function getUserMedia(callback) {
navigator.mediaDevices.getUserMedia({video: true, audio: false}).then(
function(stream) {
callback(stream);
return stream;
}).catch(logError);
}
function displayLocalVideo(stream) {
localStream = stream;
local.src = window.URL.createObjectURL(stream);
local.play();
}
function displayRemoteVideo(stream) {
remoteStream = stream;
remote.src = window.URL.createObjectURL(stream);
remote.play();
}
function logError(error) {
console.log(error);
}
function sendMessage(message) {
socket.emit("message", message);
}
/////// receiving stream //////////
socket.on("message", function(evt){
if(!pc)
createPeerConnection();
var message = JSON.parse(evt.data);
if(message.sdp) {
pc.setRemoteDescription(new RTCSessionDescription(), function() {
if(pc.remoteDescription.type == 'offer')
pc.createAnswer(localDescCreated, logError);
}, logError);
} else {
pc.addIceCandidate(new RTCIceCandidate(message.candidate));
}
});
I think call.onclick() has to work properly for video streaming but it does not also.

You are not seeing your video because you are not using the stream that getUserMedia returns. You need to attach that stream to the video.

Related

Making a value from a fetch call available immediately

I have a Go program written that has a form which checks for the existence of a file by calling a fetch on a route inside the Go code. If the file exists or not, a boolean is return inside of a JSON as fileExists. I'm having trouble with the fetch call's JSON updating this.found boolean immediately.
What happens is that when I press enter or click the buttons, the form is submitted via call to onSubmit where the checkFile() is called which does the fetch. Somehow, I have to press enter twice to see the value returned by the fetch as it is not updating the this.found immediately. I am probably thinking about this the wrong way, but I figure it wouldn't to ask. Here's the code, if anyone can help so that clicking or submitting will be based on the correct value returned by the checkFile call:
<div class="jumbotron">
<div class="container">
<div class="alert alert-dark" role="alert">
</div>
<h1 class="display-3">Title</h1>
<div id="app">
<form ref="myForm" method="POST" v-on:submit.prevent="onSubmit" action="/push" class="needs-validation" id="myForm" novalidate="true">
<div class="form-group">
Canned List:
<input v-model="cannedlist" ref="cannedlist" type="text" class="form-control" name="fileListFile" id="filelist"
aria-describedby="fileListFileHelp"
autocomplete="off" :disabled="!!individuallist" v-on:submit.prevent="onSubmit" />
</div>
<div class="form-group">
Path List:
<textarea v-model="individuallist" ref="cannedlist" :disabled="!!cannedlist" class="form-control" rows=10 name="fileListRaw" id="files" autocomplete="off"></textarea>
</div>
<div class="form-group">
<button v-on:submit.prevent="onSubmit" type="submit" name="button" value="submit" id="submitButton" class="btn btn-primary" :disabled="isDisabled">Submit</button>
<button v-on:submit.prevent="onSubmit" type="submit" name="button" value="checkOnly" id="checkOnlyButton" class="btn btn-primary" :disabled="isDisabled">Submit 2</button>
</div>
</form>
</div>
</div>
</div>
<script src="/static/js/vue.min.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
// cannedlist: "filelist.txt",
individuallist: "",
found: false,
},
computed: {
isDisabled: function() {
//found = !found;
return (this.cannedlist.length <= 0 && this.individuallist.length <= 0);
},
},
methods: {
isDisabledNew: function() {
alert((this.cannedlist.length <= 0 && this.individuallist.length <= 0));
// return (this.cannedlist.length <= 0 && this.individuallist.length <= 0);
return false;
},
isFieldDisabled: function(e) {
//console.log(app.$refs.individuallist.disabled);
return false;
},
onSubmit: function() {
if (this.cannedlist.length > 0) {
this.checkFile();
if (this.found == true) {
this.$refs.myForm.submit();
return;
}
} else if (this.individuallist.length > 0) {
this.$refs.myForm.submit();
return;
}
},
checkFile: function() {
var url = 'http://localhost:9000/CheckIfFileExists?name=' + this.cannedlist;
return fetch(url)
.then(response => {
if (response.ok) {
var v = response.json().then( response => { this.found = response.fileExists; } );
return this.found;
}
return response.json().then(error => ({ error }));
});
return this.found;
},
}
});
</script>
Your onSubmit function calls checkFile and expects found to be updated:
onSubmit: function() {
if (this.cannedlist.length > 0) {
this.checkFile();
if (this.found == true) {
this.$refs.myForm.submit();
return;
}
} else if (this.individuallist.length > 0) {
this.$refs.myForm.submit();
return;
}
},
But checkFile returns a Promise. The Promise resolves by updating found. So you need to put your found checking inside a then block:
onSubmit: function() {
if (this.cannedlist.length > 0) {
this.checkFile()
.then(() => {
if (this.found == true) {
this.$refs.myForm.submit();
}
});
return;
} else if (this.individuallist.length > 0) {
this.$refs.myForm.submit();
return;
}
},
Here're the changes I made:
methods: {
onSubmit: function(event) {
if (this.cannedlist.length > 0) {
this.checkFile()
// This promise capture is the key I was missing
.then( (data) => {
this.found = data.fileExists;
if (this.found == true) {
this.$refs.myForm.submit();
} else {
alert("File not found: " + this.cannedlist);
}
});
} else if (this.individuallist.length > 0) {
this.$refs.myForm.submit();
}
},
checkFile: function() {
var url = 'http://localhost:9000/CheckIfFileExists?name=' + this.cannedlist;
return fetch(url).then((response) => response.json());
}

Vue Axios form sending empty data instead of image

Alright so I am trying to send image data using JSON but no matter what I do I always end up in sending an empty object... I've tried to console log results but no matter what it just sends empty object
CODE:
<body>
<div id="app">
<div v-if="!image">
<h2>Select an image</h2>
<input type="file" #change="onFileChange" multiple>
</div>
<div v-else>
<div v-for="img in image" class="img_overlay">
<img :src="img" class="img_set"/><br/>
<button #click="removeImage(img)">Remove image</button>
</div>
</div>
</div>
<style>
.img_overlay {
width: 25%;
height: 250px;
float: left;
text-align: center;
}
img {
width: 250px;
height: 200px;
}
</style>
<script type="text/javascript">
new Vue({
el: "#app",
data: {
image: "",
file_data: []
},
methods: {
onFileChange(e) {
var files = e.target.files || e.dataTransfer.files;
if (!files.length)
return;
else if(files.length == 1)
this.createImage(files)
else if(files.length >= 2)
this.createImage(files)
this.file_data = e.target.files;
this.uploadImage(e.target.files);
},
createImage(file) {
var tmp = [];
for(let i = 0; i < file.length; i++) {
var image = new Image();
var reader = new FileReader();
var vm = this;
reader.onload = (e) => {
tmp.push(e.target.result);
};
reader.readAsDataURL(file[i]);
}
vm.image = tmp;
},
removeImage: function (img) {
for(let i = 0; i < this.image.length; i++) {
if(this.image[i] == img) {
this.image.splice(i, 1);
}
}
},
uploadImage: function(x_file) {
const config = {
headers: { 'content-type': 'multipart/form-data' }
}
axios.post('/theme/post_new_image', x_file, config).then(function (response) {
console.log(response);
}).catch(e => { console.log(e); });
}
}
});
</script>
</body>
The result I usualy get is empty object with 5 keys. I've tried to stringify the data and such but I've couldn't find the correct solution for it
You are passing an array of files to your uploadImage function. Try iterating over the array to upload each file:
for (var i = 0, f; f = e.target.files[i]; i++) {
uploadImage(f);
}

Google maps api departureTime in directionsService

I'm trying to set a departureTime options but does not seem to work.
in the example the road ss38 between Bormio and Prato allo Stelvio this season is closed.
Starting in August, I expect that you are using this road and not the one that currently offers through the Swiss.
thanks
Here's my code:
function initialize() {
map = new google.maps.Map(document.getElementById("map"), {
mapTypeId: google.maps.MapTypeId.ROADMAP,
mapTypeControlOptions: {
style: google.maps.MapTypeControlStyle.HORIZONTAL_BAR,
position: google.maps.ControlPosition.TOP_CENTER
},
streetViewControl: true,
streetViewControlOptions: {
position: google.maps.ControlPosition.TOP_LEFT
},
zoomControl: true,
zoomControlOptions: {
position: google.maps.ControlPosition.LEFT_TOP
}
});
map.setZoom(10); // This will trigger a zoom_changed on the map
map.setCenter(new google.maps.LatLng(46.6199, 10.5924));
directionsDisplay.setMap(map);
geocoderService = new google.maps.Geocoder();
directionsService = new google.maps.DirectionsService;
var marker = new google.maps.Marker({
position: new google.maps.LatLng(46.6199, 10.5924),
map: map,
draggable: true
});
var marker2 = new google.maps.Marker({
position: new google.maps.LatLng(46.4693, 10.3731),
map: map,
draggable: true
});
calcolapercorso(tipodipercorso);
}
function calcolapercorso(tipodipercorso) {
var request = {
origin: new google.maps.LatLng(46.6199, 10.5924),
destination: new google.maps.LatLng(46.4693, 10.3731),
optimizeWaypoints: false,
avoidHighways: true,
region: "IT",
travelMode: google.maps.TravelMode.DRIVING,
drivingOptions: {
departureTime: new Date('2016-08-11T00:00:00'),
trafficModel: google.maps.TrafficModel.PESSIMISTIC
}
};
//request.travelMode = google.maps.DirectionsTravelMode.DRIVING;
request.unitSystem = google.maps.UnitSystem.METRIC;
directionsService.route(request, function(response, status) {
if (status == google.maps.DirectionsStatus.OK) {
var polyLine = {
strokeColor: "#2B8B3F",
strokeOpacity: 1,
strokeWeight: 4,
};
directionsDisplay.setOptions({
polylineOptions: polyLine,
suppressMarkers: true
});
directionsDisplay.setDirections(response);
} else if (status == google.maps.DirectionsStatus.ZERO_RESULTS) {
alert("Could not find a route between these points");
} else {
alert("Directions request failed");
}
});
}
I figured out that the departureTime option does not work when you set any waypoints (at least in Google Maps Javascript API. I didn't confirm RestAPI).
Without waypoints, it worked.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<style type="text/css">
#map_canvas {
width: 600px;
height: 400px;
border: 1px solid gray;
float: left;
}
#direction_panel {
width: 250px;
height: 400px;
border: 1px solid gray;
overflow-y:scroll;
}
</style>
<script src="https://maps.googleapis.com/maps/api/js?language=en&v=3.exp&client=[YOUR_CLIENT_ID]"></script>
<script>
function initialize() {
var mapDiv = document.getElementById("map_canvas");
var map = new google.maps.Map(mapDiv, {
mapTypeId: google.maps.MapTypeId.ROADMAP
});
var form = document.getElementById("form");
google.maps.event.addDomListener(form, "submit", function(event) {
if (event.preventDefault) {
event.preventDefault();
} else {
event.cancelBubble = true;
event.returnValue = false;
}
map.set("traffic", google.maps.TrafficModel[this.trafficModel.value]);
});
var directionsService = new google.maps.DirectionsService();
map.set("directionsService", directionsService);
var panelDiv = document.getElementById("direction_panel");
var directionsRenderer = new google.maps.DirectionsRenderer({
map: map,
panel: panelDiv
});
map.set("directionsRenderer", directionsRenderer);
map.addListener("traffic_changed", onTrafficModelChanged);
}
function onTrafficModelChanged() {
var map = this;
var departureDateTime = document.getElementById("departureTime").value;
var directionsService = map.get("directionsService");
var directionsRenderer = map.get("directionsRenderer");
var trafficModel = map.get("traffic");
var request = {
origin: "<YOUR ORIGIN>",
destination: "<YOUR DESTINATION>",
travelMode: google.maps.TravelMode.DRIVING,
drivingOptions: {
departureTime: new Date(departureDateTime),
trafficModel: trafficModel
}
};
directionsService.route(request, function(result, status) {
if (status != google.maps.DirectionsStatus.OK) {
alert(status);
return;
}
directionsRenderer.setDirections(result);
});
}
google.maps.event.addDomListener(window, "load", initialize);
</script>
</head>
<body>
<div id="frame">
<div id="map_canvas"></div>
<div id="direction_panel"></div>
</div>
<form id="form">
Departure Time: <input type="text" id="departureTime" size=40 value="2016/01/25 21:00 PST"><br>
<input type="radio" name="trafficModel" value="OPTIMISTIC">Optimistic
<input type="radio" name="trafficModel" value="BEST_GUESS" checked>BEST_GUESS
<input type="radio" name="trafficModel" value="PESSIMISTIC">PESSIMISTIC
<input type="submit" value="Search">
</form>
</body>
</html>

cannot remove knockout observableArray item with SingalR

I am struggling with two issues. The first one is that after I pushed a new item into observableArray and try to refresh the accordion. The new item did not show up in the accordion. But the producs().length increased by one.
this.hub.client.productAdded = function (p) {
products.push(new productListViewModel(p.id, p.Name, self));
$("#accordion").accordion("refresh");
//loadAccordion();
};
My second issue is that After SignalR deleted an item in the database and returned with the deleted object I tried to remove the deleted object from the observableArray. I have tried different ways and none of them work.
this.hub.client.productRemoved = function (deleted) {
//var deleted = ko.utils.arrayFilter(products(), function (item) {
// return item.id == deleted.id;
//})[0];
products.remove(function (item) { return item.id == deleted.id; });
//products.remove(deleted);
$("#accordion").accordion("refresh");
};
What do I miss here? Below is the whole page code for reference
#{
ViewBag.Title = "SignalR";
}
<h2>SignalR</h2>
<div id="error"></div>
<h2>Add Product</h2>
<form data-bind="submit: addProduct">
<input data-bind="value: newProductText" class="ui-corner-all" placeholder="New product name?" />
<input type="submit" class="ui-button" value="Add Product" />
</form>
<h2>Our Products</h2>
listed: <b data-bind="text: productCount"></b> product(s)
#*<div id="accordion" data-bind="template: {name: productTemplate, foreach: products }, visible: products.Length > 0"></div>*#
<div id="accordion" data-bind='template: {name: "product-template", foreach: products }'></div>
<script type="text/html" id="product-template">
<h3 data-bind="text: name"></h3>
<div>
<input type="button" class="ui-button" value="Remove Rroduct" data-bind="click: removeProduct" />
</div>
</script>
<span data-bind="visible: productCount() == 0">What? No products?</span>
#section Scripts {
#Scripts.Render("~/bundles/knockout")
#Scripts.Render("~/bundles/signalr")
<script src="/Scripts/jquery.signalR-2.0.1.min.js" type="text/javascript"></script>
<script src="~/signalr/hubs" type="text/javascript"></script>
<script src="/Scripts/jquery.livequery.min.js"></script>
<style>
#accordion {width: 300px;}
#accordion h3 { padding-left: 30px}
</style>
<script>
function productViewModel(id, name, ownerViewModel) {
this.id = ko.observable(id);
this.name = ko.observable(name);
var self = this;
this.removeProduct = function () { ownerViewModel.removeProduct( id); };
this.name.subscribe(function (newValue) {
ownerViewModel.updateProduct(ko.toJS(self));
});
}
function productListViewModel() {
this.hub = $.connection.products;
this.products = ko.observableArray([]);
this.newProductText = ko.observable();
chat = this.hub
var products = this.products;
var self = this;
// Get All
this.init = function () {
this.hub.server.getAll();
}
this.hub.client.productAll = function (allProducts) {
//var mappedProducts = $.map(allProducts, function (item) {
// return new productViewModel(item.id, item.name, self);
//});
//products(mappedProducts);
$.each(allProducts, function (index, item) {
products.push(new productViewModel(item.id, item.Name, self));
});
loadAccordion();
};
this.hub.reportError = function (error) {
$("#error").text(error);
};
$.connection.hub.error(function (error) {
console.log('SignalR error: ' + error)
});
this.hub.client.productAdded = function (p) {
products.push(new productListViewModel(p.id, p.Name, self));
$("#accordion").accordion("refresh");
//loadAccordion();
};
this.hub.client.productRemoved = function (deleted) {
//var deleted = ko.utils.arrayFilter(products(), function (item) {
// return item.id == deleted.id;
//})[0];
products.remove(function (item) { return item.id == deleted.id; });
//products.remove(deleted);
$("#accordion").accordion("refresh");
};
// Commands
this.addProduct = function () {
var p = { "Name": this.newProductText() };
this.hub.server.add(p).done(function () { }).fail(function (e) { alert(e); });
this.newProductText("");
};
this.removeProduct = function (id) {
this.hub.server.remove(id).done(function () { alert("aa"); }).fail(function (e) { alert(e+" aa"); });
};
this.productCount = ko.dependentObservable(function () {
return products().length;
}, this);
}
function loadAccordion() {
$("#accordion").accordion({ event: "mouseover" });
}
$(function () {
var viewModel = new productListViewModel();
ko.applyBindings(viewModel);
// connect SinalR
$.connection.hub.start(function () { viewModel.init(); });
//$.connection.hub.start(function () { chat.server.getAll(); });
});
</script>
}
To solve your add problem: you are creating a new productListViewModel but you need to add a new productViewModel, so you just need to create the correct viewmodel:
this.hub.client.productAdded = function (p) {
products.push(new productViewModel(p.id, p.Name, self));
$("#accordion").accordion("refresh");
};
To solve your delete problem: in your productViewModel the id is a ko.observable so you need to write item.id() to access its value in the remove function:
this.hub.client.productRemoved = function (deleted) {
products.remove(function (item) { return item.id() == deleted.id; });
$("#accordion").accordion("refresh");
};

Error when running Google Places Autocomplete API

I'm new to the Google Places Autocomplete API, and to development in general but I'm hoping someone can help point me in the right direction. I've reviewed the Google Places documentation and example. In trying to duplicate Google's example in order to gain a better understanding (http://code.google.com/apis/maps/documentation/javascript/examples/places-autocomplete.html), I receive the following error when I run it:
"The Google Maps API server rejected your request. The "sensor" parameter specified in the request must be set to either "true" or "false"."
What's maddening is I do have "sensor" set to "false"! Please see below for the full page code. Any advice would be greatly appreciated.
<html>
<head>
<title>Google Maps JavaScript API v3 Example: Places Autocomplete</title>
<script src="https://maps.googleapis.com/maps/api/js?sensor=false&libraries=places"
type="text/javascript"></script>
<style type="text/css">
body {
font-family: sans-serif;
font-size: 14px;
}
#map_canvas {
height: 400px;
width: 600px;
margin-top: 0.6em;
}
</style>
<script type="text/javascript">
function initialize() {
var mapOptions = {
center: new google.maps.LatLng(-33.8688, 151.2195),
zoom: 13,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById('map_canvas'),
mapOptions);
var input = document.getElementById('searchTextField');
var autocomplete = new google.maps.places.Autocomplete(input);
autocomplete.bindTo('bounds', map);
var infowindow = new google.maps.InfoWindow();
var marker = new google.maps.Marker({
map: map
});
google.maps.event.addListener(autocomplete, 'place_changed', function () {
infowindow.close();
var place = autocomplete.getPlace();
if (place.geometry.viewport) {
map.fitBounds(place.geometry.viewport);
} else {
map.setCenter(place.geometry.location);
map.setZoom(17); // Why 17? Because it looks good.
}
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(35, 35));
marker.setIcon(image);
marker.setPosition(place.geometry.location);
var address = '';
if (place.address_components) {
address = [(place.address_components[0] &&
place.address_components[0].short_name || ''),
(place.address_components[1] &&
place.address_components[1].short_name || ''),
(place.address_components[2] &&
place.address_components[2].short_name || '')
].join(' ');
}
infowindow.setContent('<div><strong>' + place.name + '</strong><br>' + address);
infowindow.open(map, marker);
});
// Sets a listener on a radio button to change the filter type on Places
// Autocomplete.
function setupClickListener(id, types) {
var radioButton = document.getElementById(id);
google.maps.event.addDomListener(radioButton, 'click', function () {
autocomplete.setTypes(types);
});
}
setupClickListener('changetype-all', []);
setupClickListener('changetype-establishment', ['establishment']);
setupClickListener('changetype-geocode', ['geocode']);
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
</head>
<body>
<div>
<input id="searchTextField" type="text" size="50">
<input type="radio" name="type" id="changetype-all" checked="checked">
<label for="changetype-all">All</label>
<input type="radio" name="type" id="changetype-establishment">
<label for="changetype-establishment">Establishments</label>
<input type="radio" name="type" id="changetype-geocode">
<label for="changetype-geocode">Geocodes</label>
</div>
<div id="map_canvas"></div>
</body>
</html>
Try this script
<script>
function initialize() {
var mapOptions = {
center: new google.maps.LatLng(-33.8688, 151.2195),
zoom: 13,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById('map_canvas'),
mapOptions);
var input = document.getElementById('searchTextField');
var autocomplete = new google.maps.places.Autocomplete(input);
autocomplete.bindTo('bounds', map);
var infowindow = new google.maps.InfoWindow();
var marker = new google.maps.Marker({
map: map
});
google.maps.event.addListener(autocomplete, 'place_changed', function() {
infowindow.close();
marker.setVisible(false);
input.className = '';
var place = autocomplete.getPlace();
if (!place.geometry) {
// Inform the user that the place was not found and return.
input.className = 'notfound';
return;
}
// If the place has a geometry, then present it on a map.
if (place.geometry.viewport) {
map.fitBounds(place.geometry.viewport);
} else {
map.setCenter(place.geometry.location);
map.setZoom(17); // Why 17? Because it looks good.
}
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(35, 35));
marker.setIcon(image);
marker.setPosition(place.geometry.location);
var address = '';
if (place.address_components) {
address = [
(place.address_components[0] && place.address_components[0].short_name || ''),
(place.address_components[1] && place.address_components[1].short_name || ''),
(place.address_components[2] && place.address_components[2].short_name || '')
].join(' ');
}
infowindow.setContent('<div><strong>' + place.name + '</strong><br>' + address);
infowindow.open(map, marker);
});
// Sets a listener on a radio button to change the filter type on Places
// Autocomplete.
function setupClickListener(id, types) {
var radioButton = document.getElementById(id);
google.maps.event.addDomListener(radioButton, 'click', function() {
autocomplete.setTypes(types);
});
}
setupClickListener('changetype-all', []);
setupClickListener('changetype-establishment', ['establishment']);
setupClickListener('changetype-geocode', ['geocode']);
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>