I recently wrote a small demo that allows users to send and receive files from an HTML5 Javascript application. It's all client-side. I thought this would be a good place to get feedback about what I've done.
It's hosted here: http://danielsadventure.info/HTML5FileDemo/
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>HTML5 File Upload Demo With Saxon-CE and ACE</title>
<style>
/* ACE won't work without explicit CSS. */
.aceEditor
{
position: relative;
width: 500px;
height: 200px;
}
</style>
<script src='Scripts/ace/ace.js'></script>
<script src='Scripts/saxon-ce/Saxonce.nocache.js'></script>
<!--
FileSaver.js is an open-source Javascript project that provides support for the HTML5 FileSaver API
on browsers that do not natively support it.
-->
<script src='Scripts/FileSaver.js'></script>
</head>
<body>
Input XML
<br />
<div class='aceEditor' id='aceInputXml' style='float:left;'><test>
<testing>
1 2 3
</testing>
</test></div>
<div>
To input XML, drag-and-drop a file into the text editor to the left,
use the file input below, or key XML into the text editor.
<br />
<input id='xmlFileInput' type='file' />
</div>
<br style='clear:both;' />
Input XSLT
<br />
<div class='aceEditor' id='aceInputXslt' style='float:left;'><!--
Note: This sample XSLT is an "identity" transformation.
The result of applying this transformation to a document should be the original document.
-->
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet></div>
<div>
To input XSLT, drag-and-drop a file into the text editor to the left,
use the file input below, or key XSLT into the text editor.
<br />
<input id='xsltFileInput' type='file' />
</div>
<br style='clear:both;' />
Output
<div class='aceEditor' id='aceOutputXml'></div>
<br />
<input type='button' id='btnTransform' value='Transform' />
<input type='button' id='btnSave' value='Save' />
</body>
<script>
(function () {
'use strict';
var aceInputXml, aceInputXslt, aceOutputXml, editors, saxon;
setupAce();
setupFileDragAndDrop();
setupFileInput();
setupFileDownload();
setupSaxonce();
// Initialize the ACE editors and save their object references.
function setupAce() {
var x;
aceInputXml = ace.edit('aceInputXml');
aceInputXslt = ace.edit('aceInputXslt');
aceOutputXml = ace.edit('aceOutputXml');
editors = [aceInputXml, aceInputXslt, aceOutputXml];
for (x in editors) {
editors[x].setTheme('ace/theme/monokai');
editors[x].getSession().setMode('ace/mode/xml');
}
}
// Rig up the Input XML and Input XSLT ACE editors so that the user can populate them
// by dragging and dropping a file that contains XML.
function setupFileDragAndDrop() {
var inputXml, inputXslt;
inputXml = document.getElementById('aceInputXml');
inputXslt = document.getElementById('aceInputXslt');
addFileDragAndDropEventListeners(inputXml, aceInputXml);
addFileDragAndDropEventListeners(inputXslt, aceInputXslt);
function addFileDragAndDropEventListeners(aceInputDiv, aceObject) {
aceInputDiv.addEventListener('dragover', function (e) {
stopEvent(e);
});
aceInputDiv.addEventListener('drop', function (e) {
putFileContentsInAceEditor(e.dataTransfer.files[0], aceObject);
stopEvent(e);
});
function stopEvent(e) {
e.stopPropagation();
e.preventDefault();
}
} // end addFileDragAndDropEventListeners
} // end setupFileDragAndDrop
// Set up the HTML5 file inputs so that the user can populate the ACE editors
// by selecting a file.
function setupFileInput() {
(function () {
var xmlFileInput;
xmlFileInput = document.getElementById('xmlFileInput');
xmlFileInput.addEventListener('change', function (e) {
var file;
file = e.srcElement.files[0];
putFileContentsInAceEditor(file, aceInputXml);
});
})();
(function () {
var xsltFileInput;
xsltFileInput = document.getElementById('xsltFileInput');
xsltFileInput.addEventListener('change', function (e) {
var file;
file = e.srcElement.files[0];
putFileContentsInAceEditor(file, aceInputXslt);
});
})();
}
// Setup the button that the user can click to download the output.
function setupFileDownload() {
var button;
button = document.getElementById('btnSave');
button.addEventListener('click', function (e) {
var outputXmlStr, blob;
outputXmlStr = aceOutputXml.getSession().getValue();
// If the string is null or empty, do nothing.
if (!outputXmlStr)
return;
blob = new Blob([outputXmlStr], { type: 'text/plain' });
// Use the FileSaver.js interface to download the file.
saveAs(blob, 'Output.xml');
});
}
// A small function that takes a file and an ACE editor object.
// The function reads the file and copies its contents into the ACE editor.
function putFileContentsInAceEditor(file, aceEditor) {
var reader, text;
reader = new FileReader();
reader.onload = (function (file) {
text = file.target.result;
aceEditor.getSession().setValue(text);
});
reader.readAsText(file);
}
function setupSaxonce() {
// This object is required by Saxon.
// Saxon will automatically invoke this function when it loads.
window.onSaxonLoad = function () {
saxon = Saxon;
setupTransformButton(Saxon);
};
}
// Note that this gets called when setupSaxonce runs.
// This ensures that the Saxon object is available when the user clicks the [Transform] button.
function setupTransformButton(Saxon) {
var button;
button = document.getElementById('btnTransform');
button.addEventListener('click', function (e) {
var inputXmlStr, inputXsltStr, outputXmlStr,
inputXmlDoc, inputXsltDoc, outputXmlDoc, processor;
// Get the input XML and XSLT strings from the ACE editors.
inputXmlStr = aceInputXml.getSession().getValue();
inputXsltStr = aceInputXslt.getSession().getValue();
// Transform the inputs into Saxon XML documents.
inputXmlDoc = Saxon.parseXML(inputXmlStr);
inputXsltDoc = Saxon.parseXML(inputXsltStr);
// Get an XSLT20Processor object that will apply the transformation.
processor = Saxon.newXSLT20Processor(inputXsltDoc);
// Apply the transformation.
outputXmlDoc = processor.transformToDocument(inputXmlDoc);
outputXmlStr = Saxon.serializeXML(outputXmlDoc);
// Put the results of the transformation in the output ACE editor.
aceOutputXml.getSession().setValue(outputXmlStr);
});
}
})();
</script>
</html>