简体   繁体   中英

Global variable not picking up change within function

I have a piece of code I picked up from html5rocks for loading a file which you drag and drop onto to your page, and I'm modifying it so that it reads the file into a string, which I then muck about with, and output to the page. That bit is working, but I also need to be able to pick up the string outside the function that created it, and I can't.

I think this is either a scope problem, or perhaps some sort of callback issue. Anyway here is the code:

function handleFileSelect(evt) {
    evt.stopPropagation();
    evt.preventDefault();
    var files = evt.dataTransfer.files; // FileList object.
    var output = [];
    var OutString = []; // < --my variable that I want to use

    for (var i = 0, f; f = files[i]; i++) {
        if (f.name.match('\.csv')) { // if 1
            var Filename = decodeURI(escape(f.name));
            var reader = new FileReader();
            reader.onload = (function (theFile) { 
                return function (e) {        
                    var contents = e.target.result;
                    var FileLines = contents.split("\n");
                    var LineCount = FileLines.length;
                    OutString = '<table id="mytab" border = "1" width = "90%"><tr>';
                    var ColCount = 1;
                    for (var i = 0; i < LineCount; ++i) {
                        OutString = // I format a table here..
                    }
                    OutString += '</tr></table>';

                    var span = document.createElement('span');
                    span.innerHTML = [OutString].join('');
                    document.getElementById('list').insertBefore(span, null);
                };
            })(f);

            reader.readAsText(f);
            // if format up a word document using xml here 
            testFunc = // I want to read the contents of OutString here

            // this creates the button that opens the finished document 
            var OutPutLine = "<a href='data:application/msword;charset=UTF-8, " + encodeURIComponent(TestFunc) + "' ><input id='Button1' type='button' value='Open printable sheet1' /></a>";
            output.push(OutPutLine);

        } else {
            // this triggers if its not a csv file that drag n drops
            output.push('<strong>', escape(f.name), ' is not a comma seperated (.csv) file!!!!</strong>');
        }
    }

    document.getElementById('list').innerHTML = '<ul>' + output.join('') + '</ul>';
}

function handleDragOver(evt) {
    evt.stopPropagation();
    evt.preventDefault();
    evt.dataTransfer.dropEffect = 'copy'; // Explicitly show this is a copy.
}

// Setup the dnd listeners.
var dropZone = document.getElementById('drop_zone');
dropZone.addEventListener('dragover', handleDragOver, false);
dropZone.addEventListener('drop', handleFileSelect, false);

I don't mind if I get the string form a variable, or pick it up from the document (it's a table), but at the moment I can't do either.

Your variable OutString is declared inside handleFileSelect (it has the var -keyword in front of it), which means it will only be availible to that function (or functions declared inside that function).

To fix it, you could declare your OutString outside handleFileSelect , making it availible for access outside the function.

Alternatively you could get the <table> -element by referencing the id , that you're assigning to it:

document.getElementById('mytab')

You also set a callback for the FileReaders onload -event. This is done by a self-calling function , to prevent issues with scope. A new function is returned by the self-calling one and that function is used as the callback for the onload -event. As this is an event, it will only be called when that event fires, which might be before or after you access OutString (outside handleFileSelect ). You could add a callback to handleFileSelect like this:

function handleFileSelect(evt, callback) {
    //Removed some code to shorten the example

    for (var i = 0, f; f = files[i]; i++) {
        if (f.name.match('\.csv')) { // if 1
            var Filename = decodeURI(escape(f.name));
            var reader = new FileReader();
            reader.onload = (function (theFile, onloadCallback) { 
                return function (e) {        
                    //Removed some code to shorten the example
                    document.getElementById('list').insertBefore(span, null);

                    if( onloadCallback && typeof onloadCallback === 'function' )
                        onloadCallback();
                };
            })(f, callback);

            //Removed some code to shorten the example
        } else {
            //Removed some code to shorten the example
    }
    //Removed some code to shorten the example
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM