Richlewis
Richlewis

Reputation: 15374

Use function on many elements

I have a function that will validate the file size of an attachment and add errors if the file size exceeds the limit set, but it is limited to a specific file field with an id at the moment and i would like to be able to use the function on many file fields.

If a user wants to add say two images then they can click a button to clone the file field.

// First Example with ID
$('#animal_image_file_0').bind('change', is_valid_dog_image_size);

function is_valid_dog_image_size() {
  $this = $('#animal_image_file_0');
    if($this[0].files[0].size < 3000000){ // valid
     if ($this.closest(".form-group").hasClass("has-error")) 
      $this.closest(".form-group").removeClass("has-error");
      $this.siblings(".help-inline, .form-inline .has-feedback .form-control-feedback, .has-feedback").css("display", "none");
    return true
  } else { // error
    if (!$this.closest(".form-group").hasClass("has-error")) 
      $this.closest(".form-group").addClass("has-error");
      $this.siblings(".help-inline, .form-inline .has-feedback .form-control-feedback, .has-feedback ").css("display", "block");
    return false;
   }
  }

So I thought to apply this to many file fields I could use a class instead and then fire the function using the .on('click') method when the button to clone a field is clicked, but the assignment of $(this) in the function will not work now will it?

$('.add_nested_fields').on('click', function(){
  $('.animal_file').bind('change', is_valid_dog_image_size);
});

function is_valid_dog_image_size() {
  $this = $('.animal_file');
    if($this[0].files[0].size < 3000000){ // valid
     if ($this.closest(".form-group").hasClass("has-error")) 
      $this.closest(".form-group").removeClass("has-error");
      $this.siblings(".help-inline, .form-inline .has-feedback .form-control-feedback, .has-feedback").css("display", "none");
    return true
  } else { // error
    if (!$this.closest(".form-group").hasClass("has-error")) 
      $this.closest(".form-group").addClass("has-error");
      $this.siblings(".help-inline, .form-inline .has-feedback .form-control-feedback, .has-feedback ").css("display", "block");
    return false;
   }
  }

When i click .add_nested_fields it clones the file field so how could i go about ensuring that i could use the same function on all instances of this class in the DOM?

Thanks

Upvotes: 0

Views: 74

Answers (2)

Scimonster
Scimonster

Reputation: 33399

Just set $this to a jQuery wrapper of this. jQuery sets it properly for you when running an event callback.

$('.add_nested_fields').on('click', function(){
  $('.animal_file').bind('change', is_valid_dog_image_size);
});

function is_valid_dog_image_size() {
    $this = $(this);
    if(this.files[0].size < 3000000){ // valid
     if ($this.closest(".form-group").hasClass("has-error")) 
      $this.closest(".form-group").removeClass("has-error");
      $this.siblings(".help-inline, .form-inline .has-feedback .form-control-feedback, .has-feedback").css("display", "none");
    return true
  } else { // error
    if (!$this.closest(".form-group").hasClass("has-error")) 
      $this.closest(".form-group").addClass("has-error");
      $this.siblings(".help-inline, .form-inline .has-feedback .form-control-feedback, .has-feedback ").css("display", "block");
    return false;
   }
  }

Upvotes: 1

MarioDS
MarioDS

Reputation: 13063

The main problem is that you will be attaching multiple handlers to each field:

$('.animal_file').bind

is problematic, because you want to handle only events on the new field (the other handlers stay). The best way for your situation is to use a delegate handler (JQuery version 1.4.2+ and 1.7). The idea is that you attach the event handler on the parent element and filter for the target:

$('#parent-of-animal_file').on('change', '.animal-file', is_valid_dog_image_size);

Then, in your handler, simply use the native this and wrap it in a jQuery object:

function is_valid_dog_image_size() {
  $this = $(this);
  ...

Upvotes: 1

Related Questions