AJAX not working properly in Firefox - javascript

I'm using Firefox 20.0.1 and Apache. I have some AJAX calls to retrieve an HTML document from the server. The strange thing is that in one function an AJAX call works fine, but in another function to get a different document it doesn't work. Also, it does work in Chrome.
Any ideas on what this could be? The code is as follows:
loc = "Temp\folder1\folder2\title.html";
var req = new XMLHttpRequest();
req.open("POST", loc, false);
req.send();
alert(req.responseText); // Displays "object not found" error.
Background Information:
I am writing an EPUB reader. The EPUB file is stored on the server and extracted using PHP. I want to get (for example) chapter 1's content, which is stored in an HTML document in the extracted location.
Solution
The problem was the Firefox has issues with backslashes in URLs.
I simply replaced all backslashes with forward slashes before sending the request.

The "object not found" text is an alias for an HTTP 404 error in some web servers. If you run alert(req.status); after your req.send();, it can provide insight into what may be the problem. In your case, it is in fact showing a 404 error, and can be traced back to the URL having \ characters in it.

Related

Perform window.location.replace multiple times in for loop

I'm not able to get my script to run window.location.replace multiple times. I have a flask application that create files given the unique ids found from streaming access logs on the server. Once the file is on the server, I have a flask route that if the user is redirected to https://somewebsite.com/getFile/<id>, it will than push the file that was created on the server to the client.
Here's my script below:
<script>
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
var response = '';
if(xhr.readyState === 4 && xhr.status === 200){
response = xhr.responseText;
response = response.substring(0, response.length-1);
response = response.split('\n');
for(x in response){
url_path = response[x];
window.location.replace(url_path);
};
};
};
xhr.open('GET', '{{ url_for('stream') }}', true);
xhr.send();
</script>
I did a few console.log() calls to see if the for loop is running correctly and it is. Even the url_path given to window.location.replace is correct. One thing to note is that when being redirecting to https://somewebsite.com/getFile/<id>, the browser doesn't technically change to that url path, because flask isn't rendering a template, but instead returning a download file, so the browser stays at the current url path after the file is downloaded.
I'm not sure why I am not able to get the script to run window.location.replace more than once. It seems like if there's 2 url_path in the response object, only the last one is being downloaded. Same goes with 3 or 4 paths. Any insight would be helpful. Thanks
An alternative solution I just figured out was instead of redirecting the same browser to multiple urls, why not just open them up in different tabs. I did this by using window.open, which to my surprise did work.
However, my browser pop up blocker did block them out at first, but after changing the settings and allowing pop ups for the page, I was successfully able to have multiple files downloaded to the client. Also, since there's no template rendering on the server side, the tabs themselves don't actually pop up, so the browser won't be flooded with tabs.
I'm still interested in knowing why window.location.replace didn't work if anyone knows why.
Your code is not working because what window.location.replace does is to literally replace the source document (see documentation) with the one provided by the new URL.
What this means is that any code you put after window.location.replace won't be executed.
That is why window.open works perfectly for your situation, because it will open a new document apart from the one it is called. But be careful because not all parameters work for all browsers (check this for compatibility specifications).

How can I get the HTML of a site as a variable in Javascript or jQuery?

I'm trying to get 10 million digits of pi from this site to use as a variable in Javascript. I'd like to get the HTML from the site with a simple command instead of hardcoding it. I'm using Codepen so I can't just copy and paste the text (Codepen doesn't allow so many characters). Can you help me get the HTML?
Any help is greatly appreciated!
Copying and pasting those digits would take hours
Shouldn't it be as simple as ctrl+a then copy? Then just trim the top and bottom unnecessary parts? Anyway here's a solution you could try.
Open the website
Open the Developer Tools [ Ctrl+Shift+i ], I'm on Google Chrome on a linux build
Copy & Paste the code below into the console
Profit, 10MB file
saveToFile(document.querySelector('center').textContent);
function saveToFile(string){
var blob = new Blob([string], {type:'application/text'});
var url = URL.createObjectURL(blob);
var hiddenAnchorElem = document.createElement('a');
applyAttrs.call(hiddenAnchorElem, {
href: url,
target: '_blank',
download: 'pi.text'
});
hiddenAnchorElem.click();
function applyAttrs( attrs ){
var keys = Object.keys;
keys(attrs).forEach( attr => {
this[attr] = attrs[attr];
});
}
}
You could use AJAX, if it's on the same server as your website, or if CORS is allowed by the site (which is unfortunately not likely).
You'll probably want to write server side code that pulls in the HTML of the page you would like to request, and prints it out - a proxy of sorts - and use the URL of that page rather than the actual page you are trying to get the HTML for.
Here's an example of how AJAX can be used: https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest. In that example, the HTML of the page would be stored in this.responseText in the callback handler for the AJAX call's onload event.
If you're just using this locally, though, you may be able to get around the Cross Origin Request Policy.
If you run Chrome from your Command Prompt using:
Chrome.exe --disable-web-security
...from the directory in which Chrome is installed, you'll be able to use AJAX to get the contents of the page without any server-side code.

How to start two or more custom URL Protocol from Javascript

I have an old html page that creates a script file and executes it using:
fsoObject = new ActiveXObject("Scripting.FileSystemObject")
wshObject = new ActiveXObject("WScript.Shell")
I am trying to modify it and make it usable also from other browsers. If you know the answer stop reading and please answer. If there is no quick answer, here is the description of my attempts. I was successful in doing the job, but only when the script is shorter than 2000 characters. I need help for scripts longer than 2000 characters.
The webpage is for internal use only, so it is easy for me to create a custom URL protocol on each computer that runs a VBScript file from a network drive.
I created my custom URL Protocol that starts a VBScript file like this:
Windows Registry Editor Version 5.00
[HKEY_CLASSES_ROOT\MyUrlProtocol]
"URL Protocol"=""
#="Url:MyUrlProtocol"
"UseOriginalUrlEncoding"=dword:00000001
[HKEY_CLASSES_ROOT\MyUrlProtocol\DefaultIcon]
#="C:\\Windows\\System32\\WScript.exe"
[HKEY_CLASSES_ROOT\MyUrlProtocol\shell]
[HKEY_CLASSES_ROOT\MyUrlProtocol\shell\open]
[HKEY_CLASSES_ROOT\MyUrlProtocol\shell\open\command]
#="C:\\Windows\\System32\\WScript.exe \"X:\\MyUrlProtocol.vbs\" \"%1\""
In MyUrlProtocol.vbs I have this:
MsgBox "The length of the link is " & Len(WScript.Arguments(0)) & " characters"
MsgBox "The content of the link is: " & WScript.Arguments(0)
When I click on click me I see two messages, so everything works well (tested with Chrome and IE in Windows 7.)
It works also when I execute document.getElementById("test").click()
I thought this could be the solution: I would pass the text of the script to the VBS static script, which would create the dynamic script and run it, but with this system I can't pass more than ~2000 characters.
So I tried to split the text of the script in chunks smaller than 2000 characters and simulate several clicks on the link, but only the first one works.
So I tried with xmlhttp.open("GET","MyUrlProtocol:test",false);, but Chrome says Cross origin requests are only supported for HTTP.
Is it possible to pass more than 2000 characters to a VBScript script via a custom URL protocol?
If not, is it possible to call several custom URL protocols in sequence?
If not, is there another way to create a script file and run it from Javascript?
EDIT 1
I found a solution, but in Chrome only works when it likes, so I'm back to square one.
The code below in IE executes the script 4 times (correct), but in Chrome only the first execution runs.
If I change it to delay += 2000, then Chrome usually runs the script 2 times, but sometimes 1 and sometimes 3 or even 4 times.
If I change it to delay += 10000, then it usually runs the script 4 times, but sometimes misses one.
The function is always executed 4 times, both in Chrome and IE. What is weird is that the sr.click() sometimes does nothing and the function execution continues.
<HTML>
<HEAD>
<script>
var delay;
function runScript(text) {
setTimeout(function(){runScript2(text)}, delay);
delay += 100;
}
function runScript2(text) {
var sr = document.getElementById('scriptRunner');
sr.href='intelliclad:'+text;
sr.click();
}
function test(){
delay = 0;
runScript("uno");
runScript("due");
runScript("tre");
runScript("quattro");
}
</script>
</HEAD>
<BODY>
<input type="button" value="Run test" onclick="test()">
scriptRunner
</BODY>
</HMTL>
EDIT 2
I tried with Luke's suggestion of setting the next timeout from inside the call back but nothing changed (IE works always, Chrome whenever it likes).
Here is the new code:
var scripts;
var delay = 2000;
function runScript() {
var sr = document.getElementById('scriptRunner');
sr.href = 'intelliclad:' + scripts.shift();
sr.click();
if(scripts.length)
setTimeout(function() {runScript()}, delay);
}
function test(){
scripts = ["uno", "due", "tre", "quattro"];
runScript();
}
Some background: The page asks for the shape of a panel, which can be just a few parameters [nfaces=1, shape1='square', width1=100] or hundreds of parameters for panels with many faces, many slots, many fasteners, etc. After asking for all the parameters a script for our internal 3D CAD (which can be larger than 20KB) is generated and the CAD is started and asked to execute the script.
I would like to do all on the client side, because the page is served by a Domino web server, which can't even dream of managing such a complex script.
I didn't read your whole post...have an answer:
I too wish that custom url protocols can handle long urls. They simply do not. IE is even worse as some OSs only accept 800 chars.
So, here's the solution:
For long urls, only pass a single use token. The vbscript uses the token
and does a url get to your web server to get all of the data.
This is the only way I've been able to successfully pass lots of data around. If you ever find a clearer solution, please remember to post it here.
Update:
Note that this is the best way I have found to deal with the url protocol limitations. I too wish this was not necessary. This does work and works well.
You mentioned Dominos, so possibly you need something in a POS environment... I create a web based POS system, so we could face a lot of the same issues.
Suppose you want a custom url to print a pdf to the default printer without the annoying popup window. We need to do this thousands of times a day...
When building the web page, add the print button which when pressed calls the custom url: myproto://printpdf?id=12345&tocken=onetimetoken
this will execute your vbscript on the local desktop
in your vbscript, parse the arguments and react. In this case, your command is printpdf and the id is 123456 and you have a onetime tocken key.
have the vb script to an https get to: https://mydomain.com/APIs/printpdf.whatever?id=12345&key=onetimetoken
check the credentials based on the ip address and token, if all aligns, then return the contents of the pdf (you may want to convert the pdf to a byte array string)
now the vbscript has the pdf, assemble it and write it to a temp folder then execute a silent pdf print command (I use Sumatra PDF http://blog.kowalczyk.info/software/sumatrapdf/free-pdf-reader.html)
mission accomplished.
Since I do know what you what to do in your custom url and the general workflow, I can only describe how I've solved the sort url issue.
Using this technique, the possibilities are limitless. You have full control over the local computer running the web browser, you have a onetime use token which grants access to a web API with can return any sort of information you program.
You could write a custom url protocol to turn on the pizza oven if you wanted :)
If you are not able to create the server side code which is listening for vbscript's get request then this would not work.
You might be able to pass the data from the browser to the vbscript using the clipboard.
Update 2:
Since in this case the data is on the client (one single form can define hundreds of parameters), the server API doesn't know what to answer to the vb script request. So the workflow described above must be preceded by these two steps:
The onkeypress event executes a submit to send the current parameters to the server
The server replies with the refreshed form, adding to the body onload a call to a function which uses another submit to call the custom url, as described on point 1 listed above.
Update 3:
stenci, what you've added (in Update 2) will work. I would do it like this:
user presses a button saying I'm done editing the form
ajax post the form to the server
the server saves the data and attaches unique key to the datastore
the server returns the key to ajax callback function
now the client has a single use key and invokes the url schema passing the key
vbscript does an https get to the server and passes the key
server returns the data to the vbscript
It is a bit long winded. Once coded it will work like a charm.
The only other alternative I can see is to copy the form data to the clipboard using something like: http://zeroclipboard.org/
and then in vbscript see if you can read the clipboard like: Use clipboard from VBScript
How about creating an iFrame for each instance?
Something like this:
function runScript(text) {
var iframe = document.createElement('iframe');
iframe.src = 'intelliclad:'+text;
document.body.appendChild(iframe);
}
function test(){
runScript("uno");
runScript("due");
runScript("tre");
runScript("quattro");
}
You can then use css styling to make these iframes transparent / hidden.
You might not like this answer, but I've used this method in the past and it works.
Instead of relying on ActiveX, consider using a Java Applet, and JNI.
Basically, you have to make sure the native scripts you want to run are available on your client machine, along with a JNI wrapper.
The applet will have to be at least self signed, for the browser to allow it to load and access a native library. Once the JNI libraries are loaded, you can easily call methods from the page / applet.
As a consequence of using Java, you could possibly use the same applet for windows as well as linux clients, provided of course you have native libraries present on the respective clients.
This series of articles talks about precisely your problem : http://www.javaworld.com/article/2076775/java-security/escape-the-sandbox--access-native-methods-from-an-applet.html
P.S the article is really old, but the concept remains unchanged.

In JavaScript: Is there a way to make an HTTP request that loads a JavaScript file and is synchronous in IE 9 without jQuery?

Just like the title says. I need a way to load a JavaScript file via a synchronous ajax request that works in IE 9. The solution cannot use jQuery.
What I have so far (which works in chrome/ff/opera/etc.) is good but gives an "Access Denied" error when used in IE 9. Here is what I have now:
var xhr=new XMLHttpRequest();
xhr.open("GET","//path/to/someJsFile.min.js",false);
xhr.send(null);
var jsText = xhr.responseText;
The XMLHttpRequest object seems to work for some file types, but not .js files. Any ideas? This code is going on a client's page so I have no access to their backend code or the rest of the site's code.

Getting ResponseText without calling servlet using xmlhttprequest in IE(Any version)

I'm using xmlhttprequest to call servlet. It is working fine in Firefox. But, in IE, only if I click refresh button, it is working(that too sometimes). Otherwise, it is not triggering. Moreover, the response text is displayed without calling the servlet. Is that using Cache or what? I don't have any idea . Help me out please.
MSIE is too eager in caching XHR requests. The only feasible way to get around this is to add a querystring with a timestamp to the XHR URL.
var url = '/url/to/your/servlet?' + new Date().getTime();
Thanks one and all. Actually, I used "GET" instead of "POST" while calling the servlet in javascript. When I tried POST, it is working fine.
To get around IEs over zelous caching of xhr you must get your servlet to add
Cach-Control:max-age=0
to the response headers of all html and .js files served up.
This will cause a revalidate of all files with this response, next time they are requested from IE including XHR. (must-revalidate did not seem to work on xhr loaded java script file, not sure why)
Be sure to clear the IE cache after this is done for it to take effect the next load.
IE will behave nicely with this setting. But dont put this into production of course.

Categories