Can't access javascript function from python through eel - javascript

I've been trying to learn the basics of Eel through their documentation. I struggled learning how to trigger a javascript function through python so I tried to download their Hello World example straight from their github. You can open it here.
But I still get the same error, namely: Exception has occurred: AttributeError
module 'eel' has no attribute 'say_hello_js'
The code is as following: (you can also look it up on github in the link abov)
hello.py
import eel
# Set web files folder
eel.init('web')
#eel.expose # Expose this function to Javascript
def say_hello_py(x):
print('Hello from %s' % x)
say_hello_py('Python World!')
eel.say_hello_js('Python World!') # Call a Javascript function
eel.start('hello.html', size=(300, 200)) # Start
web/index.html
<!DOCTYPE html>
<html>
<head>
<title>Hello, World!</title>
<!-- Include eel.js - note this file doesn't exist in the 'web' directory -->
<script type="text/javascript" src="/eel.js"></script>
<script type="text/javascript">
eel.expose(say_hello_js); // Expose this function to Python
function say_hello_js(x) {
console.log("Hello from " + x);
}
say_hello_js("Javascript World!");
eel.say_hello_py("Javascript World!"); // Call a Python function
</script>
</head>
<body>
Hello, World!
</body>
</html>
Could it be that I have a wrong version of python or Eel? I am running Python 3.8.10. I ran pip install eel --upgrade but the issue still occurs.

I cannot pin point the exact issue based on the details you provided. But you can try the following these steps if you're using VSC:
Run this command py -m venv .venv and it will create your virtual environment.
Select the virtual environment's Python interpreter with CTRL + SHIFT + K.
Close out your terminal with the trash icon.
Start the terminal using the virtual environment's Python interpreter with CTRL + J.
Run the command pip install eel.
Create the file hello.py.
Create the directory web.
In web create the file hello.html.
In hello.py use this code:
import eel
eel.init('web')
eel.say_hello_js('Hi from Python')
eel.start('hello.html')
In hello.html use this code:
<!DOCTYPE html>
<html>
<head>
<title>Hello, World!</title>
<!-- Include eel.js - note this file doesn't exist in the 'web' directory -->
<script type="text/javascript" src="/eel.js"></script>
<script type="text/javascript">
eel.expose(say_hello_js); // Expose this function to Python
function say_hello_js(x) {
alert("Hello from " + x);
}
</script>
</head>
<body>
Hello, World!
</body>
</html>
If you followed these steps, you should see the alert box pop up. To trigger a JS function from Python you need to precede the function with the eel expose function like this eel.expose(your_js_function_name);. From Python you would call this function using the eel module and calling that function name like this eel.your_js_function_name(parameter_if_any). Make sure that in your HTML file you have the eel script element in the head. Then another script element after that one with all your functions.

Related

CertStream Javascript gives error "Uncaught ReferenceError: require is not defined"

I'm setting up a HTML page that want to use the data from CertStream.
The Javascript library is located at https://github.com/CaliDog/certstream-js
In the install instructions it says " if you're using this in the browser, just add dist/certstream.min.js to a tag, and interact with it as normal!".
I have therefor created a HTML page that uses this tag:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Certstream</title>
<meta name="viewport" content="width=device-width; initial-scale=1.0;"/>
<meta http-equiv="Content-Type" content="text/html; charset=UFT-8" />
</head>
<body>
<h1>CertStream</h1>
<!-- CertStream script -->
<script src="dist/certstream.min.js"></script>
<script>
const CertStreamClient = require('certstream');
let client = new CertStreamClient(function(message){
console.log("Received -> ", message)
});
client.connect();
</script>
<!-- //CertStream script -->
</body>
</html>
But I get the error:
Uncaught ReferenceError: require is not defined
http://localhost/certstream-js/test.html:15
certstream.min.js is located on in the folder "dist":
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.CertStream=t():e.CertStream=t()}(this,function(){return function(e){function t(o){if(n[o])return n[o].exports;var c=n[o]={exports:{},id:o,loaded:!1};return e[o].call(c.exports,c,c.exports,t),c.loaded=!0,c.exports}var n={};return t.m=e,t.c=n,t.p="",t(0)}([function(e,t,n){"use strict";function o(e){return e&&e.__esModule?e:{default:e}}function c(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(t,"__esModule",{value:!0});var r=function(){function e(e,t){for(var n=0;n<t.length;n++){var o=t[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(e,o.key,o)}}return function(t,n,o){return n&&e(t.prototype,n),o&&e(t,o),t}}(),i=n(1),s=o(i),a=function(){function e(t){var n=arguments.length>1&&void 0!==arguments[1]&&arguments[1];c(this,e),this.context={},this.callback=t,this.skipHeartbeats=n}return r(e,[{key:"connect",value:function(){var e=this;console.log("Connecting..."),this.ws=new s.default("wss://certstream.calidog.io/"),console.log("Created ws -> ",this.ws),this.ws.onmessage=function(t){console.log("onmessage called!");var n=JSON.parse(t.data);"heartbeat"===n.message_type&&e.skipHeartbeats||e.callback(t,e.context)},this.ws.onopen=function(){console.log("Connection established to certstream! Waiting for messages...")},this.ws.open()}}]),e}();t.default=a},function(e,t,n){var o,c,r;!function(n,i){c=[],o=i,r="function"==typeof o?o.apply(t,c):o,!(void 0!==r&&(e.exports=r))}(this,function(){function e(t,n,o){function c(e,t){var n=document.createEvent("CustomEvent");return n.initCustomEvent(e,!1,!1,t),n}var r={debug:!1,automaticOpen:!0,reconnectInterval:1e3,maxReconnectInterval:3e4,reconnectDecay:1.5,timeoutInterval:2e3,maxReconnectAttempts:null};o||(o={});for(var i in r)"undefined"!=typeof o[i]?this[i]=o[i]:this[i]=r[i];this.url=t,this.reconnectAttempts=0,this.readyState=WebSocket.CONNECTING,this.protocol=null;var s,a=this,u=!1,l=!1,d=document.createElement("div");d.addEventListener("open",function(e){a.onopen(e)}),d.addEventListener("close",function(e){a.onclose(e)}),d.addEventListener("connecting",function(e){a.onconnecting(e)}),d.addEventListener("message",function(e){a.onmessage(e)}),d.addEventListener("error",function(e){a.onerror(e)}),this.addEventListener=d.addEventListener.bind(d),this.removeEventListener=d.removeEventListener.bind(d),this.dispatchEvent=d.dispatchEvent.bind(d),this.open=function(t){if(s=new WebSocket(a.url,n||[]),t){if(this.maxReconnectAttempts&&this.reconnectAttempts>this.maxReconnectAttempts)return}else d.dispatchEvent(c("connecting")),this.reconnectAttempts=0;(a.debug||e.debugAll)&&console.debug("ReconnectingWebSocket","attempt-connect",a.url);var o=s,r=setTimeout(function(){(a.debug||e.debugAll)&&console.debug("ReconnectingWebSocket","connection-timeout",a.url),l=!0,o.close(),l=!1},a.timeoutInterval);s.onopen=function(n){clearTimeout(r),(a.debug||e.debugAll)&&console.debug("ReconnectingWebSocket","onopen",a.url),a.protocol=s.protocol,a.readyState=WebSocket.OPEN,a.reconnectAttempts=0;var o=c("open");o.isReconnect=t,t=!1,d.dispatchEvent(o)},s.onclose=function(n){if(clearTimeout(r),s=null,u)a.readyState=WebSocket.CLOSED,d.dispatchEvent(c("close"));else{a.readyState=WebSocket.CONNECTING;var o=c("connecting");o.code=n.code,o.reason=n.reason,o.wasClean=n.wasClean,d.dispatchEvent(o),t||l||((a.debug||e.debugAll)&&console.debug("ReconnectingWebSocket","onclose",a.url),d.dispatchEvent(c("close")));var r=a.reconnectInterval*Math.pow(a.reconnectDecay,a.reconnectAttempts);setTimeout(function(){a.reconnectAttempts++,a.open(!0)},r>a.maxReconnectInterval?a.maxReconnectInterval:r)}},s.onmessage=function(t){(a.debug||e.debugAll)&&console.debug("ReconnectingWebSocket","onmessage",a.url,t.data);var n=c("message");n.data=t.data,d.dispatchEvent(n)},s.onerror=function(t){(a.debug||e.debugAll)&&console.debug("ReconnectingWebSocket","onerror",a.url,t),d.dispatchEvent(c("error"))}},1==this.automaticOpen&&this.open(!1),this.send=function(t){if(s)return(a.debug||e.debugAll)&&console.debug("ReconnectingWebSocket","send",a.url,t),s.send(t);throw"INVALID_STATE_ERR : Pausing to reconnect websocket"},this.close=function(e,t){"undefined"==typeof e&&(e=1e3),u=!0,s&&s.close(e,t)},this.refresh=function(){s&&s.close()}}if("WebSocket"in window)return e.prototype.onopen=function(e){},e.prototype.onclose=function(e){},e.prototype.onconnecting=function(e){},e.prototype.onmessage=function(e){},e.prototype.onerror=function(e){},e.debugAll=!1,e.CONNECTING=WebSocket.CONNECTING,e.OPEN=WebSocket.OPEN,e.CLOSING=WebSocket.CLOSING,e.CLOSED=WebSocket.CLOSED,e})}])});
//# sourceMappingURL=certstream.min.js.map
What they mean by
...if you're using this in the browser, just add dist/certstream.min.js to a tag, and interact with it as normal!
...is that you don't need the require call (require is CommonJS, not standard JavaScript, and not provided by default on browsers). If you just include the script file in your page, it defines a global CertStream object with a default property providing the default export of the module. (I suspected this was the case, so I grabbed a copy and tried it.)
The docs could be clearer.๐Ÿ™‚ In particular, it looks like after including the library in the browser, you have to use CertStream.default rather than CertStreamClient. I'd probably do that by doing this up-front:
const CertStreamClient = CertStream.default;
(It's too bad they don't provide a native JavaScript module [ESM] file in their dist folder.)
I looked up into certstream.js module in the dist folder and it is a UMD module. Basically, a UMD module is a JavaScript file that tries to guess at runtime which module system itโ€™s being used in, and then it acts as that kind of module. So you can load the file in a plain <script>, or you can load it from an AMD module loader, or you can load it as a Node.js module, and it will always do something sensible.
In your code since you have already loaded the module using <script> tag, the global CertStream object can be directly used without requiring the module again.

Javascript Modules SyntaxError: Cannot use import statement outside a module

So I am trying to learn modules from a youtube video and I'm following along with him but for some reason my code is the exact same as his and is giving me the error
SyntaxError: Cannot use import statement outside a module
I'm not sure if its because my directories are wrong? I have it under
This PC > Desktop > Javascript > module > js > main.js
This is the code from main.js
import{double} from './utils.js'
console.log(double(5))
I also have a index.html file located in the module folder
This is my index.html code.
<!DOCTYPE html>
<head>
<title>JavaScript Modules</title>
<meta name="viewport" content="width=device-width, initial scale=1.0">
<meta charset="utf-8">
<link rel="stylesheet" href="/assets/dcode.css">
<link rel="shortcut icon" href="/assets/favicon.ico" type="image/x-icon">
</head>
<body>
<h1>JavaScript Modules</h1>
<u1>
<li>Split up your code into separate components</li>
<li>Therefore easier to maintain and organize</li>
<li>Supported in major browsers(excl. IE)</li>
</u1>
<script type="module" src="./js/main.js"></script>
</body>
I'm trying to import code from my utils.js file which is in the same folder as main.js
This is my utils.js code.
export function double(n){
return n * 2;
}
When I run the code on the main.js file is where I'm getting the error:
SyntaxError: Cannot use import statement outside a module
You need to run your own webserver. An easy one is to get the Web Server for Chrome. You just run it, point it to your local computer folder, and it will give you a localhost port number where your computer is serving the folder. That way you can access your local folders over HTTP.
With the following folder structure:
/exports/
user.html
importer.js
exporter.js
Where user.html is the page using the importer.js script, which in turn loads exporter.js, you use the following syntax:
user.html
-- the type="module" notation is necessary.
<script src="importer.js" type="module"></script>
importer.js
-- the ./ relative notation is obligatory.
import { doStuff } from './exporter.js'
doStuff()
exporter.js
-- in a production environment, this is your library or module.
function doStuff() {
console.log('Do stuff')
}
export { doStuff }
With a local server, the above setup will log Do stuff in the console.
Forgetting type="module" results in an Uncaught SyntaxError: Cannot use import statement outside a module, not having a relative URL will result in an Uncaught TypeError: Failed to resolve module specifier "exporter.js". Relative references must start with either "/", "./", or "../", and having the wrong URL results in a 404.

How to call a "JS file" by a html "button-click" and the JS file is running a bash script using shell.js

I want to connect to the "server.js" file by a html-button click.
The "server.js" file is running a "bash.sh" file using shell.js
Can anyone give some ideas or directions on how to proceed?
button.html
<!DOCTYPE html>
<html>
<body>
<button onclick="myFunction()">Click me</button>
<p id="demo"></p>
<script src="server.js"></script>
</body>
client.js
function myFunction() {
document.getElementById("demo").innerHTML = "Hello World";
}
server.js
const shell = require('shelljs');
shell.exec('./bash.sh')
bash.sh
#!/bin/bash
printf "command 1 is running...\n\n"
mlpack_linear_regression --training_file aircon.csv -v -M lr.xml
printf "\ncommand 2 is running...\n\n"
mlpack_linear_regression --training_file aircon.csv --test_file
predict.csv --output_predictions_file prediction.csv -v
printf "\nPredicted Output: \n\n"
cat prediction.csv # after this command the result should shown on
#the browser screen
echo "hello" >> file # To test if connection is happening or not
#by writing a string in a file
Look at the documentation for shell.js. It says:
Portable Unix shell commands for Node.js
You are trying to use it in a web browser. It is not designed to run in a web browser and will not work there.
You need to run it using Node.js.
You could write an HTTP server using Node.js, and then use Ajax (or just a regular link click or form submission) to make an HTTP request to that server to cause it to do whatever you want to so with the shell.

Long load using ES6 modules in Chrome

My javascript app is for a kiosk and is only targeting the Chrome browser. I'm using Chrome version 65. I am trying to use ES6 modules without using a transpiler like Babel. My code was originally:
in index.html:
<script src="js/index.js"></script>
index.js:
import Main from './classes/Main.js';
const init = () => {
const app = new Main();
};
init();
Main.js:
export default class Main {
constructor() {
}
}
Originally I got the error "Uncaught SyntaxError: Unexpected identifier" from index.js line 1. Then based on ES6 module Import giving "Uncaught SyntaxError: Unexpected identifier" I added 'type="module"' to the html tag:
<script type="module" src="js/index.js"></script>
This did load, but it takes my browser about 15 seconds to load index.js and main.js according to the network profiler. What could be going on?
So I ran some tests on my local box. I have a simple NodeJs server running with the following three files:
index.html
<!doctype html>
<html>
<head>
<title>es6 Module test</title>
<script>
console.time('load module');
console.time('time until constructor called');
</script>
<script type="module" src="module.js"></script>
<script>
console.timeEnd('load module');
</script>
</head>
<body>
See console output.
</body>
</html>
module.js
import Main from './Main.js';
const init = () => {
const app = new Main();
};
init();
and
Main.js
export default class Main {
constructor() {
console.timeEnd('time until constructor called');
}
}
Running this code in Chrome 65 (On a Mac)
I get the following output:
Run 1
load module: 0.141845703125ms
time until constructor called: 7.90087890625ms
Run 2
load module: 0.139892578125ms
time until constructor called: 6.5498046875ms
Run 3
load module: 0.160888671875ms
time until constructor called: 7.14404296875ms
Run 4
load module: 0.297119140625ms
time until constructor called: 7.4228515625ms
My download times ranged between 2ms and 10ms for each of the three files.
I really can't tell why your times are so much slower. But they should not be. Maybe your server is getting hammered and unable to respond fast enough?
Possible things to check:
What happens if you try to download each of the files from the address bar? Do they still take forever to download?
What about on a different server?
I was was having the same problem when serving my files using:
python -m SimpleHTTPServer
After changing to use python3 http.server instead it fixed the problem:
python3 -m http.server

Using HTML reporting with Mocha test framework

I've been generating some tests using NodeJS and Mocha, and I'd like to find a way to place the results into a browser. I know that Mocha has support for this using 'html' reporter and mocha init <dir> however neither seem to be working for me (the reporter actually throws errors without even running a test).
Could someone give me a good example of running a test via Mocha and generating a HTML report?An example I want to mimic is on the visionmedia site. Also, for examples sake we'll say I'm using a test file called example.js.
Thanks in advance for any assistance, it's surprising there are so few example pieces around.
You try to use the html reporter, which throws when you try to use it in Node:
$ mocha --reporter html > report.html
/usr/local/lib/node_modules/mocha/lib/reporters/html.js:194
, div = document.createElement('div')
^
ReferenceError: document is not defined
Per the Mocha documentation (and relevant issue in Github), the htmlreporter only works in the browser, ie. to test client-side code in the browser.
If you want to output HTML for a Node.js test script, use the doc reporter, which will generate HTML.
To get Mocha to run your test in both browser and in the terminal follow this small tutorial:
I'm assuming the following plugins for a normal node.js mocha test suite.
Node.js
Mocha
And the following tree structure:
/root
/test
my_something_spec.js
/javascript
index.html
index.html
Disclaimer: I've blatantly forgone all kinds of best practices but just to point you in the right direction.
<html>
<head>
<meta charset="utf-8">
<title>Mocha Tests</title>
<link rel="stylesheet" href="node_modules/mocha/mocha.css" />
</head>
<body>
<div id="mocha"></div>
<script src="node_modules/mocha/mocha.js"></script>
<script>mocha.setup('bdd')</script>
<script src="test/my_something_spec.js"></script>
<script>
mocha.checkLeaks();
mocha.run();
</script>
</body>
</html>
test/my_something_spec.js
describe("my function", function() {
it("is a function", function() {
expect(true).to.be(true);
});
});
Serving this up with a simple python server python -m SimpleHTTPServer 8080 from the root and visit localhost:8080 will give you a nice and failing test.
And running mocha from the terminal will give you the same output, that expect isn't defined.
I like to test the same code through Node.js and in a browser, depending on the situation. I know you were asking to "place the results into a browser" (from Node.js?), but I hope this will suffice.
This example was created on a windows machine, but it will work on a Mac and Linux also.
You do not require a web-server (Node.js or other) for this to work.
To run the tests in a browser, open up the ./test/index.html file.
To run the tests in command-line, just execute "mocha".
Starting from nothing:
C:\TEMP>mkdir mocha_node_browser
C:\TEMP>cd mocha_node_browser
C:\TEMP\mocha_node_browser>dir
Volume in drive C is MessedUp
Volume Serial Number is CAB2-E609
Directory of C:\TEMP\mocha_node_browser
2014-08-09 12:17 <DIR> .
2014-08-09 12:17 <DIR> ..
0 File(s) 0 bytes
2 Dir(s) 287,218,769,920 bytes free
Initialize the directory that will hold all of your tests. Always call it "test":
C:\TEMP\mocha_node_browser>mocha init test
Edit and/or create some files:
C:\TEMP\mocha_node_browser>gvim -p test_me.js test\index.html test\tests.js
I use Chai. The same chai.js file will be used in both tests.
C:\TEMP\mocha_node_browser>cd test
C:\TEMP\mocha_node_browser\test>curl -O http://chaijs.com/chai.js
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 117k 100 117k 0 0 99902 0 0:00:01 0:00:01 --:--:-- 99902
C:\TEMP\mocha_node_browser\test>cd ..
After creating/editing the files, run the tests via command-line:
C:\TEMP\mocha_node_browser>mocha
.
1 passing (15ms)
...or point your browser at ./test/index.html.
passes: 1
failures: 0
duration: 0.03s
whatever
should return "it worked!"
File contents:
C:\TEMP\mocha_node_browser>type test_me.js
// the function to be tested
function whatever() {
return 'it worked!';
}
// only kicks in when running in Node.js via "mocha"
if (typeof module !== 'undefined') {
module.exports = whatever;
}
Add Chai and your source that you want to test into test/index.html:
C:\TEMP\mocha_node_browser>type test\index.html
<!DOCTYPE html>
<html>
<head>
<title>Mocha</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="mocha.css" />
</head>
<body>
<div id="mocha"></div>
<script src="mocha.js"></script>
<script>mocha.setup('bdd')</script>
<!-- added to index.html: -->
<script src="./chai.js"></script>
<script src="../test_me.js"></script>
<script src="tests.js"></script>
<script>
mocha.run();
</script>
</body>
</html>
Make your tests compatible with command-line and browser
C:\TEMP\mocha_node_browser>type test\tests.js
if (typeof require !== 'undefined') {
// testing in command-line
var chai = require('./chai');
var whatever = require('../test_me');
}
var expect = chai.expect;
describe('whatever', function() {
it('should return "it worked!"', function() {
expect(whatever()).to.equal("it worked!");
});
});

Categories