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 ?
I have created a sample amp page with
<amp-list width=auto
height=100
layout=fixed-height
src="https://my-azurewebsite/Data/Services.json"
>
Its showing error as below :
o 'Access-Control-Allow-Origin' header is present on the requested resource.
If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
I enabled CORS using Azure portal. But still its not working. I can access the json via the browser directly.
Please have a try to import the amp-list and amp-mustache components in the header, more details please refer to document
The amp-list component fetches dynamic content from a CORS JSON endpoint and renders it using a supplied template.
<script async custom-template="amp-mustache" src="https://cdn.ampproject.org/v0/amp-mustache-0.1.js"></script>
<script async custom-element="amp-list" src="https://cdn.ampproject.org/v0/amp-list-0.1.js"></script>
I create a demo for this. The following is my detail steps:
1. Published a Web App with AMP page
2. Enable the CORS for the Web App in the Azure Portal.
3. Try to view the page from the browser
AMP page code:
<!doctype html>
<html ⚡>
<head>
<meta charset="utf-8">
<link rel="canonical" href="https://ampbyexample.com/components/amp-list/">
<meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">
<style amp-boilerplate>
body {
-webkit-animation: -amp-start 8s steps(1,end) 0s 1 normal both;
-moz-animation: -amp-start 8s steps(1,end) 0s 1 normal both;
-ms-animation: -amp-start 8s steps(1,end) 0s 1 normal both;
animation: -amp-start 8s steps(1,end) 0s 1 normal both;
}
#-webkit-keyframes -amp-start {
from {
visibility: hidden;
}
to {
visibility: visible;
}
}
#-moz-keyframes -amp-start {
from {
visibility: hidden;
}
to {
visibility: visible;
}
}
#-ms-keyframes -amp-start {
from {
visibility: hidden;
}
to {
visibility: visible;
}
}
#-o-keyframes -amp-start {
from {
visibility: hidden;
}
to {
visibility: visible;
}
}
#keyframes -amp-start {
from {
visibility: hidden;
}
to {
visibility: visible;
}
}
</style>
<noscript>
<style amp-boilerplate>
body {
-webkit-animation: none;
-moz-animation: none;
-ms-animation: none;
animation: none;
}
</style></noscript>
<style amp-custom>
amp-list {
margin-left: 16px;
}
.list-overflow {
position: absolute;
bottom: 0;
right: 0;
}
</style>
<script async src="https://cdn.ampproject.org/v0.js"></script>
<script async custom-template="amp-mustache" src="https://cdn.ampproject.org/v0/amp-mustache-0.1.js"></script>
<script async custom-element="amp-list" src="https://cdn.ampproject.org/v0/amp-list-0.1.js"></script>
</head>
<body>
<amp-list width=auto
height=100
layout=fixed-height
src="https://my.azurewebsites.net/test.json"
template="amp-template-id"
>
</amp-list>
<template id="amp-template-id" type="amp-mustache">
<div>
<p>FirstName : {{firstName}}</p>
</div>
</template>
</body>
</html>
test.json :
{
"items": [
{
"firstName": "tom",
"lastName": "test"
},
{
"firstName": "tom1",
"lastName": "test"
},
{
"firstName": "tom2",
"lastName": "test"
}
]
}
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'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
I am developing a chrome extension , i need to get selected text from any page to chrome extension.I am unable to get the output
I just want to take selected image or any text to extension
In console getting the following error
Uncaught IndexSizeError: Index or size was negative, or greater than the allowed value.
//script.js
var selection = window.getSelection();
var range = selection.getRangeAt(0); //Getting error in this line.window.getSelection() is always null
if (range) {
var div = document.createElement('div');
div.appendChild(range.cloneContents());
vs=div.innerHTML;
}
chrome.extension.sendRequest({viewsource: vs}, function(response) {
console.log(response.farewell);
});
chrome.tabs.executeScript(null, {file:"script.js"});
chrome.extension.onRequest.addListener(
function(request, sender, sendResponse) {
document.getElementById("txtar").innerText=request.viewsource;
});
//popup.html
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="script.js"></script>
<style>
body {
margin:0px;
padding:0px;
overflow:hidden;
background:pink;
}
#txtar {
height: 200px;
width: 300px;
max-width:780px;
max-height:560px;
min-width:300px;
min-height:200px;
padding:6px;
margin:0px;
background-color:white;
color:#000088;
border:none;
}
#boohle {
position:absolute;
bottom:0px;
left:0px;
font-size:10px;
font-family:Arial;
float:left;
background-color:white;
z-index:200;
font-weight:normal;
}
#boohle a {
color:#008800;
text-decoration:none;
}
#boohle a:hover {
color:#ff0000;
}
</style>
</head>
<body>
<textarea id="txtar" readonly></textarea>
</body>
</html>
//manifest.json
{
"name": "Selection",
"version": "1.0",
"browser_action": {
"default_icon": "img/19x19.png",
"default_title": "View Selection Source",
"default_popup": "popup.html"
},
"manifest_version": 2,
"description": "View selection source in resizable popup. Drag the bottom right corner to resize. Simple, but very useful for web developers.",
"icons": {
"128": "img/128x128.png",
"16": "img/16x16.png",
"19": "img/19x19.png",
"32": "img/32x32.png",
"48": "img/48x48.png"
}
}
Please help.