I have wrong output of peerjs webrtc call. can anyone help me on how to show the remote and local video chat in the same screen? currently it is showing only one video chat user. Also, I want the design view like this.
https://drive.google.com/file/d/1KPnoEBanIUuThrPuavL1bnqIlG5yjC0o/view?usp=sharing
Can anyone help me by share the total code of this picture UX design view?
My project server is on peerjs cloud server, so no need to put hard coded ip address of 2 peer hosts.
The project has 3 files. main.js, index.html and style.css. Here is the code for main.js .
const peer = new Peer();
var currentCall;
peer.on("open", function (id) {
document.getElementById("uuid").textContent = id;
});
async function callUser() {
// get the id entered by the user
const peerId = document.querySelector("input").value;
// grab the camera and mic
const stream = await navigator.mediaDevices.getUserMedia({
video: true,
audio: true,
});
// switch to the video call and play the camera preview
document.getElementById("menu").style.display = "none";
document.getElementById("live").style.display = "block";
document.getElementById("local-video").srcObject = stream;
document.getElementById("local-video").play();
// make the call
const call = peer.call(peerId, stream);
call.on("stream", (stream) => {
document.getElementById("remote-video").srcObject = stream;
document.getElementById("remote-video").play();
});
call.on("data", (stream) => {
document.querySelector("#remote-video").srcObject = stream;
});
call.on("error", (err) => {
console.log(err);
});
call.on('close', () => {
endCall()
})
// save the close function
currentCall = call;
}
peer.on("call", (call) => {
if (confirm(`Accept call from ${call.peer}?`)) {
// grab the camera and mic
navigator.mediaDevices
.getUserMedia({ video: true, audio: true })
.then((stream) => {
// play the local preview
document.querySelector("#local-video").srcObject = stream;
document.querySelector("#local-video").play();
// answer the call
call.answer(stream);
// save the close function
currentCall = call;
// change to the video view
document.querySelector("#menu").style.display = "none";
document.querySelector("#live").style.display = "block";
call.on("stream", (remoteStream) => {
// when we receive the remote stream, play it
document.getElementById("remote-video").srcObject = remoteStream;
document.getElementById("remote-video").play();
});
})
.catch((err) => {
console.log("Failed to get local stream:", err);
});
} else {
// user rejected the call, close it
call.close();
}
});
function endCall() {
// Go back to the menu
document.querySelector("#menu").style.display = "block";
document.querySelector("#live").style.display = "none";
// If there is no current call, return
if (!currentCall) return;
// Close the call, and reset the function
try {
currentCall.close();
} catch {}
currentCall = undefined;
}
Here is code for style.css.
#live {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
width: 100%;
height: 100%;
background-color: #000;
display: none;
}
#local-video {
position: absolute;
bottom: 0;
left: 0;
width: 250px;
-webkit-transform: scaleX(-1);
transform: scaleX(-1);
margin: 16px;
border: 2px solid #fff;
}
#remote-video {
position: absolute;
max-width: 100%;
height: 100%;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
#end-call {
position: absolute;
bottom: 0;
right: 0;
padding: 8px;
background-color: red;
color: white;
border: none;
margin: 16px;
}
Here is code for index.html .
<!DOCTYPE html>
<html lang="en">
<head>
<title>P2P Video Chat</title>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script src="https://unpkg.com/peerjs#1.3.1/dist/peerjs.min.js"></script>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<!-- App code -->
<div id="menu">
<p>Your ID:</p>
<p id="uuid"></p>
<input type="text" placeholder="Peer id" />
<button onclick="callUser()">Connect</button>
</div>
<div id="live">
<video id="remote-video"></video>
<video id="local-video" muted="true"></video>
<button id="end-call" onclick="endCall()">End Call</button>
</div>
<div id="menu">
<p>Your ID:</p>
<p id="uuid"></p>
<input type="text" placeholder="Peer id" />
<button onclick="callUser()">Connect</button>
</div>
<script src="main.js"></script>
</body>
</html>
Any one come with
complete solution and help by working code links
that is >>compatible on All modern browsers>> is much appreciated. what do you think, which one active/compatible on all browsers >> opensip or peerjs ?
Related
i made a loading bar for my website. On the live preview with brackets, when I scroll down to my bar, the animation become visible. When I open my html page with a browser (chrome or edge), The loading bar animation does not appear... Although I think I used the right prefixes. Below you can see my code:
**CSS**
.laden100 {
animation-name: laden100;
-webkit-animation-name: laden100;
animation-duration: 4s;
-webkit-animation-duration: 4s;
visibility: visible;
width: 100%;
height: 20px;
background-image: linear-gradient(to bottom, #308355, #308355, #308355, #00cc66);
background-image: -webkit-linear-gradient(to bottom, #308355, #308355, #308355, #00cc66);
box-shadow: 5px 5px 5px grey;
border-radius: 5px 5px 5px 5px;
position: relative;
margin-top: 20px;
margin-left: 20px;
margin-right: 20px;
}
#keyframes laden100 {
0% {
opacity: 0;
width: 0%;
}
100% {
opacity: 1;
width: 100%;
}
}
#-webkit-keyframes laden100 {
0% {
opacity: 0;
width: 0%;
}
100% {
opacity: 1;
width: 50%;
}
}
**HTML**
<div class="container wit mt-5">
<h1 id="skills">Skills</h1>
<p style="color:#308355">Below you can see my skills I have. This learning process is still ongoing. I hope to achieve at least 80% for each coding language.</p>
<br>
<div class="container">
<div class="row">
<div class="vak">HTML</div>
<div class="laadbalk100"></div>
<div class="score100">%</div>
</div>
<br>
</div>
</div>
**JAVASCRIPT**
<!----------------------- only load the load bar on scroll-------------->
<script>
$(document).ready(function() {
// Add smooth scrolling to all links in navbar + footer link
$(".navbar a, footer a[href='#myPage']").on('click', function(event) {
// Make sure this.hash has a value before overriding default behavior
if (this.hash !== "") {
// Prevent default anchor click behavior
event.preventDefault();
// Store hash
var hash = this.hash;
// Using jQuery's animate() method to add smooth page scroll
// The optional number (900) specifies the number of milliseconds it takes to scroll to the specified area
$('html, body').animate({
scrollTop: $(hash).offset().top
}, 900, function() {
// Add hash (#) to URL when done scrolling (default click behavior)
window.location.hash = hash;
});
} // End if
});
$(window).scroll(function() {
$(".laadbalk100").each(function() {
var pos = $(this).offset().top;
var winTop = $(window).scrollTop();
if (pos < winTop + 600) {
$(this).addClass("laden100");
}
});
});
})
</script>
I used prefixes because I think it has something to do with browser support. According to me, Brackets uses plugins to add the right prefixes.
OK sry Guys,
I found the answer to my own question... :D.
Because browsers have different screen resolutions, I had to increase wintop +600 to wintop +1000. See the correction below:
$(window).scroll(function() {
$(".laadbalk100").each(function() {
var pos = $(this).offset().top;
var winTop = $(window).scrollTop();
if (pos < winTop + 1000) {
$(this).addClass("laden100");
}
});
});
I want develop ( Chrome Extension with ) a popup with persistent data when close popup, but I want delete storage data when close browser.
This example save current status of button [start/stop] , but I want reset storage data when close the browser, how to delete storage data when close browser ?
Goal about this code example
When close popup save correctly status ( work )
When close browser, clean current status and set to start ( I need to implement )
I read this solution, but is not clear how to implement in my case
let button = document.querySelector('button');
let options = document.querySelector("#btn-start");
chrome.storage.local.get(['button'], function(status) {
console.log('Value currently is ' + status.button);
console.log(typeof(status.button))
if ( status.button === 'Stop') {
setButtonStop();
}
});
button.addEventListener("click", changeButtonStatus);
function changeButtonStatus(){
let buttonStatus = document.querySelector("button").innerText;
let status = '';
if ( buttonStatus === 'Start')
status = setButtonStop();
if ( buttonStatus === 'Stop')
status = setButtonStart();
chrome.storage.local.set({button: status }, function() {
console.log('Value is set to ' + [status]);
});
}
function setButtonStop () {
options.setAttribute("id", "btn-stop");
button.innerText = "Stop";
return button.innerText;
}
function setButtonStart () {
options.setAttribute("id", "btn-start");
button.innerText = "Start";
return button.innerText;
}
a:link,
a:visited,
a:hover,
a:active {
text-decoration: none;
}
/* Popup Window */
#modal-popup {
display: flex;
flex-direction: column;
background: gainsboro;
}
#btn-start button {
width: 100%;
background: green;
color:white;
}
#btn-start button:active {
border-color: green;
background: rgb(0, 255, 0);
color: black;
}
#btn-stop button {
width: 100%;
background: red;
color:white;
}
#btn-stop button:active {
border-color: red;
background: rgb(148, 0, 0);
color: rgb(255, 255, 255);
}
#btn-options button {
width: 100%;
background: white;
border: 0;
}
#btn-options button:active {
background-color: transparent;
animation: rotate 5s infinite;
}
#keyframes rotate {
0% {
transform: rotate(-45deg)
}
100% {
transform: rotate(45deg)
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="app.css">
<title>Popup</title>
</head>
<body>
<div id="modal-popup">
<div id="btn-start"><button type="button" name="control">Start</button></div>
<div id="btn-options"><button type="button" name="options">⚙️</button><div>
</div>
<script src="popup.js"></script>
</body>
</html>
{
"name": "popup tutorial #1",
"description": "persistent data settings",
"version": "0.0.1",
"manifest_version": 3,
"permissions": ["storage"],
"action": {
"default_popup": "popup.html",
"default_icon": {
"16": "/images/16.png",
"32": "/images/32.png",
"48": "/images/48.png",
"128": "/images/128.png"
}
},
"icons": {
"16": "/images/16.png",
"32": "/images/32.png",
"48": "/images/48.png",
"128": "/images/128.png"
}
}
use chrome.storage.session instead chrome.storage.local
I'm hoping to combine the following two codes to create a map that not only searches with a layer of KMZ on top, but also shows navigation options in the infowindow. An example of the two maps side by side can be viewed here. But I want to combine the two maps into one. I've included my attempt at this at the bottom of this post - but it doesn't work.
Firstly, I've adapted this code for searching a map with my kmz (or kml) layered onto it and it works just fine ...
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta charset="utf-8">
<style>
html, body {
height: 100%;
margin: 0;
padding: 0;
}
#map-canvas {
height: 100%;
}
.controls {
margin-top: 10px;
border: 1px solid transparent;
border-radius: 2px 0 0 2px;
box-sizing: border-box;
-moz-box-sizing: border-box;
height: 32px;
outline: none;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
}
#pac-input {
background-color: #fff;
font-family: Roboto;
font-size: 15px;
font-weight: 300;
margin-left: 12px;
padding: 0 11px 0 13px;
text-overflow: ellipsis;
width: 300px;
}
#pac-input:focus {
border-color: #4d90fe;
}
.pac-container {
font-family: Roboto;
}
#type-selector {
color: #fff;
background-color: #4d90fe;
padding: 5px 11px 0px 11px;
}
#type-selector label {
font-family: Roboto;
font-size: 13px;
font-weight: 300;
}
</style>
<title>Places Searchbox</title>
<style>
#target {
width: 345px;
}
</style>
</head>
<body>
<input id="pac-input" class="controls" type="text" placeholder="Search Box">
<div id="map-canvas"></div>
<script>
// This example adds a search box to a map, using the Google Place Autocomplete
// feature. People can enter geographical searches. The search box will return a
// pick list containing a mix of places and predicted search terms.
function initAutocomplete() {
var map = new google.maps.Map(document.getElementById('map-canvas'), {
center: {lat:53.6292604,lng:-2.9380916},
zoom: 5,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
var mapLayer = new google.maps.KmlLayer({
url: "https://www.google.com/maps/d/kml?mid=zQWA66D2AmlU.kGvUUZ4wvdYo",
suppressInfoWindows:false,
preserveViewport:true });
mapLayer.setMap(map);
// Create the search box and link it to the UI element.
var input = document.getElementById('pac-input');
var searchBox = new google.maps.places.SearchBox(input);
map.controls[google.maps.ControlPosition.TOP_LEFT].push(input);
// Bias the SearchBox results towards current map's viewport.
map.addListener('bounds_changed', function() {
searchBox.setBounds(map.getBounds());
});
var markers = [];
// [START region_getplaces] this was the first to cause problems
// Listen for the event fired when the user selects a prediction and retrieve
// more details for that place.
searchBox.addListener('places_changed', function() {
var places = searchBox.getPlaces();
if (places.length == 0) {
return;
}
// Clear out the old markers.
markers.forEach(function(marker) {
marker.setMap(null);
});
markers = [];
// For each place, get the icon, name and location.
var bounds = new google.maps.LatLngBounds();
places.forEach(function(place) {
var icon = {
url: place.icon,
size: new google.maps.Size(71, 71),
origin: new google.maps.Point(0, 0),
anchor: new google.maps.Point(17, 34),
scaledSize: new google.maps.Size(25, 25)
};
// Create a marker for each place.
markers.push(new google.maps.Marker({
map: map,
icon: icon,
title: place.name,
position: place.geometry.location
}));
if (place.geometry.viewport) {
// Only geocodes have viewport.
bounds.union(place.geometry.viewport);
} else {
bounds.extend(place.geometry.location);
}
});
map.fitBounds(bounds);
});
// [END region_getplaces]
}
</script>
<script src="https://maps.googleapis.com/maps/api/js?key=[MY-KEY]&libraries=places&callback=initAutocomplete"
async defer></script>
</body>
</html>
This second code works great with adding a direction link to the info window so you can drive there using your smartphone ...
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html><head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta charset="utf-8"><title>Embedded Map</title>
<style>
html, body, #map-canvas {
height: 100%;
margin: 0px;
padding: 0px
}
</style>
<script src="https://maps.googleapis.com/maps/api/js?v=3"></script>
<script>
var map;
var infowindow;
function initialize() {
var mapOptions = {center: {lat:53.6292604,lng:-2.9380916},
zoom: 5}
map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
var mapLayer = new google.maps.KmlLayer({
url: "https://www.google.com/maps/d/kml?mid=zQWA66D2AmlU.kGvUUZ4wvdYo",
suppressInfoWindows:true,
preserveViewport:true });
mapLayer.setMap(map);
google.maps.event.addListener(mapLayer, 'click', function(kmlEvent) {
var text = kmlEvent.featureData.infoWindowHtml;
text = text + '<br>Navigate to Here';
if (infowindow) { infowindow.setContent(text);
} else {
infowindow = new google.maps.InfoWindow({content: text});
}
infowindow.setOptions({position:kmlEvent.latLng, pixelOffset:kmlEvent.pixelOffset});
infowindow.open(map);
});
}
google.maps.event.addDomListener(window, 'load', initialize);
</script></head>
<body>
<div id="map-canvas"></div>
</body></html>
Putting the two scripts together here, it looks something like this, although this doesn't work. Any answers gratefully received about whats going wrong here please ...
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta charset="utf-8">
<style>
html, body {
height: 100%;
margin: 0;
padding: 0;
}
#map-canvas {
height: 100%;
}
.controls {
margin-top: 10px;
border: 1px solid transparent;
border-radius: 2px 0 0 2px;
box-sizing: border-box;
-moz-box-sizing: border-box;
height: 32px;
outline: none;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
}
#pac-input {
background-color: #fff;
font-family: Roboto;
font-size: 15px;
font-weight: 300;
margin-left: 12px;
padding: 0 11px 0 13px;
text-overflow: ellipsis;
width: 300px;
}
#pac-input:focus {
border-color: #4d90fe;
}
.pac-container {
font-family: Roboto;
}
#type-selector {
color: #fff;
background-color: #4d90fe;
padding: 5px 11px 0px 11px;
}
#type-selector label {
font-family: Roboto;
font-size: 13px;
font-weight: 300;
}
</style>
<title>Places Searchbox</title>
<style>
#target {
width: 345px;
}
</style>
</head>
<body>
<input id="pac-input" class="controls" type="text" placeholder="Search Box">
<div id="map-canvas"></div>
<script>
// This example adds a search box to a map, using the Google Place Autocomplete
// feature. People can enter geographical searches. The search box will return a
// pick list containing a mix of places and predicted search terms.
function initAutocomplete() {
var map = new google.maps.Map(document.getElementById('map-canvas'), {
center: {lat:53.6292604,lng:-2.9380916},
zoom: 5,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
var mapLayer = new google.maps.KmlLayer({
url: "https://www.google.com/maps/d/kml?mid=zQWA66D2AmlU.kGvUUZ4wvdYo",
suppressInfoWindows:false,
preserveViewport:true });
mapLayer.setMap(map);
// Create the search box and link it to the UI element.
var input = document.getElementById('pac-input');
var searchBox = new google.maps.places.SearchBox(input);
map.controls[google.maps.ControlPosition.TOP_LEFT].push(input);
// Bias the SearchBox results towards current map's viewport.
map.addListener('bounds_changed', function() {
searchBox.setBounds(map.getBounds());
});
var markers = [];
// [START region_getplaces] this was the first to cause problems
// Listen for the event fired when the user selects a prediction and retrieve
// more details for that place.
searchBox.addListener('places_changed', function() {
var places = searchBox.getPlaces();
if (places.length == 0) {
return;
}
// Clear out the old markers.
markers.forEach(function(marker) {
marker.setMap(null);
});
markers = [];
// For each place, get the icon, name and location.
var bounds = new google.maps.LatLngBounds();
places.forEach(function(place) {
var icon = {
url: place.icon,
size: new google.maps.Size(71, 71),
origin: new google.maps.Point(0, 0),
anchor: new google.maps.Point(17, 34),
scaledSize: new google.maps.Size(25, 25)
};
// Create a marker for each place.
markers.push(new google.maps.Marker({
map: map,
icon: icon,
title: place.name,
position: place.geometry.location
}));
if (place.geometry.viewport) {
// Only geocodes have viewport.
bounds.union(place.geometry.viewport);
} else {
bounds.extend(place.geometry.location);
}
});
map.fitBounds(bounds);
});
// [END region_getplaces]
var map;
var infowindow;
mapLayer.setMap(map);
google.maps.event.addListener(mapLayer, 'click', function(kmlEvent) {
var text = kmlEvent.featureData.infoWindowHtml;
text = text + '<br>Navigate to Here';
if (infowindow) { infowindow.setContent(text);
} else {
infowindow = new google.maps.InfoWindow({content: text});
}
infowindow.setOptions({position:kmlEvent.latLng, pixelOffset:kmlEvent.pixelOffset});
infowindow.open(map);
});
}
google.maps.event.addDomListener(window, 'load', initialize);
}
</script>
<script src="https://maps.googleapis.com/maps/api/js?key=[MY-KEY]&libraries=places&callback=initAutocomplete"
async defer></script>
</body>
</html>
remove the final } in the javascript, it generates a syntax error: Uncaught SyntaxError: Unexpected token }.
change suppressInfoWindows: false to suppressInfoWindows: true (removes the extraneous second copy of the infowindow).
code snippet:
// This example adds a search box to a map, using the Google Place Autocomplete
// feature. People can enter geographical searches. The search box will return a
// pick list containing a mix of places and predicted search terms.
function initAutocomplete() {
var map = new google.maps.Map(document.getElementById('map-canvas'), {
center: {
lat: 53.6292604,
lng: -2.9380916
},
zoom: 5,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
var mapLayer = new google.maps.KmlLayer({
url: "https://www.google.com/maps/d/kml?mid=zQWA66D2AmlU.kGvUUZ4wvdYo",
suppressInfoWindows: true,
preserveViewport: true
});
mapLayer.setMap(map);
// Create the search box and link it to the UI element.
var input = document.getElementById('pac-input');
var searchBox = new google.maps.places.SearchBox(input);
map.controls[google.maps.ControlPosition.TOP_LEFT].push(input);
// Bias the SearchBox results towards current map's viewport.
map.addListener('bounds_changed', function() {
searchBox.setBounds(map.getBounds());
});
var markers = [];
// [START region_getplaces] this was the first to cause problems
// Listen for the event fired when the user selects a prediction and retrieve
// more details for that place.
searchBox.addListener('places_changed', function() {
var places = searchBox.getPlaces();
if (places.length == 0) {
return;
}
// Clear out the old markers.
markers.forEach(function(marker) {
marker.setMap(null);
});
markers = [];
// For each place, get the icon, name and location.
var bounds = new google.maps.LatLngBounds();
places.forEach(function(place) {
var icon = {
url: place.icon,
size: new google.maps.Size(71, 71),
origin: new google.maps.Point(0, 0),
anchor: new google.maps.Point(17, 34),
scaledSize: new google.maps.Size(25, 25)
};
// Create a marker for each place.
markers.push(new google.maps.Marker({
map: map,
icon: icon,
title: place.name,
position: place.geometry.location
}));
if (place.geometry.viewport) {
// Only geocodes have viewport.
bounds.union(place.geometry.viewport);
} else {
bounds.extend(place.geometry.location);
}
});
map.fitBounds(bounds);
});
// [END region_getplaces]
var map;
var infowindow;
mapLayer.setMap(map);
google.maps.event.addListener(mapLayer, 'click', function(kmlEvent) {
var text = kmlEvent.featureData.infoWindowHtml;
text = text + '<br>Navigate to Here';
if (infowindow && infowindow.setContent) {
infowindow.setContent(text);
} else {
infowindow = new google.maps.InfoWindow({
content: text
});
}
infowindow.setOptions({
position: kmlEvent.latLng,
pixelOffset: kmlEvent.pixelOffset
});
infowindow.open(map);
});
}
google.maps.event.addDomListener(window, 'load', initAutocomplete);
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
#map-canvas {
height: 100%;
}
.controls {
margin-top: 10px;
border: 1px solid transparent;
border-radius: 2px 0 0 2px;
box-sizing: border-box;
-moz-box-sizing: border-box;
height: 32px;
outline: none;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
}
#pac-input {
background-color: #fff;
font-family: Roboto;
font-size: 15px;
font-weight: 300;
margin-left: 12px;
padding: 0 11px 0 13px;
text-overflow: ellipsis;
width: 300px;
}
#pac-input:focus {
border-color: #4d90fe;
}
.pac-container {
font-family: Roboto;
}
#type-selector {
color: #fff;
background-color: #4d90fe;
padding: 5px 11px 0px 11px;
}
#type-selector label {
font-family: Roboto;
font-size: 13px;
font-weight: 300;
}
</style> <title>Places Searchbox</title> <style> #target {
width: 345px;
}
<script src="https://maps.googleapis.com/maps/api/js?libraries=places"></script>
<input id="pac-input" class="controls" type="text" placeholder="Search Box">
<div id="map-canvas"></div>
I am trying to render an html+js page in nodejs using jade. I used the online available html to jade converters to convert my html to jade and then render it from my nodejs app. However, I am not able to render the jade properly.
The example that I used is the one provided by google in their documentation for google maps API
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Marker animations with google</title>
<style>
html, body, #map-canvas {
height: 100%;
margin: 0px;
padding: 0px
}
#panel {
position: absolute;
top: 5px;
left: 50%;
margin-left: -180px;
z-index: 5;
background-color: #fff;
padding: 5px;
border: 1px solid #999;
}
</style>
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp"></script>
<script>
var berlin = new google.maps.LatLng(52.520816, 13.410186);
var neighborhoods = [
new google.maps.LatLng(52.511467, 13.447179),
new google.maps.LatLng(52.549061, 13.422975),
new google.maps.LatLng(52.497622, 13.396110),
new google.maps.LatLng(52.517683, 13.394393)
];
var markers = [];
var iterator = 0;
var map;
function initialize() {
var mapOptions = {
zoom: 12,
center: berlin
};
map = new google.maps.Map(document.getElementById('map-canvas'),
mapOptions);
}
function drop() {
for (var i = 0; i < neighborhoods.length; i++) {
setTimeout(function() {
addMarker();
}, i * 200);
}
}
function addMarker() {
markers.push(new google.maps.Marker({
position: neighborhoods[iterator],
map: map,
draggable: false,
animation: google.maps.Animation.DROP
}));
iterator++;
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
</head>
<body>
<div id="panel" style="margin-left: -52px">
<button id="drop" onclick="drop()">Drop Markers</button>
</div>
<div id="map-canvas"></div>
</body>
</html>
I tried many converters to convert but each of them gave me one or the other error. The http://html2jade.vida.io/ was able to convert it into jade.
I saved the file as maps_marker.jade in my views directory and from one of my APIs in web.js I made a call "res.render('maps_marker',{})" to render this page.
However the page rendered the following html as text
<!DOCTYPE html><html><head><meta charset="utf-8"><title>Marker animations with google</title><style><html>, body, #map-canvas {height: 100%;margin: 0px;padding: 0px}</html><div id="panel">{position: absolute;top: 5px;left: 50%;margin-left: -180px;z-index: 5;background-color: #fff;padding: 5px;border: 1px solid #999;}</div></style><script src="https://maps.googleapis.com/maps/api/js?v=3.exp"></script><script><var>berlin = new google.maps.LatLng(52.520816, 13.410186);</var><var>neighborhoods = [</var><new>google.maps.LatLng(52.511467, 13.447179),</new><new>google.maps.LatLng(52.549061, 13.422975),</new><new>google.maps.LatLng(52.497622, 13.396110),</new><new>google.maps.LatLng(52.517683, 13.394393)</new>];<var>markers = [];</var><var>iterator = 0;</var><var>map;</var><function>initialize() {</function><var>mapOptions = {zoom: 12,center: berlin};</var><map>= new google.maps.Map(document.getElementById('map-canvas'),mapOptions);}</map><function>drop() {for (var i = 0; i < neighborhoods.length; i++) {setTimeout(function() {addMarker();}, i * 200);}}</function><function>addMarker() {markers.push(new google.maps.Marker({position: neighborhoods[iterator],map: map,draggable: false,animation: google.maps.Animation.DROP}));iterator++;}</function><google window load initialize class="maps event addDomListener"></google></script></head><body><div id="panel" style="margin-left: -52px"><button id="drop" onclick="drop()">Drop Markers</button></div><div id="map-canvas"></div></body></html>
Can someone help me understand how to render such html+js in node.js.
I am currently try to use the jade template engine, but am open to using any other template engine as well.
UPdated to add snippet from my web.js and input from
I have an index.html(in public folder) with the following form within it
<form id="searchForm" action="/submit_search" method="POST" enctype="multipart/form-data">
<input name="latitude" type="text" id="latitude"/>
<input name="longitude" type="text" id="longitude"/>
<input type="submit" value="Submit" onclick="submitForm()">
</form>
In my javascript - I submit the form.
IN my web.js I have the following snippet for submit_search API
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.post('/submit_search', function(req,res){
console.log(JSON.stringify(req.body));
pg.connect(database_url, function(err, pgclient, done){
if(err)
{
console.log("Error in fetching pgclient from pool");
res.send(500, "Load the error connection page");
}
else if(pgclient != null)
{
console.log("Got an instance of pgclient");
generateDataForMap(req, res, pgclient, done);
}
});
});
And then I have defined my generateDataForMap method
var generateDataForMap = function(req, res, pgclient, done){
... some processing.....
..... create the required json.....
res.render('maps_marker',json);
}
I have put the maps_marker.jade file in the views folder..
The jade file produced by http://html2jade.vida.io/ is not valid. To fix it, you need to add a . (dot char) after the style and script tags to turn them in to style. and script. respectively.
doctype html
html
head
meta(charset="utf-8")
title Marker animations with google
style.
html, body, #map-canvas {
height: 100%;
margin: 0px;
padding: 0px
}
#panel {
position: absolute;
top: 5px;
left: 50%;
margin-left: -180px;
z-index: 5;
background-color: #fff;
padding: 5px;
border: 1px solid #999;
}
script(src="https://maps.googleapis.com/maps/api/js?v=3.exp")
script.
var berlin = new google.maps.LatLng(52.520816, 13.410186);
var neighborhoods = [
new google.maps.LatLng(52.511467, 13.447179),
new google.maps.LatLng(52.549061, 13.422975),
new google.maps.LatLng(52.497622, 13.396110),
new google.maps.LatLng(52.517683, 13.394393)
];
var markers = [];
var iterator = 0;
var map;
function initialize() {
var mapOptions = {
zoom: 12,
center: berlin
};
map = new google.maps.Map(document.getElementById('map-canvas'),
mapOptions);
}
function drop() {
for (var i = 0; i < neighborhoods.length; i++) {
setTimeout(function() {
addMarker();
}, i * 200);
}
}
function addMarker() {
markers.push(new google.maps.Marker({
position: neighborhoods[iterator],
map: map,
draggable: false,
animation: google.maps.Animation.DROP
}));
iterator++;
}
google.maps.event.addDomListener(window, 'load', initialize);
body
#panel(style="margin-left: -52px")
button#drop(onclick="drop()") Drop Markers
#map-canvas
I've been searching for a way to do this effect: http://www.discovershadow.com/
Especially the iPhone reveal part at the bottom where the iPhone stays but the content inside changes at the same time as the background.
Can this be achieved with only css or is it something much more complicated?
This is the way that I found to do this... no one seemed interested in the question but I hope you like the answer:
<html>
<head>
<style>
html, body {
min-height: 100%;
margin: 0;
padding: 0;
}
#container {
height: 100%;
width: 100%;
overflow-y: scroll;
position: fixed;
}
.items {
width: 100%;
height: 102%;
background-attachment: fixed;
background-position: 50%;
background-repeat: no-repeat;
position: relative;
}
#box1 {
background-image: url(yourimage1.png);
background-color: #03F;
}
#box2 {
background-image: url(yourimage2.png);
background-color: #609;
}
#box3 {
background-image: url(yourimage3.png);
background-color: #3C0;
}
</style>
</head>
<body>
<div id="container">
<div class="items" id="box1"></div>
<div class="items" id="box2"></div>
<div class="items" id="box3"></div>
</div>
</body>
</html>
Yes can achieve that... You have not added any code or not even tried i think. Here is simple code for you to get you started.
.a
{
background-image : url('http://hdwallpaper2013.com/wp-content/uploads/2013/02/Beautiful-Nature-Images-HD-Wallpaper.jpg');
height: 200px;
width: 100%;
position: fixed;
}
p
{
color : #000;
font-size: 72px;
position: relative;
z-index: 999;
}
fiddle
This effect does require CSS + Javascript, there is no way to do it effectively without using these technologies. You could have the iPhone centred on screen and the rest of the screen move around it but it wouldn't create such as nice effect as seen on the website.
I would personally recommend looking at the source of the target website and investigate yourself how it was achieved, never hurts to have a sneek peek at source from other websites.
Looking at that sites script.js page they handle scrolling with
// handle scrolling
$window.scroll(function() {
handleScroll();
});
Which does this. You will need to look at the full code to work out exactly how its done.
// handle scroll
function handleScroll() {
scrolledWin = getPageScroll();
$body.addClass('scrolling');
// show logo
if((scrolledWin * 1.5) > winH) {
$body.addClass('content');
}
// show navigation
if(scrolledWin > 50) {
$body.addClass('scrolled');
}
// app img animation
if(topOff >= scrolledWin) {
$appImg.removeClass('sticky');
} else {
$appImg.addClass('sticky');
}
if(topOff2 >= scrolledWin) {
$appImg2.removeClass('sticky');
} else {
$appImg2.addClass('sticky');
}
// fix navigation issue on top scroll
if ((scrolledWin > -(winH - (winH * (f1 *0.8)))) && $('#hook2').hasClass('inViewport')) {
$nav.attr("class", "").addClass('a2');
} else if ($('#hook2').hasClass('inViewport')) {
$nav.attr("class", "").addClass('a1');
}
//fix navigation issue between how it works and next section
if ($s9.hasClass('inViewport')) {
if ($('#hook5').hasClass('inViewport')) {
$nav.attr("class", "").addClass('a5');
} else {
$nav.attr("class", "").addClass('a4');
}
}
//fix navigation issue between Experts and next section
if ($sExperts.hasClass('inViewport')) {
if ($('#hook6').hasClass('inViewport')) {
$nav.attr("class", "").addClass('a6');
} else {
$nav.attr("class", "").addClass('a5');
}
}
}
Ref: http://www.discovershadow.com/js/script.js?v=2.14