2014-10-08 51 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