This works in Chrome when doing it on my local server. However, when I transfer over to NodeWebkit, it fails with status === 0.
function ReadText(filename) {
var txtFile = new XMLHttpRequest();
txtFile.open("GET", filename, true);
txtFile.onreadystatechange = function () {
if (txtFile.readyState === 4) // Makes sure the document is ready to parse.
{
if (txtFile.status === 200) // Makes sure it's found the file.
{
g_FileLoadContents = txtFile.responseText;
ReadFile();
}
}
}
txtFile.send(null);
};
g_FileLoadContents is a global and ReadFile is a function that does some work on g_FileLoadContents... but it does not get that far in the NodeWebkit (Again, I'll stress all is ok in Chrome when on my local server).
In NodeWebkit I watch txtFile.readyState change up to 4, but then txtFile.status is 0.
Why is the status 0? When I use the nodeWebkit, should I just let the status be 0 in my code above?
I hope someone can explain, as I am very confused.
HTTP status codes are returned by webservers. Presumedly your local server returns 200 when you're doing this in Chrome, but node-webkit just returns 0 (Unknown?).
Normally reading local files is restricted though. Does the code above actually produce the file contents? Even so, if you're trying to read files in node-webkit I would suggest using the node fs module to access the filesystem directly.
Related
I have a custom URL protocol handler cgit:[...]
It launches up a background process which configures some stuff on the local machine. The protocol works fine, i'm launching it from JavaScript (currently using document.location = 'cgit:[...]'), but i actually want JavaScript to wait until the associated program exits.
So basically the steps i want JavaScript to do:
JavaScript does something
JavaScript launches cgit:[...]
Javascript waits until cgit:[...] exits
JavaScript does something else
Code:
function launchCgit(params)
{
showProgressBar();
document.location="cgit:"+params;
document.addEventListener( /* CGit-Program exited event */, hideProgressBar );
}
or:
function launchCgit(params)
{
showProgressBar();
// setLocationAndWait("cgit:"+params);
hideProgressBar();
}
Any ideas if this is possible?
Since this isn't really an expected use of window.location I would doubt that there's an easy way. My recommendation would be to use an AJAX request and have the c++ program send a response when it's done. That way, whatever code needs to run after the c++ program can be run when the request completes.
As i didn't find a suitable way to solve my problem using ajax requests or anything similar, i finally solved my problem using a kind-of-ugly workarround including XmlHttpRequest
For launching the protocol i'm still using document.location=cgit:[...]
I'm using a server side system including "lock-files" - that's like generic dummy files, with generated names for each request.
Once the user requests to open the custom protocol, such a file is being generated on the server specifically for that one protocol-opening-request.
I created a folder called "$locks" on the server where these files are being placed in. Once the protocol-associated program exits, the appropriate file is being deleted.
The website continuously checks if the file for a request still exists using XmlHttpRequest and fires a callback if it doesn't (example timout between tests: 1 sec).
The structure of the new files is the following:
lockThisRequest.php: It creates a file in the $locks directory based on the req url-parameter.
unlockThisRequest.php: It deletes a file in the $locks directory; again based on the req url-parameter.
The JavaScript part of it goes:
function launchCgit(params,callback)
{
var lock = /* Generate valid filename from params variable */;
// "Lock" that Request (means: telling the server that a request with this ID is now in use)
var locker = new XmlHttpRequest();
locker.open('GET', 'lockThisRequest.php?req='+lock, true)
locker.send(null);
function retry()
{
// Test if the lock-file still exists on the server
var req = new XmlHttpRequest();
req.open('GET', '$locks/'+lock, true);
req.onReadyStateChanged=function()
{
if (req.readyState == 4)
{
if (req.status == 200)
{
// lock-file exists -> cgit has not exited yet
window.setTimeout(retry,1000);
}
else if (req.status == 404)
{
// lock-file not found -> request has been proceeded
callback();
}
}
}
req.send(null);
}
document.location = 'cgit:'+params; // execute custom protocol
retry(); // initialize lockfileCheck-loop
}
Ussage is:
launchCgit("doThisAndThat",function()
{
alert("ThisAndThat finished.");
});
the lockThisRequest.php-file:
<?php
file_put_contents("$locks/".$_GET["req"],""); // Create lock file
?>
and unlockThisRequest.php:
<?php
unlink("../\$locks/".$_GET["req"]); // Delete lock file
?>
The local program / script executed by the protocol can simply call something like:
#!/bin/bash
curl "http://servername/unlockThisRequest.php?req=$1"
after it finished.
As i just said this works, but it's anything else than nice (congratulations if you kept track of those instructions)
I'd rather prefered a more simple way and (important) this also may cause security issues with the lockThisRequest.php and unlockThisRequest.php files!
I'm fine with this solution, because i'm only using it on a password protected private page. But if you plan to use it on a public or non protected page, you may want to add some security to the php files.
Anyways, the solution works for me now, but if anyone finds a better way to do it - for example by using ajax requests - he/she would be very welcome to add that way to the respective stackoverflow-documentation or the like and post a link to it on this thread. I'd still be interested in alternative solutions :)
I am using Chrome. In my dev tools console, I tried the following:
Everything works as expected except last line. Why can't I set currentTime on it?
Also in general, I am finding this whole HTML5 Audio thing to not be very reliable. Is there a robust javascript wrapper that fallsback to flash ?
You need to do something like this (if you use jQuery)
$('#elem_audio').bind('canplay', function() {
this.currentTime = 10;
});
or in Javascript
var aud = document.getElementById("elem_audio");
aud.oncanplay = function() {
aud.currentTime = 10;
};
The reason behind for this setup is you need to make sure the audio is ready to play.
Check your HTTP server configuration, in my testing environment ( Chrome 69 on Mac OS) setting currentTime property of audio element works only when the audio source is served by a HTTP server support persistent connection.
If the HTTP server you used support persistent connection, you will found (in Chrome DevTool) the Connection field of response headers of your audio source be keep-alive. By contrast if the audio source is served by a persistent connection incompatible server, there will be no Connection field in response headers.
The status code of your audio source HTTP request will be a reference too, 206 Partial Content for persistent connection supported server, 200 OK for an inferior one.
I had the same problem, and the reason was missing headers on the mp3 file, like:
Content-Length, Content-Range, Content-Type
Why cant I set currentTime on it?
Could not reproduce currentTime being set to 0 after setting to 10. Is 18.mp3 duration less than 10?
var request = new XMLHttpRequest();
request.open("GET", "/assets/audio/18.mp3", true);
request.responseType = "blob";
request.onload = function() {
if (this.status == 200) {
var audio = new Audio(URL.createObjectURL(this.response));
audio.load();
audio.currentTime = 10;
audio.play();
}
}
request.send();
jsfiddle http://jsfiddle.net/Lg5L4qso/3/
I ran into this problem after I'd started to use the PHP Server extension to VS Code to serve my HTML/PHP local testing. The problem was resolved for me by going back to my old Abysswebserver setup.
So, it's not simply that "you can't manipulate .currentTime on locally served files" but rather that "you need to pick a server that gives you the right headers". The Status entry for my file from AbyssWebserver, for example, read "Status Code: 206 Partial Content" while the one from PHP Server read "Status Code: 200 OK".
There are other differences though so there may be more to this than just the Status entry. See https://github.com/brapifra/vscode-phpserver/issues/85, for a full header comparison.
If you want to return to the beginning of the audio after it has been played, use load().
// x.currentTime = 0;
x.load();
( https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/load )
this worked for me:
var callaudio = audio; // the audio variable
function fetchAudioFile() {
var requestObj = new Request(callaudio.src, {
method: 'GET',
headers: {
'Accept-Ranges': '1000000000'
},
referrerPolicy: 'no-referrer'
});
fetch(requestObj).then(function (response) {
returnresponse;
}).then(async function (outcome) {
const blob = await outcome.blob();
const url = window.URL.createObjectURL(blob);
callaudio.src = url;
});
};
fetchAudioFile();
The only solution for setting currentTime I got to work reliably was using the onprogress event.
audio.onprogress = function() {
if (audio.currentTime == 0) {
audio.currentTime = 10;
}
}
The solution which worked for me was not setting "src" on directly, but use with type attribute, maybe type attribute is helping browser some way.
My guess is that '10' is longer that you mp3's length.
But that logs the length of mp3 instead of '0'.
I'm doing a project with arduino in which I send different requests to the server (the arduino board) with the method XMLHttprequest and Get from a webpage. Except one of the request the others are used only for sending orders to the server, so I don't expect for an XML response. The other one is a request sent in intervals of 5 seconds for getting different values from the server.
The problem arrives with this last one. Actually the webpage sends the request (because I see it on the browser console and the arduino serial monitor) every 5 seconds, but it doesn't get anything, just the headers of the answer confirming the response but nothing about the XML file. Surprisingly, when I write a normal request using the get method in the browser I get instantly the XML file with the values, and It happens all the time I do that.
I'm going to write the javascript code I'm using on the webpage
setInterval(function tiempo()
{
var request = new XMLHttpRequest();
request.onreadystatechange = function()
{
if (this.readyState == 4) {
if (this.status == 200) {
if (this.responseXML != null) {
// extract XML data from XML file (containing switch states and analog value)
document.getElementById("input1").innerHTML = this.responseXML.getElementsByTagName('dato')[0].childNodes[0].nodeValue;
document.getElementById("input2").innerHTML = this.responseXML.getElementsByTagName('dato')[1].childNodes[0].nodeValue;
document.getElementById("input3").innerHTML = this.responseXML.getElementsByTagName('dato')[2].childNodes[0].nodeValue;
document.getElementById("input4").innerHTML = this.responseXML.getElementsByTagName('dato')[3].childNodes[0].nodeValue;
document.getElementById("input5").innerHTML = this.responseXML.getElementsByTagName('dato')[4].childNodes[0].nodeValue;
document.getElementById("input6").innerHTML = this.responseXML.getElementsByTagName('dato')[5].childNodes[0].nodeValue;
document.getElementById("input7").innerHTML = this.responseXML.getElementsByTagName('dato')[6].childNodes[0].nodeValue;
}
}
}
}
request.open("GET", "URL" + Math.random(), true);
request.send(null);
}
, 5000);
On the other hand, if I only write in the browser URL, I get the XML without any problem.
One las thing I have to say is that right now I'm using a webpage stored in my computer but before I was using a webpage stored in the arduino (on an SD card) and loaded also through the internet from arduino. The same code in that case worked perfectly. The reason because I changed It is because arduino ethernet is not too fast and It took so much time. With the webpage stored in my computer It goes faster because It only needs to send the orders.
Thanks!!
Finally, I figured out the problem. It is the browser. For any reason only Internet Explorer works correctly with the webpage. Neither firefox nor other web browsers got the xml file. I don't know the reason but I would like to find it.
If someone knows something about I would be glad of trying to resolve the problem.
Thanks!!
I have the following function executing on page load:
function get_words()
{
var rawFile = new XMLHttpRequest();
rawFile.open("GET", "file:///C:\Users\myMachineName\Documents\PersonalSite_Improved\wordsEn.txt", true);
rawFile.onreadystatechange = function ()
{
if (rawFile.readyState === 4)
{
if (rawFile.status === 200 || rawFile.status == 0)
{
var allText = rawFile.responseText;
alert(allText);
}
}
rawFile.send(null);
}
}
It is my own use of the procedure from this S.O. thread: Javascript - read local text file
I'll confess that I don't totally understand the procedure. However, I can obviously see that I would be getting an alert of the text file contents if the page was working properly. I ran some tests using console.log() to determine that the first if statement is never entered. But since I have no idea what's going on here, I have no idea how to troubleshoot the issue.
Any help?
The document you are trying to read must be served by an HTTP server, you can't pull up local files from your hard drive or machine. The reason for this is simply security, for if JavaScript could read files on local machines, everyone would be able to open, view and read everything on people's computers. Just run a local HTTP server such as WampServer or something of that nature.
You cannot use an xml request to read a local file due to security reasons.
See this answer for more info.
html
click me
js code
var MyObj =
{
startup : function()
{
var ajax = null;
ajax = new XMLHttpRequest();
ajax.open('GET', 'http://www.nasa.gov', true);
ajax.onreadystatechange = function(evt)
{
if(ajax.readyState == 4)
{
if (ajax.status == 200)
{
window.dump(":)\n");
}
else
{
window.dump(":(\n");
}
}
}
ajax.send(null);
}
}
ajax.status always returning 0, no matter which site it is, no matter what is the actual return code. I say actual, because ajax.statusText returning correct value, eg OK or Redirecting...
ajax.readyState also returns proper values and 4 at the end.
You can overcome this easily in a local environment by setting up a php proxy (xampp a server and pass a querystring for the url you want to grab). Have your php proxy wget the url and echo its contents. That way your local html file (when viewed as http://localhost/your.html) can send ajax requests out of domain all day. Just don't expect the content to work as though it were local to that domain.
Is your site part of http://www.nasa.gov/? Otherwise, XMLHttpRequest will fail due to Same Origin Policy.
Also, if the page is served as a non-HTTP request, the status can be 0. See https://developer.mozilla.org/En/Using_XMLHttpRequest#section_3.