Using Python 3 with Socket.
I'm having trouble linking a javascript file to an HTML file. I have the following 3 files in particular in the same directory:
webserver.py
import socket
def getTextFromFile(filename):
with open(filename, 'r') as myFile:
return myFile.read()
host, port = '192.168.0.7', 11010
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((host, port))
s.listen(1)
print('Now serving: ' + host + ' at: ' + str(port))
while True:
try:
c, addr = s.accept()
print('Received connection form: ' + str(addr))
request = c.recv(1024)
response = '\HTTP/1.1 200 OK' + getTextFromFile("index.html")
c.sendall(response.encode())
c.close()
except Exception as e:
print(e)
index.html
<html>
<head>
<title>Title</title>
<script src="indexjs.js"></script>
</head>
<body>
<h1>Hello there.</h1>
<p>This is a webserver test.</p>
<button type="button" onclick="myFunction()">Click me!</button>
<p id="demo"></p>
</body>
</html>
indexjs.js
function myFunction(){
document.getElementById("demo").innerHTML = "Hello";
}
The web server code itself works fine, the router is port-forwarded, can be accessed from an entirely different network, yada-yada; but when the website is visited, the javascript doesn't seem to execute. If I place the same javascript code inside the script tags of index.html and omit indexjs.js then it does work as intended. How do I make it to where indexjs.js can be properly linked with index.html without putting the javascript code in script tags?
I also tried another similar approach by trying to put an image in index.html (png file, same directory as index.html of course) with the img tags, but it did not display either, so it seems like my code is having issues linking any files to index.html whatsoever.
The steps I'm taking:
Run webserver.py
Open browser (in my case it happens to be Chrome)
Type in my public ip xxx.xxx.xxx.xxx:11010 in the address bar, hit enter
The web page shows, but pictures don't show (or any other asset that's linked) and javascript functions aren't executed when, for example, buttons are pressed.
Any help would be appreciated, thanks in advance.
Normally you would have a public folder for your static assets. And you would put your static css and js files into it.
Related
I have a very simple JavaScript file named as MyJava.htm as shown below:
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script type="text/javascript">
function ShowMe(message)
{
var n = message.length;
var s = a.toString();
alert("total length = " + s);
}
</script>
</head>
<body style='background-color:transparent'>
<P>Empty</P>
</body>
</html>
As you can see, there is an error in the code ('a' is undefined). I saved the file into my local machine's web server folder, which is c:\inetpub\wwwroot.
When I first run it using WPF WebBrowser control (this) as follows:
JavascriptInterface jint = new JavascriptInterface(mainWindow);
this.myBrowser.ObjectForScripting = jint;
this.myBrowser.Source = new Uri( #"http://127.0.0.1/myJava.htm");
this.myBrowser.InvokeScript("ShowMe", "Hello");
where mainWindow is a dialog. I'll get the error message saying 'a' is undefined.
Then, I went into the file MyJava.htm and corrected it (replacing variable 'a' with 'n'); saved the file; reran the WPF application.
I still get the 'a' is undefined error.
If I rename the file and change the URL accordingly, then everything works.
Apparently, the old script was being loaded even I've altered the content of the file.
How do I resolve this? How can I tell WPF (or whoever) to load the new contents from the URL?
I have external programs such as ffmpeg and gstreamer running in the background and writing to a log file. I want to display the contents of this log with my Flask application, so that the user can watch the log update, like tail -f job.log would do in the terminal.
I tried to use <object data="/out.log" type="text/plain"> to point at the log file, but that failed to show the data, or the browser told me I needed a plugin.
How can I embed and update the log file in an HTML page?
Use a Flask view to continuously read from the file forever and stream the response. Use JavaScript to read from the stream and update the page. This example sends the entire file, you may want to truncate that at some point to save bandwidth and memory. This example sleeps between reads to reduce cpu load from the endless loop and allow other threads more active time.
from time import sleep
from flask import Flask, render_template
app = Flask(__name__)
#app.route('/')
def index():
return render_template('index.html')
#app.route('/stream')
def stream():
def generate():
with open('job.log') as f:
while True:
yield f.read()
sleep(1)
return app.response_class(generate(), mimetype='text/plain')
app.run()
<pre id="output"></pre>
<script>
var output = document.getElementById('output');
var xhr = new XMLHttpRequest();
xhr.open('GET', '{{ url_for('stream') }}');
xhr.send();
setInterval(function() {
output.textContent = xhr.responseText;
}, 1000);
</script>
This is almost the same as this answer, which describes how to stream and parse messages, although reading from an external file forever was novel enough to be it's own answer. The code here is simpler because we don't care about parsing messages or ending the stream, just tailing the file forever.
I am using frontail package from npm.
npm i frontail -g
frontail /var/log/syslog
visit http://127.0.0.1:9001 to view logs
Source: https://github.com/mthenw/frontail
This may not be the exact answer for the question(to embed an html page), but it solves the problem of many users who are looking specifically only for
Display the contents of a log file as it is updated
For me #davidism solution (accepted answer) worked only on Firefox. It didnt work in Chrome, Brave, Vivaldi. Maybe there was some kind of de-sync in backend and frontend loops? I dont know.
Anyway i used far simpler solution, without loop on the backend and javascript loop on frontend. Maybe it's "uglier" and may cause trouble for some very long logs, but at least it works on every browser i use.
#app.route('/stream')
def stream():
with open("job.log", "r") as f:
content = f.read()
# as you see, file is loaded only once, no loop here, (loop is on frontend side)
return app.response_class(content, mimetype='text/plain')
<!DOCTYPE html>
<html>
<head>
<!-- page auto-refresh every 10 seconds -->
<meta http-equiv="refresh" content="10">
<title>Some title</title>
</head>
<body>
<h1>Log file ...</h1>
<script>
// function for adjusting iframe height to log size
function resizeIframe(obj) {
obj.style.height = obj.contentWindow.document.documentElement.scrollHeight + 'px';
}
</script>
<!-- iframe pulls whole file -->
<iframe src="{{ url_for('stream') }}" frameborder="0" style="overflow:hidden;width:100%" width="100%" frameborder="0" scrolling="no" onload="resizeIframe(this)"></iframe>
</body>
</html>
As you see the only javascript code is used to adjust iframe height to current text size.
I am trying to display a variable inside my Thermostat.js file onto my webpage using index.html, the variable name I want to pass into the webpage is "roomTemp". I searched some up and this is what I've come up with but I get a reference error in my console "$ is not defined" within my javascript file at line 5 "$('#printHere').html(roomTemp);".
Thermostat.js
var http = require('http'); //need to http
var fs = require('fs'); //need to read static files
var roomTemp=20;
$('#printHere').html(roomTemp);
//this function is identical to the serve file function from the course web page
//it will read the contents of a file and serve them as the specified content type
//this is only used to serve the static index page
function serveStaticFile(res, path, contentType, responseCode){
if(!responseCode) responseCode = 200;
fs.readFile(__dirname + path, function(err, data){
if(err){
//for now use success code
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('500 INTERNAL FILE ERROR' + '\n');
}
else {
res.writeHead(responseCode , {'Content-Type': contentType});
res.end(data);
}
});
}
//this function is nearly identical to the routing examples from the course web page
http.createServer(function (request,response){
var path = request.url.replace(/\/?(?:\?.*)$/,'').toLowerCase();
switch(path){
//serve the static index page
case '/index.html':
serveStaticFile(response,
'/index.html',
'text/html');
break;
default:
serveStaticFile(response,
'/index.html',
'text/html');
break;
}
}).listen(3000, "127.0.0.1");
console.log('Server Running at http://127.0.0.1:3000 CNTL-C to quit');
function save() {
var desTemp;
desTemp = document.getElementById("desTemp").value;
roomTemp = desTemp;
}
Index.html
<!DOCTYPE html>
<html>
<head>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
</head>
<body>
<p>Current Temp: <span id="printHere"></span></p>
<form action="demo_form.asp">
Desired Room Temperature: <input type="number" id="desTemp" onchange="save()"><br>
</br>
<input type="submit" value="Set">
</form>
</body>
</html>
You are getting confused with javascript, node.js scripts & asp.
In your thermostat.js, it's clearly a node.js (server side) script. You can't mix your client-side script (jQuery) on node.js.
$('#printHere').html(roomTemp);
This line is trying to search through the DOM and get the html values, which can't be done on the server side
Index.html
<form action="demo_form.asp">
You are creating a html page that has a form that submits to demo_form.asp, which again is another server side technology (Active Server Pages), by Microsoft.
Lastly, $ is just a shorthand for jQuery, you need to understand your software stack properly before attempting any further.
<head>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script src="Thermostat.js"></script>
</head>
You have to include these lines in you <script src="Thermostat.js"></script> in your head for your javascript to work. Remember defining the correct path for the src="<....\Thermostat.js">
Until you do not include your JS it won't work and also jQuery JS has to be included before your JS.
The title of this question may be slightly misleading, but I'm not sure what the best title would be (since I can't guess at a solution yet).
Basically the system I am developing relies heavily on canvas graphs. These graphs are generated through javascript, and are made using data pulled via ajax from an API server.
The tricky part is, I'd like to be able to email these graphs to users of this system, without them actually having to go to the web page at all. So while I'm aware that it is possible to get the Base64 value of an image generated with javascript in a browser, what about if no one is there to run that javascript?
I'd like to keep the graphs generated in javascript/canvas, rather than making them in a common server-side graphics library (GD, ImageMagick). The Canvas graphs are dynamic, and allow for interaction via javascript. Though I don't want that functionality in the email notification, I do want them to be identical otherwise (at least in appearance).
So the question is, how can I get these graphs into an email?
At this point, my only guess is that I'd need to literally make a website that does AJAX requests for "graphs to render", renders these graphs, and sends the results to the server. Then I'd need a "server" that just sits there on that web page and churns out graphs. Is that the only solution here?
I used phantomJs (like node.js but different) serverside to run exactly the same code as client side, and get the same result. all you need is one single exe-file (like a webkit stand alone web brower)
The following program (in Perl, but should be feasible to translate to you favourite language) takes some data, inserts into a web-page (could be ajax'ed) and either sends that web page to the client, or stores it as a temporary file, and starts PhantomJs on the same page. Then ask PhantomJs to generate a jpg, that is then picked up (and in this case sendt to the client).
#!/usr/bin/perl
use strict;
use File::Temp;
$|=1;
#this script returns a graph, either as html +js web page to render client side,
#or renders the same page server side, and returns the jpg image.
#files needed:
#.\phantom_srv_client.pl #this script
#.\phantomjs.exe #the webkit runtime stand alone file, from http://phantomjs.org/
#.\Scripts\excanvas.min.js #canvas simulator for IE8-
#.\Scripts\jquery.min.js #jQuery as we know it
#.\Scripts\jquery.jqplot.min.js #graph library on top of jQuery from http://www.jqplot.com/ (Flot or any can be used)
#do we want client side rendering (html + js), or server side rendering (jpg)
#jpg seems to render nicer than png on some pages?
use CGI;
my $show_as_jpg = CGI::param("jpg");
#path to javascript libraries (jQuery etc).
#Must be absolute file location for server rendering, relative for web
use FindBin;
my $script_path = $show_as_jpg
? $FindBin::Bin."/Scripts"
: './Scripts';
#data to send to graph (two sets)
my $data = [[2,5,4], [6,4,5]];
#use json to get this as a javascript text
my $json_data;
eval {require JSON; $json_data=JSON::to_json($data)};
#in case JSON is not installed, get the json/javascript data manually (just for demo)
$json_data ||= "[[2,5,4], [6,4,9]]"; #here 9 at the end to see a difference
#The following is the web page that renders the graph, client or server side
#(links to scripts must be abolute to work serverside, as temp-files may go anywhere, $script_path keeps track of that)
#$json_data is the Perl data structure converted to JSON (aka javascript, but not)
my $graph_html =qq|
<!DOCTYPE html>
<html>
<head>
<!--[if lt IE 9]><script language="javascript" type="text/javascript" src="$script_path/excanvas.min.js"></script><![endif]-->
<script class="include" type="text/javascript" src="$script_path/jquery.min.js"></script>
<script class="include" type="text/javascript" src="$script_path/jquery.jqplot.min.js"></script>
<script class="code" type="text/javascript" language="javascript">
jQuery(document).ready(function(){
/*data from perl (\$json_data) inserted here */
var data = $json_data;
jQuery.jqplot("chart1", data );
});
</script>
</head>
<body>
<div id="chart1" style="width:600px; height:400px;"></div>
<a href='?jpg=1'>View as jpg</a>
</body>
</html>
|;
#this is the javascript that tells PhantomJs what to do (ie open a doc and render it to bitmap)
my $phantom_doc_js =qq|
var system = require('system');
//read from commandline which files to open, and write to
var open_doc = system.args[1];
var return_doc = system.args[2];
var page = require('webpage').create();
page.open(open_doc, function () {
page.render(return_doc);
phantom.exit();
});
|;
#see if we shall render this page serverside
if ($show_as_jpg) {
#get temporary filenames with related file handlers
#where to put phantomjs script (generic so could be a static file)
my ($phantom_doc_filehandler, $phantom_doc_filename) = File::Temp::tempfile( SUFFIX => '.js', TMPDIR => 1);
#where to put web page with data to render and ref to javascripts etc
my ($phantom_graph_filehandler, $phantom_graph_filename) = File::Temp::tempfile(SUFFIX => '.html', TMPDIR => 1);
#also get a filename with no handler, so phantomjs can return the jpg file. Extention must be .jpg!
my (undef, $image_filename) = File::Temp::tempfile( SUFFIX => '.jpg',TMPDIR => 1, OPEN => 0);
#store file content and close files
print $phantom_doc_filehandler $phantom_doc_js; close $phantom_doc_filehandler;
print $phantom_graph_filehandler $graph_html; close $phantom_graph_filehandler;
#now call PhantomJs with filenames to read from and write to.
#Next version should support piping, which would simplify a lot
#use absolute path to phantomjs.exe in case web-server does not use current path
system($FindBin::Bin.'\\phantomjs', $phantom_doc_filename, $phantom_graph_filename, $image_filename) == 0
or die "system failed: $?";
#read the entire image file
my $img = slurp_file($image_filename);
print "Content-Type: image/jpeg\nPragma: no-cache\n\n".$img;
#The temp files are no more needed
unlink $phantom_doc_filename, $phantom_graph_filename, $image_filename;
} else { # just render client side
print "Content-Type: text/html\nPragma: no-cache\n\n".$graph_html;
}
#slurp is not always std perl
sub slurp_file{
my $filename = shift;
my $string;
local $/ = undef;
open FILE, $filename or die "Couldn't open file: $!";
binmode FILE;
$string = <FILE>;
close FILE;
return $string;
}
I have Windows Application (.EXE file is written in C and built with MS-Visual Studio), that outputs ASCII text to stdout. I’m looking to enhance the ASCII text to include limited HTML with a few links. I’d like to invoke this application (.EXE File) and take the output of that application and pipe it into a Browser. This is not a one time thing, each new web page would be another run of the Local Application!
The HTML/java-script application below has worked for me to execute the application, but the output has gone into a DOS Box windows and not to pipe it into the Browser. I’d like to update this HTML Application to enable the Browser to capture that text (that is enhanced with HTML) and display it with the browser.
<body>
<script>
function go() {
w = new ActiveXObject("WScript.Shell");
w.run('C:/DL/Browser/mk_html.exe');
return true;
}
</script>
<form>
Run My Application (Window with explorer only)
<input type="button" value="Go"
onClick="return go()">
</FORM>
</body>
Have the executable listen on a port following the HTTP protocol.
Then have the web page make AJAX-style HTTP requests to the local port with JAvascript.
The executable returns text.
The web page updates itself through DOM manipulation in Javascript.
Yes, this works. It is happening 5 feet away from me right now in another cubicle.
This is called CGI
Your already using WScript to launch, it can also read StdOut.
<html>
<head>
<script type="text/javascript">
function foo() {
var WshShell = new ActiveXObject("WScript.Shell");
var oExec = WshShell.Exec("ipconfig.exe");
var input = "";
while (!oExec.StdOut.AtEndOfStream) {
input += oExec.StdOut.ReadLine() + "<br />";
}
if (input)
document.getElementById("plop").innerHTML = input;
}
</script>
</head>
<body onload="foo();">
<code id="plop"></code>
</body>
</html>
It would be easier to have your EXE create a temp file containing the HTML, then just tell Windows to open the temp HTML file in the browser.