jQuery匿名函数通过事件委派运行两次,应该只运行一次

时间:2013-09-26 23:01:41

标签: jquery

第一次发帖。有一些jquery问题,花了一段时间,但我能够通过它,现在我只是想知道为什么。

我有一个CMS,其中我试图通过一个通过AJAX调用填充图像的灯箱一次填充2个表单字段。单击该字段旁边的“浏览图像”按钮,进行AJAX调用以使用一系列图像填充灯箱。单击图像将关闭灯箱并使用该图像的路径填充相应的表单域。

整个过程一直有效,直到我进行第二次图像选择。两个表单字段都填充了第二个选择,从而删除了我做的第一个选择。

function AssetsPicker (el){
  this.el = el;
  this.url = el.attr('href') || '';
  this.gallery = el.data('gallery') || '';      

  this.show_assets = function(){
    //shows a lightbox of the thumbnails
    this.selected_asset();
  }

  //on thumbnail click
  //Grab the image src from the data attribute
  this.selected_asset = function(){
    var gallery = this.gallery, 
        empty_formfield = this.empty_formfield;

            //*************
            this was the problematic event. Works on first click, on second click it would populate both fields with the value.
           ********************//
        $('#lightbox_display').on('click', '.final-asset', function(e){
          e.preventDefault();
          var   el = $(this);
          src = el.data('file');    

          empty_formfield(src, gallery);                
        });
    }

    //empty out the appropriate form field
    //populate appropriate form field with src  
    this.empty_formfield = function(src, field){        
      var targetfield = $('#edit_project').find("[data-field='" + field + "']");                
      targetfield.val('').val(src);     
      console.log("[data-field='" + field + "']");
    }

}//AssetsPicker

var AssetsAjax =  {
    images: function(url, gallery){
        var promise = $.Deferred();         
        $.ajax(url, {
            dataType: 'json',
            contentType: 'application/json',
            success: function(result){
                promise.resolve(result); //when we have a result, then resolve our promise
            },
            error: function(){
                promise.reject('something went wrong. sorry.'); //if an error, then reject our promise
            }

        });//$.ajax         
    return promise;
    }
}//var AssetsAjax


$('#edit_project').on('click', '.gallery-window', function(e){
  e.preventDefault();
  var el = $(this),
    url = el.attr('href');

  var assetspicker = new AssetsPicker(el);                  

  $.when(
    AssetsAjax.images(url)
  ).then(function(result){              
    assetspicker.open_gallery();
    assetspicker.show_assets(result);
  });       
});

只有当我更改了此事件处理程序时,才能停止删除其他字段

    $('#lightbox_display .final-asset').on('click', function(e){
        //anonymous function unchanged              
    });

HTML

//lightbox that gets populated via AJAX depending on which browse <a> was clicked (thumbnails or large images)
<div id="lightbox_display">
    <a href="thumbs/3d-1.jpg" class="final-asset" data-file="3d-1.jpg"><img src="thumbs/3d-1.jpg"></a>
    <a href="thumbs/3d-2.jpg" class="final-asset" data-file="3d-2.jpg"><img src="thumbs/3d-2.jpg"></a>
    ...
</div>

//elsewhere in the DOM, both applicable fields
<div id="edit_project">
    <div>
        //clicked thumbnail image goes in here
        <input type="text" name="thumb" value="" data-field="thumbs">
        //this triggers the lightbox to show thumbnails
        <a href="file_assets/?q=thumbs" id="browse_thumbs" class="gallery-window" data-gallery="thumbs">Browse Thumbnails</a>
    </div>
    <div>
        //clicked large image goes here
        <input type="text" name="large" value="" data-field="large">
        //this triggers the lightbox to show large images
        <a href="file_assets/?q=large" id="browse_large" class="gallery-window" data-gallery="large">Browse Large Images</a>
</div>
</div>

1 个答案:

答案 0 :(得分:2)

问题在于$('#edit_project').on('click', '.gallery-window', function(e){#edit_project元素每次点击都会运行。{/ p>

在那里,在ajax完成后,你运行assetspicker.show_assets,然后运行$('#lightbox_display').on('click', '.final-asset', function(e){

因此,每次点击#edit_project时, 添加 一个新的处理程序,#lightbox_display点击.final-asset

因为我无法理解你最终想要做什么(由于缺乏完整的html / live示例),我建议你每次都解开点击处理程序(以便只一个人仍然活跃

因此,将assetspicker.show_assets中的代码更改为

$('#lightbox_display')
    .off('click','.final-asset')  // added this line to ubind the existing handler
    .on('click', '.final-asset', function(e){
        e.preventDefault();
        var   el = $(this);
        src = el.data('file');    

        empty_formfield(src, gallery);                
    });