JavaScript FileReader to get data from file - javascript

After browsing around the internet for a few hours to find a solution, I found out a few methods of getting the information from a filereader, but not quite to what I need.
function submitfile() {
var reader = new FileReader();
reader.readAsDataURL(document.getElementById("filesubmission").files[0]);
reader.onload = function (REvent) {
document.getElementById("outputcontent").innerHTML = "<iframe width='100%' id='outputdata' scrolling='yes' onload='resizeIframe(this)' src='"+REvent.target.result+"'></iframe>";
};
}
function resizeIframe(obj) {
obj.style.height = obj.contentWindow.document.body.scrollHeight + 'px';
}
That is the code that I'm using after a user selects a file, which I allow .html, .htm, .txt, or .xml. The Iframe is then resized to match the content. I have that functionality working, however I need to have a method of replacing text in the iframe with certain values that the user provides in <input> tags earlier. An example would be I need to be able to replace "[c1]" in the file the user provides with a client's name, such as "John Smith".
The way I would prefer to do this would be through the content of the file itself, rather than using a source in an iframe or data in an object. If I can get this into the original file itself where it can be edited, that would solve the problem.
I need to be able to do this without the use of jQuery or other plugins, since this is a local file that should be able to work standalone as a tool for my client.

Use the DOMParser to parse the reader's result:
var doc = (new DOMParser).parseFromString(reader.result,"text/html");
or any other mime type,
Then, update the some nodes within the doc based on the inputs you mention.
Then use the iframe's contentDocument to adopt the node using document.adoptNode. That will return the node with its ownerDocument pointing to the iframe. Lastly append it to the iframe's body.

Related

Display pdf file over 2MB using embed element

I am making an application that brings up a preview of PDF files. Embedding with an embed element works well for small PDF files but fails for larger PDF files because of the size limits for data urls. I'm looking for a way to use the browser's native PDF viewer to view PDF files but without using data urls.
My code currently looks something like the following:
<script>
function addToCard(input) {
if (input.files.length <= 0) return;
let fileReader = new FileReader();
fileReader.onload = async function () {
pdfCard.src = fileReader.result;
};
fileReader.readAsDataURL(input.files[0]);
}
</script>
<input type=file oninput="addToCard(this)" />
<embed id=pdfCard style="width:100%;height:100%" />
Example. The original PDF is here.
You could use URL.createObjectURL() on the PDF. It also creates a URL representing the object; however, the difference between an object URL and a data URL is that, while a data URL contains the object itself, an object URL is a reference to the object, which is stored in memory. This means that object URLs are significantly shorter than data URLs and take less time to create.
There are two drawbacks to this approach that may prevent you from using it. The first is that an object URL will only work on the page on which it was created. Attempting to use an object URL on a different page will not work. If you need to access this URL anywhere other than the page it was created on, this approach will not work.
The second is that object URLs keep the object for which they were created stored in memory. You have to revoke the object URL when you are done using it with the URL.revokeObjectURL() method, otherwise it will cause a memory leak. This means that you might have to add some extra code that revokes the object URL once the PDF is loaded. This example may be helpful.
The implementation might look something like this:
function addToCard(input) {
if (input.files.length <= 0) return;
pdfCard.src = URL.createObjectURL(input.files[0])
// gonna have to call revokeObjectURL eventually...
}

Change element css class based on xml file value

Is this even a possibility? Never attempted or tried anything like this before, I have no idea where to start.
I have a local file that when a manual button is pressed, it updates an xml file changing
<status>live<\status>
to
<status>killed<\status>
I also have a HTML page that has Iframes pulling live camera feeds for IP cameras. I want to hide the iframe and show a graphic instead when the status is ‘killed’.
Does anyone know if this is possible and where I’d start? Somehow check the xml file regularly or somehow know it has been updated.
Then somehow apply classes or introduce elements such as a div to mask the iframe.
Yes, you can work with XML in JavaScript almost the same as if you were working with HTML. However, without a server-side component, writing the xml document back to the file system will not be possible. You can always download it for the user, but you can't write directly to the file system.
Here's a simple example of updating an XML document with JS. I put both the string of xml and the logic to parse string into an xml doc in the example since I'm not sure what your setup is.
const xmlString = `
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
`;
const xmlDoc = new DOMParser().parseFromString(xmlString, 'text/xml');
document.getElementById('btn').addEventListener('click', e => {
const to = xmlDoc.querySelector('note to');
to.innerHTML = 'Someone New';
console.log('The TO field is now ', xmlDoc.querySelector('note to').innerHTML);
// Set HTML Element from XML
const h1 = document.getElementById('fromXml');
h1.innerText = xmlDoc.querySelector('note heading').innerHTML;
});
<button id="btn">Set To</button>
<h1 id="fromXml"></h1>

Javascript File from Local Storage

I have a large JavaScript file that I'd rather not send to the client on each request and it's too large for the browser to cache.
My thought is that I will save the file to HTML5 local storage and attempt to retrieve it. If the file is found then I'd like to link/import/export(I don't know the proper terminology) it into the same scope that a html src tag would.
My question is: how do I take a file that I've pulled from local storage and get my webpage to recognize it as a JavaScript file that was included via src tag? (minus the logic for pulling the file from storage)
My question is: how do I take a file that I've pulled from local storage and get my webpage to recognize it as a JavaScript file that was included via src tag?
Two possible ways (amongst maybe others):
create a script element, and assign your JS code as the “text content” of that element before appending it to the DOM. “Text content” in quotes here, because it is not as simple as it sounds cross-browser – see f.e. Javascript script element set inner text, Executing elements inserted with .innerHTML, or
assign your script code to the src attribute of a script element via a Data URI, data:text/javascript,… – but that approach has several disadvantages as well, also mostly in older IE (size limitation; only “non-navigable” content, meaning no scripts). But depending on your target environment that might well work. You will not necessarily need to base64 encode the script code, URL-percent-encoding via encodeURIComponent should work as well.
Take a look at this:
http://jsfiddle.net/611e96mz/1/
var tag = getId('testjs'),
a = getId('a'),
b = getId('b'),
c = getId('c'),
script;
a.addEventListener('click', function () {
localStorage.setItem('js', tag.innerHTML);
});
b.addEventListener('click', function () {
script.textContent = localStorage.getItem('js');
});
c.addEventListener('click', function () {
document.body.appendChild(script);
alertMe();
});
var script = document.createElement("script");
script.type = "text/javascript";
function getId(x) {
return document.getElementById(x);
}
You can use JSON to stringfy your file content and put it on localstorage.
var content = JSON.stringify([1, "some info"]); // '[1,"some info"]'
localStorage.setItem('fileContent', content);
// Retrieve
var content = localStorage.getItem('fileContent');
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify

How to extract images from Word documents using JavaScript?

I am trying to extract images from Word documents using the ActiveXObject in JavaScript (IE only).
I was unable to find any API reference for the Word object, only a few hints from around the Internet:
var filename = 'path/to/word/doc.docx'
var word = new ActiveXObject('Word.Application')
var doc = w.Documents.Open(filename)
// Displays the text
var docText = doc.Content
How would I access images in the Word doc using something like doc.Content?
Also, if anyone has a definitive source (preferably from Microsoft) for the API that'd be extremely helpful.
So after a few weeks of research, I found it would be easiest to extract the images by using the SaveAs function that is part of the Word ActiveXObject. If the file is saved as an HTML document, Word will make a folder containing the images.
From there, you can use XMLHttp to grab the HTML file and create new IMG tags that can be viewable by the browser (I'm using IE (9) because the ActiveXObject only works in Internet Explorer).
Let's begin with the SaveAs portion:
// Define the path to the file
var filepath = 'path/to/the/word/doc.docx'
// Make a new ActiveXWord application
var word = new ActiveXObject('Word.Application')
// Open the document
var doc = word.Documents.Open(filepath)
// Save the DOCX as an HTML file (the 8 specifies you want to save it as an HTML document)
doc.SaveAs(filepath + '.htm', 8)
Now we should have a folder in the same directory with the image files in them.
Note: In the Word HTML the images use <v:imagedata> tags which are stored in a <v:shape> tag; for example:
<v:shape style="width: 241.5pt; height: 71.25pt;">
<v:imagedata src="path/to/the/word/doc.docx_files/image001.png">
...
</v:imagedata>
</v:shape>
I've removed the extraneous attributes and tags that Word saves.
To access the HTML using JavaScript, use an XMLHttpRequest object.
var xmlhttp = new XMLHttpRequest()
var html_text = ""
Because I am accessing hundreds of Word docs, I've found it is best to define the XMLHttp's onreadystatechange callback before sending the call.
// Define the onreadystatechange callback function
xmlhttp.onreadystatechange = function() {
// Check to make sure the response has fully loaded
if (xmlhttp.readyState==4 && xmlhttp.status==200) {
// Grab the response text
var html_text=xmlhttp.responseText
// Load the HTML into the innerHTML of a DIV to add the HTML to the DOM
document.getElementById('doc_html').innerHTML=html_text.replace("<html>", "").replace("</html>","")
// Define a new array of all HTML elements with the "v:imagedata" tag
var images =document.getElementById('doc_html').getElementsByTagName("v:imagedata")
// Loop through each image
for(j=0;j<images.length;j++) {
// Grab the source attribute to get the image name
var src = images[j].getAttribute('src')
// Check to make sure the image has a 'src' attribute
if(src!=undefined) {
...
I've had many issues loading the correct src attribute because of the way IE escapes it's HTML attributes when it loads them into the innerHTML doc_html div so in the below example I am using a pseudo-path and src.split('/')[1] to grab the image name (this method won't work if there are more than 1 forward slashes!):
...
images[j].setAttribute('src', '/path/to/the/folder/containing/the/images/'+src.split('/')[1])
...
Here is where we add a new img tag to the HTML div using the parent's (the v:shape object) parent (happens to be a p object). We append the new img tag to the innerHTML by grabbing the src attribute from the image and the style information from the v:shape element:
...
images[j].parentElement.parentElement.innerHTML+="<img src='"+images[j].getAttribute('src')+"' style='"+images[j].parentElement.getAttribute('style')+"'>"
}
}
}
}
// Read the HTML Document using XMLHttpRequest
xmlhttp.open("POST", filepath + '.htm', false)
xmlhttp.send()
Although it is a bit specific, the above method was able to successfully add img tags to the HTML where they were in the original document.

HTML5 FileApi + FileReader - Feed <object> with SWF

I want to use the HTML5 FileApi to read a SWF to an OBJECT (or EMBED, if it's better to do?).
My current code crashes on Chrome/Iron (the only stable browser which also supports the xmlhttprequest v2 FormData). I got it to read image data into a on-the-fly created IMG. But the object one crashes the current tab in the browser.
else if (file.type == "application/x-shockwave-flash") {
var show = document.createElement("object");
show.type = "application/x-shockwave-flash"
show.style.width = "100%";
show.style.height = "100%";
show.id = "thumb";
document.getElementById("thumbnails").appendChild(show);
var reader = new FileReader();
reader.onload = (function (aImg) {
return function (e) { aImg.data = e.target.result; };
})(show);
reader.readAsDataURL(file);
Do I really read to the object.data part? How is it done right? Anybody know? Or is this incomplete and I have to wait for better implementation?
A few things I'd recommend trying (in order of increasing complexity):
base64 encode the data with btoa and set it using a data: URI,
instead of creating the object using createElement, construct the <object> tag with all attributes as an HTML string (including the base64 advice above), then inject it into a DOM element with innerHTML,
create a reflector web service where you POST the swf content, it gives you a URL, then pass the URL off to the object,
similar to the previous, create a reflector web service where you POST the swf content, targeting a full-screen IFRAM as the target, have the service spits back an HTML doc including an <object> pointing back to the server.
The later of these options is more intense, and requires round-trips from the server that you'd probably want to avoid - just some more options you might want to consider.
ActionScript 3 has a Loader which may be useful as well. I don't know if it supports data: URI's, but if it does, you could write a boot loader SWF which runs the contents of the local swf file directly.

Categories