Read contents of folder with Ajax WITOUT jquery - ajax

Setup:
html file on local machine in parent dir
js file in sub dir
image files in sub dir "Fotos"
Following code in js file:
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (true/*this.readyState == 4 && this.status == 200*/) {
alert(this.responseText);
}
};
xhttp.open("GET", "/Fotos", true);
xhttp.send();
This causes TWO alerts to pop up with completely empty message box. I tried playing around with the directory path, but nothing changed, even with just "/". If I delete the true and replace it with the line in /* it doesn't yield a message box at all.
I was hoping to get some form of parsable list of image files from this.
I realize this has been solved with jQuery before, but I want to do this without, as it should be simple enough. Well, why isn't it?

It fails if the /Fotos folder does not exist (or does not have the correct permissions).
Additionally, for XMLHttpRequest to work, it needs the web page to be served by a web server. It must be accessed with http or https protocol (even if in localhost). E.g. http ://localhost/myfolder/pagewithcode.html Then, the Fotos folder must be a subfolder of "myfolder". The code would also work if the route is http: //localhost/pagewithcode.html (and Fotos is a subfolder of the one where pagewithcode.html is).
The code below (slightly modified from yours) gets the contents of the current folder (in which the html page with the JavaScript code is stored).
Notice that the responseText is HTML, with all the tags, not just the list of files, so that it could be shown in the browser.
<html>
<body>
<script>
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
// enter here only when success
console.log(this.readyState);
console.log(this.responseText);
}
else {
// enter here for all state changes except success
console.log(this.readyState);
console.log(this.responseText);
}
};
xhttp.open("GET", ".", true);
xhttp.send();
</script>
</body>
</html>
If Fotos is a subfolder of the one the html page is in, then you'd better remove the initial '/' of the path (otherwise, you are getting a Fotos folder in the root folder of the server):
xhttp.open("GET", "Fotos", true);

Related

Ajax path issues

I am using XAMP localhost. I have a folder named wesite in my htdocs for my website template I am creating. My ajax call works fine when both js and php is in the root of this folder. However, when I create a folder name functions and put the js and php script there at the root, the js ajax call don't call the php. Below is the code. It works fine when both are in the directory as the index.php or any other html files, but not in a sub directory. I know it has to do with the path because the scripts work otherwise.
The folder structure is like this there is a folder called Website which has all the html files saved with php ext. Inside this Website folder I have the functions folder which has all the js and php functions no sub directory in the functions folder so all js and php files are at the root of the functions folder. When I look at the inspect element in Chrome, it says the update.php file has a 404 file not found error. This is weird giving the fact that both the js and php are in the same folder. The php script is a simple test script which just echo "Hello From php" to see if I am getting a response
function navUpdate(){
alert('Hello from functins');
var navItemOne = document.getElementById('menu-item-one').innerHTML;
var navItemTwo = document.getElementById('menu-item-two').innerHTML;
var navItemThree = document.getElementById('menu-item-three').innerHTML;
var navItemFour = document.getElementById('menu-item-four').innerHTML;
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function(){
if(this.readyState == 4 && this.status == 200){
alert(this.responseText);
}
}
xhttp.open("POST", "update.php", true);
xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhttp.send(`nav-item-one=${navItemOne}&nav-item-two=${navItemTwo}&nav-item-
three=${navItemThree}&nav-item-four=${navItemFour}`);
}

AJAX response returns current page

I was searching for a similar issue for a while now, but none of the solutions worked for me (and I couldn't find exactly the same issue).
First of all, the website I'm working on is running on Zend Framework. I suspect that it has something to do with the issue.
I want to make a pretty basic AJAX functionality, but for some reason my response always equals the html of the current page. I don't need any of Zend's functionality, the functions I need to implement could (and I'd prefer them to) work separately from the framework.
For testing purposes I made it as simple as I could and yet I fail to find the error. I have a page "test.php" which only has a link that triggers the ajax call. Here's how this call looks:
$('.quiz-link').click(function(e){
e.preventDefault();
$.ajax({
URL: "/quiz_api.php",
type: "POST",
cache: false,
data: {
'test': 'test'
},
success: function(resp){
console.log(resp);
},
error: function(resp){
console.log("Error: " + reps);
}
});
});
And this quiz_api.php is just:
<?php
echo "This is a test";
?>
When I click on the link I get the entire HTML of the current page. "This is a test" can't be found there. I'm also getting an error: "Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check http://xhr.spec.whatwg.org/."
I reckon it has to do with the JS files that are included into this HTML response, but I've also tried setting "async: true" and it didn't help.
I would like to avoid using Zend Framework functions for this task, because I'm not well familiar with it and even making a simple controller sounds rather painful. Instead I want to find out what's causing such behavior and see if it can be changed.
PS: I've also tried moving quiz_api.php to another domain, but it didn't change anything.
I know that it might be an older code but it works, simple and very adaptable. Here's what I came up with. Hope it works for you.
//Here is the html
Link Test
<div id="test_div"></div>
function test(){
// Create our XMLHttpRequest object
var hr = new XMLHttpRequest();
// This is the php file link
var url = "quiz_api.php";
// Attaches the variables to the url ie:var1=1&var2=2 etc...
var vars = '';
hr.open("POST", url, true);
//Set content type header information for sending url encoded variables in the request
hr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
// Access the onreadystatechange event for the XMLHttpRequest object
hr.onreadystatechange =
function(){
if(hr.readyState == 4 && hr.status == 200){
var return_data = hr.responseText;
console.log(return_data);
document.getElementById('test_div').innerHTML = return_data;
}else{
document.getElementById('test_div').innerHTML = "XMLHttpRequest failed";
}
}
//Send the data to PHP now... and wait for response to update the login_error div
hr.send(vars); // Actually execute the request
}
you can change the whole page with a document.write instead of changing individual "div"s

304 not modified, Ajax is not working?

<script>
var xmlHttp =new XMLHttpRequest();
var url= "summary.txt";
xmlHttp.onreadystatechange = function() {
if (xmlHttp.readyState == 4 && xmlHttp.status == 200) {
var myArr = JSON.parse(xmlHttp.responseText);
myFunction(myArr);
}
xmlHttp.open("GET", url , true);
xmlHttp.send();
} function myFunction(arr)
var output="";
var i;
for(i=0;i<arr.length;i++){
output+='<p>'+arr[i].title+arr[i].image+arr[i].price+'</p>';
}
document.getElementById("proTab").innerHTML = output;
}
</script>
I stored all both the HTML and JSON in the htdocs folder, did xampp start and made sure Apache and mysql were running on the control panel. I then typed the link to the html using the "localhost/" to get to the html but the page was blank. Sorry for all the details.
Console says 304 Not modified. What should I do?
My guess is that you are using IE, which caches AJAX GET requests aggressively. I would suggest changing to using POST for the AJAX request.
Another alternative if you must use GET requests. You can add a unique querystring value to each GET request like this:
var url = 'summary.txt' + '?' + Math.random()*Math.random();
I used this for jQuery AJAX:
$.ajaxSetup({
// Disable caching of AJAX responses
cache: false
});
I think you can find how to use this for JS without jQuery. So the idea is to clear cache before sending the request, because server responds that nothing changed and sends 304 NOT MODIFIED instead of 200 OK. Namely, your summary.txt hasn't changed (not modified), so that's what server telling you.

Firefox extensions and full file paths from HTML form?

I have built a Firefox extension using the Addon SDK that opens up a new tab with a HTML page from the extensions directory and attaches a content script to it:
function openHtmlLoadFormTab(htmlFileName, jsWorkerFileName) {
tabs.open({
url: data.url(htmlFileName),
onReady: function(tab) {
var tabWorker = tab.attach({
contentScriptFile: [ data.url(jsJquery), data.url(jsWorkerFileName) ]
});
}
});
}
I have an <input type="file"> in the HTML file and some code that handles the "submit" event in the JS file (these files are given by htmlFileName and jsWorkerFileName respectively)
Because of security reasons, I cannot access the full file path in JS with document.getElementById('uploadid').value. I only get the file's name.
However, since this is a Firefox extension, I'm wondering if there is anyway to override this restriction?
I have been looking into netscape.security.PrivilegeManager.enablePrivilege("UniversalFileRead") and mozFullPath but I haven't been able to get it to work. I believe it's deprecated anyway?
The other solution is to build an XUL-based UI and prompt for the file there somehow, but I would like to know for sure if there is anyway to get this to work in HTML.
First edit with small example code
I built a small sample extension to illustrate how I'm doing things.
lib/main.js
var self = require('self');
var tabs = require('tabs');
var data = self.data;
var jsLoadForm = "load-form.js", htmlLoadForm = "load-form.html";
var jsJquery = 'jquery-1.8.0.min.js';
exports.onUnload = function(reason) {};
exports.main = function(options, callbacks) {
// TODO: remove this debugging line
openHtmlLoadFormTab(htmlLoadForm, jsLoadForm);
};
function openHtmlLoadFormTab(htmlFileName, jsWorkerFileName) {
tabs.open({
url: data.url(htmlFileName),
onReady: function(tab) {
var tabWorker = tab.attach({
contentScriptFile: [ data.url(jsJquery), data.url(jsWorkerFileName) ]
});
}
});
}
data/load-form.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Form</title>
<script lang="text/javascript">
function fileChanged(e) {
// this is just the file name
alert("html js: files[0].name: " + e.files[0].name);
// mozFullPath is indeed empty, NOT undefined
alert("html js: files[0].mozFullPath: " + e.files[0].mozFullPath);
}
</script>
</head>
<body>
<form name="my-form" id="my-form" action="">
<div>
<label for="uploadid1" id="uploadlabel1">File (JS in HTML):</label>
<input type="file" name="uploadid1" id="uploadid1" onchange="fileChanged(this)"/>
</div>
<div>
<label for="uploadid2" id="uploadlabel2">File (JS in content script): </label>
<input type="file" name="uploadid2" id="uploadid2" onchange="fileChangedInContentScript(this)"/>
</div>
<div>
<label for="uploadid3" id="uploadlabel3">File (JS using jQuery in content script):</label>
<input type="file" name="uploadid3" id="uploadid3" />
</div>
</form>
</body>
</html>
data/load-form.js
$(document).ready(function() {
$("#uploadid3").change(function(e) {
// in jquery, e.files is null
if(e.files != null)
console.log("jquery: e.files is defined");
else
console.log("jquery: e.files is null");
// this works, prints the file name though
console.log("$('#uploadid3').val(): " + $("#uploadid3").val());
// this is undefined
console.log("$('#uploadid3').mozFullPath: " + $("#uploadid3").mozFullPath);
});
});
// this handler never gets called
function fileChangedInContentScript(e) {
alert("js content script: filechanged in content script called");
}
As you can see in main.js, I used jquery-1.8.0.min.js, downloaded from the jQuery website.
Note: I also tried these without jQuery included as a content script when I opened the tab in main.js, but no luck.
The conclusion is that mozFullPath is indeed empty when I access it from JS embedded in the HTML page and I cannot find a way to access mozFullPath from jQuery, nor can I find a way to add a onchange handler in load-form.html that's defined in load-form.js
Second edit with onchange handler in the load-form.js content-script
I added the following code to load-form.js to catch the onchange event.
I also removed the jQuery content script from main.js
document.addEventListener("DOMContentLoaded", function() {
try {
document.getElementById("uploadid2").addEventListener('change', function(e) {
console.log("addeventlistener worked!");
console.log("e: " + e);
console.log("e.target: " + e.target);
console.log("e.target.files: " + e.target.files);
console.log("e.target.files[0].name: " + e.target.files[0].name);
console.log("e.target.files[0].mozFullPath: " + e.target.files[0].mozFullPath);
});
console.log('added event listener')
} catch(e) {
console.log('adding event listener failed: ' + e);
}
}, false);
This still outputs an empty string for mozFullPath:
info: added event listener
info: addeventlistener worked!
info: e: [object Event]
info: e.target: [object HTMLInputElement]
info: e.target.files: [object FileList]
info: e.target.files[0].name: test.sh
info: e.target.files[0].mozFullPath:
Is there anyway to acquire the needed permissions? How can I get my hands on that full path? I need the full path so I can pass it to an application the extension launches. (There are workaround solutions where I can do without the full path, but they decrease the quality of the extension)
fileInput.value property is meant to be accessible to web pages so it will only give you the file name, not the full path - web pages have no reason to know the full path on your machine. However, as a privileged extension you should be able to access the File.mozFullPath property. In this particular case you would do it like this:
var files = document.getElementById('uploadid').files;
if (files.length > 0)
{
// Assuming that only one file can be selected
// we care only about the first entry
console.log(files[0].mozFullPath);
}
The big question of course is whether your code is allowed to access File.mozFullPath. I suspect that a content script in the Add-on SDK won't have the necessary privileges. The main extension code will have the privileges but getting to the input field from there is hard...

Using xmlhttprequest in IE only includes the contents of the body tag

When I try to get the contents of a htm file into a div using a xmlhttprequest object in Firefox it includes everything, but in IE it only includes the contents of the body tag. In other words it ignores all the styling (in the head tag) of the page, rendering it ugly.
Is it possible to get the full page when using xmlhttprequest in internet explorer?
edit:
document.getElementById('divtoreceivetheresponse').innerHTML = xmlHTTP.responseText
This line in FF gets the page contents including the <head></head> section.
In IE it just gets the contents inside the <body></body> section.
I got an answer from elsewhere. Basically it does include all the page (not just the body) but IE chooses not to render it (probably the correct behavour)
I therefore worked out some code to extract the css, place it in the head, and place the body stuff in the target div. So both html and css from the external page would be got.
<html><head>
<script type="text/javascript" language="javascript">
function include(lyr,url)
{
if (document.all)
{
try {
var xml = new ActiveXObject("Microsoft.XMLHTTP");
xml.Open( "GET", url, false );
xml.Send()
}
catch (e) {
var xml = new ActiveXObject("MSXML2.XMLHTTP.4.0");
xml.Open( "GET", url, false );
xml.Send()
}
}
else
{
var xml=new XMLHttpRequest();
xml.open("GET",url,false);
xml.send(null);
}
text = xml.responseText;
text = text.replace("<html>","");
text = text.replace("</html>","");
text = text.replace("<head>","");
text = text.replace("</head>","");
text = text.replace("<body>","");
text = text.replace("</body>","");
splittext = text.split("<style type=\"text/css\">");
splittext = splittext[1].split("</style>");
css = splittext[0];
everythingelse = splittext[1];
addCss(css);
document.getElementById(lyr).innerHTML=everythingelse;
}
function addCss(cssCode) {
var styleElement = document.createElement("style");
styleElement.type = "text/css";
if (styleElement.styleSheet) {
styleElement.styleSheet.cssText = cssCode;
} else {
styleElement.appendChild(document.createTextNode(cssCode));
}
document.getElementsByTagName("head")[0].appendChild(styleElement);
}
</script>
</head>
<body onload="include('adiv','test.htm')">
<div id="adiv">sdfgboui hsdguhwruh o ikuy </div>
</body>
</html>
The code is far from perfect, but it does the job and I will probably improve the code bit by bit now that I know it works

Resources