INTELLIGENT WORK FORUMS
FOR COMPUTER PROFESSIONALS

Log In

Come Join Us!

Are you a
Computer / IT professional?
Join Tek-Tips Forums!
  • Talk With Other Members
  • Be Notified Of Responses
    To Your Posts
  • Keyword Search
  • One-Click Access To Your
    Favorite Forums
  • Automated Signatures
    On Your Posts
  • Best Of All, It's Free!

*Tek-Tips's functionality depends on members receiving e-mail. By joining you are opting in to receive e-mail.

Posting Guidelines

Promoting, selling, recruiting, coursework and thesis posting is forbidden.

Jobs

getting return values from load events or waiting till finished

getting return values from load events or waiting till finished

getting return values from load events or waiting till finished

(OP)
Hi,

Hope this makes sense!

Basically I have a file control on a form and when a file is selected I want to check a few details and decide if the file is 'valid'

The initial function call needs a Boolean return value to decide if all was OK, but I can't get my head round how I do this when the code for a fileReader object and image object uses onload events.

Here is some code to hopefully explain better...

I call my function 'fileSelected' via a JQuery change event...


CODE

// upload file selected 
$('body').on('change','#file',function() {
    // validate selected file
    if(fileSelected( $(this), fileObj ))
    {
        // show selected file.
        $(this).removeClass('invalid').addClass('valid');
        displayBanner();
    }
    else
    {
        $(this).removeClass('valid').addClass('invalid');
    }
    
}); 

fileSelected does a few things such as check file type and file size, I then do the following validation

CODE

// set up a fileReader object and image object
var reader = new FileReader();
fObj.file = new Image();

// load event to capture the file information.
reader.onload = (function(file) {

    // load event to check image dimensions
    fObj.file.onload = function(){
        
        if(this.width != fObj.imgWidth || this.height != fObj.imgHeight)
        {
            showDialog({content:'Image dimensions invalid. Must be (Width: ' + fObj.imgWidth + 'px, Height:' + fObj.imgHeight + 'px)'});
            clearFile(ele);
            return false;
        }
    };
    fObj.file.src = file.target.result;
});

// read selected file
reader.readAsDataURL(myFile);

// DO SOMETHING HERE TO CHECK AND RETURN TRUE OR FALSE 

here is where I'm stuck for a start I know the 'return false' in the file.onload event is not returning to the fileSelected method, I doubt it's returning false to the fileReader reader.onload event either, how would you capture the return value of a bound function to an event handler?.

What I need after the 'read selected file' is to know was any of this OK, if so return true to the caller of fileSelected, otherwise false.

But I don't understand how I can do this?

I've googled and there is not a JS sleep/wait and apparently it's bad practice to try. I know there is some kind of when / deferred / promise in JQuery, but I could do with a hand getting my head round this if this is what I need to do.

How can you call a procedural function that needs to return a Boolean value when the function is creating event based actions and the procedural function ends before these events have finished but I don't want it to?

Advice appreciated.
1DMF

"In complete darkness we are all the same, it is only our knowledge and wisdom that separates us, don't let your eyes deceive you."

"If a shortcut was meant to be easy, it wouldn't be a shortcut, it would be the way!"
Free Electronic Dance Music

RE: getting return values from load events or waiting till finished

isn't the boolean returning to the fObj.onload object? the question is whether that event supports cancellation. perhaps better to unload the object programmatically.

RE: getting return values from load events or waiting till finished

(OP)
I'm not sure but I don't want it to, I'm trying to return to the initial fileSelected function call but I think it's impossible because of the way event handlers are asynchronous.

I have a call if(fileSelected)...

So fileSelected needs to return true or false.

but in fileSelected it's creating an onload event for fileReader, which inside that has an onload event for the Image() object.

I see no way of getting the return code to fileSelected from inside the second onload event handler..

I've given up with this, it's flawed thinking as I'm trying to do something you simply can't do with events in this way.

"In complete darkness we are all the same, it is only our knowledge and wisdom that separates us, don't let your eyes deceive you."

"If a shortcut was meant to be easy, it wouldn't be a shortcut, it would be the way!"
Free Electronic Dance Music

RE: getting return values from load events or waiting till finished

i can't see the fileSelected function

consider a closure instead for the callback

CODE

var reader = new FileReader();

reader.onload = (function(file){
    return function(e){        
        if(this.width != fObj.imgWidth || this.height != fObj.imgHeight){
            showDialog({content:'Image dimensions invalid. Must be (Width: ' + fObj.imgWidth + 'px, Height:' + fObj.imgHeight + 'px)'});
            clearFile(ele);
            return false;
        };
     };
})(file); 

p.s. not sure i have that syntax quite right. may have some semicolons wrong.

RE: getting return values from load events or waiting till finished

(OP)

Quote:

consider a closure instead
what does that mean?

How have you tacked an argument on the end of the function like it's part of the signature?

here is the full fileSelected function

CODE

/ File selected helper
function fileSelected(ele,fObj)
{    

    // get selected file
    var myFile = ele.prop('files')[0];      
    fObj.fileSize = 0;
    
    if(myFile)    
    {       
        // add file details
        fObj.fileName = myFile.name;
        fObj.fileMIME = myFile.type;
                
        // validate file type
        if(! checkFile(fObj.fileName,fObj.fileType))
        {
            showDialog({content:'Invalid file selected! '+(fObj.fileInvalid||'')});
            clearFile(ele);
            return false;
        }                       
        
        // validate file size
        if(myFile.size > 1024 * 1024)
        {
            fObj.fileSize = (Math.round(myFile.size * 100 / (1024 * 1024)) / 100);
            
            // check file size
            if(fObj.fileSize > fObj.maxSize)
            {
                showDialog({content:'File size is too large. Max ' + fObj.maxSize + 'MB.'});
                clearFile(ele);
                return false;                
            }                
            else
            {
                fObj.sizeUnit = 'MB';
            }                       
        } 
        else
        {
            fObj.fileSize = (Math.round(myFile.size * 100 / 1024) / 100);
            fObj.sizeUnit = 'KB';            
        }
        
        // if image file check dimensions if provided
        if(fObj.fileType == 'img' && (fObj.imgHeight || fObj.imgWidth))
        {
            // set up a fileReader object and image object
            var reader = new FileReader();
            fObj.file = new Image();
            
            // load event to capture the file information.
            reader.onload = function(aFile) {
                
                // load event to check image dimensions                
                fObj.file.onload = function(){                   
                    if(this.width != fObj.imgWidth || this.height != fObj.imgHeight)
                    {
                        showDialog({content:'Image dimensions invalid. Must be (Width: ' + fObj.imgWidth + 'px, Height:' + fObj.imgHeight + 'px)'});
                        fObj.file = undefined; 
                        ele.trigger('imageFailed',fObj);
                        clearFile(ele);                        
                    } 
                    else
                    {
                        ele.trigger('imageLoaded',fObj);
                    }                    
                };
                
                fObj.file.src = aFile.target.result;
                                
            };
            
            // read selected file
            reader.readAsDataURL(myFile);            
                      
        }
        else
        {
            // clear previous file
            fObj.file = undefined;
            
            // show file details
            showFileDetails(fObj);                    
            
        }                    
        
        return true;
    
    }     
    else
    {
        clearFile(ele);
        return false;
    }
    
} 

"In complete darkness we are all the same, it is only our knowledge and wisdom that separates us, don't let your eyes deceive you."

"If a shortcut was meant to be easy, it wouldn't be a shortcut, it would be the way!"
Free Electronic Dance Music

RE: getting return values from load events or waiting till finished

Re the tack on: That's what a closure is!

I'm only on a mobile at the moment so difficult to take a wider look at that function.

RE: getting return values from load events or waiting till finished

(OP)
you've melted my tiny brain!

http://jondavidjohn.com/javascript-closure-explain...

So you are instantly running a function passing in file (via the closure), to a function that returns another function using file?

How does this help, what does this achieve?

How does the Image object src ever get populated from the fileReader source?

"In complete darkness we are all the same, it is only our knowledge and wisdom that separates us, don't let your eyes deceive you."

"If a shortcut was meant to be easy, it wouldn't be a shortcut, it would be the way!"
Free Electronic Dance Music

RE: getting return values from load events or waiting till finished

(OP)
Well I've tried to use closures, but I'm not getting anywhere...

CODE

// load event to capture the file information.
reader.onload = (function(aFile) {
    
    // load event                 
    fObj.file.onload = (function(aFile){     
                
        // check dimensions if provided      
        if( (fObj.imgHeight || fObj.imgWidth) && this.width != fObj.imgWidth || this.height != fObj.imgHeight) 
        {
            showDialog({content:'Image dimensions invalid. Must be (Width: ' + fObj.imgWidth + 'px, Height:' + fObj.imgHeight + 'px)'});
            fObj.file = undefined; 
            ele.trigger('imageFailed',fObj);
            clearFile(ele);                        
        } 
        else
        {
            ele.trigger('imageLoaded',fObj);
        }                    
    })(aFile);                
    
    fObj.file.src = aFile.target.result;
                    
})(myFile); 

it errors with

Quote:

TypeError: aFile.target is undefined

I'm not sure what it is I'm doing or why I'm doing it and would appreciate some guidance.

Regards,
1DMF

"In complete darkness we are all the same, it is only our knowledge and wisdom that separates us, don't let your eyes deceive you."

"If a shortcut was meant to be easy, it wouldn't be a shortcut, it would be the way!"
Free Electronic Dance Music

RE: getting return values from load events or waiting till finished

I'm not familiar with the filereader html5 thing other than from answering (or trying to) previous questions from you.

i will give it all a proper try this evening or on the train.

RE: getting return values from load events or waiting till finished

(OP)
No worries, I just need to understand the scope of the closure and its usefulness, before I can apply it.

I've have a working app currently now that I have refactored to use custom events, so this is no longer an pressing issue the needs solving, but more for enlightenment and progressive improvement of my JS coding.

As always your input is very much appreciated.

I've read a few articles, but its all still a little murky!

I got the previous link posted above from

http://stackoverflow.com/questions/111102/how-do-j...

where an example given is

CODE

function foo(x) {
  var tmp = 3;
  function bar(y) {
    alert(x + y + (++tmp)); // will alert 16
  }
  bar(10);
}
foo(2); 

Which I kind of get, though ++ in front of a variable has me stumped. I would use var++ to increment a number, but when I tried that I get 15 as a result?

It's never easy learning a new concept especially when the coding style shown to explain it, uses syntax you don't understand. In this example you just want bar to see x from foo, ok I get it, but what is it giving if I apply the same to my code.

Having played a little it seems if you use closure, then the inner function can no longer see the initial function scoped arguments of 'fileSelected' so my ele & fObj vars are no longer available to the inner function?

I read closures as a way of giving access to vars normally outside the local lexical scope, but so far all I seem to have done is block access to vars accessible when not using closures?

Apparently the SO thread is meant to explain it to a 6 year old, I must have the brain of a 3 year old then! baby

"In complete darkness we are all the same, it is only our knowledge and wisdom that separates us, don't let your eyes deceive you."

"If a shortcut was meant to be easy, it wouldn't be a shortcut, it would be the way!"
Free Electronic Dance Music

RE: getting return values from load events or waiting till finished

on the ++ operator

the difference is when the increment is done, before or after the other operations.

so

CODE

var x = 10;
y = x;

//y = 10, x=10

y = x++;
//y = 10, x = 11

y = ++x;
//y = 11, x = 11 

on the closures, I tend to use them most when i'm using anonymous functions inside event handlers, where another value cannot be known until the event is fired.

Red Flag This Post

Please let us know here why this post is inappropriate. Reasons such as off-topic, duplicates, flames, illegal, vulgar, or students posting their homework.

Red Flag Submitted

Thank you for helping keep Tek-Tips Forums free from inappropriate posts.
The Tek-Tips staff will check this out and take appropriate action.

Reply To This Thread

Posting in the Tek-Tips forums is a member-only feature.

Click Here to join Tek-Tips and talk with other members!

Resources

Close Box

Join Tek-Tips® Today!

Join your peers on the Internet's largest technical computer professional community.
It's easy to join and it's free.

Here's Why Members Love Tek-Tips Forums:

Register now while it's still free!

Already a member? Close this window and log in.

Join Us             Close