I've got a relatively complicated jQuery UI sortable, which I'm able to drag in elements from somewhere else. I'm using the following code, and am attempting to find the first element inside of what's been dropped with a class of editable, and trigger a click on it. This isn't working. I've thrown in some alerts and a console.log of ui.item[0].innerHTML returns an object with the correct DOM elements in it. So, I'm not quite sure what's going on here.
stop : function(event, ui){
$(ui.item[0].innerHTML).find('.editable').first().trigger('click');
}
Can anybody throw some of their wisdom my way? I'd greatly appreciate it. Just to note - if I click on the added element manually, it works as expected.
Thank you!
I would guess that you want just $(ui.item[0]) and not $(ui.item[0].innerHTML) because innerHTML returns the HTML syntax of the element ui.item[0] (a string) and not references to the DOM nodes like you want.
$(ui.item[0].innerHTML) creates a new element. So triggering an event on this element is useless.
Use $(ui.item[0]) instead.
Related
I'm building out a notifications feature with bootstrap popover. A notification should be removed after a user clicks on it, which is intuitive. However, it takes two clicks to make it work -- the first time, nothing seems to happen. The click listener is firing both times as discovered through alert().
I've simplified my problem to its most basic reproducible form in this fiddle js:
https://jsfiddle.net/ksun78/758n1azu/36/
$('body').on("click", ".popover-body .notif-popup-container", function() {
$("#" + $(this).attr("id")).remove();
})
Placing code above because it won't let me submit without code snippet, though the fiddle js should have all you need.
Can someone explain what the issue might be and how to fix it? Thanks!
I think the problem is that the popover library clones your elements so there are two elements with the same Ids. You can modify your code like this so it will work but better to avoid same Ids
$('body').on("click", ".popover-body .notif-popup-container", function() {
$(`[id="${$(this).attr("id")}"]`).remove();
})
If you simply want to delete that div you can use following code:
$(document).on("click", ".notif-popup-container", function() {
$(this).remove();
});
It turns out that behind the scenes, popover will make a copy of the elements and display them. This means that using ONLY the ID to remove the elements won't work, because it will first remove the display:none element on the page, then the copy of that shown in the popover. Thanks to #Gabriel for pointing that out.
The solution here was just to not use the id attribute of the element as it was unnecessary. A simple $(this).remove() will do the trick.
As for the issue of duplicate id's: I was originally intending on storing the notification id inside a "data-id" attribute. However, retrieving "data-id" using jquery was returning undefined, so I opted for the "id" attribute instead. Maybe #Gabriel can provide some insight into the issue of "data-id" being undefined, as it seems like a popover related issue as well.
I am new to jQuery and such kind of js frameworks. Till now I used to do like this
<div onclick="function()"></div>
But in jQuery we get the element and add the event there. How can I detect all events added on a div?
I have a div whose height is set to the remaining height. Then I cant find appropriate css for that. I strongly believe that it has been done from javascript. I cant find relavant code any where. I dont know how to debug this.
Any help is highly appreciated.
To answer your question you can use:
jQuery._data( elem, "events" );
This will become an object of all events attached to the selected element.
This will return undefined when no event is attached to the element.
Note that this should be a single element, so for a class you should use:
$._data($('.class')[0], "events")
Which only select the first element with that class, instead of all the elements with that class.
jsFiddle
Source: jQuery find events handlers registered with an object
I've got this situation:
There is a calendar script to pick a date. When the date is picked a function called onclick to make a select box available for time pick. Now its not like its display:none-->display:block, the select being generated by JS. My goal is to customize this select. For that I got a jquery script "custom.select" which just turns the select to spans. The problem is that if I add the call for this script to the onclick right after the calendar call it does not take. I am pretty sure its because at that stage the html for the select is not injected yet. If I call the custom.select function from the firebug console after the select is visible - it works just fine.
So the question is: how do I call it so it will do its magic on select box?
Thanks
Use delegation with .on():
$(function(){
$(document).on('click','.classdynamic',function(){
//do stuff here
});
});
You should delegate event to the closest static container of your target element. This means changing $(document).on('click','.classdynamic',function(){...});
by something like: $('#staticContainer').on('click','.classdynamic',function(){...});
Figuring out when elements are added is not an easy task. I answered a similar question here.
The best way would be to have some control on the script that creates the select, and append your code to it. One way to achieve this is with Aspect Oriented Programming (AOP) - not easy either.
With current browsers, the most straightforward way is to use setTimeout in a loop and poll the page until the element exists.
Ok I got this thanks to Christophe! I used the Selector Listeners script from here: http://www.backalleycoder.com/2012/08/06/css-selector-listeners/
It was even more complicated coz the parent was not present either )). So what I did was that I attached the listener to the onclick just after the calendar call lol. I needed to make another function though to make it work with the script, here is the code:
var doSelect = function(){
jQuery('#timeslots').customSelect();
};
jQuery(document).ready(function(){
jQuery('.td_calendar').on('click','#anchor1',function(){
cal.select(document.forms['frmRequest'].startdate,'anchor1','yyyy-MM-dd');
document.getElementById('slots').addSelectorListener('#timeslots', doSelect);
});
});
I've got a page with some Javascript / jQuery stuff, for example:
(function()
{
$('.tip').tooltip();
$('.test').click(function()
{
alert('Clicked!')
});
}();
On the page I insert some HTML with jQuery so the DOM changes. For example, I insert a extra element with the class "tip" or "test". The just new inserted elements doesn't work because jQuery is working with the non-manipulated DOM and the just inserted elements aren't there. So I've searched around and came to this solution for the "click":
$('body').on('click','.click',function()
{
alert('Clicked!')
});
I don't understand why, but this way it's working with the manipulated DOM and the jQuery stuff works on the new inserted elements. So my first question is, why does this work and just the click() function not? And the second question, why do I have to point to the "body"?
Finally, my third question is, how get this done with the tooltip?
I know that there is so many information about this subject (previous the delegate() and live() function I've read) but I can't found a explanation about it. And I can't get my third question solved with the information I found.
I'm looking forward to your responses!
Extra question:
4) Is it recommended to point always to the "body" for this kind of situations? It's always there but for possible performance issues?
So my first question is, why does this work and just the click()
function not?
Because the event handler is now delegated to a parent element, so it remains even after replacing/manipulating child elements.
Ancient article on event delegation for your perusal - but the concepts remain the same:
http://www.sitepoint.com/javascript-event-delegation-is-easier-than-you-think/
And the second question, why do I have to point to the "body"
You don't, any suitable parent element will do. For example, any direct parent (a div wrapper, for instance) which does not get replaced.
Finally, my third question is, how get this done with the tooltip?
You need to re-initialize your tooltip plugin on the newly inserted elements. For example:
$.get("foo.html", function (html) {
$("#someDiv").html(html);
$("#someDiv").find(".tip").tooltip();
});
The click() event doesn't work when you manipulate the DOM because JQuery is not watching for DOM changes. When you bind the click() event it is selecting the elements that are on the page at that time. New ones are not in the list unless you explicitly bind the event.
Because you have pointed the click() event on the body. JQuery then checks to see if the target of the click matches any of the event handlers (like what you have created) match the element clicked. This way any new elements will get the event 'associated' with them.
Because the tooltip isn't an event that you can place on the body, you will need to re-initialize it when the element is created.
EDIT:
For your fourth question, is it depends. The advantage of binding to the body is that you don't accidentally bind an event to an element more than once. The disadvantage is that you are adding event handlers that need to be checked on each event and this can lead to performance issues.
As for your concerns about DRY, put the initialization of the tooltips into a function and call that when you add them. Trying to avoid having the same function call is a little overkill in this regard, IMO.
Events are bound to the specific object you are binding it to.
So something like $('.tip').tooltip() will perform the tooltip() functionality on $('.tip') which is actually just a collection of objects that satisfies the css selector .tip. The thing you should take note of is, that collection is not dynamic, it is basically a "database" query of the current page, and returns a resultset of HTML DOM objects wrapped by jQuery.
Therefore calling tooptip() on that collection will only perform the tooltip functionality on the objects within that collection, anything that was not in that collection when tooltip is called will not have the tooltip functionality. So adding an element that satisfies the .tip selector, after the tooltip() call, will not give it the tooltip functionality.
Now, $('body').on('click','.click', func) is actually binding the click event to the body tag (which should always exist :P), but what happens is it captures whether the click event has passed through an element your target css selector (.click in this case), so since the check is done dynamically, new elements will be captured.
This is a relatively short summary of what's going on... I hope it helped
UPDATE:
Best way for your tooltip thing is to bind tooltip after you have added elements, e.g.
$('#container').load('www.example.com/stuff', function() {
$('.tip', $(this)).tooltip();
});
I am trying to make a basic captcha module for jQuery. I have a decent start on it, but for some reason .children() doesn't seem to work. See it here: http://jsfiddle.net/pTbeW/
I currently have this:
$(this).children('.captchain-start').hide();
$(this).children('.captchain-show').show();
If I change it to
$('.captchain-start').hide();
$('.captchain-show').show();
it works perfectly. But this solution is less than ideal, because it wouldn't allow two instances of this captcha to be on the same page. I suspect it has to do with the html being set by query, but I'm not sure how. I'm far from a javascript and jQuery expert, but this seemed like a relatively easy thing to do. What am I missing? Do I have tired eyes from looking at it so long? Any help would be appreciated.
Because the '.captchain-*' elements are not children, but are siblings. Try the following:
$(this).nextAll('.captchain-start').hide();
$(this).nextAll('.captchain-show').show();
You should use $(this).nextAll() instead of $(this).children() because the elements you want to hide and show are not children of the a element, but siblings.
See http://api.jquery.com/nextAll/
this
In your click event references the clicked element, which is the element with the class 'captchain-start'. So you do not have to scan for the children, you can use:
$(this)
for the actually clicked element or the element selector instead
instead.