gorill
gorill

Reputation: 1673

misunderstood Javascript functions call

I trying to customize HTML file input and wrote simplest jquery API function:

(function($)
{    
  $.fn.selectFileInputGUI = function()
  { 
    var outerWrapper = $('<div>').css({'display':'inline-block'});
    var innerWrapper = $('<div>').css({'width':'0', 'height':'0', 'overflow':'hidden'});
    var fileInput    = $('<input>').attr({type:'file'});
    var fileNameHTML = $('<div>').css({'display':'inline-block', 'margin-left':'3px'});

    var selectBtnGUI = $('<button>').addClass('btn btn-success btn-sm').text('Select file').click(function()
       {
          $.fn.selectFileInputGUI.resetInput();
          fileInput.trigger('click');
       });

       fileInput.on('change', function()
       {   
          $.fn.selectFileInputGUI.displayFileName();
       });

    $(this)
    .append(outerWrapper.append(innerWrapper.append(fileInput)).append(selectBtnGUI))
    .append(fileNameHTML);

   $.fn.selectFileInputGUI.displayFileName = function()
   {
      var fileName = fileInput.val();
      if(fileName.length > 0)
      {
          var pos = fileName.lastIndexOf("\\");
          if(pos != -1) fileName = fileName.substr(pos + 1);
          if(fileName.length > 14) fileName = fileName.substr(0, 14) + '...';
       } else
       {
          fileName = 'File not selected';
       }
       fileNameHTML.text(fileName);
};


   $.fn.selectFileInputGUI.resetInput = function()
   {           
     fileInput.wrap('<form>').parent('form').trigger('reset');
     fileInput.unwrap();
   };   
}
})(jQuery);

When I trying to apply selectFileInputGUI api function to the several selectors, only last selector handles well - http://jsfiddle.net/URKM5/5/

How to implement it correctly?

Upvotes: 0

Views: 57

Answers (1)

King King
King King

Reputation: 63327

Looks like your problem is in how you reuse the variable fileInput and fileNameHTML, after user selecting the file, and you call this $.fn.selectFileInputGUI.displayFileName(); the fileInput and fileNameHTML always refer to the fileInput and fileNameHTML of the second fileDialog (because the second fileDialog is initialized after the first and all these variables are overridden). So to solve this problem, you have to pass these variables via the so-called event data, it's much helpful in this case:

//Note the second argument, it's passed in as event data
//You can access the event data via e.data
fileInput.on('change', fileNameHTML, function(e) {              
    $.fn.selectFileInputGUI.displayFileName($(this), e.data);
});

Your displayFileName need to accept 2 arguments, the first refers to the fileInput (which can be passed in as $(this) in the onchange event handler of the fileInput), the second refers to the fileNameHTML (which is passed in as e.data).

//note about the change of the arguments
$.fn.selectFileInputGUI.displayFileName = function(fileInput, fileNameHTML) {
   //the code is unchanged here ...
}

Now selecting the files between the 2 dialogs is independent.

Demo.

After some deeper looking into the problem, looks like you don't need to use event data here. Just pass the fileNameHTML right as the second argument into displayFileName(...) function. Updated Demo

Upvotes: 1

Related Questions