I am trying to serve some HTML from a Google Colab notebook using the following:
from IPython.display import IFrame
IFrame(src='./output/index.html', width=700, height=600)
However, this throws localhost refused to connect:
Does anyone know how I can serve the html in index.html (which must load javascript) inside the Colab notebook? Any pointers would be hugely appreciated!
You can serve content from the path /nbextensions/ which maps to /usr/local/share/jupyter/nbextensions.
So you can put content there.
!ln -s /usr/local/share/jupyter/nbextensions /nbextensions
%cd /nbextensions
!wget -q https://upload.wikimedia.org/wikipedia/commons/3/37/Youtube.svg
Then serve the image
%%html
<img src=/nbextensions/Youtube.svg>
I can't make it works with IFrame, thought. I don't know why.
Here's an example colab notebook.
This built-in example notebook gives a demo:
https://colab.research.google.com/notebooks/snippets/advanced_outputs.ipynb#scrollTo=R8ZvCXC5A0wT
Reproducing the example here of serving content from the backend:
import portpicker
import threading
import socket
import IPython
from six.moves import socketserver
from six.moves import SimpleHTTPServer
class V6Server(socketserver.TCPServer):
address_family = socket.AF_INET6
class Handler(SimpleHTTPServer.SimpleHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
# If the response should not be cached in the notebook for
# offline access:
# self.send_header('x-colab-notebook-cache-control', 'no-cache')
self.end_headers()
self.wfile.write(b'''
document.querySelector('#output-area').appendChild(document.createTextNode('Script result!'));
''')
port = portpicker.pick_unused_port()
def server_entry():
httpd = V6Server(('::', port), Handler)
# Handle a single request then exit the thread.
httpd.serve_forever()
thread = threading.Thread(target=server_entry)
thread.start()
# Display some HTML referencing the resource.
display(IPython.display.HTML('<script src="https://localhost:{port}/"></script>'.format(port=port)))
This works for me on Aug 2022:
First, as #korakot mentioned, if you have any javascript used in your html, please copy them into /usr/local/share/jupyter/nbextensions
e.g.
!cp -r ./output/ /usr/local/share/jupyter/nbextensions/google.colab/
use !ls /usr/local/share/jupyter/nbextensions/google.colab/ to check if file already exists
Then, instead of referring to html file by path, simple copy the html code in <body> into colab cell:
%%html
<!-- move your head part resources here -->
<script src="/nbextensions/google.colab/output/xxxx.js"></script>
<link type="text/css" href="/nbextensions/google.colab/outut/xxxx.css" rel="stylesheet" />
<!-- here is your body code -->
<div id="files"></div>
<div id="canvasArea" height="720px"></div>
...
<script>
// set the cell height
google.colab.output.setIframeHeight(document.documentElement.scrollHeight, true);
// you can also log some testing code here, to check whether it works or not
console.log("hello world");
console.log(variables_in_your_js)
</script>
Run the cell to check whether works or not.
Related
I am just trying to have fun with JS, I am creating a small project trying to implement a new architecture that I di not use before, I was always using js in React apps, or using native JS but not creating an app with it, I was using it to create some animations and handle some changes in my pages, nothing complex).
I want to learn how to create a JS app, implementing a MVC architecture ! I am not following any tutorial, so here is my folder structure :
Here is my index.html :
<html>
<head>
<title>Test js PROJECT</title>
</head>
<body>
<div id="root"></div>
<script src="app.js"></script>
</body>
</html>
And that's my app.js :
import { loadApp } from './MVC/controllers/loadApp';
loadApp();
And that's is my loadApp.js :
const loadApp = () => {
const showUsersOption = document.createElement('button');
const showProductsOption = document.createElement('button');
showUsersOption.createTextNode('Users');
showProductsOption.createTextNode('Products');
const app = document.getElementById('root');
app.appendChild(showUsersOption);
app.appendChild(showProductsOption);
}
export default loadApp;
So I think what I am trying to do is simple, adding two buttons to the root element, But I got this :
app.js:1 Uncaught SyntaxError: Cannot use import statement outside a
module
Based on this comment to the question, I added type module in my script like that :
<html>
<head>
<title>Test js PROJECT</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="app.js"></script>
</body>
</html>
But I got this :
Access to script at
'file:///C:/Users/Taoufiq.BENALLAH/Desktop/Master/js/app.js' from
origin 'null' has been blocked by CORS policy: Cross origin requests
are only supported for protocol schemes: http, data, chrome,
chrome-extension, chrome-untrusted, https.
GET file:///C:/Users/Taoufiq.BENALLAH/Desktop/Master/js/app.js
net::ERR_FAILED
Based on the comments in this question here, I have to restart my editor or run npm install, but I am not using node modules or anything, my app is simpler than that.
Any idea ? Any help would be much appreciated.
I am having a hard time importing my custom external JS files to Google Colab. I work with html + js, following this workflow:
1 / imports
from IPython.display import HTML, SVG
from IPython.core.magic import register_cell_magic
2 / mount drive
from google.colab import drive
drive.mount('/content/drive')
3 / html
#register_cell_magic
def dojs(line, src):
return HTML(f"""
<canvas id="renderCanvas" touch-action="none" width="1280px" height="720px"></canvas>
<script src="content/drive/My Drive/Colab Notebooks/files/testJavascript.js"></script>
<script>
{src}
</script>
""")
4 / js
%%dojs
//...trying to use functions from testJavascript.js
Maybe it's really trivial how to do this but I'm new at Colab. I get "Failed to load resource: the server responded with a status of 500 ()".
You need to put your JS file in here:
/usr/local/share/jupyter/nbextensions/google.colab/
Then it can be access through the path
/nbextensions/google.colab/
In your case, you need to copy your js file there:
!cp /content/drive/My\ Drive/Colab\ Notebooks/files/testJavascript.js \
/usr/local/share/jupyter/nbextensions/google.colab/
Then change dojs() to be
#register_cell_magic
def dojs(line, src):
return HTML(f"""
<canvas id="renderCanvas" touch-action="none" width="1280px" height="720px"></canvas>
<script src="/nbextensions/google.colab/testJavascript.js"></script>
<script>
{src}
</script>
""")
Lines like script src="content/drive... won't work. The reason is that your Drive files are present on the backend VM executing your code. But, using a <script> tag is going to be resolved by your browser against the current base origin, which is colab.research.google.com, which doesn't serve your Drive files.
There are some recipes for serving local files in the advanced outputs example here:
https://colab.research.google.com/notebooks/snippets/advanced_outputs.ipynb#scrollTo=R8ZvCXC5A0wT
I am having trouble getting files such as index.html, main.js, style.css and more on my server made in Go.
My html file works fine with javascript and css on my local file but I can not make it work on a server.
I already tried making this in my code, but it only starts html file and javascript, css, jquer, font are listed in console like the page was not found (404 Page not found).
r := mux.NewRouter()
r.Handle("/", http.FileServer(http.Dir("./static")))
r.HandleFunc("/events", eventHandler) //Ignore this
r.NotFoundHandler = http.HandlerFunc(notFound) //This is just a custom 404.
// Create and start HTTP server.
s := &http.Server{
Handler: r,
Addr: config.Address,
}
My question is:
Is there any possibility to do this without Node.js. Is there any option that will display all my javascript files and css in the html. I really would not like to get this things complicated with Node.
Note
My codes for html, css, javascript all work. My server also works, the only thing needed now is adding the files to the server.
This is what I get This is what I should get on server.
<html>
<head>
<link rel="stylesheet" href="main.css">
<script src="jquery-3.3.1.min.js"></script>
</head>
<body id='body'>
<div class="app-body">
<div id='left' class="left">
<div class='conferenceRoom'>Conference room
<h1 class="roomName">crane
</h1>
</div>
<div class="status">
<h1 id="free_busy" class="free_busy"></h1>
<h1 id="duration" class="duration"></h1>
</div>
</div>
</div>
<div class="right">
<div class="date" id="date"></div>
<div id='eventList' class="eventList"></div>
</div>
</div>
<script src="main.js"></script>
</body>
index.html
This are my files in a directory called Website. Server is started by:
go run *.go -c config.toml
This is ran from the website folder. And this is what the files look like
The problem is you're trying to feed a http.FileServer to Gorilla mux's route.Handle function. This handles a single URL, so it's only valid for the given URL, /.
What you want for serving static files is a route.PathPrefix(). This serves any URL path which begins with the given string, while route.Handle() serves only a path which matches the string exactly.
package main
import (
"log"
"net/http"
"github.com/gorilla/mux"
)
func main() {
r := mux.NewRouter()
r.PathPrefix("/").Handler(http.FileServer(http.Dir("./static")))
// Create and start HTTP server.
s := &http.Server{
Handler: r,
Addr: ":8009",
}
log.Fatalln(s.ListenAndServe())
}
I'm trying to get images to display in real-time only on my machine. Think a really basic version of Google Images. The user types in "red hammer" and I show them a picture of red hammer
The problem is the refresh rate. I update the image file to be shown, and when I look it up directly as http://127.0.0.1:6007/static/tree.jpg, that will immediately give me the most recent jpg. And then, strangely enough after I look up something like http://127.0.0.1:6007/static/tree.jpg, the image changes on the initial http://127.0.0.1:6007 !
My setup:
In the static/ directory, tree.jpg:
templates/
show.html
In templates/, show.html:
<!DOCTYPE html>
<html>
<body>
<h1>Text-to-Image Synthesis</h1>
<form method="POST" action="/generator">
<p>Input to Generator: <input type="text" name="input_text"><input type="submit" value="Generate Image"></p>
</form>
<img src="{{url_for('static', filename='tree.jpg')}}" />
</body>
</html>
index.html
and index.html:
<!DOCTYPE html>
<html>
<body>
<h1>Text-to-Image Synthesis</h1>
<form method="POST" action="/generator">
<!-- button -->
<p>Input to Generator: <input type="text" name="input_text"><input type="submit" value="Generate Image"></p>
</form>
</body>
</html>
These two are the same except show.html shows the image on the src=... line.
server.py
#!/usr/bin/env python2.7
import os
from flask import Flask, request, render_template, g, redirect, Response, send_from_directory
tmpl_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'templates')
app = Flask(__name__, template_folder=tmpl_dir)
#app.route('/')
def index():
return render_template("index.html")
#app.route('/generator', methods=['POST'])
def generator():
# save typed-in text
text = request.form['input_text']
filename = "/home/ubuntu/icml2016/scripts/cub_queries.txt"
with open(filename, "a+") as f:
f.write(text + "\n")
"""
print('start')
subprocess.call('./scripts/demo_cub.sh', shell=True) # change the image in the background
print('end')
"""
return render_template("show.html")
if __name__ == "__main__":
HOST='0.0.0.0'
PORT=6007
app.run(host=HOST, port=PORT)
So now if I've properly given you everything, you should be able to call python3 server.py and see this:
and if you type in "hi" to the box it'll show this:
but when I change tree.jpg to some other image in the background and type in something else, I don't get the instant image update I'm looking for. In other words, that tree won't become the most recent tree :( We want to see Maury's beautiful face on my basic webpage
Your problem relates to http caching - read about the http Expires header. Flask defaults to setting an Expires header of 12 hours. This instructs your web browser that there is no need to ask for tree.jpg again for 12 hours. When your browser needs tree.jpg again it will simply load it from cache, it will not even make a request to your server. Manually entering this tree.jpg URL in your browser overrides this, in doing so you ask your browser to request it again.
You don't appear to have provided the relevant code -- the send_from_directory call serving your static file is where you need to make change.
send_from_directory(directory, filename, cache_timeout=0)
Relevant documentation:
http://flask.pocoo.org/docs/0.12/api/#flask.send_from_directory
http://flask.pocoo.org/docs/0.12/api/#flask.send_file
and send_file_max_age on the same page (the default Expiry)
I'm trying to use pyjamas (http://pyjs.org/). My input file, named hi.py, looks like this:
from pyjamas import Window
from pyjamas.ui import RootPanel, Button
from pyjamas.ui import HTML
def greet(sender):
Window.alert("Hello!")
b = Button("Click me", greet)
RootPanel().add(b)
I run the following command:
python ~/pyjs-pyjs-07f54ad/bin/pyjsbuild hi.py
Building : hi
PYJSPATH : [
/Users/michaelnatkin/HelloPyjs
/Users/michaelnatkin/pyjs-pyjs-07f54ad/library
/Users/michaelnatkin/pyjs-pyjs-07f54ad/addons
]
Built to : /Users/michaelnatkin/HelloPyjs/output
Which appears to run without errors, and here is my resulting directory:
Michael-Natkins-MacBook-Pro-2:HelloPyjs michaelnatkin$ ls .
hi.js hi.py output
Michael-Natkins-MacBook-Pro-2:HelloPyjs michaelnatkin$ ls output
__init__.py gchart.gif hi.safari.cache.html
_pyjs.js hi.html history.html
bootstrap.js hi.ie6.cache.html tree_closed.gif
bootstrap_progress.js hi.mozilla.cache.html tree_open.gif
disclosurePanelClosed.png hi.nocache.html tree_white.gif
disclosurePanelClosed_rtl.png hi.oldmoz.cache.html
disclosurePanelOpen.png hi.opera.cache.html
I then direct my browser to one of the html files: file:///Users/michaelnatkin/HelloPyjs/output/hi.html
and I get... a blank page. The only error in my js console is:
Uncaught SecurityError: Blocked a frame with origin "null" from accessing a frame with origin "null". Protocols, domains, and ports must match.
which I guess isn't too surprising since the html file says:
<html>
<!-- auto-generated html - You should consider editing and adapting this
to suit your requirements. No doctype used here to force quirks mode; see
wiki for details: http://pyjs.org/wiki/csshellandhowtodealwithit/
-->
<head>
<title>hi (Pyjamas Auto-Generated HTML file)</title>
<meta name="pygwt:module" content="hi">
</head>
<body style="background-color:white">
<script type="text/javascript" src="bootstrap.js"></script>
<iframe id="__pygwt_historyFrame" style="display:none;"></iframe>
<script type="text/javascript" src="bootstrap.js"></script>
<iframe id="__pygwt_historyFrame" style="display:none;"></iframe>
</body>
</html>
So.. I'm completely stuck. Can someone tell me how to get this bad boy to produce output? I've got a much more complicated app I want to create, but if I can't say "Hello" it isn't going to go well. Thank you!
Have you tried it in Firefox too? While nothing is displayed with Chrome, with Firefox I get an error message which comes from the way you import RootPanel and Button. You should replace your single line by:
from pyjamas.ui.RootPanel import RootPanel
from pyjamas.ui.Button import Button
After that your button greets me properly.
And regarding the Chrome issue, either launch it with --allow-file-access-from-files or run a local web server to display your page. More details there: https://github.com/pyjs/pyjs/wiki/googlechromeproblems