2017-10-01 2 views
0

AJAX 요청을 발생시키고 <div> ($container) 요소를 HTML로 채우는 입력 필드가 있습니다.AJAX success 함수의 클릭 핸들러가 모든 단일 요소에 바인딩되지 않는 이유는 무엇입니까?

json으로 노드 response.resultsHTML$container에 추가 할 수있는 HTML을 포함는 HTML 보이는 같은 :

<div class="js_livesearch livesearch"> 
    <div class="js_livesearch_results livesearch_results"> 
    <div class="js_livesearch_result livesearch_result" data-id="3">item_1</div> 
    <div class="js_livesearch_result livesearch_result" data-id="2">item_2</div> 
    <div class="js_livesearch_result livesearch_result" data-id="1">item_3</div> 
    <div class="js_livesearch_result livesearch_result" data-id="4">item_4</div> 
    </div> 
</div> 

AJAX 호출을 수행하고 DOM의 외모에 AJAX 응답의 HTML을 추가 자바 스크립트/jQuery를 다음과 같이 : 이제

$liveSearchTrigger.on('input', function() { 
     var search = this.value; 
     if (search) { 
      $.ajax({ 
       url: '/ajax/livesearch/' + $(this).data('identifier'), 
       type: 'POST', 
       dataType: 'JSON', 
       data: { 
        search: search 
       }, 
       success: function (response) { 
        if (response.success) { 
         if (response.resultsCount) { 
          $container.html(response.resultsHTML); 

          $container.find('.js_livesearch_result').each(function() { 
           var $result = $(this); 

           //this is being called correctly for EVERY SINGLE $result 
           alert("found: " + $result.text()); 

           //this is only sporadically bound to $result, not every single $result has the click handler - WHY? 
           $result.on('click', function() { 
            $liveSearchTrigger.val($result.text()); 
            alert('attempting to set ' + $result.text()); 
           }); 
          }); 

          reLayout(); 
          $container.slideDown(150); 
         } else { 
          $container.slideUp(150); 
         } 
        } 
       } 
      }); 
     } else { 
      $container.slideUp(150); 
     } 
    }); 

$container.html(response.resultsHTML);를 사용하여 DOM에 새로 생성 된 HTML을 추가 한 후 나는 매일 $('.js_livesearch_result') 요소에 클릭 이벤트를 바인딩 할. $container.find('.js_livesearch_result').each(function() { ... }); 범위에서

는 경고가 모든 .js_livesearch_result 항목이라고하며 'ITEM_1는'ITEM_2이 ', [...] 모든 요소에 대한하지만 $result.on('click', function() { ... }); 그들 모두에 바인딩되지 경고합니다. 때로는 처음 두 개만, 때로는 3 개가 클릭 이벤트에 바인딩됩니다.

나는 매일.js_livesearch_result 요소가 클릭 핸들러가 결합 된 것을 있도록 동적으로 생성 .js_livesearch_result 요소에 클릭 이벤트를 바인딩하는 방법 내가 이벤트가 적절하게 결합 할 시도 잘못 뭐하는 거지?

편집 :

$liveSearchTrigger 요소의 HTML :

<input class="js_livesearch" type="text" name="key" value="" data-identifier="langkey" autocomplete="off" /> 

여기

이 때문에 나는 아직도 제대로 작동하려면 $('.js_livesearch_result').on('click', function() {...});를 얻을 수없는 이상 (업데이트) 코드 response.resultsHTML 구조에 추가됩니다. $container :

$(document).ready(function() { 
    $('.js_livesearch').liveSearch(); 
}); 

livesearch.js (플러그인) : 나는 에 추가되는 모든.js_livesearch_result 요소를 클릭 이벤트를 바인딩하려면 어떻게

(function ($, window) { 

    $.fn.liveSearch = function (options) { 

     var defaults = { 
      highlightCSS: { 
       'background-color': "lightgoldenrodyellow", 
      } 
     }; 

     var settings = $.extend({}, defaults, options); 



     var $liveSearchTrigger = $(this); 


     var searchUID = Math.floor(Math.random() * 26) + Date.now(); 
     var $container = $('.js_livesearch_uid' + searchUID); 

     if (!$container.length) { 
      var $elem = $('<div>').addClass('js_livesearch_uid' + searchUID).addClass('hidden'); 
      $('body').append($elem); 
      $container = $('.js_livesearch_uid' + searchUID); 
     } 

     $liveSearchTrigger.on('input', function() { 
      var search = this.value; 
      if (search) { 
       $.ajax({ 
        url: '/ajax/livesearch/' + $(this).data('identifier'), 
        type: 'POST', 
        dataType: 'JSON', 
        data: { 
         search: search 
        }, 
        success: function (response) { 
         if (response.success) { 
          if (response.resultsCount) { 
           $container.html(response.resultsHTML); 

           //this works fine if uncommented, every single 
           //element gets a highlight applied 
//        $container.find('.js_livesearch_result').each(function() { 
//         $(this).highlight(search, settings.highlightCSS); 
//        }); 

           //this does not work consistently, sometimes the first 3 (out of 4) 
           //items will bind the click handler sometimes only the first two 
           //elements will bind the click handler 
           $container.on('click', '.js_livesearch_result', function() { 
            console.log('Clicked: ' + $(this).text()); 
           }); 

           //another test which didn't work: 
//        $container.find('.js_livesearch_result').each(function() { 
//         $(this).unbind('click.resultItemClick').bind('click.resultItemClick', function() { 
//          console.log('Clicked: ' + $(this).text()); 
//         }); 
//        }); 

           reLayout(); 
           $container.slideDown(150); 
           $container.removeClass('hidden'); 
          } else { 
           $container.slideUp(150); 
           $container.addClass('hidden'); 
          } 
         } 
        } 
       }); 
      } else { 
       $container.slideUp(150); 
       $container.addClass('hidden'); 
      } 
     }); 

     $(window).resize(function() { 
      reLayout(); 
     }); 

     $liveSearchTrigger.on('focus', function() { 
      reLayout(); 
      $container.slideDown(150); 
      $container.removeClass('hidden'); 
     }); 

     $liveSearchTrigger.on('blur', function() { 
      $container.slideUp(150); 
      $container.addClass('hidden'); 
     }); 

     function reLayout() { 
      var position = $liveSearchTrigger.position(); 
      var layoutCSS = { 
       'position': 'absolute', 
       'z-index': '1000', 
       'top': (position.top + $liveSearchTrigger.outerHeight()) + 'px', 
       'left': position.left + 'px', 
       'width': $liveSearchTrigger.outerWidth() + 'px' 
      }; 
      $container.css(layoutCSS); 
     } 

     return this; 
    }; 

}(jQuery, window)); 

page.js

<div class="js_livesearch_results livesearch_results"> 
    <div class="js_livesearch_result livesearch_result" data-id="3">menu_code</div> 
    <div class="js_livesearch_result livesearch_result" data-id="2">menu_gallery</div> 
    <div class="js_livesearch_result livesearch_result" data-id="1">menu_home</div> 
    <div class="js_livesearch_result livesearch_result" data-id="4">menu_user</div> 
</div> 
은 플러그인을 초기화 DOM을 AJAX를 통해?

+0

동적으로 추가 된 DOM 요소에 이벤트 처리기를 추가하는 방법을 묻는 중입니까? –

+0

예. AJAX를 통해 '

item
'을 추가하고 이러한 추가 된 요소에 클릭 이벤트를 바인딩하려고합니다. 어떤 이유로 모든 요소가 (항상은 아니지만) 클릭 핸들러를 받으면서, (무작위로) 여러 요소에 대해서만 작동합니다. 나는 이미 행운없이 @Rory McCrossan이 제안한 것을 시도했다. 더 많은 코드를 게시 할 예정입니다. 처음에는 바인드가 발생하는 AJAX 부분 자체가 실수를하고있는 곳이라고 생각했습니다. 이제 다른 곳의 코드를 놓치고 있다고 생각합니다. – phew

+1

이벤트 버블 링 또는 위임을 검색합니다. –

답변

0

문제가 $liveSearchTrigger.on('blur', ...) 이었으므로 문제가 해결되었습니다.