When I replaceWith an element to bring one out of the DOM, then replaceWith it back in, events registered to it do not fire. I need to events to remain intact.
Here's my Javascript:
var replacement = $(document.createElement('span'));
var original = $(this).replaceWith(replacement);
replacement
.css('background-color', 'green')
.text('replacement for ' + $(this).text())
.click(function() {
replacement.replaceWith(original);
});
Live demo
In the demo, when you click an element, it is replaced with another element using replaceWith. When you click the new element, that is replaced with the original element using replaceWith. However, the click handler does not work any more (where I would think it should).
Because when you replace the original element, events bound to it are removed. You'll need to re-attach the click event handler on original after the call to replacement.replaceWith(original):
$(function()
{
function replace()
{
var replacement = $(document.createElement('span'));
var original = $(this).replaceWith(replacement);
replacement
.css('background-color', 'green')
.text('replacement for ' + $(this).text())
.click(function()
{
replacement.replaceWith(original);
original.click(replace);
});
}
$('.x').click(replace);
});
UPDATE: live() and bind() have been deprecated, in favour of on().
You can use live() and bind() events, this is your new code:
$(function() {
$('.x').live('click', function() {
var replacement = $(document.createElement('span'));
var original = $(this).replaceWith(replacement);
replacement
.css('background-color', 'green')
.text('replacement for ' + $(this).text())
.bind('click', function() {
replacement.replaceWith(original);
});
});
});
-Live event works with jQuery 1.3 and upper.
-if you want to stop the live propagation use die() function.
live events are what you are looking for
Related
I am trying to load content from a hidden div container into an active container. This should be so simple. The code I have works fine with old jQuery, but is broken with the latest version. What am I missing here?
Here is my code in JSFiddle
http://jsfiddle.net/poaw07w4/
$('.campuslink').live('click', function () {
var id = $(this).attr("id").replace(/^.(\s+)?/, "");
var contentTobeLoaded = $("#faq_" + id).html();
$('#campusfaq').fadeOut(600,function(){
$('#campusfaq').html(contentTobeLoaded).fadeIn(500, function () {
});
});
e.preventDefault();
The live method was deprecated in version 1.7 and removed in version 1.9. You can use the on method to create a delegated event. (Don't forget the e parameter):
$(document).on('click', '.campuslink', function (e) {
Demo: http://jsfiddle.net/poaw07w4/3/
Note: Binding the event on the document element corresponds to how live worked. If possible you should use an element closer to the element where the event occurs, to reduce the overhead.
Try using .on('click') instead of .live('click')
https://jsfiddle.net/dotnetmensch/poaw07w4/1/
$('.campuslink').on('click', function () {
var id = $(this).attr("id").replace(/^.(\s+)?/, "");
var contentTobeLoaded = $("#faq_" + id).html();
$('#campusfaq').fadeOut(600, function () {
$('#campusfaq').html(contentTobeLoaded).fadeIn(500, function () {});
});
e.preventDefault();
});
The live() method has been deprecated since JQuery 1.7 (more here). If you replace it with the on() method, it should work fine (note also that preventDefault() is moved):
$('.campuslink').on('click', function (e) {
e.preventDefault();
var id = $(this).attr("id").replace(/^.(\s+)?/, "");
var contentTobeLoaded = $("#faq_" + id).html();
$('#campusfaq').fadeOut(600,function(){
$('#campusfaq').html(contentTobeLoaded).fadeIn(500, function () {
});
});
I'll try to explain my problem:
I have a website where the user dynamically adds elements. They all belong to the "toBuy" class. Whenever a new element is added to this class I need to attach a click-handler to only this element but not to all others. To keep my code clean I want to have a function that does this work. Here is what i've tried:
this is how the stuff is added:
$("#addItemButton").click(function(){
var item= $('#item').val();
$('#item').val("");
var quantity= $('#quantity').val();
$('#quantity').val("");
var comment=$('#addComment').val();
$('#addComment').val("");
//construct new html
var newitem="<div class='toBuyItem'><div class='item'>";
newitem+=item;
newitem+="</div><div class='quantity'>";
newitem+=quantity;
newitem+="</div><div class='comment'><img src='img/comment";
if(comment==""){
newitem+="_none"
}
newitem+=".png' alt='Comment'></div><div class='itemComment'>"
newitem+=comment;
newitem+="</div></div>";
$("#toBuyItems" ).prepend( newitem );
toggle("#addItemClicked");
initializeEventListeners();
});
then this is the initializeEventListeners function (which I also run when the page loads so that the existing elements have the event handlers already:
function initializeEventListeners(){
$(".toBuyItem").click(function(){
console.log($(this).html());
console.log($(this).has('.itemComment').length);
if($(this).has('.itemComment').length != 0){
console.log("toggling");
$(this).addClass("toggling");
toggle(".toggling .itemComment");
$(this).removeClass("toggling");
}
});
}
function toggle(item){
$( item ).slideToggle(500);
}
now apparently what happens is that when a new element is added the existing elements get a new event handler for clicking (so they have it twice). Meaning that they toggle on and off with just one click. Probably it's damn simple but I cannot wrap my head around it....
EDIT:
so this works:
$(document).on('click', '.toBuyItem', function(){
if($(this).has('.itemComment').length != 0){
console.log("toggling");
$(this).addClass("toggling");
toggle(".toggling .itemComment");
$(this).removeClass("toggling");
}
});
Use jquery's on method. This way you have to add event only once. This will be added automatically to dynamically added elements.
$(document/parentSelector).on('click', '.toBuyItem', function() {
// Event handler code here
});
If you are using parentSelector in the above syntax, it has to be present at the time of adding event.
Docs: https://api.jquery.com/on
You can use jQuery.on method. It can attach handlers to all existing in the DOM and created in future tags of the selector. Syntax is as follows:
$(document).on('click', '.toBuyItem', function(){
//do onClick stuff
})
As others have suggested, you can delegate click handling to document or some suitable container element, and that's probably what I would do.
But you could alternatively define a named click handler, which would be available to be attached to elements already present on page load, and (scope permitting) to elements added later.
You might choose to write ...
function buy() {
if($(this).has('.itemComment').length != 0) {
$(this).addClass("toggling");
toggle(".toggling .itemComment");
$(this).removeClass("toggling");
}
}
function initializeEventListeners() {
$(".toBuyItem").on('click', buy);
}
$("#addItemButton").on('click', function() {
var item = $('#item').val(),
quantity = $('#quantity').val(),
comment = $('#addComment').val();
$('#item', '#quantity', '#addComment').val("");
//construct and append a new item
var $newitem = $('<div class="toBuyItem"><div class="item">' + item + '</div><div class="quantity">' + quantity + '</div><div class="comment"><img alt="Comment"></div><div class="itemComment">' + comment + '</div></div>').prependTo("#toBuyItems").on('click', buy);// <<<<< here, you benefit from having named the click handler
$newitem.find(".comment img").attr('src', comment ? 'img/comment.png' : 'img/comment_none.png');
toggle("#addItemClicked");
});
$(function() {
$.getJSON("companies.json", function(response) {
var html = '<table id="tbl">';
response.businesses.forEach(function(row) {
html += '<tr><td>' + row.id + '</td><td>' + row.name;
});
html += '</table>';
$("#tabledata").html(html);
});
$(".move").click(function() {
var $id = $(this).attr("idname");
$.getJSON("companies.json", function(response) {
$.map(response.businesses, function(obj) {
if (obj.id == $id)
console.log(obj);
return obj; // or return obj.name, whatever.
});
});
});
});
HTML:
<div id="tabledata" class='left'></div>
<div class="right"></div>
Please help?
As your .move element is added to your page dynamically, you have to make use of jQuery's on() method to delegate the event to an ancestor of the .move element which does exist when your JavaScript first loads.
$(document).on('click', '.move', function() { ... });
Event delegation allows us to attach a single event listener, to a parent element, that will fire for all descendants matching a selector, whether those descendants exist now or are added in the future.
You can read more about jQuery's event delegation here.
If you use event delegation, your problem goes away (and your app becomes more performant and less prone to memory leaks).
// Only do this once, when your page loads...
$(document.body).on('click', '.move', function (ev) {
// This is the link that was clicked.
var $targ = $(ev.target);
});
Try This
$('#tabledata').on('click', '.move', function(e) { ... });
The reason the event isn't being triggered is because the event is only added to elements that exist on the page when you call the .click() method.
Instead, you can use event delegation:
$(document.body).on('click', '.move', function (ev) {
var $targ = $(ev.target);
});
which really says: call the function when any element that matches .move that's inside document.body is clicked.
I know others have said this already but I wanted to make event delegation clearer.
I have function to detect idle state of user. I want to update database if any of the event occurs.Now i have script like this
$("body").mousemove(function(event) {
myfuction();
});
I want to convert above script like this
$("body").anyOfTheEvent(function(event) {
myfuction();
});
How can i do this?
You can find the event name using the e.type property. Try looking this example
$('#element').bind('click dblclick mousedown mouseenter mouseleave',
function(e){
alert("EventName:"+e.type);
});
The jsfiddle for this is here http://jsfiddle.net/qp2PP/
You could have an array of the events you're interested in and subscribe to all of them
var events = ['click','mousemove','keydown'] // etc
$.each(events,function(i,e){
$('body')[e](myfuction);
});
Get a list of events here: http://api.jquery.com/category/events/
You can bind more than one event with bind()
$('#foo').bind('click mousemove', function(evt) {
console.log(evt.type);
});
just use on(), with a space-delimited list of events:
$('body').on('mousedown click', function(e) {
var eventType = e.type;
// do stuff
});
References:
on().
Instead of bind to specific element, you can bind directly to document.
$(document).bind('click mousemove', function(evt) {
document.getElementById("demo").innerHTML = Math.random();
});
Example in CODEPEN
I have a piece of JQuery that creates a row in a table and in one of the cells there is an X that is surrounded by a class. When it is dynamically created and then clicked on the click listener does not fire.
Here is the code.
$('#add').click(function() {
$( '#table' ).append('<td class="x">X</td></tr>');
});
$('.x').click(function() {
alert('Fired');
});
Since the <td> element does not yet exist when you register your event handler, you have to use live() or delegate() for the handler to be triggered later:
$(".x").live("click", function() {
alert("Fired");
});
$(".x").live("click", function()
{
alert("Fired");
});
Live adds events to anything added later in the DOM as well as what's currently there.
Instead of
$('.x').click(function() {
alert('Fired');
});
Change to this
$('.x').live('click', function() {
alert('Fired');
});
It binds the click function to any created element with class x
You need to use the .live function for content that's dynamically generated.
so replace
$('.x').click(function() {
with
$('.x').live('click',function() {
You are first creating the listener to all .x elements (of which there are presumably zero), then later adding new .x elements.
There are two solutions: one is to use jQuery live, the other is to rewrite your code:
var xClickHandler = function() {
alert('Fired');
};
$('#add').click(function() {
$('#table').append(
$('<td class="x">X</td></tr>').click(xClickHandler);
);
});
Use live instead of click:
$('.x').live("click", function() {
alert('Fired');
});
The html you are appending to the table has a typo, you have missed out the beggining tr tag:
$('#add').click(function() {
$( '#table' ).append('<tr><td class="x">X</td></tr>');
});
$('.x').click(function() {
alert('Fired');
});
I think you need to use the live method. http://api.jquery.com/live/
$('.x').live('click', function() {
// Live handler called.
});