0

I'm trying to remove a click handler from an a element, but .off() does not remove it. I already looked here and here.

My HTML (which is generated dynamically in document.ready() event):

<ul id="catalog">
<li data-id="2">
    <div class="item">
        <div class="image">
            <a href=""><center><i class="fa fa-picture-o fa-lg noitemimage"></i></center><span class="txt">My title</span></a>
        </div>
        <div class="details"><button class="delete btn-primary-grey-s">Delete</button></div>
    </div>
</li>
</ul>

Javascript:

$(document).on('click', '#catalog a', function () {
    ShowData();
    return false;
});

At a user action the following code is called and I want to remove the click handler that was set in the above code. However, after execution I can still click the hyperlink and the above code is still executed.

$.ajax({
    type: "GET",
    url: "/api/deleteitem/?itemid=" + itemid,
    data: "",
    contentType: "application/json; charset=utf-8",
    dataType: "json",
    success: function (data) {

        //disable the events on this elements' "a" click

        //ALL THESE 3 OPTIONS BELOW DO NOT WORK
        //$(document).off('click', 'ul#catalog li[data-id=' + itemid + '] a', '**');
        //$('ul#catalog li[data-id=' + itemid + '] a').off();
        $('ul#catalog li[data-id=' + itemid + '] a').off('click');

    }
});

** UPDATE 1 **

        $.ajax({
            type: "GET",
            url: "/api/getitems/?id=" + id ,
            data: "",
            contentType: "application/json; charset=utf-8",
            dataType: "json",
            success: function (data) {

                DYNAMIC HTML CODE GENERATED FROM HERE WORKS DIFFERENTLY??

                }

            }
        });
Community
  • 1
  • 1
Flo
  • 6,070
  • 26
  • 97
  • 171

2 Answers2

1

Your first selector uses event delegation method where the document object contains the registered event handler. When a click happens, it then filters and delegates the event to its children that matches the sub-selector,

'#catalog a'

If you want to remove the event, then you must add click handler directly to the child element as,

$('#catalog a').on('click', function () {
    ShowData();
    return false;
});

(or) you can use off with selector argument as,

$(document).off('click', '#catalog a')
  • Ah, that makes sense. However, the `ul` list HTML is generated through jQuery on `document.ready()` (I updated my post) so all elements do not exist yet, that's why I used `$(document).on`. So when I use `$('#catalog a').on('click', function () {` now undesirably works as a regular hyperlink. What else can I do? – Flo Apr 27 '16 at 15:05
  • try `$(document).off('click', '#catalog a')` –  Apr 27 '16 at 15:25
  • Thanks, but I don't want to disable ALL links, just the link belonging to the item that was just clicked. And that I already tried without success, see '**' in my post. I also tried `$(document).off('click', 'ul#catalog li[data-id=' + registryItemId + '] a');` but that does not work either. (both selectors are valid btw and return the desired element) – Flo Apr 27 '16 at 16:38
0
//<a href="javascript:;">

//ShowData logs only first time

var $test = $("#catalog a");

function ShowData() {
    console.log("ShowData");
}

function doNothing() {
  console.log("Off");   
  $test.off("click", ShowData);
}

$test.on("click", doNothing); 
$test.on("click", ShowData);

//For Dynamic

   $("#catalog a").on("click.doNothing", function(){
      console.log("Off");   
      $(this).off("click.ShowData");
   }); 
   $("#catalog a").on("click.ShowData", function(){
     console.log("ShowData");
     //your ajax code
   });

//Update Okay i don't find solve for on/off after ajax success. And also i try $(document).on("click.ShowData", "#catalog a" function(){ etc...

At last this approach work for me.

var i = 0;
function build(){
      var li_builder = '';
      li_builder += '<a href="javascript:;">';
      li_builder += '<span class="txt">' + i + '</span>';
      li_builder += '</a>';
      var attach = $(li_builder).on("click.doNothing", function(){
        console.log("Off");   
        $(this).off("click.ShowData");
      }).on("click.ShowData", function(){
            console.log("showData");
            ajax();
      });
      $('#catalog').append(attach);

      $("#catalog a").each(function(){
      if($(this).parent("li").length > 0){
        console.log("has_li");
      }else{
        console.log("no_li");
        $($(this)).wrap("<li/>");
      }
      });
      i++;
}

function ajax(){
    $.ajax({
            type: "GET",
            url: "",
            data: "",
            success: function (data) {
                build();
            }
        });
}

$(document).ready(function(){
    build();
});
turkaze
  • 56
  • 1
  • 9
  • try For Dynamic in my answer. This works. This doesn't disable all links. – turkaze Apr 28 '16 at 00:52
  • Could you explain what exactly you are doing here? I don't see the element that is selected by selector `click.doNothing` for example. – Flo Apr 29 '16 at 01:28
  • Are you test it? I test with your list. Only i give javascript:; to your links. And test it. There's two namespaces on same selector. if you first time click catalogs a, doNothing and showData run together. After if you click same one only doNothing run. And after if you click another link same scenario is repeat for others. I think this approach solve your problem. – turkaze Apr 29 '16 at 01:49
  • I placed your code in the `document.ready()`, but the click on `#catalog a` never triggers. To be honest, the code looks like quite a lot of lines for something which should be really simple to achieve through 1 or 2 jQuery calls wouldn't you agree? – Flo Apr 29 '16 at 13:23
  • That code indeed works, but copy-paste into my project does not...the alert is never shown and hyperlinks now work as regular hyperlinks :s. The only thing other than your Fiddle code is that my `ul` element is dynamically generated (but that should be covered by the `.on()` handler in your code right). Can I somehow check if some other function/handler is interfering with your event handler? – Flo Apr 29 '16 at 14:47
  • if i understand clearly give the or – turkaze Apr 29 '16 at 15:06
  • If you want to solve please paste your code somewhere and add link to comment. – turkaze Apr 29 '16 at 16:23
  • Please see here (I've renamed `ShowData` to `ShowMe` btw): https://jsfiddle.net/5fwnskk9/ – Flo Apr 29 '16 at 18:00
  • https://jsfiddle.net/5fwnskk9/1/ this is update version which is same. it works only you not include jquery library in jsfiddle. – turkaze Apr 29 '16 at 18:35
  • Ok. I tried something else now: https://jsfiddle.net/gb68Lun9/. I noticed that when I generate the dynamic HTML directly from within the javascript `script` tag it works as expected. However when I place the code in block `DYNAMIC GENERATOR` in the `success` condition of an ajax call, it does NOT work anymore. Not sure how I can simulate that for you in a jsfiddle, but there seems to be something different. See my "update 1" in the original post. – Flo Apr 29 '16 at 19:50
  • okay i understand your problem i update new ones. i send there. – turkaze Apr 29 '16 at 20:31
  • https://jsfiddle.net/gb68Lun9/4/ look at this. If you don't like this approach another way is use in a tag class="enabled" and class="disabled" and toggle this class. – turkaze Apr 30 '16 at 14:55
  • But if you want use only off i look at now but not solve. Maybe i look at tommorrow and send there if i have more time. – turkaze Apr 30 '16 at 15:00
  • Solved! I uses the addition/removal of css classes to prevent a second click..thanks! :) – Flo Apr 30 '16 at 20:20
  • Look on my answer last edit again //Update section. I hope helpful for you. – turkaze May 01 '16 at 14:36
  • I'd rather see you post your suggestion with classes as an answer as that actually solved it...that way I can give you answer points :) – Flo May 03 '16 at 03:22
  • i'm not writing answer for points. I use stackoverflow sometimes. in past four years i only answer 4-5 questions. Bye. – turkaze May 03 '16 at 12:57