var FileReader = {
    _dispatchProgressEvent : function(target, type, bubble, capture, lengthComputable, loaded, total, message) {
        var evt = document.createEvent("ProgressEvent");
        evt.initProgressEvent(type, bubble, capture, lengthComputable, loaded, total);
        evt.message = message;
        target.dispatchEvent(evt);
    },
    _mozilla_xml_parse_error_ns : "http://www.mozilla.org/newlayout/xml/parsererror.xml",
    _xhtml_ns : "http://www.w3.org/1999/xhtml",
    _requestFile : function(req, fileURI, error_callback) {
        var ref = this;
        req.addEventListener("error", function(e) {
            if (typeof e.message !== "string") {
                e.message = "Unknown Error:\n\nPerhaps a request to a file on a different domain was made?";
            }
            error_callback(e);
        }, false);
        if (document.location.protocol !== "file:") {
            ref._dispatchProgressEvent(req, "error", false, false, 0, 0, 0, "Access Error - XMLFileReader() is only for file: pages!");
            return;
        }
        var loc = document.location.href;
        var base = loc.substring(0, loc.lastIndexOf('/') + 1);
        var a = document.createElementNS(ref._xhtml_ns, "a");
        a.href = fileURI;
        if (a.href.indexOf("file://") !== 0) {
            ref._dispatchProgressEvent(req, "error", false, false, 0, 0, 0, "Access Error - Request URI uses a different scheme than 'file:'");
            return;
        }
        if (a.href.indexOf(base) !== 0) {
            ref._dispatchProgressEvent(req, "error", false, false, 0, 0, 0, "Access Error - Requested file must be in this page's directory or its subdirectories!");
            return;
        }
        try {
            req.open("GET", fileURI);
            req.send();
        } catch (err) {
            ref._dispatchProgressEvent(req, "error", false, false, 0, 0, 0,  "Generic Access Error:\n\nDoes the file exist?\nIs the URI to the file correct?\nPerhaps .open() was never called?");
        }
    },
    TextFileReader : function(fileURI, load_callback, error_callback) {
        var ref = this;
        var req = new XMLHttpRequest();
        req.addEventListener("load", function(e) {
            if (typeof this.responseText === "string") {
                load_callback(e);
            } else {
                ref._dispatchProgressEvent(req, "error", false, false, e.lengthComputable, e.loaded, e.total, "Non-specific Load Error - Response is null.");
            }
        }, false);
        ref._requestFile(req, fileURI, error_callback);
    },
    XMLFileReader : function(fileURI, load_callback, error_callback) {
        var ref = this;
        var req = new XMLHttpRequest();
        req.addEventListener("load", function(e) {
            var xmlDoc = e.target.responseXML;
            if (xmlDoc instanceof XMLDocument && xmlDoc.documentElement instanceof Element) {
                var parse_err_el = xmlDoc.getElementsByTagNameNS(ref._mozilla_xml_parse_error_ns, "parsererror");
                if (parse_err_el.length > 0) {
                    ref._dispatchProgressEvent(e.target, "error", false, false, e.lengthComputable, e.loaded, e.total, "XML Parse Error - Information shown below if available:\n\n" + xmlDoc.documentElement.textContent);
                } else {
                    load_callback(e);
                }
            } else {
                ref._dispatchProgressEvent(e.target, "error", false, false, e.lengthComputable, e.loaded, e.total, "Non-specific XML Parse Error\n\nIs the file an XML file?\nDoes it contain a syntax error?");
            }
        }, false);
        ref._requestFile(req, fileURI, error_callback);
    }
};
/* Usage:
FileReader.XMLFileReader("test.xml", function(e) {
    alert(e.target.responseXML);
}, function(e) {
    alert(e.message);
});

FileReader.TextFileReader("test.xml", function(e) {
    alert(e.target.responseText);
}, function(e) {
    alert(e.message);
});
*/




