How to use JQuery.find() when DOM is dynamic - javascript

I have a cascading menu with the following flow;
click on an item from menu-1
creates and updates menu-2 li elements
click on an item from menu-2
creates and updates menu-3 li elements
etc..
```
$firstMenu = $('.prime-menu');
$secondtMenu = $('.second-menu');
$thirdMenu = $('.third-menu');
```
As i'm traversing through different elems. within each menu, using find() comes as a blessing, the issue is that the script loads when no menu other than the first menu is created so $secondtMenu.find('.item-year').click(function (clickEvent) {}) is 0 length.
What are my options in JQuery to make my find() functions work on elements that are not loaded yet in the DOM?
I thought of creating an event listener, but I think there are more terse approaches than that.

You should use delegates when dealing with dynamic HTML. For instance, use an outer element like document or body to "start" your finds.
$(document).find(".prime-menu");
EDIT: Find and event delegation
The solution was to use find with event delegation. Example event.
$(document).find(".prime-menu").on('mouseenter', '.track-table tbody tr', function(){ });

You state that when you click on an item from menu-1 it creates and updates menu-2 li elements. In this function is where you should do your event binding. The DOMElement will exist in js before being added to the dom, and that is where your bindings should be set.
If you need help share this code with us I'm sure myself or someone will be able to help you sort it out.

Bind the click handler to the menu parent, not the actual menu items.
Something like this might work...
$("#menuparent").on("click",".item-year",function(event) {
var clicked_element = event.currentTarget;
});
Doing it this way, even if the element with class .item-year is added to the dom after the click event is bound, it will still register the click.

Related

Newly added elements $.each and events

I’ve read many posts already on the $.each and newly added elements + event attachment. Many of the current Questions regarding this topic on StackOverflow don’t seem to work for me. $.on() is normally recommended since it allows us to append new elements and still maintain a single event listener + handler.
In my current code:
1.$(‘input[type="checkbox"]’).on(“change”, function(e){});
//I do a logical if-statement, if(this.checked) else
//With-in the if-statement I run $.each, however, once I have appended new element in this context a new li to the ul, it stops working.
Out of the curiosity has anyone encountered something like this before, and if YES, how have you folks solved this?
Some StackOverflow posts I have already seen:
jQuery $(element).each function doesn't work on newly added elements
jquery: dynamically appending li items to ul then adding click, but click runs through each li
Event binding on dynamically created elements?
Currently what you are using is called a "direct" binding which will only attach to element that exist on the page at the time your code makes the event binding call.
Delegated events have the advantage that they can process events from descendant elements that are added to the document at a later time.
As you are creating elements.
You need to use Event Delegation. You have to use .on() using delegated-events approach.
General Syntax
$(document).on(event, selector, eventHandler);
Ideally you should replace document with closest static container.
Example
$(document).on('change', 'input[type="checkbox"]', function(){
//Your code
});

Add Event listener using Jquery

I am creating a clone of a div, but unfortunately i am not able to add event listener to cloned div.
I tried using clone(true,true) but still did not get it running.
Can some one help me out with it please
JS fiddle for clone
Clicking image next to And, adds a new div
Code i tried for adding event listener
$("#add").on('click',function () {
$("#cont").clone(true, true).appendTo(".container");
});
First you should change your cont id to a class as multiple ids are bad and won't work properly.
Second, use jQuery's first method to grab the first in the returned jQuery nodelist that you get from grabbing all the cont classes: $('.cont') and then clone the node. You have to grab only the first one or you'll end up adding multiples of the div back on to the page.
$(".cont").first().clone(true, true).appendTo(".container");
Third, change the delete id to a class.
Fourth, because you're adding to the DOM you need to use event delegation on the parent node in order to catch the events properly. Use closest to find the nearest cont class and remove it.
$('.container').on('click', '.delete', function () {
$(this).closest('.cont').hide();
});
Fiddle
Hope this helps.

Adding an event listener to a div to perform an event if the div becomes empty (has no children)

My goal is the following: create a listener that will be bound to a div and it will fire up if there are no children left in that div.
I keep seeing how to bind a listener to say onClick etc.. but I cannot seem to find anyone that deals with actual states of the elements (empty, at least one child, etc... ). I have not started coding anything yet because I am not sure what kind of approach I need to take, since I am pretty new to JavaScript development. I am not necessarily looking for an answer with code in it but more of an advise on what approach to take.
One of the approaches that I was thinking of was to simply have a function call every single time I make a change to the div such as deleting a child but that seems too trivial. I want to create some kind of automation in that process of checking for no children.
jQuery has remove event fired when element is removed
$(el).on("remove", function () {
alert("Element was removed");
});
You could use live (if they are appended dynamically to parent container) or on (if statically) method to bind this event to child nodes of particular container and on every remove event check if parent container has any child nodes. If not then do some actions.
You cannot assign a listener to a div element to check if the element has no children(done automatically without knowing which function is removing the children, but only knows that there was a child removed). Granted you could do a function to check every so many seconds but that is not what I wanted. Anyways, where I remove the children, I simply added a function that checks if the parent is left with no children and it handles it there.

event.target points to a child element

When a user clicks on a <li>-element or on a child element of it, I want to add a class to this <li>-element.
This works fine, but for performance enhancement I decided to bind this event to the <ul>-element, so unbinding and binding this event is much faster in a list consisting of 1000 <li>-elements. The only change I thought I had to make was to replace this with event.target BUT event.target can also refer to a child element of a list item or even to a grandchild.
Is there an easy way to check this target element is part of a list item or do I need to walk the path from event.target till I reach a <li> element?
This is what I had before I decided to bind an event to the <ul> tag, which works but is not fast enough:
$('#list li').mousedown(function(){
$(this).addClass('green');
});
And this is what I have now which doesn't work properly, mousedown on a child element doesn't give the <li> another classname:
$('#list').mousedown(function(event){
if(event.target.nodeName == 'LI'){
$(event.target).addClass('green');
}
});
I wonder if my second way to achieve this is faster if there is not a simple solution to check if that target element is part of a list item...
Well, you could do all of this with the jQuery on tool:
$('#list li').on('mousedown', function() {
$(this).addClass('green');
});
You can read about what on does here: http://api.jquery.com/on/
You need to check if there is a LI tag in the parents of the target element.
All of the common frameworks have a way of determining this, it is up() in prototype, ancestor() in YUI3, and looking at the JQuery docs, it seems like it has a parent(), and parents() function that you can use for this.
See: http://docs.jquery.com/Traversing
Haven't used JQuery, but it I assume checking for $(event.target).parent('li') is the answer.

Adding, Removing and Adding Element again removes its Event

I have a hyperlink with an ID when clicked will perform a certain event using JQuery. JQuery records the existence of this link on document load. Some time during the course of the users visit. I remove that link and the re-add it later. However, that even is not fired off again when that link is clicked after it has been removed and added.
Why is the case and how can I remedy it? Something to do with event binding?? Or shall I just add an onclick attribute?
You've been using a tag like this to add the click event:
$('#speciallink').click(function(){
// do something
return false;
});
This will bind the event to the elements that are selected at that moment.
Removing a link and adding it again, will effectively create a new element, without this event. You can use the "live" method to add rules that will be applied to events matching the rule, even when these elements are created after creating the rule:
$('#speciallink').live("click",function(){
// do something
return false;
});
You will need to bind that event handler to the new element when it is added or you could use live() instead of bind to achieve what you need.
Basically, the event handler references the original element. When that element is removed, even though a new element is added with the same id, it is a different element.
Don't remove the link from the DOM tree. Instead, just toggle its visibility with show() and hide().
Removing the element from the DOM tree with remove() will remove the element and all of its event handlers, even if you add it back with the same id.
If you completely remove the element, you will need to reattach any event listeners to the element when you recreate it.
Alternatively, just hide the element by setting its style to display:none with .show() and .hide()

Categories

Resources