2014-10-08 32 views
0

我有一个画廊,在页面中点击加号和减号来添加和删除画廊项目,然后添加文件添加到新添加的项目的输入。我如何获得jQuery的.each函数动态元素的.on('更改')功能

我已经创建了一个文件读取器来获取文件的url,但它只能在该页面上的第一个元素上工作,在这之后添加的任何内容都不会受到影响。

这里是我的JS:

$('#gallery .gallery-item .file_upload').each(function() { 
    var $this = $(this); 
    //$('body').on('click', 'input', function() { 
    $this.on('change', 'input', function(evt){ 
     var files = evt.target.files; 
     var file = files[0]; 
     console.log(files[0]); 
     var reader = new FileReader(); 
     reader.onload = (function(file) { 
      return function(e) { 
       console.log(e.target.result); 
      }; 
     })(file); 
     reader.readAsDataURL(file); 
    }); 
    }); 

追加画廊项功能:

$('#gallery') 
    .on('cocoon:before-insert', function(e,image_field) { 
     image_field.insertAfter($(this).next()); 
    }) 
    .on('cocoon:after-remove', function(e, image_field) { 
     $(this).data('remove-timeout', 1000); 
     image_field.fadeOut('slow'); 
}); 

    $('.gallery-item').each(function() { 
     $(this).next('a.add_fields').appendTo(this); 
     $(this).next('input').appendTo(this); 
    }); 

HTML:

<div class="image-field"> 
      <div class="file_upload"> 
       <input class="image_file" id="gallery_files" name="book[gallery_attributes][images_attributes][1412768497650][file]" type="file"> 
      </div> 
     </div> 

谁能告诉我为什么。每个功能将无法正常工作这个.on函数用于附加的新项目。我认为这是最重要的功能,显然不适用于这里,而不是下面的其他功能。

回答

1

您已正确识别出您需要使用事件委派,因为您已在页面上动态添加元素。问题是事件委托对代码运行时存在的元素起作用,并且您使用.each()循环遍历期望包含动态添加元素的集合(这不会因为它们不会目前不存在)。

本质上,问题是初始选择器$('#gallery .gallery-item .file_upload')

该选择的.gallery-item .file_upload部分是什么标识事件代理动态元素的一部分,所以你需要更多像这样用的东西:

$('#gallery').on('change', '.gallery-item .file_upload input', function(e) { 
    // your code here 
}); 

我已经采取了调用.each(),因为它是多余的; .on()已经在一组匹配元素上进行迭代,并且您的$('#gallery')选择器应该只匹配单个元素。

注意:您已在选择器中使用.gallery-item,但您提供的HTML中只有image-field类。这可能是也可能不是问题,具体取决于页面的外观,因为您没有提供我不得不猜测的信息。

+0

工作是的,它是委托的顺序,所以它从父div的id开始,而.on基本上贯穿'.gallery-item .file_upload input'中的每个子节点,然后运行'.on( '变化')'。很感谢Anthony的解释。 :) – 2014-10-08 12:08:30

0

为什么你甚至使用.each()?所有你需要做它的工作是使用选择,因为jQuery的已经将循环所有选定的项目,以.on()

$('#gallery .gallery-item .file_upload').on('change', 'input', function(evt){ 
     var files = evt.target.files; 
     var file = files[0]; 
     console.log(files[0]); 
     var reader = new FileReader(); 
     reader.onload = (function(file) { 
      return function(e) { 
       console.log(e.target.result); 
      }; 
     })(file); 
     reader.readAsDataURL(file); 
}); 

的问题是,每一个是从画廊采取curently现有的输入,除非你是循环每次你正在追加新的项目,但是你会在同一个元素上绑定处理程序很多次。

+0

Spokey是啊,所以我按了一个加号按钮,它添加了一个新的字段,然后将图像添加到输入我点击上传图像。新添加的文件字段将添加到加载到页面的第一个字段旁边。当我尝试这个时,它只能从第一个项目中读取 – 2014-10-08 12:02:24

+0

啊试着改变选择器'$('#gallery .gallery-item')'。不太明白哪些项目是动态添加的,您的选择器应该是静态页面上的父页面,并且从一开始就存在。 – Spokey 2014-10-08 12:04:42

+2

@WouterFlorijn不,你不需要添加事件监听器 - 这正是事件代理存在的原因。问题是,正如我的回答所述,他的'.each()'选择器太具体,'.on()'调用的选择器可能不够具体(或者根据他的确切HTML)。 – 2014-10-08 12:08:19