I'm receiving an error that says "puppeteer is not defined" when it is clearly in the only javaScript file.
How do i get the JavaScript/single page html project to recognize the puppeteer module? I have already looked into this potential answer;[Nodejs. Proper way to include modules, however it does not help.
(The goal is to launch the html page, enter a url from booking.com, click the button, and have the scraped hotel name, rating, etc returned in the console)
app.js
function main()
{
var Url = document.getElementById('inputUrl').value
const puppeteer = require('puppeteer');
let bookingUrl = Url;
(async () => {
const browser = await puppeteer.launch({ headless: true });
const page = await browser.newPage();
await page.goto(bookingUrl);
await page.waitForSelector('div.sr_property_block[data-hotelid]');
let hotelData = await page.evaluate(() => {
...
...
...
}
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<script src="app.js" type="text/javascript"></script>
<meta name="description" content="">
<link rel="stylesheet" href="">
</head>
<body>
<input id = "inputUrl" type="text" placeholder = "type url here"/>
<button id = "button" button onclick="main();"> click</button>
</body>
</html>
Puppeteer is a library that requires a server (like node.js), you can't run it on the client side.
Related
I have a html file and 2 JavaScript files: mainscript.js and script1.js. I inject the script1.js inside the mainscript.js. However, what happens is that by calling script1.js, the htmltags created by mainscript.js got removed. Any idea why this happens?
html code:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Linear Call</title>
</head>
<body>
<div id="main"><p>hi</p></div>
<script src="js/recursion_linear/MainScript.js">
</script>
</body>
</html>
mainscript.js:
const loadScript = async(url) => {
const response = await fetch(url)
const script = await response.text()
eval(script)
}
var s = document.createElement("span");
document.write("<br>");
s.innerText="This is main script";
s.id="mainscript";
document.body.append(s);
const scriptUrl_1 = "js/recursion_linear/Script1.js"
loadScript(scriptUrl_1)
script1.js:
document.write("<br>");
var s = document.createElement("span");
s.innerText="This is Script1";
s.id="script1";
document.body.append(s);
The output is
This is Script1
While the expected one is
This is main script
This is Script1
Basic HTML
<!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">
<title>Document</title>
</head>
<body>
<button class = "hitknop">Hit!</button>
</body>
<script src="index.js" defer></script>
</html>
My JS
const deckinit = "https://deckofcardsapi.com/api/deck/new/shuffle/?deck_count=1";
const hitknoppie = document.querySelector("hitknop");
let deckId;
async function deckophalen(){
const response = await fetch (deckinit);
const deckopties = await response.json();
deckId = deckopties.deck_id;
console.log(deckId);
}
deckophalen();
hitknoppie.onclick = async function (){
const kaartlink = `https://deckofcardsapi.com/api/deck/${deckId}/draw/?count=1`;
const response = await fetch (kaartlink);
const kaart = await response.json();
console.log(kaart);
}
I was expecting it to show the result of a single card, but it now just gives me the error that I cannot set properties of null setting 'onclick'.
I tried moving the script tag and adding defer to my Js document without success.
You must add . because you are calling a class. It must look like this:const hitknoppie = document.querySelector(".hitknop");
I am using a basic html/javascript script where I load a webcam component.
<html>
<head>
<!-- Load the latest version of TensorFlow.js -->
<script src="https://cdn.jsdelivr.net/npm/#tensorflow/tfjs"></script>
<script src="https://cdn.jsdelivr.net/npm/#tensorflow-models/mobilenet"></script>
</head>
<body>
<div id="console"></div>
<!-- Add an image that we will use to test -->
<video autoplay playsinline muted id="webcam" width="224" height="224"></video>
<!-- Load index.js after the content of the page -->
<script src="index.js"></script>
</body>
</html>
const webcamElement = document.getElementById('webcam');
async function app() {
console.log('Loading mobilenet..');
// Load the model.
net = await mobilenet.load();
console.log('Successfully loaded model');
const webcam = await tf.data.webcam(webcamElement);
while (true) {
const img = await webcam.capture();
const result = await net.classify(img);
document.getElementById('console').innerText = `
prediction: ${result[0].className}\n
probability: ${result[0].probability}
`;
img.dispose();
await tf.nextFrame();
}
}
This seems to be the correct way to load a webcam as per other answers. However, nothing opens for me. No console logs as well. I am trying this on Firefox.
First of all, simply include the script webcam-easy.min.js in the section of the html file.
and try instead of that js, you will get the web cam output
I am trying to import https://github.com/tkurki/dnssd.js and make html file like this:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1">
<script src="/index.js"></script>
</head>
<body>
<section>
<h1>DNS-SD Browser</h1>
<div id="services"></div>
</section>
<script>
const dnssd = require('dnssd2');
// advertise a http server on port 4321
const ad = new dnssd2.Advertisement(dnssd.tcp('http'), 4321);
ad.start();
// find all chromecasts
const browser = dnssd2.Browser(dnssd.tcp('_http'))
.on('serviceUp', service => console.log("Device up: ", service))
.on('serviceDown', service => console.log("Device down: ", service))
.start();
</script>
</body>
</html>
But somehow it shows me error in console log:
Uncaught ReferenceError: require is not defined at index.js:1
Uncaught ReferenceError: require is not defined at index.js:18
What am I doing wrong please?
index.js contains:
var Advertisement = require('./lib/Advertisement');
var Browser = require('./lib/Browser');
var ServiceType = require('./lib/ServiceType');
var validate = require('./lib/validate');
var resolve = require('./lib/resolve');
var NetworkInterface = require('./lib/NetworkInterface');
module.exports = {
Advertisement: Advertisement,
Browser: Browser,
ServiceType: ServiceType,
tcp: ServiceType.tcp,
udp: ServiceType.udp,
all: ServiceType.all,
validate: validate,
resolve: resolve.resolve,
resolveA: resolve.resolveA,
resolveAAAA: resolve.resolveAAAA,
resolveSRV: resolve.resolveSRV,
resolveTXT: resolve.resolveTXT,
resolveService: resolve.resolveService,
};
The browser doesn't support require function
Use requirejs. You can also use it with jquery
You can learn about requirejs from here
Browser doesn't support require out-of-box. try adding this script tag to manually import require from its cdn.
<script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.6/require.js"></script>
<script src="/index.js"></script>
I want to test the new Firefox Storage Access API to allow 1st party storage (cookie, local storage, indexeddb, ...) to an iframe of a different domain (but still under my control).
Parent Markup / code
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Parent Domain</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/js-cookie/2.2.0/js.cookie.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jschannel/1.0.0-git-commit1-8c4f7eb/jschannel.min.js"></script>
</head>
<body>
<div>
Cookies: <ul class="cookie-data"></ul>
</div>
<iframe
id="rpc-gateway"
src="http://child.local:8080/iframe-firefox.html"
sandbox="allow-storage-access-by-user-activation allow-scripts allow-same-origin"></iframe>
<script type="text/javascript">
var chan = Channel.build({
window: document.getElementById("rpc-gateway").contentWindow,
origin: "*",
scope: "testScope"
});
</script>
</body>
</html>
Child Iframe Markup / code
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Child Domain</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/js-cookie/2.2.0/js.cookie.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jschannel/1.0.0-git-commit1-8c4f7eb/jschannel.min.js"></script>
</head>
<body>
<button onClick="onLoginClick()">Login</button>
<script type="text/javascript">
var chan = Channel.build({
window: window.parent,
origin: "*",
scope: "testScope"
});
let onLoginClick = function(trans, params) {
document.hasStorageAccess().then(hasAccess => {
if (!hasAccess) {
console.log("no access - requesting access");
return document.requestStorageAccess();
}
}).then(_ => {
document.hasStorageAccess().then(hasAccess => {
console.log("hasAccess:", hasAccess);
window.localStorage.setItem('foo', 'bar');
})
}).catch((err) => {
console.log("hasStorageAccess() failed", err);
});
};
</script>
</body>
</html>
When clicking on the "Login" button from the Child Iframe, the following log output is generated:
no access - requesting access # iframe-firefox.html:22:25
hasAccess: true # iframe-firefox.html:27:25
Request to access cookie or storage on “http://child.local:8080/iframe-firefox.html” was blocked because we are blocking all third-party storage access requests and content blocking is enabled. # iframe-firefox.html:28:24
The visible conclusion is:
The promise document.hasStorageAccess() resolves
The hasAccess parameter is initially 'false'
The promise of document.requestStorageAccess() is returned and resolves
The 2nd promise document.hasStorageAccess() resolves
The hasAccess parameter is now 'true'
nevertheless, simple storage access to local storage is not possible.
What do I do wrong?
More Info's:
Firefox Developer Edition Version 65.0b9
Content Blocking Setting:
This seems to be a bug in the version of Firefox you're using. I set up a test locally of what you have and in Firefox 69.0.1 (64 bit), I get no error and the value is stored to local storage. When I took the sandbox flag allow-storage-access-by-user-activation out of the parent iframe, the child failed to get permission for local storage, so that confirms that my setup was actually working properly. Here's what I did:
Created a Node.js/Express server for the parent:
const express = require('express');
const cors = require('cors');
const path = require('path');
const server = express();
server.use(cors());
server.use(express.static(path.resolve('./public')));
server.listen(8080, function() {
console.log('listening on *:8080');
});
Created a Node.js/Express server for the child (with different port to trigger same origin policy):
const express = require('express');
const cors = require('cors');
const path = require('path');
const server = express();
server.use(cors());
server.use(express.static(path.resolve('./public')));
server.listen(8081, function() {
console.log('listening on *:8081');
});
Created an index.html for the parent (pretty much the same as yours):
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Parent Domain</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/js-cookie/2.2.0/js.cookie.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jschannel/1.0.0-git-commit1-8c4f7eb/jschannel.min.js"></script>
</head>
<body>
<div>
Cookies: <ul class="cookie-data"></ul>
</div>
<iframe
id="rpc-gateway"
src="http://127.0.0.1:8081/iframe-firefox.html"
sandbox="allow-storage-access-by-user-activation allow-scripts allow-same-origin"></iframe>
<script type="text/javascript">
var chan = Channel.build({
window: document.getElementById("rpc-gateway").contentWindow,
origin: "*",
scope: "testScope"
});
// Added this to try out the JSChannel
chan.call({
method: "reverse",
params: "hello world!",
success: function(v) {
console.log(v);
}
});
</script>
</body>
</html>
And created iframe-firefox.html for the child:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Child Domain</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/js-cookie/2.2.0/js.cookie.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jschannel/1.0.0-git-commit1-8c4f7eb/jschannel.min.js"></script>
</head>
<body>
<button onClick="onLoginClick()">Login</button>
<script type="text/javascript">
var chan = Channel.build({
window: window.parent,
origin: "*",
scope: "testScope"
});
// Other end of the JSChannel call
chan.bind("reverse", function(trans, s) {
return s.split("").reverse().join("");
});
let onLoginClick = function(trans, params) {
document.hasStorageAccess().then(hasAccess => {
if (!hasAccess) {
console.log("no access - requesting access");
return document.requestStorageAccess();
}
}).then(_ => {
document.hasStorageAccess().then(hasAccess => {
console.log("hasAccess:", hasAccess);
window.localStorage.setItem('foo', 'bar');
})
}).catch((err) => {
console.log("hasStorageAccess() failed", err);
});
};
</script>
</body>
</html>
And everything worked as expected... So I'm feeling pretty sure that the issue is with the specific version of Firefox Developer Edition that you're using.
Also, here's a link to a zip of my setup if you want to give it a try on your end and see if this works differently than what you have: server.zip
Let me know if there's anything else I can do to help.