JavaScript - Scan and create link files from a folder - javascript

I have created a bunch of local HTML files and I'm trying to translate them thanks to xml files and a lot of JavaScript/JQuery. The translation part is done and I'm now trying to do a pulldown menu with all of the xml files to select the desired language.
First, I tried to scan a local folder named "images" and print the name of my files in a blank html page but I was not able to do it. I did a lot of research on stack overflow and on forum.jquery.com but even if I tried a lot of things, nothing worked.
Here is what I pulled of for the moment :
HTML side :
<body>
<div id="fileNames">
<p></p>
</div>
<script>window.onload=ChangeLangue</script>
</body>
JS/Jquery side :
var folder = "images/";
$.ajax({
url: folder,
success: function (data) {
$(data).find("a").attr("href", function (i, val) {
if (val.match(/\.(jpe?g|png|gif)$/)) {
$("body").append("<img src='" + folder + val + "'>");
}
});
}
});
What am I doing wrong? Is this possible?

Browsers don't allow cross origin requests. An error will be thrown as
Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https. Because the protocol is file://
You can do it by setting a flag:
Quit Chrome.
Restart using following command.
MAC : In terminal, open /Applications/Google\ Chrome.app --args --allow-file-access-from-files
WINDOWS : In Run, C:/PATH_TO_CHROME_INSTALLATION_FOLDER/chrome.exe --allow-file-access-from-files
Now you can access the files from your computer. To verify it, you can go to chrome://version and you can see the flag enabled under the Command Line section.
As you have var folder="images/", and suppose the page loaded in the browser is in /Users/Default/Desktop folder, the ajax request made will be
file:///Users/Default/Desktop/images
If you add / before the folder var folder = "/images/",
the request will be file:///images/.
Make sure to provide the required/complete path.
After getting the response, since the response is in html format, you can use document.write(response). From there you can view and navigate in/out of folders.
I tried with below JS Code and got the result.
<script type="application/javascript">
var url = "/Users/Default/Downloads";
var req = new XMLHttpRequest();
req.open("GET",url,true);
req.onreadystatechange=function(){
if(req.readyState === 4)
{
document.write(req.responseText);
}
};
req.send();
</script>
P.S. : No idea if it works in Windows machines. Correct me if I am wrong. TIA.

Related

Trying to use XML returned by merriam webster dictionary API but request getting failed. Status returned is zero. What to do?

I saw this great API (http://www.dictionaryapi.com/products/api-collegiate-dictionary.htm) by merriam webster that returns an XML file with all the details in it including definitions and pronunciations.
This API requires a key so i registered and got a key for my account.
I am making the request using Javascript(XHR) but the status returned is zero.
Then i googled the error it said that it may be because my request is going from a "file:///" protocol instead of "http://", so i installed LAMP stack on my PC then hosted the file on my localhost server and even then no luck.
Another thread said that i cant make cross domain requests.
Please can you help me. Below is my HTML code from which i call function in my javascript file.
<html>
<head>
<script type="text/javascript" src="context-script.js">
</script>
</head>
<body>
<h1>Merriam Webster</h1>
<div>
<b>To:</b> <span id="to"></span><br />
<b>From:</b> <span id="from"></span><br />
<b>Message:</b> <span id="message"></span><br/>
<b>Sound:</b><span id="sound"></span><br />
</div>
<script>
callOtherDomain();
</script>
</body>
</html>
Below is my JAvascript file context-script.js code:
function callOtherDomain()
{
invocation = new XMLHttpRequest();
var url = 'http://www.dictionaryapi.com/api/v1/references/collegiate/xml/happy?key=8f394b2c-77e8-433d-b599-f3ca87660067';
//url="note.xml";
if(invocation)
{
invocation.open('GET', url, true);
invocation.withCredentials = "true";
invocation.onreadystatechange = handler;
invocation.send();
alert("ref");
}
}
function handler(evtXHR)
{
if (invocation.readyState == 4)
{
alert("erg");
if (invocation.status == 200)
{
var response = invocation.responseXML;
document.getElementById("to").innerHTML=
response.getElementsByTagName("dt")[0].childNodes[0].nodeValue;
document.getElementById("from").innerHTML=
response.getElementsByTagName("dt")[1].childNodes[0].nodeValue;
document.getElementById("message").innerHTML=
response.getElementsByTagName("dt")[2].childNodes[0].nodeValue;
}
else
alert(invocation.status);
}
else
dump("currently the application is at" + invocation.readyState);
}
But when i change the URL to "note.xml" which is locally stored on the localhost code works absolutely fine.
Thanks in advance.
While this question is several years old, I worked with dictionaryapi.com previously and the solution is two-fold:
Your first step to host on a local server was right on (localhost:8000 or http://127.0.0.1:8000). I prefer using the Python SimpleHTTPServer, started in the root directory of the page you're trying to host with whichever CLI tool you're most familiar/comfortable with, py -m http.server.
After that, just complete a jQuery call using ajax, get, or XMLHttpRequest—whichever you prefer. For example:
$.ajax({
url: 'http://www.dictionaryapi.com/api/v1/references/collegiate/xml/[YourWord]?key=[YourKeyHere],
method: "GET"
}).done(function(response){
console.log(response);
});

Why is this a Cross Domain Request and how to solve it? [duplicate]

I'm currently working through the book "Head first HTML5 programming". I want to load the content of a file named sales.json from a web server on my own machine. I used wampserver for this.
In the folder wamp/www/gumball/ I put all relevant .html, .js and .css files, and also the sales.json file.
My JavaScript code is very simple:
window.onload = function() {
var url = "http://localhost/gumball/sales.json";
var request = new XMLHttpRequest();
request.open("GET", url);
request.onload = function() {
if (request.status == 200) {
updateSales(request.responseText);
}
};
request.send(null);
}
function updateSales(responseText) {
var salesDiv = document.getElementById("sales");
salesDiv.innerHTML = responseText;
}
This doesn't do anything! Typing the link: http://localhost/gumball/sales.json in my browser opens the right file, so the link should be correct. Even when using the .js files that come with the book (with a finished version of the application I'm trying to make), nothing loads.
Testing with alert statements tells me the request.onload event never happens. I'm clueless as to why this is the case.
A fact I don't quite understand yet: when I type: http://localhost/gumball/sales.json: in my browser (I added a colon at the end of the link), I get a 403 Forbidden error! Why does this happen? Does this have something to do with my problem?
I open html document with firefox
Your HTML document must be open with a URL in http://, not file://, if you want it to be able to open in javascript another document, unless the second document is served with relevant CORS headers.
This is due to same origin policy.
As you have a local WAMP server, there is no problem : simply open your file using a http:// URL like you do for your JSON file.

Getting a JSON file using jQuery without a web server

I had a coding interview quiz for front-end working with JSON and whatnot. I submitted my file but I'd just like to learn what I was missing.
And one of the reqs was Should not require a web server, and should be able to run offline..
I used jQuery and used $.getJSON() to get the data from the .JSON file. I threw it up on my WAMP localserver and it worked flawlessly across all three major browsers (IE, Firefox, Chrome). Then I moved that project to Desktop, so essentally, without a LOCALSERVER.
On Firefox 30.0, it worked great. No problems.
Oon Google Chrome, I know you can't access local files without a web server...
On Internet Explorer 11, however... it didn't work. Why?
Here is what I am using. It's not complex.
function loadTasks() {
console.log("Loading tasks...");
$.getJSON("data.json", function(result) {
$.each(result, function(i, task) {
$("#load_tasks").append(
"<div class='row'><span class='data-task'>" + task.name +
"</span> <span class='data-date'>" + task.date +
"</span> <span class='data-name'>" + task.assigned +
"</span> </div>");
});
});
}
and here is data.json
This seems to be a bug in jQuery. This bug has been reported to jQuery. The bugs status is fixed. But it seems, the bug is still at large.
Explanation
Generally in IE, ajax is implemented through ActiveXObjects. But in IE11, they made some tweaks to ActiveXObject implementation that if we try to do the following:
typeof(window.ActiveXObject)
instead of returning 'function', as it is said in IE docs, it returns undefined. jQuery used to use this to switch between xhr in normal browsers and between one in IE. Since the check evaluates to undefined, code used to create xhr object in normal browsers is run.(which of-course is a bug, strangely, for non-local files it working fine).
In a bug filed to bugs.jquery.com, the bug reporter asks,
To fix the problem it's enough to change the condition: use
"window.ActiveXObject !== undefined ?" instead of
"window.ActiveXObject ?"
jQuery developers does try to fix this with this commit, but the comment under the commit says its still not fixed and also suggests a possible way to approach this problem.
var activex; // save activex somewhere so that it only need to check once
if ( activex === undefined )
try {
new ActiveXObject("MSXML2.XMLHTTP.3.0");
activex = true;
} catch (e) {
activex = false
}
xhr = activex ? createActiveXHR() : createStandardXHR();
I tried running your code in my machine and it works fine in IE.
However if this is not running in your machine there should be some issue with IE settings. Apart from this if you want to read local file you can try the below code to resolve this issue for IE
function showData(){
function getLocalPath(fileName/*file name assuming in same directory*/){
// Remove any location or query part of the URL
var directoryPath = window.location.href.split("#")[0].split("?")[0];
var localPath;
if (directoryPath.charAt(9) == ":") {
localPath = unescape(directoryPath.substr(8)).replace(new RegExp("/","g"),"\\");
}
localPath = localPath.substring(0, localPath.lastIndexOf("\\")+1)+fileName;
console.log(localPath);
return localPath;
}
var content = null;
try {
var fileSystemObj = new ActiveXObject("Scripting.FileSystemObject");
var file = fileSystemObj.OpenTextFile(getLocalPath("data.json"),1);
content = file.ReadAll();
file.Close();
} catch(ex) {
console.log(ex);
}
console.log(content);
}
showData();
Run your html file in browser from file path and try running above function in console. It will output the content of json file in console.
You can create a wrapper for above code to use in XHR request. Let me know if you need help in integrating this with jQuery AJAX request.
What you we're missing was the use of appCache,
<html manifest="example.appcache">
in your HTACCESS add
AddType text/cache-manifest .appcache
inside example.appcache
CACHE MANIFEST
data.json
index.php
someimage.png
# continue for all the file needed for the web site to work
This means that once you have connected and downloaded the content once it's not needed again. on another note you not supposed to be able to access a file:// URI though XHR/ajax as there is no way to send the content if you wanted it offline you could have just embedded the content of the json file into you code as a string and just use var jsonStr = '{}'; var jsonObj = JSON.parse(jsonStr); where jsonStr is you code. this would have meant no connections to the server as there would be no ajax/XHR request
jQuery .getJSON uses ajax. http://api.jquery.com/jquery.getjson/
.ajax uses a XMLHttpRequest
The web security of chrome and other browsers block XMLHttpRequest to local files because it is a security issue.
Via Security in Depth: Local Web Pages
http://blog.chromium.org/2008/12/security-in-depth-local-web-pages.html
You receive an email message from an attacker containing a web page as
an attachment, which you download.
You open the now-local web page in your browser.
The local web page creates an iframe whose source is
https://mail.google.com/mail/.
Because you are logged in to Gmail, the frame loads the messages in
your inbox.
The local web page reads the contents of the frame by using JavaScript
to access frames[0].document.documentElement.innerHTML. (An Internet
web page would not be able to perform this step because it would come
from a non-Gmail origin; the same-origin policy would cause the read
to fail.)
The local web page places the contents of your inbox into a
and submits the data via a form POST to the attacker's web server. Now
the attacker has your inbox, which may be useful for spamming or
identify theft.
The solution for data which does not need same-origin policy security, is padded json. Since jsonp is not a secure format for data. Jsonp does not have the same-origin policy.
/* secured json */
{
"one": "Singular sensation",
"two": "Beady little eyes",
"three": "Little birds pitch by my doorstep"
}
/* padded json aka jsonp */
Mycallback ({
"one": "Singular sensation",
"two": "Beady little eyes",
"three": "Little birds pitch by my doorstep"
});
Since with jsonp the json is wrapped in a valid javascript function it can be opened the same way as any one would add any javascript to a page.
var element = document.createElement("script");
element.src = "jsonp.js";
document.body.appendChild(element);
And your callback processes the data,
function Mycallback(jsondata) {
}
This is functionally the same as a ajax request but different because it is a jsonp request, which is actually easier.
jQuery libs do directly support jsonp as well http://api.jquery.com/jquery.getjson/ See the example using Flickr's JSONP API; unless one was aware of the dual standards they may not even notice that jsonp is being used.
(function() { /* jsonp request note callback in url, otherwise same json*/
var flickerAPI = "http://api.flickr.com/services/feeds/photos_public.gne?jsoncallback=?";
$.getJSON( flickerAPI, {
tags: "mount rainier",
tagmode: "any",
format: "json"
})
.done(function( data ) {
$.each( data.items, function( i, item ) {
$( "<img>" ).attr( "src", item.media.m ).appendTo( "#images" );
if ( i === 3 ) {
return false;
}
});
});
})();
Local access to json can be enabled but it is done differently depending on browswer.
Use --allow-file-access-from-files to enable it in chrome. https://code.google.com/p/chromium/issues/detail?id=40787
FYI: they are working on encripted json https://datatracker.ietf.org/doc/html/draft-ietf-jose-json-web-encryption-08 I am fairly certain that there will be no method of using this locally the intention is to make it really, really secure.
Source: https://stackoverflow.com/a/22368301/1845953
Posting the answer just in case somebody else runs into it. In my case
IE was loading a version of jquery that apparently causes "JSON
undefined" error. Here is what I did to solve it:
<!--[if lt IE 9]>
<script src="http://code.jquery.com/jquery-1.10.2.js"></script>
<![endif]-->
<!--[if gte IE 9]><!-->
<script src="http://code.jquery.com/jquery-2.0.3.js"></script>
<!--<![endif]-->
The latest one is jquery 2.1.1: direct link but it says:
(IE <9 not supported)
So I guess jquery 1.11.1: direct link
And I found out you can develop ajax and jquery stuff in Chrome on local files if you use Chrome with this flag: --allow-file-access-from-files (source)
<meta http-equiv="X-UA-Compatible" content="IE=edge">
Try adding this meta tag and check in IE
Here's a working solution.
I've included handlebars because it's cleaner.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>JSON TEST</title>
</head>
<body>
<div id="load-tasks">
</div>
<script src="jquery.min.js"></script>
<script src="handlebars.min.js"></script>
<script id="tasks-template" type="text/x-handlebars-template">
{{#each .}}
<div class="row">
<span class="data-task">
{{this.name}}
</span> <span class="data-date">
{{this.date}}
</span> <span class="data-name">
{{this.assigned}}
</span>
</div>
{{/each}}
</script>
<script>
$(function () {
var loadTasksContainer = $('#load-tasks'),
tasksTemplate = Handlebars.compile($('#tasks-template').html());
$.ajax({
type: "GET",
url: "data.json",
dataType: "json",
cache: false,
success: function (data) {
var html = tasksTemplate(data);
loadTasksContainer.append(html);
},
error: function (xhr, status, error) {
//log error and status
}
});
});
</script>
</body>
</html>
Using JSONP you could make this work for all browsers with or without a web server or even cross domain.
Example data.jsonp file:
loadTasks([
{name:"Task 1", date:"Date 1", assigned:"John Doe"},
{name:"Task 2", date:"Date 2", assigned:"Jane Doe"}
]);
Then on your page just load the data.jsonp using a script tag:
<script>
function loadTasks(tasks) {
$.each(tasks, function (i, task) {
$("#load_tasks").append(
"<div class='row'><span class='data-task'>" + task.name +
"</span> <span class='data-date'>" + task.date +
"</span> <span class='data-name'>" + task.assigned +
"</span> </div>");
});
}
</script>
<script src="data.jsonp"></script>
Try including an error callback ; jqxhr.responseText may still contain data.json .
data.json
{"data":{"abc":[123]}}
json.html
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="jquery-1.11.1.min.js"></script>
<script type="text/javascript">
$(function() {
$.getJSON(document.location.protocol + "data.json")
.then(function(data, textStatus, jqxhr) {
var response = JSON.parse(data);
console.log(textStatus, response);
}
// `error` callback
, function(jqxhr, textStatus, errorThrown) {
var response = JSON.parse(jqxhr.responseText);
console.log(textStatus, errorThrown, response);
$("body").append(response.data.abc);
});
})
</script>
</head>
<body>
</body>
</html>
Dealing with this problem will lead you to anywhere. It is a difficult task and it could be easily solved using any http server.
If your problem is that it is difficult to set up one, try this:
https://www.npmjs.org/package/http-server
On your shell you go to the directory where are your files and then you just type
http-server ./ -p 12345
where 12345 can be changed by any valid and not already used port of your choice.

How to load a txt/csv file into javascript string/array while offline

I have a small html/javascript webpage that I want to run in a browser offline.
In the same way the page can include an image or a css file and use it while offline, I want to include a 3mb spreadsheet that the javascript reads into a 2d-array, and I'm hoping for something that would work on IE8 as well as modern browsers.
C:\Folder\index.html
C:\Folder\code.js
C:\Folder\picture.png
C:\Folder\spreadsheet.csv
I've found multiple methods online like
<script src="jquery-csv.js"></script>
var table = $.csv.toArrays("spreadsheet.csv");
or
d3.text('spreadsheet.csv', function(error, _data){
var table = d3.csv.parseRows(_data);
});
or
$(document).ready(function() {
$.ajax({
type: "GET",
url: "data.txt",
dataType: "text",
success: function(data) {processData(data);}
});
});
But I tend to get same-origin policy errors such as:
XMLHttpRequest cannot load file://data.txt. Received an invalid response. Origin 'null' is therefore not allowed access.
Uncaught SecurityError: Failed to read the 'contentDocument' property from 'HTMLIFrameElement': Blocked a frame with origin "null" from accessing a frame with origin "null". Protocols, domains, and ports must match.
I can't seem to get these to work offline. How could I accomplish this?
Edit:
I'm managed to get the following to work for a text file only on Firefox using the CSVToArray function found here, which is pretty sluggish with a file of this size, and a hidden iframe.
Ultimately, it would be preferable if this was capable of running on IE8, and if I used a csv rather than a txt file, but at least it's a start.
<iframe style="display:none;" id='text' src = 'file.txt' onload='read_text_file()'>
</iframe>
<script type="text/javascript" >
function read_text_file() {
var text = document.getElementById('text').contentDocument.body.firstChild.innerHTML;
var table = CSVToArray(text);
}
For IE8 I managed to get this to work on a small scale but with the 3mb file it will occasionally crash the browser and will always accost the user with both a ton of warning messages that activex is being used and a wave of warnings that the script will slow down the computer.
window.onLoad = readFileInIE("file.csv");
function readFileInIE(filePath) {
try {
var fso = new ActiveXObject("Scripting.FileSystemObject");
var file = fso.OpenTextFile(filePath, true);
var text = file.ReadAll();
var table = CSVToArray(text);
file.Close();
return fileContent;
} catch (e) {
if (e.number == -2146827859) {
alert('Unable to access local files due to browser security settings. ' +
'To overcome this, go to Tools->Internet Options->Security->Custom Level. ' +
'Find the setting for "Initialize and script ActiveX controls not marked as safe" and change it to "Enable" or "Prompt"');
}
}
}
This might not work in IE8, but the HTML5 API is really useful for this. Just use:
window.onload = function() {
var fileInput = document.getElementById('fileInput');
fileInput.addEventListener('change', function(e) {
var file = fileInput.files[0];
var textType = //format you'd like to recieve;
if (file.type.match(textType)) {
var reader = new FileReader();
reader.onload = function(e) {
// apply magic here
}
reader.readAsText(file);
}
else
{
fileDisplayArea.innerText ="Sorry matey, can't help you with that filetype."
}
});
}
Then after that, a simple .html file that looks like this would do the trick:
<html lang="en">
<head>
<script src="script.js"></script>
</head>
<body>
<div id="page-wrapper">
<div>
<input type="file" id="fileInput">
</div>
<pre id="fileDisplayArea"></pre> //display any output here
</div>
</body>
</html>
It's not quite clear what you want to do.
Using jQuery it's possible to modify events that happen in the DOM. Using this you could potentially save the source code when you're done making changes. You would then need to replace your current source code with the saved code to use the changes the next time you open up the page. However, this would be a very laborious process and there are likely a number of better ways to accomplish what you want to do depending on what that is.
Also, in regards to Shota's post. You can't use AJAX unless you have a server running in the background. If you decide to set the system up on a server there are a number of options for accomplishing what you want.
My comment become too long.
You can't include data files in the same way as media. The easiest way would be to preprocess the csv into a js array and then include the csv like js <script src="mydata.csv.js"></script>.
By offline you mean local files and not public? The first suggestion would be to upgrade your browser. It doesn't quiet make sense if its a local file supporting all major browsers. Sorry I'm sure you have reasons why you can't. But upgrading would get around the non Ecmascript 5 support in ie8.
To get around the cross origin policy you'd have to run your file on a local webserver. So your html page would be on something like localhost:8080 and your csv localhost:8080/mydata.csv this gives privileges to the html to allow access to the csv file as they're now on the same domain. D3, jquerycsv should now work. Its a big security risk allowing any html file to access the filesystem freely.
If a local server isn't an option. You have to select the file each time you load with an input field. This grants the browser permissions to access this file.
After selecting the file, to read the contents for the main browsers (with Ecma5) look into FileReader on MDN, and an example of use can be found here. For ie8 + 9 there is VBscript support to read files. You can use VB just like JS using <script type="text/vbscript"></script>
If you really want to access local resources from a sever page then you need also a local page that allows the access. A local HTML page inside an <iframe> could read the text file and post contents to the main page via window.postMessage().
There might also be a way with HTML5 iframes and the sandbox attribute, but not in IE9 and below.
see:
https://developer.mozilla.org/en-US/docs/Web/API/Window.postMessage
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe
As you have realized, any AJAX-based solution will be affected by security restrictions for local file access. Instead of finding browser-specific workarounds, you could go the JSONP way which avoids AJAX.
This would require you to pre-process your CSV data and save it in a more JS-friendly format. But this would be a good idea anyway, as native JS parsing is likely to perform better than a CSV parser implemented in JS.
It could look roughly like this:
index.html
</head>
<body>
<div id="page-wrapper">
<div>
<input type="file" id="fileInput">
</div>
<pre id="fileDisplayArea"></pre> <!-- display any output here -->
</div>
<script src="script.js"></script>
<script src="data.js"></script>
</body>
</html>
script.js
function processData(data) {
// Your logic
// (will be called once data.js is loaded)
}
data.js
processData([
["your", "data"]
]);

jquery load() equivalent for offline use

I am looking for an equivalent to jquery's load() method that will work offline. I know from jquery's documentation that it only works on a server. I have some files from which I need to call the html found inside a particular <div> in those files. I simply want to take the entire site and put it on a computer without an internet connection, and have that portion of the site (the load() portion) function just as if it was connected to the internet. Thanks.
Edit: BTW, it doesn't have to be js; it can be any language that will work.
Edit2:
My sample code (just in case there are syntax errors I am missing; this is for the files in the same directory):
function clickMe() {
var book = document.getElementById("book").value;
var chapter = document.getElementById("chapter").value;
var myFile = "'" + book + chapter + ".html'";
$('#text').load(myFile + '#source')
}
You can't achieve load() over the file protocol, no other ajax request is going to work for html files. I have tried even with the crossDomain and isLocale option on without anything success, even if precising the protocol.
The problem is that even if jQuery is trying the browser will stop the request for security issues (well most browsers as the snippet below works in FF) as it allows you to load locale file so you could get access to a lot of things.
The one thing you could load locally is javascript files, but that probably means changing a lot of the application/website architecture.
Only works in FF
$.ajax({
url: 'test.html',
type: 'GET',
dataType: 'text',
isLocale: true,
success: function(data) {
document.body.innerHTML = data;
}
});
What FF does well is that it detect that the file requesting local files is on the file protocol too when other don't. I am not sure if it has restriction over the type of files you can request.
You can still use the JQuery load function in this context:
You would could add an OfflineContent div on your page:
<div id="OfflineContent">
</div>
And then click a button which calls:
$('#OfflineContent').load('OfflinePage.html #contentToLoad');
Button code:
$("#btnLoadContent").click(function() {
$('#OfflineContent').load('OfflinePage.html #contentToLoad');
});
In the OfflinePage.html you could have to have another section called contentToLoad which would display on the initial page.

Categories