开发者

Re-Tying a the jquery click dynamically after replacing the element

I have a set of nested elements like such.

<div id="master">开发者_高级运维
    <span id="num-1" class="num"></span>
    <span id="num-2" class="num"></span>
    <span id="num-3" class="num"></span>
    <span id="num-4" class="num"></span>
</div>

And I have the following script

$( document ).ready( function() {
    $( '#master > span.num' ).click( function() {
        q = $( "span[id*=num-']" ).attr( "id" );
        $( '#master' ).html( '&nbsp;' ).load( 'www.someurl.com/?rating=' + q );
    });
});

The load function returns a completely new set of span elements for inside the div. Problem is that I can't seem to figure out how to get this to work past the first time I click one. Since the click is tied to the spans and the spans get replaced, I understand that they no longer have a script tied to them, but I haven't been able to figure out how to get this to re-tie on the fly. I'm super new to jquery and javascript so any help would be appriciated.

All my experiments with using .live() have merely rendered my script useless. Help?


  • DEMO: https://so.lucafilosofi.com/re-tying-a-the-jquery-click-dynamically-after-replacing-the-element/

EDITED: as suggested by Beejamin

$( function() {
    $('#master').click( function(e) { 
    if (e.target.className.indexOf('num') !== -1) {
        var num = e.target.id.split('-')[1]; //this give you # instead of num-#
        $(this).load( 'rating.php/?rating=' + num );
      }  
    });
});

  $(function() {
    $('.num').live('click',function() {
     var num = this.id.split('-')[1]; //this give you # instead of num-#
        $('#master').load( 'rating.php?rating=' + num );
          return false;
    });
});

I suppose you are trying to do a rating system? just for sake my PHP file look like this:

<?php
  if (isset($_GET['rating'])) {
  $rating = (int) $_GET['rating'];
  for ($i = 1; $i < 5; $i++) {
    $a .= "<a id='num-{$i}' class='num".($rating >= $i ? ' rated' : '')."'></a>";
  }
  echo $a;
}
?>


There's a better way of handling this called 'event delegation' - rather than assigning your click events to each individual span, you can assign the event to the #master div. Because click events 'bubble up' - when you click any element, the click event will be passed up to the #master div. The event itself contains the .target property, which is a reference to the original element that was clicked.

This is much faster (you only have to assign one event, not many), and only needs to be set once.

Your code example becomes:

$( document ).ready( function() {
    $( '#master' ).click( function(e) {
    if (e.target.className == 'num') {//Check if the target that was clicked is one of the elements we want.
        q = $(e.target).attr('id');
        $('#master').html('&nbsp;').load( 'http://www.someurl.com/?rating=' + q );
      }
    });
});

Here's some background on event delegation: http://www.cherny.com/webdev/70/javascript-event-delegation-and-event-hanlders, and more info on event bubbling: http://www.quirksmode.org/js/events_order.html

The only thing you'd have to watch, is that, if you put extra HTML inside your span.num, e.target will point to that element if it's clicked (which is easy enough to account for). If you're only ever going to have text inside the span, you'll be fine with this code.


You can define a function for that and provide recursion

function spanClicked(){
    q = $( "span[id*=num-']" ).attr( "id" );
    $( '#master' ).html( '&nbsp;' ).load( 'www.someurl.com/?rating=' + q );
    $( '#master > span.num' ).click( spanClicked);
}

$( document ).ready( function() {
    $( '#master > span.num' ).click( spanClicked);
});


You can use jQuery .live() to bind events on the fly. You can check the plugin http://docs.jquery.com/Plugins/livequery For more flexibility.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜