How to send data from a chrome extension to a react app - reactjs

I am very new to chrome extensions and react. An overview of what I am doing is pretty straight forward. I have a chrome extension which takes a screenshot of the activeTab and I want to send that screenshot from the extension to my react app.
From what I understand, I need to dispatch an event from the extension and have the react app listen to it. I have an event listener in the index.html of my react app to listen to events that are dispatched by the extension. I have been unsuccessful in my attempts.
Here's what I have so far:
Chrome extension
popup.js
let tabImage = document.getElementById('tabImage');
let capturedImage = null;
tabImage.onclick = () => {
chrome.tabs.captureVisibleTab(null, (image) => {
document.dispatchEvent(new CustomEvent('csEvent', { data: image })) // send image to react app
viewScreenshot(image);
});
}
//Create a new window in the browser with the captured image
viewScreenshot = (capturedImage) => {
const b64 = capturedImage;
const contentType = 'image/jpeg';
const byteCharacters = atob(b64.substr(`data:${contentType};base64,`.length));
const byteArrays = [];
for (let offset = 0; offset < byteCharacters.length; offset += 1024) {
const slice = byteCharacters.slice(offset, offset + 1024);
const byteNumbers = new Array(slice.length);
for (let i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
const byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
const blob = new Blob(byteArrays, { type: contentType });
const blobUrl = URL.createObjectURL(blob);
window.open(blobUrl, '_blank');
}
popup.html
<html lang="en">
<head>
</head>
<body>
<button id="tabImage">Get a screenshot!</button>
<script src='popup.js'></script>
</body>
</html>
reactJS app
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Shots</title>
</head>
<body>
<iframe id="qa_films" src="./demo_course_classic_player_html5-flash-AMP/story.html"
style="position:absolute ;top:0; left:0; bottom:0; right:0; width:100%; height:90%; border:none; margin:0 auto; padding:0; z-index: 0; overflow:hidden; "></iframe>
<div id="screenshot"></div>
</body>
<script>
document.body.addEventListener('csEvent', (event) => {
console.log(event);
})
</script>
</html>
I would like to know which part I am doing it wrong or is there a better way of implementing what I'm trying to achieve. Any help is appreciated. Thanks!

Related

Half Solid Gauge Chart with trends

do you have a type of "half gauge", that show the trends on top of it?like in this picture:enter image description here
For business purpose, so we are open to buy the licence
Yes, you can create the required chart with AnyChart library. We have prepared a similar sample, you can check it below.
For purchasing AnyChart, please, contact us by email - sales#anychart.com
var data = [45, 67, 56];
var axisMaximum = 100;
data.push(axisMaximum);
var dataSet = anychart.data.set(data);
anychart.onDocumentReady(function () {
var stage = anychart.graphics.create("container");
var circularGauge = anychart.gauges.circular();
circularGauge.data(dataSet);
circularGauge.fill('#fff')
.stroke(null)
.padding(0)
.startAngle(270)
.sweepAngle(180);
var circularAxis = circularGauge.axis().radius(100).width(1).fill(null);
circularAxis.scale()
.minimum(0)
.maximum(axisMaximum);
circularAxis.labels().enabled(false);
circularAxis.ticks().enabled(false);
circularAxis.minorTicks().enabled(false);
circularGauge.bar(0).dataIndex(0)
.radius(100)
.width(15)
.fill('red')
.stroke(null)
.zIndex(5);
circularGauge.bar(1).dataIndex(3)
.radius(100)
.width(15)
.fill('#cecece')
.stroke(null)
.zIndex(3);
// marker
circularGauge.marker(0)
.axisIndex(0)
.dataIndex(1)
.size(7)
.stroke(null)
.fill('blue')
.type("triangle-down")
.position("outside")
.radius(108);
// marker
circularGauge.marker(1)
.axisIndex(0)
.dataIndex(2)
.size(7)
.stroke(null)
.fill('green')
.type("triangle-down")
.position("outside")
.radius(108);
var circularLabel0 = circularGauge.label(0);
circularLabel0
.enabled(true)
.anchor('center-bottom')
.useHtml(true)
.hAlign("center")
.text("<p style='color:red; font-size:20'>30 %</p><br>" +
"<p style='color:black; font-size:20; text-decoration:overline;'>% of Gross sales</p>");
var circularLabel1 = circularGauge.label(1);
circularLabel1
.enabled(true)
.anchor('center-top')
.padding(15)
.fontSize(20)
.fontColor('black')
.text('Product 1.1');
var circularTitle = circularGauge.title();
circularTitle.enabled(true)
.text('Division 1')
.fontColor('black')
.fontSize(25);
circularGauge.container(stage).draw();
});
html, body, #container {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
<link href="https://cdn.anychart.com/releases/8.2.1/fonts/css/anychart-font.min.css" rel="stylesheet"/>
<link href="https://cdn.anychart.com/releases/8.2.1/css/anychart-ui.min.css" rel="stylesheet"/>
<script src="https://cdn.anychart.com/releases/8.2.1/js/anychart-base.min.js"></script>
<script src="https://cdn.anychart.com/releases/8.2.1/js/anychart-ui.min.js"></script>
<script src="https://cdn.anychart.com/releases/8.2.1/js/anychart-exports.min.js"></script>
<script src="https://cdn.anychart.com/releases/8.2.1/js/anychart-circular-gauge.min.js"></script>
<div id="container"></div>

Cannot recieve the values from JSON-string by angular.js

I have tried to implement some methods from a tutorial javasampleapproach.com/spring-framework/spring-boot/spring-jpa-postgresql-angularjs-example-spring-boot but it doesn't work for me.
When I hit the GET ALL CUSTOMERS-button nothing comes up. When I tried to add a testmessage with the json-text that I have requested from the RestController and just use #scope.allPersons.data the complete json-text come up but if I try to get the valuesin the json-responese it is either undefined or nothing comes up.
First of all, the RestController. I have tried with #RequestMapping(value="/findallresponse", produces = "application/json")and the default from the tutorial as showed in the code. The reason for making my own String Json is that if I responded with the Iteratable-object the response get recursive because of #ManyToMany-relation. And when I troubleshoot I left out the Hobbypart because that was the ManyToMany-relationship value.
#RequestMapping("/findallresponse")
public Response findAllResponse(){
ArrayList firstNameStr=new ArrayList<String>();
ArrayList lastNameStr=new ArrayList<String>();
ArrayList hobbyStr=new ArrayList<String>();
ArrayList idStr=new ArrayList<String>();
boolean startLoop=true;
String jsonPersonBeggining="{\"persons\":[";
String jsonPersonEnd="]}";
String jsonPerson="";
for(Person person : personService.findAll()){
if(startLoop==true)
{
startLoop=false;
}
else
{
jsonPerson+=",";
}
jsonPerson+="{";
jsonPerson+="\"firstName\":\""+person.getFirstName()+"\",";
jsonPerson+="\"lastName\":\""+person.getLastName()+"\",";
//jsonPerson+="\"hobby\":\""+person.getHobby()+"\",";
jsonPerson+="\"id\":\""+person.getId()+"\"";
jsonPerson+="}";
}
jsonPerson=jsonPersonBeggining+jsonPerson+jsonPersonEnd;
return new Response("Done",jsonPerson);
}
Here is the Response-class just as in the tutorial
public class Response {
private String status;
private Object data;
public Response() {
}
public Response(String status, String data) {
this.status = status;
this.data = data;
}
public String getStatus() {
return status;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public void setStatus(String status) {
this.status = status;
}
}
The javascript-file as in the tutorial. The #getResultMessage is to test that the json-string is recieved at all. And it is. But after that I can't access the post in it, for instance
firstName or
lastName
var app = angular.module('app', []);
app.controller('getallpersonsController', function($scope, $http, $location)
{
$scope.showAllPersons = false;
$scope.getAllPersons = function() {
var url = $location.absUrl() + "findallresponse";
var config = {
headers : {
'Content-Type' : 'application/json;charset=utf-8;'
}
}
$http.get(url, config).then(function(response) {
if (response.data.status == "Done") {
$scope.allpersons = response.data;
$scope.showAllPersons = true;
$scope.getResultMessage = $scope.allpersons.data;
} else {
$scope.getResultMessage = "get All Customers Data Error!";
}
}, function(response) {
$scope.getResultMessage = "Fail!";
});
}
});
This is the output on this is the #getResultMessage taken from #scope.allpersons.data
{"persons":[{"firstName":"Adam","lastName":"Johnson","id":"87"},{"firstName":"Anna","lastName":"Persson","id":"90"},{"firstName":"Nils","lastName":"Svensson","id":"93"}]}
And the jsp-file
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Spring Boot Example</title>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script
src="http://ajax.googleapis.com/ajax/libs/angularjs/1.6.0/angular.min.js">
</script>
<script src="/js/angular.js"></script>
<link rel="stylesheet"
href="http://netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css"
/>
</head>
<body>
<div class="container" ng-app="app">
<h1>AngularJS - Spring JPA - PostgreSQL</h1>
<div class="row">
<div ng-controller="getallpersonsController" class="col-md-3">
<h3>All Customers</h3>
<button ng-click="getAllPersons()">
Get All Customers
</button>
<div ng-show="showAllPersons">
<ul class="list-group">
<li ng-repeat="persons in allpersons.data">
<h4 class="list-group-item">
<strong>Customer {{$index}}</strong><br />
Id: {{persons.id}}<br />
First Name: {{persons.firstName}}<br />
Last Name: {{persons.lastName}}
</h4>
</li>
</ul>
</div>
<p>{{getResultMessage}}</p>
</div>
</div>
</div>
</body>
</html>
UPDATE!!
Here is some calls on the response if that can give any clue?
data=[object Object] status=200
statustext=undefined
headers=function (d){b||(b=od(a));return d?(d=b[L(d)],void 0===d&&(d=null),d):b} config=[object Object]
Can anyone see if I missed something? In the jsp-file the ng-repeatloop is not working, it doesn't seems to be able to get the value from the json? Thanks

Diffing two Observables

I'm looking for a best way to Diff two Observables.
Filtered values from ObservableA should be emited as soon as ObservableB completes without waiting for ObservableA to complete.
<html>
<head>
<title></title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.3.0/Rx.js"></script>
<script>
const observable_a = Rx.Observable.interval(2000).take(10);//0,1,2,3,4,5,6,7,8,9
const observable_b = Rx.Observable.interval(1000).map(x=>x+3).take(5);//3,4,5,6,7
someDiffObservable(observable_a,observable_b).subscribe(console.log);//should output 0,1,2,8,9
</script>
</head>
<body></body>
</html>
Try this:
const a$ = Rx.Observable.interval(2000).take(10).share();
const b$ = Rx.Observable.interval(1000).map(x=>x+3).take(5);
Rx.Observable.combineLatest(
a$.buffer(
b$.startWith(null).last().concat(a$)
),
b$.toArray(),
(aItems, bItems) => aItems.filter(a => !bItems.includes(a))
)
.concatMap(filteredItems => Rx.Observable.from(filteredItems))
.subscribe(console.log);
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.5.2/Rx.js"></script>
Currently i've came up with following function to diff two observables.
Is there a simpler/faster/better way to achieve this?
<html>
<head>
<title></title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.3.0/Rx.js"></script>
<script>
const observable_a = Rx.Observable.interval(2000).take(10);//0,1,2,3,4,5,6,7,8,9
const observable_b = Rx.Observable.interval(1000).map(x=>x+3).take(5);//3,4,5,6,7
function observableDiff(a,b,filter) {
if(!filter) {
filter = (value_to_check,blacklist_array)=>{
return blacklist_array.indexOf(value_to_check)===-1;
};
}
return Rx.Observable.create(observer=>{
let a_values = [];
let b_values = [];
let a_completed = false;
let b_completed = false;
a.forEach(a_value=>{
if(b_completed) {
if(filter(a_value,b_values)) {
observer.next(a_value);
}
} else {
a_values.push(a_value);
}
}).then(()=>{
a_completed = true;
if(b_completed) {
observer.complete();
}
});
b.forEach(b_value=>{
b_values.push(b_value);
}).then(()=>{
b_completed = true;
a_values.forEach(a_value=>{
if(filter(a_value,b_values)) {
observer.next(a_value);
}
});
a_values = [];
if(a_completed) {
observer.complete();
}
});
});
}
observableDiff(observable_a,observable_b).subscribe(console.log);//0,1,2,8,9
</script>
</head>
<body></body>
</html>

How to create autogenerate ID in angular?

Want to create autogenerate code in angular inputbox on refresh page
like rand(function) in php. Im using this script for this. But problem
is its vanished on page refresh not working properly.
<script type="text/javascript">
function randString(x){
var s = "OL-";
while(s.length<x&&x>0){
var r = Math.random();
s+= (r<0.1?Math.floor(r*100):String.fromCharCode(Math.floor(r*26) + (r>0.5?97:65)));
}
return s;
}
document.getElementById("referal_code").value = randString(10);
</script>
<input required type='text' class='span2' id='referal_code' ng-model='empInfo.referal_code'>
Try this
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
function getNewID() {
try {
var myDate = new Date();
var varID = myDate.getHours() + "" + myDate.getMinutes() + "" + myDate.getSeconds() + "" + myDate.getMilliseconds();
if (varID.Length > 15) {
varID = varID.substr(0, 15);
}
return varID;
} catch (e) {
console.log(e.message);
}
}
function randString(x){
var s = getNewID();
return s;
}
window.onload = function(){
document.getElementById("referal_code").value = randString(10);
}
</script>
</head>
<body>
<input required type='text' class='span2' id='referal_code' ng-model='empInfo.referal_code'>
</body>
</html>
For any attribute in angular world you can use interpolation like this:
<input id="{{randString(10)}}"/>
If you want to have a certain value as id and not get lost after refresh you have to save it on some web storage (localstorage, sessionstorage).
e.g. :
function randString(x){
// ... your function's logic
//Save it in localStorage before returning it
localStorage.inputId = s;
return s;
}
document.getElementById("referal_code").value = localStorage.inputId || randString(10)

Bing Map V8 Infobox Visible not working

Example from Bing map V8 official documentation. By default infobox is given false but inspite its displaying for the first time.
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8" />
<script type='text/javascript'
src='http://www.bing.com/api/maps/mapcontrol?callback=GetMap' async defer></script>
<script type="text/javascript">
var map, clusterLayer, infobox;
function GetMap() {
map = new Microsoft.Maps.Map('#myMap', {
credentials: 'Bing Map Key'
});
//Add an infobox to the map.
infobox = new Microsoft.Maps.Infobox(map.getCenter(), { visible: false });
infobox.setMap(map);
Microsoft.Maps.loadModule("Microsoft.Maps.Clustering", function () {
//Create a clustering layer
clusterLayer = new Microsoft.Maps.ClusterLayer(createCustomPushpins(100), {
clusteredPinCallback: createCustomClusterPushpins,
callback: createPushpinList
});
map.layers.insert(clusterLayer);
});
}
function createCustomPushpins(size) {
//Generate random pushpins within the map bounds.
var pins = Microsoft.Maps.TestDataGenerator.getPushpins(size, map.getBounds());
for (var i = 0; i < size; i++) {
//Create a title for each pushpin.
pins[i].setOptions({ title: 'Pushpin #' + i });
//Add handler for the pushpin click event.
Microsoft.Maps.Events.addHandler(pins[i], 'click', pushpinClicked);
}
return pins;
}
function createCustomClusterPushpins(cluster) {
//Create a title for the cluster.
cluster.setOptions({
title: 'Cluster of ' + cluster.containedPushpins.length + ' pins'
});
//Add handler for the cluster click event.
Microsoft.Maps.Events.addHandler(cluster, 'click', pushpinClicked);
}
function pushpinClicked(e) {
//Show an infobox when a pushpin is clicked.
showInfobox(e.target);
}
function createPushpinList() {
//Create a list of displayed pushpins each time clustering layer updates.
if (clusterLayer != null) {
infobox.setOptions({ visible: false });
//Get all pushpins that are currently displayed.
var data = clusterLayer.getDisplayedPushpins();
var output = [];
//Create a list of links for each pushpin that opens up the infobox for it.
for (var i = 0; i < data.length; i++) {
output.push("<a href='javascript:void(0);' onclick='showInfoboxByGridKey(", data[i].gridKey, ");'>");
output.push(data[i].getTitle(), "</a><br/>");
}
document.getElementById('listOfPins').innerHTML = output.join('');
}
}
function showInfoboxByGridKey(gridKey) {
//Look up the cluster or pushpin by gridKey.
var clusterPin = clusterLayer.getClusterPushpinByGridKey(gridKey);
//Show an infobox for the cluster or pushpin.
showInfobox(clusterPin);
}
function showInfobox(pin) {
var description = [];
//Check to see if the pushpin is a cluster.
if (pin.containedPushpins) {
//Create a list of all pushpins that are in the cluster.
description.push('<div style="max-height:75px;overflow-y:auto;"><ul>');
for (var i = 0; i < pin.containedPushpins.length; i++) {
description.push('<li>', pin.containedPushpins[i].getTitle(), '</li>');
}
description.push('</ul></div>');
}
//Display an infobox for the pushpin.
infobox.setOptions({
title: pin.getTitle(),
location: pin.getLocation(),
description: description.join(''),
visible: true
});
}
</script>
</head>
<body>
<div id="myMap" style="position:relative; width:600px; height:400px;"></div>
<br />
<div id="listOfPins" style="max-height:250px;width:250px;overflow-y:scroll;"></div>
</body>
</html>
As per official documentation, we have to pass visible false while instantiating the infobox object (infobox = new Microsoft.Maps.Infobox(map.getCenter(), { visible: false });) Any suggestions where I am going wrong?
Strange, just tried the code provided in IE11, Edge, Chrome and Firefox. It worked correctly in all browsers other than Chrome. Not sure why Chrome is acting differently. Will have the team look into this. Thanks for reporting.

Resources