I have a project where I need to load html from an external file and add it to an existing div element.
It works great, except that the .click() events never fire when clicking on the desired icon in the generated html.
Code that loads the html:
$.each(data, function (index, review) {
let html = $.parseHTML($.trim(review));
$(html).appendTo($items);
});
Root element of the loaded html is a class named "lc-rating-wrap".
The js that doesn't fire on click:
$(".lc-rating-wrap > .vote-wrap > .do-vote-wrap > .icon").click(function () {
//doStuff
});
I guess it has something to do with that the elements isnt there when I load the js file?
Am I using parseHTML() correctly?
Your content is dynamic, but your event is binded only for existing elements. Change it to be $(static).on(event, dynamic, callback):
$(document).on('click', ".lc-rating-wrap > .vote-wrap > .do-vote-wrap > .icon", function () {
//doStuff
});
Please use delegate instead click.
$( "#parent" ).delegate( ".icon", "click", function() {
//dostuff
});
Parent is a element which you using to generate your elements (inside).
So it cannot be generated dynamicaly.
use jquery click event delegation. see https://learn.jquery.com/events/event-delegation/
Bind event to an parent element already found in your page when js is binding click event. Use .on("click", "your selector", function(){})
Related
I want to make a web site for a photos.
Inside a dynamic div created with a jquery function (.append) there is this anchor:
<a href='#' style='color:green;' id='"+this.foto_id+"' data-id='"+this.foto_id+"' class='modificaDataFoto modificaDataFoto"+this.foto_id+"'>Modifica</a>
The page is load normally and if I use the browser debugger I see all the HTML code including all dynamic data from database...
But if I try to set a class of the anchor in a jquery function it doesn't run:
$('.modificaDataFoto').bind('click', function(event) {
event.preventDefault();
var idFotoModifica= $(this).attr("data-id");
console.log(idFotoModifica);
$("dataFoto"+idFotoModifica).focus();
$("dataFoto"+idFotoModifica).css("color", "red");
$(this).attr("class", "modificaDataFotoConferma");
});
Why does that function not work?
.bind() only works on elements that are already present in the DOM. It's likely that you're trying to bind the click event to the element before the dynamic element exists.
There are two ways to fix this:
wait until after the <a> element has been appended to the document before running your $('.modificaDataFoto').bind(), or
Delegate the click event from a non-dynamic element (or the document itself):
$(document).on('click', '.modificaDataFoto', function() {
// this is essentially the same as your existing function; I've
// consolidated it a bit and removed the no-longer-needed preventDefault.
$("dataFoto" + $(this).attr("data-id")).css("color", "red").focus();
$(this).attr("class", "modificaDataFotoConferma");
}
Use this code:
$(document).on('click', '.modificaDataFoto', function(event) {
event.preventDefault();
var idFotoModifica = $(this).attr("data-id");
console.log(idFotoModifica);
$("dataFoto"+idFotoModifica).focus();
$("dataFoto"+idFotoModifica).css("color", "red");
$(this).attr("class", "modificaDataFotoConferma");
});
I'm not entirely sure if I understood your question but if you are trying to change the element's class name then you can simply do this:
$( this ).switchClass( "old class", "modificaDataFotoConferma", 1000, "easeInOutQuad" );
instead of
$(this).attr("class", "modificaDataFotoConferma");
You also have the .toggleClass()
EDIT:
You can also use removeClass() and then use the addClass().
In framework7, how to add click event on dynamic elements?
If I add my element first on my view, the click event works fine like below:
<div class="test">Click Me</div>
$$('.test').on('click', function () {
myApp.alert("Gotcha!");
});
But if I have dynamic elements, especially elements dynamically added to virtual-list, I cannot make the click event to work. What is the right way to do this?
I even tried inline function, ex: <div class="test" onclick="myFunction();">Click Me</div>, still this won't work.
You can use:
// Live/delegated event handler
$$(document).on('click', 'a', function (e) {
console.log('link clicked');
});
For your case:
$$(document).on('click', '.test', function(e){
console.log('Some code...');
});
Here is docs. Scroll until events section.
Use this for dinamically added elements:
$$(document).on('click', '.test', function () {
myApp.alert("Gotcha!");
});
All answers are good to go with. But if you are using this class 'test' for other elements of the page, you will end up firing some extra click event(when you click on any other element of same class). So if you wanna prevent that, you should add listener to that particular element.
if you're adding an element of class test to an existing element of id testId, then use
$('#testId').on('click', '.test', function(this){
}
In the function where you dynamically add the new elements you have to assign an event handler for them.
Lets say you have a function something like this
function addNewLines(){
//add the new lines here
// you have to run this again
$$('.test').on('click', function () {
myApp.alert("Gotcha!");
});
}
Here is what I'm doing... I have a textbox that users type something in and click an add icon. This fires some jquery code that adds the item they typed into a span within a "content" div. The generated code has a delete icon that appears on hover and when clicked it should make the span disappear. This works if the code is on the page already (before document load) but if it's dynamically created, it breaks the delete on click functionality.
Here is a JSfiddle so you can see it in action: http://jsfiddle.net/WF32y/
What can I do to fix this? I essentially want to do what happens on here (stackoverflow.com) when you enter tags to a new question.
Use event delegation for dynamically added elements by changing this:
$('a.delete').on('click', function(e) {
Into this:
$(document).on('click', 'a.delete', function(e) {
Fiddle
.on() Direct and delegated events reference
Also, concerning performance, you can attach the handler to a closer ancestor of the dynamically added elements than the document (e.g. a static wrapper element).
You can easily do it with delegate. In your case:
$('#container').delegate('a.delete','click', function(e) {
e.preventDefault();
taskID = $(this).closest('.task')[0].id;
$(this).closest('.task').fadeTo(300, 0, function() {
$(this).animate({
width: 0
}, 200, function() {
$(this).remove();
});
});
});
And by the way FYI:
// jQuery version 1.4.3+
$('#container').delegate('a.delete'...
// jQuery 1.7+
$('#container').on('click', 'a.delete', function(e) {
it is faster and more propery way than:
$(document).on('a.delete'...
or:
$('body').delegate('a.delete'...
or:
$(document).delegate('a.delete'...
I need to bind to an event (say a click on an arbitrary <input>) inside an iframe that is created dynamically after the user performs a certain action. The code that appends the iframe AND the code inside the iframe is not mine and I cannot change it in any way (this is a CMS admin panel).
How can I listen to the events using jQuery 1.6 (again, this is not my choice, I'm stuck with it). I thought delegate() might be what I want:
$('body').delegate('iframe input', 'click', function(e) {
alert('bingo?');
});
But the above does not alert when an input is clicked. The below, however, works as expected:
$('body').delegate('input', 'click', function(e) {
alert('bingo?');
});
But this is outside the iframe.
The src of iframe points to the same domain, obviously.
Any help or just a prod in the right direction is greatly appreciated.
This 'iframe input' does not selects input elements inside the iframe.
You can bind the event like
$('body iframe').contents().find('input').bind('click',function(e) {
alert('bingo?');
});
I think You can also use something like
$('body iframe').contents().find('body').delegate('input','click',function(e) {
alert('bingo?');
});
To detect if the iframe has been fully loaded, use the method described in this answer
https://stackoverflow.com/a/5788723/344304
Add In the main/parent document:
function iframeLoaded() {
$('body iframe').contents().find('input').bind('click',function(e) {
alert('bingo?');
});
}
Add In the iframe document:
window.onload = function() {
parent.iframeLoaded();
}
Or use
$('body iframe').load(function(){
$('body iframe').contents().find('input').bind('click',function(e) {
alert('bingo?');
});
});
I have two divs, one that holds some stuff and the other with all possible stuff. Clicking on one of the divs will transfer items to the other div. The code I came up with is:
$("#holder > *").each(function() {
$(this).click(function(e) {
$(this).remove();
$("#bucket").append(this);
});
});
$("#bucket > *").each(function() {
$(this).click(function(e) {
$(this).remove();
$("#holder").append(this);
});
});
This one works perfectly, except that the event handlers need to be refreshed once I append or remove elements. What I mean is, if I first click on an element, it gets added to the other div, but if I click on this element again, nothing happens. I can do this manually but is there a better way to achieve this?
Try jquery live events .. the $.live(eventname, function) will bind to any current elements that match as well as elements added to the Dom in the future by javascript manipulation.
example:
$("#holder > *").live("click", function(e) {
$(this).remove();
$("#bucket").append(this);
});
$("#bucket > *").live("click", function(e) {
$(this).remove();
$("#holder").append(this);
});
Important:
Note that $.live has since been stripped from jQuery (1.9 onwards) and that you should instead use $.on.
I suggest that you refer to this answer for an updated example.
First, live is deprecated. Second, refreshing isn't what you want. You just need to attach the click handler to the right source, in this case: the document.
When you do
$(document).on('click', <id or class of element>, <function>);
the click handler is attached to the document. When the page is loaded, the click handler is attached to a specific instance of an element. When the page is reloaded, that specific instance is gone so the handler isn't going to register any clicks. But the page remains so attach the click handler to the document. Simple and easy.
Here you go, using the more intuitive delegate API:
var holder = $('#holder'),
bucket = $('#bucket');
holder.delegate('*', 'click', function(e) {
$(this).remove();
bucket.append(this);
});
bucket.delegate('*', 'click', function(e) {
$(this).remove();
holder.append(this);
});
EDIT: don't use live, it be deprecated!
Take advantage of the fact that events bubble. Using .on():
var = function( el1, el2 ) {
var things = $('#holder, #bucket');
things.each(function( index ) {
// for every click on or in this element
things.eq(index).on('click', '> *', function() {
// append will remove the element
// Number( !0 ) => 1, Number( !1 ) => 0
things.eq( Number(!index) ).append( this );
});
});
any click on any element (existing at the time of bind or not) will bubble up (assuming you haven't manually captured the event and stopped propagation). Thus, you can use that event delegation to bind only two events, one on each container. Every click that passed the selector test of the 2nd argument (in this case, > *, will remove that element and then append it to the alternate container as accesesed by things.eq( Number(!index) )
Have you looked at jQuery's live function?
The most Efficient way (dont load all event for all elements) it:
//NORMAL FUNCTION
function myfunction_click(){
//custom action
}
$('id_or_class_of_element').on('click', myfunction_click);
//LOAD OR REFRESH EVENT
$(document).on('click', 'id_or_class_of_element', myfunction_click);