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;'>&lt;test&gt;
    &lt;testing&gt;
        1 2 3
    &lt;/testing&gt;
&lt;/test&gt;</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;'>&lt;!-- 
    Note: This sample XSLT is an "identity" transformation.
    The result of applying this transformation to a document should be the original document.
--&gt;
&lt;xsl:stylesheet version=&quot;1.0&quot;
 xmlns:xsl=&quot;http://www.w3.org/1999/XSL/Transform&quot;&gt;
    &lt;xsl:template match=&quot;node()|@*&quot;&gt;
      &lt;xsl:copy&gt;
        &lt;xsl:apply-templates select=&quot;node()|@*&quot;/&gt;
      &lt;/xsl:copy&gt;
    &lt;/xsl:template&gt;
&lt;/xsl:stylesheet&gt;</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>

```