简体   繁体   中英

jquery bind and unbind without function

Objective

  • A division is clicked.
  • The contents of that division changes to a form field to update it.
  • The "click" event is removed so form field and button can be clicked
  • The form is generated with default value etc from database using $("#x").load
  • The data is saved via $.post and form is removed and replace by the new value.
  • The division should now become clickable again < PROBLEM

What I've tried so far...

I have lots of divisions with multiple "data-?" attributes for different uses. I'll keep my examples simple

<div class="profile_value" id="div1" data-id="1" data-name="john">
    <span id="field1">John</span>
</div>
<div class="profile_value" id="div2" data-id="2" data-name="alan">
    <span id="field2">Alan</span>
</div>

USING .ON(); - problem is unbinding

$("body").on("click", ".profile_value", function(){
    var pid = $(this).data("id");
    var name = $(this).data("name");
    $("#field"+pid).load("ajax/form/etc.etc.php");
    //now i can't seem to unbind the click with this method
    //i've tried $(this).off("click");
}

So even when the form field that's loaded via ajax with data from database is clicked, it just reloads the form again as another "click" is triggered.

USING .CLICK(); - problem is re-binding

With this, part 1 works perfectly...

$(".profile_value").click(function(){
    var pid = $(this).data("id");
    var name = $(this).data("name");
    $("#field"+pid).load("ajax/form/etc.etc.php");
    $(this).off("click"); //this works
});

And then when form is submitted (via ajax), on success it removes the form successfully and displays new data. However, this time I can't re-bind the click.

I've tried .bind("click") pointing to it's specific #ID and .on("click"); in various ways. No luck!

Note: Docs shows examples but all with external functions. I am using this on many divisions so a function doesn't seem suitable (I could be wrong)

Note 2: Other answers on SO also show many examples but all with functions and only one single clickable button or div.

The issue is that your event handler is triggered via delegation - the event propagates up the DOM until it hits the the body , and then triggers. .profile_value elements don't actually have the event directly bound to them, so using .off('click') on the individual elements won't work.

Using $('body').off('click', '.ele') would remove the handler from all elements, but this is not ideal.

An easy solution is to attach a new handler that stops the propagation of the click event. You can even use it to let the user know that the element has already been clicked.

DEMO

 $('body').on('click', '.ele', function (e) { console.log('Clicked!'); $(this).on('click', function (e) { e.stopPropagation(); console.log('New click handler, that stops propagation to the old handler.'); }); }); $('.rebind').on('click', function () { $('.ele').off('click'); console.log('A general rebind.'); }); 
 .ele { display: inline-block; width: 100px; height: 100px; background-color: pink; } .rebind { display: block; } 
 <div class="ele"></div> <div class="ele"></div> <div class="ele"></div> <div class="ele"></div> <div class="ele"></div> <button class="rebind">Rebind them all</button> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> 

To 'rebind' the delegated handler use .off('click') on the individual elements.

Reading material:

Im not sure what you are trying to do, but to unbind a handler from delegate listener, you can use this..

Fiddle demo

<div class="profile_value" id="div1" data-id="1" data-name="john">
    <span id="field1">John</span>
</div>
<div class="profile_value" id="div2" data-id="2" data-name="alan">
    <span id="field2">Alan</span>
</div>

var profile_click_handler = function() {
    var target = $(event.currentTarget);
    alert("clicked");
    setTimeout(function() {
        $("body").off("click", ".profile_value", profile_click_handler);
        console.log("clicked off", target );
        alert("click unbound");
    }, 2000);
};
$(document).ready(function() {
    $("body").on("click", ".profile_value", profile_click_handler);
});
window.rebind = function() {
    $("body").on("click", ".profile_value", profile_click_handler);
}

Add another parameter to your divisions:

<div class="profile_value" id="div1" data-id="1" data-click="0" data-name="john">
    <span id="field1">John</span>
</div>

Everytime new divisions are created they will have data-click="0" but when clicked that should change to data-click="1" . That way you can check if the division has been clicked or not. Does that make sense or I completely missunderstoo your question?

Ok it seems either I can't describe my problem clearly or everyone is simply rushing or tired :)

I have solved it by making the form appear in another division immediately after the .profile_values div so no more need to bind unbind. I just hide() the clicked div and show it again once form is submitted.

That was my solution to this annoying bind-unbind-rebind-on-off-live

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM