javascriptjquerycallbackdynamically-generated

jQuery, manipulate dynamically created element in callback of a click on it


I have a mobile menu with this (simplified) html

<ul id="mobile_menu">
    <li class="menu-item menu-item-has-children">
        <a href="#">Menu with Submenu</a>
        <ul class="sub-menu">
            <li class="menu-item"><a href="#">Submenu item 1</a></li>
            <li class="menu-item"><a href="#">Submenu item 2</a></li>
            <li class="menu-item enu-item-has-children"><a href="#">Submenu item 3</a>
                <ul class="sub-menu">
                    <li class="menu-item"><a href="#">Sub-Submenu item 1</a></li>
                    <li class="menu-item"><a href="#">Sub-Submenu item 2</a></li>
                </ul>
            </li>
        </ul>
    </li>
    <li class="menu-item"><a href="#">menu item 2</a></li>
    <li class="menu-item"><a href="#">menu item 3</a></li>
</ul>

I create an helper element to close submenus in mobile devices. I create it in a function, like this:

var mainli_a =  jQuery('#mobile_menu .menu-item-has-children > a');

mainli_a.on('touchstart click', function(e){
                  
                    "use strict";
                    var link = jQuery(this);
                    if (link.parent().hasClass('active')) {
                        return true;
                    } else {
                        link.parent().addClass('active')
                        link.parent().append('<span class="closesubmenu"> </span>');  // here I create the element
    
                        e.preventDefault();
                        return false; 
                    }
                });

The element I'm speaking about is the span.closesubmenu

Then, on a click on it, I want to remove a class to its parent element, and then remove the element .closesubmenu itself.

This is how I try:

   jQuery('body').on('touchstart click', 'span.closesubmenu', function(e){

            jQuery(this).parent().removeClass('active', 0, 'linear', function(){
                 jQuery(this).remove(); // this does not work
            });

    });

It does not matter which manipulation I try in the callback to closesubmenu. it does not work.

It only work only like this:

 jQuery('body').on('touchstart click', 'span.closesubmenu', function(e){
  
         jQuery(this).remove(); // this works    

    });

Furthermore, if I just put 2 manipulations on 2 lines, only the first one works:

 jQuery('body').on('touchstart click', 'span.closesubmenu', function(e){
  
         jQuery(this).remove(); // this works  
         jQuery(this).parent().removeClass('active'); // this does not work 

    });

 jQuery('body').on('touchstart click', 'span.closesubmenu', function(e){
  
         jQuery(this).parent().removeClass('active'); // this works  
         jQuery(this).remove(); // this does not work 

    });

What am I missing here?

UPDATE:

I tried also as suggested in answers, to store the element in a var to use in the callback, like this:

            jQuery('body').on('touchstart click', 'span.closesubmenu', function(e){
                var self = this;
                jQuery(self).parent().removeClass('active', 0, 'linear', function(){
                    jQuery(self).remove();
                });
        });

But it is not working.

UPDATE 2: jsFiddle

https://jsfiddle.net/bluantinoo/yr4gdjdz/3/

UPDATE 3: Thanks to David (chosen answer) this is the correct and working fiddle: https://jsfiddle.net/bluantinoo/yr4gdjdz/6/


Solution

  • What are all these parameters you're passing to .removeClass()?

    jQuery(this).parent().removeClass('active', 0, 'linear', function(){
        jQuery(this).remove();
    });
    

    It's only expecting the class name(s). And it's not an asynchronous operation with a callback. Just remove the class(es) and then remove the element:

    jQuery(this).parent().removeClass('active');
    jQuery(this).remove();
    

    Example.