I have the following mouseover function:
$('.msg_id').live("mouseover", function() {
$(this).css('cursor', 'pointer');
tid = $(this).attr('id');
idx = $(this).attr('name');
resp="";
$.ajax({
async: false,
url: "log_msg.asp",
data: $("#msgForm").serialize() + "&aktion=popup&msg_id="+tid+"&msg_id"+idx,
success: function(data){
$("#"+tid).html(data);
}
});
//$.post("log_msg.asp", $("#msgForm").serialize() + "&aktion=popup&msg_id="+tid+"&msg_id"+idx,
//function(data) {
//}).success(function(){
//$("#"+tid).html(data);
//resp=data;
//$('#bub'+tid).css('display', 'block');
//popd.css('display', 'block');
//});
});
It puts some html code inside .msg_id ( $("#"+tid).html(data); ).
The function mouseover is called in a loop. The ajax request is sent all the time while mouseovering it, not only once.
How can I fix it?
I have also tried mouseenter, but it fires in a loop too.
You might want to use the mouseenter() event instead, as mouseover will fire upon every move inside the element.
$('.msg_id').live("mouseenter", function() {
//Do work here
});
or if live isn't required, simply:
$('.msg_id').mouseenter(function() {
//Do work here
});
MouseOver():
Will fire upon entering an element can fire inside of any child elements.
MouseEnter():
Will fire upon entering an element, and only that element.
You want to use mouseenter
Related
I'm trying to figure out how to change behaviour of a button using AJAX.
When the button is clicked, it means that user confirmed order recently created. AJAX calls /confirm-order/<id> and if the order has been confirmed, I want to change the button to redirect to /my-orders/ after next click on it. The problem is that it calls again the same JQuery function. I've tried already to remove class="confirm-button" attribute to avoid JQuery again but it does not work. What should I do?
It would be enough, if the button has been removed and replaced by text "Confirmed", but this.html() changes only inner html which is a text of the button.
$(document).ready(function () {
$(".confirm-button").click(function (b) {
b.preventDefault();
var $this = $(this);
var id = this.value;
var url = '/confirm-order/'+id;
$.ajax({
type: 'get',
url: url,
success: function (data) {
$this.empty();
$this.attr('href','/my-orders/');
$this.parent().attr("action", "/my-orders/");
$this.html('Confirmed');
}
})
});
});
The event handler will be still attached to the button, so this will run again:
b.preventDefault();
which will prevent the default, which is opening the href. You need to remove the event handler on success. You use the jQuery #off() method:
$(".confirm-button").off('click');
or more shortly:
$this.off('click');
You can add to your success function something like: $this.data('isConfirmed', true);
And then in your click handler start by checking for it. If it's true, redirect the user to the next page.
$(".confirm-button").click(function (b) {
b.preventDefault();
var $this = $(this);
if ($this.data('isConfirmed')) {
... redirect code ...
}
else {
... your regular code ...
}
}
You need to use .on() rather than .click() to catch events after the document is ready, because the "new" button appears later.
See http://api.jquery.com/on/
$(document).ready(function() {
$('.js-confirm').click(function(){
alert('Confirmed!');
$(this).off('click').removeClass('js-confirm').addClass('js-redirect').html('Redirect');
});
$(document).on('click', '.js-redirect', function(){
alert('Redirecting');
});
});
<button class="js-confirm">Confirm</button>
I have a link, myLink, that should insert AJAX-loaded content into a div (appendedContainer) of my HTML page. The problem is that the click event I have bound with jQuery is not being executed on the newly loaded content which is inserted into the appendedContainer. The click event is bound on DOM elements that are not loaded with my AJAX function.
What do I have to change, such that the event will be bound?
My HTML:
<a class="LoadFromAjax" href="someurl">Load Ajax</a>
<div class="appendedContainer"></div>
My JavaScript:
$(".LoadFromAjax").on("click", function(event) {
event.preventDefault();
var url = $(this).attr("href"),
appendedContainer = $(".appendedContainer");
$.ajax({
url: url,
type : 'get',
complete : function( qXHR, textStatus ) {
if (textStatus === 'success') {
var data = qXHR.responseText
appendedContainer.hide();
appendedContainer.append(data);
appendedContainer.fadeIn();
}
}
});
});
$(".mylink").on("click", function(event) { alert("new link clicked!");});
The content to be loaded:
<div>some content</div>
<a class="mylink" href="otherurl">Link</a>
Use event delegation for dynamically created elements:
$(document).on("click", '.mylink', function(event) {
alert("new link clicked!");
});
This does actually work, here's an example where I appended an anchor with the class .mylink instead of data - http://jsfiddle.net/EFjzG/
If the content is appended after .on() is called, you'll need to create a delegated event on a parent element of the loaded content. This is because event handlers are bound when .on() is called (i.e. usually on page load). If the element doesn't exist when .on() is called, the event will not be bound to it!
Because events propagate up through the DOM, we can solve this by creating a delegated event on a parent element (.parent-element in the example below) that we know exists when the page loads. Here's how:
$('.parent-element').on('click', '.mylink', function(){
alert ("new link clicked!");
})
Some more reading on the subject:
https://learn.jquery.com/events/event-delegation/
http://jqfundamentals.com/chapter/events
if your question is "how to bind events on ajax loaded content" you can do like this :
$("img.lazy").lazyload({
effect : "fadeIn",
event: "scrollstop",
skip_invisible : true
}).removeClass('lazy');
// lazy load to DOMNodeInserted event
$(document).bind('DOMNodeInserted', function(e) {
$("img.lazy").lazyload({
effect : "fadeIn",
event: "scrollstop",
skip_invisible : true
}).removeClass('lazy');
});
so you don't need to place your configuration to every you ajax code
As of jQuery 1.7, the .live() method is deprecated. Use .on() to attach event handlers.
Example -
$( document ).on( events, selector, data, handler );
For those who are still looking for a solution , the best way of doing it is to bind the event on the document itself and not to bind with the event "on ready"
For e.g :
$(function ajaxform_reload() {
$(document).on("submit", ".ajax_forms", function (e) {
e.preventDefault();
var url = $(this).attr('action');
$.ajax({
type: 'post',
url: url,
data: $(this).serialize(),
success: function (data) {
// DO WHAT YOU WANT WITH THE RESPONSE
}
});
});
});
If your ajax response are containing html form inputs for instance, than this would be great:
$(document).on("change", 'input[type=radio][name=fieldLoadedFromAjax]', function(event) {
if (this.value == 'Yes') {
// do something here
} else if (this.value == 'No') {
// do something else here.
} else {
console.log('The new input field from an ajax response has this value: '+ this.value);
}
});
use jQuery.live() instead . Documentation here
e.g
$("mylink").live("click", function(event) { alert("new link clicked!");});
For ASP.NET try this:
<script type="text/javascript">
Sys.Application.add_load(function() { ... });
</script>
This appears to work on page load and on update panel load
Please find the full discussion here.
Important step for Event binding on Ajax loading content...
01. First of all unbind or off the event on selector
$(".SELECTOR").off();
02. Add event listener on document level
$(document).on("EVENT", '.SELECTOR', function(event) {
console.log("Selector event occurred");
});
Here is my preferred method:
// bind button click to function after button is AJAX loaded
$('#my_button_id').bind('click', function() {
my_function(this);
});
function my_function () {
// do stuff here on click
}
I place this code right after the AJAX call is complete.
I would add one point that was NOT obvious to me as a JS newb - typically your events would be wired within document, e.g.:
$(function() {
$("#entcont_table tr td").click(function (event) {
var pk = $(this).closest("tr").children("td").first().text();
update_contracts_details(pk);
});
}
With event delegation however you'd want:
$(function() {
// other events
}
$("#entcont_table").on("click","tr td", function (event) {
var pk = $(this).closest("tr").children("td").first().text();
update_contracts_details(pk);
});
If your event delegation is done within the document ready, you'll an error of the like:
cant assign guid on th not an boject
What's the best way to prevent a double-click on a link with jQuery?
I have a link that triggers an ajax call and when that ajax call returns it shows a message.
The problem is if I double-click, or click it twice before the ajax call returns, I wind up with two messages on the page when I really want just one.
I need like a disabled attribute on a button. But that doesn't work on links.
$('a').on('click', function(e){
e.preventDefault();
//do ajax call
});
You can use data- attributes, something like this:
$('a').on('click', function () {
var $this = $(this);
var alreadyClicked = $this.data('clicked');
if (alreadyClicked) {
return false;
}
$this.data('clicked', true);
$.ajax({
//some options
success: function (data) { //or complete
//stuff
$this.data('clicked', false);
}
})
});
I came with next simple jquery plugin:
(function($) {
$.fn.oneclick = function() {
$(this).one('click', function() {
$(this).click(function() { return false; });
});
};
// auto discover one-click elements
$(function() { $('[data-oneclick]').oneclick(); });
}(jQuery || Zepto));
// Then apply to selected elements
$('a.oneclick').oneclick();
Or just add custom data atribute in html:
<a data-oneclick href="/">One click</a>
You need async:false
By default, all requests are sent asynchronously (i.e. this is set to true by default). If you need synchronous requests, set this option to false.
$.ajax({
async: false,
success: function (data) {
//your message here
}
})
you can use a dummy class for this.
$('a#anchorID').bind('click',function(){
if($(this).hasClass('alreadyClicked')){
return false;
}else{
$(this).addClass('alreadyClicked);
$/ajax({
success: function(){$('a#anchorID').removeClass('alreadyClicked');},
error: function(){$('a#anchorID').removeClass('alreadyClicked');}
});
}});
Check this example. You can disable the button via CSS attribute after the first click (and remove this attribute after an ajax request or with a setTimeout) or use the jQuery.one() function to remove the trigger after the first click (without disabling the button)
var normal_button = $('#normal'),
one_button = $('#one'),
disabled_button = $('#disabled'),
result = $('#result');
normal_button.on('click', function () {
result.removeClass('hide').append(normal_button.html()+'<br/>');
});
one_button.one('click', function () {
result.removeClass('hide').append(one_button.html()+'<br/>');
});
disabled_button.on('click', function () {
disabled_button.attr('disabled', true);
setTimeout(function () {
result.removeClass('hide').append(disabled_button.html()+'<br/>');
}, 2000);
});
Although there are some good solutions offered, the method I ended up using was to just use a <button class="link"> that I can set the disabled attribute on.
Sometimes simplest solution is best.
You can disable click event on that link second time by using Jquery
$(this).unbind('click');
See this jsfiddle for reference
Demo
You can disable your links (for instance, href="#" ), and use a click event instead, binded to the link using the jQuery one() function.
Bind all the links with class "button" and try this:
$("a.button").click(function() { $(this).attr("disabled", "disabled"); });
$(document).click(function(evt) {
if ($(evt.target).is("a[disabled]"))
return false;
});
I have a link, myLink, that should insert AJAX-loaded content into a div (appendedContainer) of my HTML page. The problem is that the click event I have bound with jQuery is not being executed on the newly loaded content which is inserted into the appendedContainer. The click event is bound on DOM elements that are not loaded with my AJAX function.
What do I have to change, such that the event will be bound?
My HTML:
<a class="LoadFromAjax" href="someurl">Load Ajax</a>
<div class="appendedContainer"></div>
My JavaScript:
$(".LoadFromAjax").on("click", function(event) {
event.preventDefault();
var url = $(this).attr("href"),
appendedContainer = $(".appendedContainer");
$.ajax({
url: url,
type : 'get',
complete : function( qXHR, textStatus ) {
if (textStatus === 'success') {
var data = qXHR.responseText
appendedContainer.hide();
appendedContainer.append(data);
appendedContainer.fadeIn();
}
}
});
});
$(".mylink").on("click", function(event) { alert("new link clicked!");});
The content to be loaded:
<div>some content</div>
<a class="mylink" href="otherurl">Link</a>
Use event delegation for dynamically created elements:
$(document).on("click", '.mylink', function(event) {
alert("new link clicked!");
});
This does actually work, here's an example where I appended an anchor with the class .mylink instead of data - http://jsfiddle.net/EFjzG/
If the content is appended after .on() is called, you'll need to create a delegated event on a parent element of the loaded content. This is because event handlers are bound when .on() is called (i.e. usually on page load). If the element doesn't exist when .on() is called, the event will not be bound to it!
Because events propagate up through the DOM, we can solve this by creating a delegated event on a parent element (.parent-element in the example below) that we know exists when the page loads. Here's how:
$('.parent-element').on('click', '.mylink', function(){
alert ("new link clicked!");
})
Some more reading on the subject:
https://learn.jquery.com/events/event-delegation/
http://jqfundamentals.com/chapter/events
if your question is "how to bind events on ajax loaded content" you can do like this :
$("img.lazy").lazyload({
effect : "fadeIn",
event: "scrollstop",
skip_invisible : true
}).removeClass('lazy');
// lazy load to DOMNodeInserted event
$(document).bind('DOMNodeInserted', function(e) {
$("img.lazy").lazyload({
effect : "fadeIn",
event: "scrollstop",
skip_invisible : true
}).removeClass('lazy');
});
so you don't need to place your configuration to every you ajax code
As of jQuery 1.7, the .live() method is deprecated. Use .on() to attach event handlers.
Example -
$( document ).on( events, selector, data, handler );
For those who are still looking for a solution , the best way of doing it is to bind the event on the document itself and not to bind with the event "on ready"
For e.g :
$(function ajaxform_reload() {
$(document).on("submit", ".ajax_forms", function (e) {
e.preventDefault();
var url = $(this).attr('action');
$.ajax({
type: 'post',
url: url,
data: $(this).serialize(),
success: function (data) {
// DO WHAT YOU WANT WITH THE RESPONSE
}
});
});
});
If your ajax response are containing html form inputs for instance, than this would be great:
$(document).on("change", 'input[type=radio][name=fieldLoadedFromAjax]', function(event) {
if (this.value == 'Yes') {
// do something here
} else if (this.value == 'No') {
// do something else here.
} else {
console.log('The new input field from an ajax response has this value: '+ this.value);
}
});
use jQuery.live() instead . Documentation here
e.g
$("mylink").live("click", function(event) { alert("new link clicked!");});
For ASP.NET try this:
<script type="text/javascript">
Sys.Application.add_load(function() { ... });
</script>
This appears to work on page load and on update panel load
Please find the full discussion here.
Important step for Event binding on Ajax loading content...
01. First of all unbind or off the event on selector
$(".SELECTOR").off();
02. Add event listener on document level
$(document).on("EVENT", '.SELECTOR', function(event) {
console.log("Selector event occurred");
});
Here is my preferred method:
// bind button click to function after button is AJAX loaded
$('#my_button_id').bind('click', function() {
my_function(this);
});
function my_function () {
// do stuff here on click
}
I place this code right after the AJAX call is complete.
I would add one point that was NOT obvious to me as a JS newb - typically your events would be wired within document, e.g.:
$(function() {
$("#entcont_table tr td").click(function (event) {
var pk = $(this).closest("tr").children("td").first().text();
update_contracts_details(pk);
});
}
With event delegation however you'd want:
$(function() {
// other events
}
$("#entcont_table").on("click","tr td", function (event) {
var pk = $(this).closest("tr").children("td").first().text();
update_contracts_details(pk);
});
If your event delegation is done within the document ready, you'll an error of the like:
cant assign guid on th not an boject
$('.add_instruction_btn').click(function(e){
e.preventDefault();
var ins_content=$('#add_instructions').val();
var id=$('.useri').val();
if(ins_content!="")
{
//write new instructions to database
var id=$('.useri').val();
var data="job_id="+job_idx+"&ins="+ins_content+"&client_id="+id+"&key=2";
$.ajax({
type:"POST",
url:"admin_includes/get_instructions.php",
data:data,
success:function(html2){
alert(html2);
}
});//end ajax
}
return false;
});
I seem to have tried evrything to stop the event from doubling each time the button is clicked. The code was originally inside another function which opened up a 'pop-up' style box but even when I move it outside the function it still seems to bubble.
As requested:-
$(document).on('click', '.bottom_links .lister a', function(e){
//e.preventDefault();
//e.stopPropagation();
$('.ind_ins').text("");
var ident=$(this).data('ref1');
if(ident==1){
var job_idx=$(this).data('job_id');
var cl_name=$(this).data('cl_name');
var icon_stat=$(this).data('img_id');
var id=$('.useri').val();
if(icon_stat=="1")
{
$('.opaque_scr,.instruction_popup').css('visibility', 'visible');
$('.instruction_popup h2').html("Add Instructions for Appointment ID: "+job_idx);
$('.client_name').html("<strong>Client Name: </strong>"+cl_name);
//get original instructions
var get_job="job_id="+job_idx+"&key=1";
$.ajax({
type:"POST",
url:"admin_includes/get_instructions.php",
data:get_job,
success:function(html){
var split_data=html.split("^");
var split_data_count=split_data.length-1;
var ins_tb="<table width='100%'>"
for(var xs=0;xs<split_data_count;xs++)
{
var ind=split_data[xs].split("|");
var ind_count=ind.length-1;
for(var xx=0;xx<ind_count;xx++)
{
ins_tb+="<tr><td width='75%'>"+ind[0]+"</td><td>"+ind[1]+"</td></tr>";
}
}
ins_tb+="</table>";
$(ins_tb).appendTo('.ind_ins');
}
})//end ajax
$('.add_instruction_btn').click(function(e){
e.preventDefault();
e.stopPropagation();
var ins_content=$('#add_instructions').val();
var id=$('.useri').val();
if(ins_content!="")
{
//write new instructions to database
var id=$('.useri').val();
var data="job_id="+job_idx+"&ins="+ins_content+"&client_id="+id+"&key=2";
$.ajax({
type:"POST",
url:"admin_includes/get_instructions.php",
data:data,
success:function(html2){
alert(html2);
}
});//end ajax
}
return false;
});
}
}
The problem is that you're hooking up the event handler more than once. Each time an element matching '.bottom_links .lister a' is clicked, provided various conditions are right, you re-run this code:
$('.add_instruction_btn').click(function(e){
// ....
});
Each time you run that code, you hook up a new copy of the handler.
If the set of elements matching '.add_instruction_btn' is fixed, just move that code out of the click handler for '.bottom_links .lister a' elements.
If the set of elements matching '.add_instruction_btn' varies, you still want to move the code outside the click handler for '.bottom_links .lister a' elements, but you probably want to make it use event delegation, too, as you do with the '.bottom_links .lister a' one.
A note about event delegation: You're "rooting" your event delegation on document, which is really, really high up. It's best to root delegation in the nearest container you can to the elements you're watching for. Obviously, if document is the nearest container, well, there you are, but there's usually something a bit further down you can use instead, while still getting the benefits of delegation.
Try e.stopPropagation:
$('.add_instruction_btn').click(function(e){
e.preventDefault();
e.stopPropagation();
....