I'm trying to take away the ability to submit a form when an ajax call is in process (it is a long query and I don't want it submitted again while it is being initially made.) However I seem to be attaching it incorrectly.
$(function(){
$("body").on("click", "#process", function(){
submit_form();
});
$("body").on("ajaxStart", "*", function(){
$("body").off("click", "#process", submit_form);
alert("test");
var div = $("<div>", {
id: "loading",
html: "Working"
}).prependTo("body");
});
$("body").on("ajaxStop", "*", function(){
alert("done");
$("#loading").remove();
});
});
I'm not seeing either the div being attached or the alerts being fired. I feel like there may be an issue with the * selector within my on() statements. I don't know though. I've tried to attach the ajaxStart with on so that $("#loading") which is dynamically added, can be removed.
I would do something more along the lines of setting a variable to allow/disallow the AJAX call:
var processing = false;
$('form').on('submit', function(e){
e.preventDefault();
if(processing === false){
processing = true;
// allow AJAX here
$.ajax({
url: 'sample.com/process',
type: 'POST',
complete: function(){
processing = false;
}
});
}
});
Related
I have a clickable <td> which does some action. However, strange things happen when I quickly make double click. Thus, I want to prevent it and make sure it is only single clickable event.
$.each(response, function(index) {
$('#myID').append('<tr><td onclick="select(this)" >'+ response[index] +'</td></tr>');
});
function select(element){
...
}
I tried to use jQuery's .one() function, but this code above is a product of another event. So, I cannot use $(document).ready(); here. In my knowledge I have to make it like onclick="select(this)"... And it works. But here I need to disable double clicking.
Any help?
So add a check that the Ajax request is active....
function select(element){
var elem = $(element);
if(elem.hasClass("active")) { // is ajax call active?
return false;
}
elem.addClass("active"); // set it that it is active
$.ajax({
url: "foo"
})
.done(function(){})
.always(function(){
elem.removeClass("active"); // call is done, so remove active state
})
}
You can simply disable button until ajax finishes its operation
function select(element){
$(element).prop('disabled', true);
$.ajax({
url'url',
success:function(response){
$(element).prop('disabled', false);
}
});
}
I have the following script I've written.
<script>
$(document).ready(function(){
$('a').data('loop',true);
$('body').on('click', 'a', function(event){
console.log($(this).data('loop'));
if ($(this).data('loop') == 'true') {
console.log('hit');
event.preventDefault();
caller = $(this);
$(this).data('loop',false);
var linkref = $(this).attr('href');
var linkpos = $(this).offset();
var screenwidth = $(window).width();
var json_data = JSON.stringify({linkref: linkref, linkpos: linkpos, screenwidth: screenwidth});
$.ajax({
url: "content/submitcontenthandler?handler=core/_dashboard&method=tracking_ping",
method: "POST",
data: "json=" + json_data,
complete: function (jqXHR, status) {
console.log(status);
console.log(caller);
$(caller).click();
}
});
} else {
console.log(event.isDefaultPrevented());
console.log('miss');
$(this).data('loop',true);
}
});
});
</script>
It works, sends me the details I want etc etc. BUT!!!
When I click a link, It fires off the details to me via Ajax, then it's meant to "click" the event again, which it does! but the event does not fire it's normal action. So When clicking a link to another page, I would go to that other page... that's not happening.
If I comment out the line event.preventDefault(); Then the event fires as I would expect...
So to me it looks like the event.preventDefault is executing even though it's not meant to be during the second call...
Sorry if this is a bit complicated to understand. I don't quite understand what's happening myself.
Is it possibly a bug, or is there something that I've done that has caused this?
I didn't think I could, but I have successfully made a jsfiddle for this.
https://jsfiddle.net/atg5m6ym/2001/
You can try this and not worry about the "loop" anymore:
$(document).ready(function () {
$('body').on('click', 'a', function (event) {
event.preventDefault();
var caller = $(this);
var linkref = $(this).attr('href');
var linkpos = $(this).offset();
var screenwidth = $(window).width();
var json_data = JSON.stringify({linkref: linkref, linkpos: linkpos, screenwidth: screenwidth});
$.ajax({
url: "content/submitcontenthandler?handler=core/_dashboard&method=tracking_ping",
method: "POST",
data: "json=" + json_data,
complete: function (jqXHR, status) {
console.log(status);
console.log(caller);
window.location.href = linkref; // Redirect happens here
}
});
});
});
UPDATE
There's a few issues to note here:
1) Some links don't require a redirect (as noted, bootstrap model links that control showing/hiding or within document anchors
To correct this it really depends on the case. Usually bootstrap adds specific classes or data attributes to the links so you can do something like.
$('body').on('click', 'a:not(list of things to exclude)'..
Personally I'd instead define the links I wanted to track as :
<a href=<link> data-tracked='true'...
<script>
$('body').on("click","a[data-tracked='true']"...
Or if you want to track most links with a few exceptions you can:
<a href=<link> data-tracked='false'...
<script>
$('body').on("click","a:not([data-tracked='false'])"...
Or more generally:
<script>
$('body').on("click","a", function () {
if ($(this).attr("data-tracked") == "false" || <you can check more things here>){
return true; //Click passes through
}
//Rest of the tracking code here
});
The following if statement will return true whenever the data-loop attribute exists against an element, regardless of it's value:
if ($(this).data('loop')) {
It needs to be changed to check for the value:
if ($(this).data('loop') == 'true') {
When you assign anything to be the value of an element attribute it becomes a string and, as such, requires a string comparison.
Event.preventDefault() is not being executed second time.
Link redirection happens when the method is completed.
So in your case redirection will happen when complete method of ajax call is completed.
lets say, we have event1 and event2 object in the code. event1 is the object in the ajax call method and event2 is the event object in recursive call (second call) method.
so when link is clicked second time , we still have complete method to be executed. as soon as it returns to the complete method of ajax call, it finds the event1 is having preventDefault property true and it does not redirect.
Try this ;)
$(document).ready(function(){
$('body').on('click', 'a', function(event){
event.preventDefault();
var caller = $(this);
var linkref = $(this).attr('href');
var linkpos = $(this).offset();
var screenwidth = $(window).width();
var json_data = JSON.stringify({
linkref: linkref,
linkpos: linkpos,
screenwidth: screenwidth
});
$.ajax({
url: "content/submitcontenthandler?handler=core/_dashboard&method=tracking_ping",
method: "POST",
/* To temprary block browser; */
async: false,
data: "json=" + json_data,
complete: function(jqXHR, status){
/* add class **ignore** to a element you don't want to redirect anywhere(tabs, modals, dropdowns, etc); */
if(!caller.hasClass('ignore')){
/* Redirect happens here */
window.location.href = linkref;
}
}
});
});
});
I have div element as
<div class="preview-image hide"><img src="{{STATIC_URL}}ui-anim_basic_16x16.gif"></div>
The hide class belongs to Twitter Bootstrap 2.3.2, the preview-image basically adds some styling to the element and used as handle for JavaScript.
I have jQuery code as below where
$loading.show() and $loading.hide() are not working.
The surprising this is when I run $preview.parent().find('.preview-image').show() from console, its working!!
(function($) {
$(document).ready(function() {
var SET_TIME = 6000;
$('[data-preview]').click(function() {
var $this = $(this);
var $preview = $('#' + $this.data('presponse'));
var $loading = $preview.parent().find('.preview-image');
$loading.show();
$.ajax({
});
$loading.hide();
});
});
})(window.jQuery);
Because $.ajax() is an asynchronous call, the $loading.hide() is being called (as it appears to the user) immediately after the $loading.show(). In order to circumvent this, you should make the $loading.hide() call after your AJAX call is complete. One way to do this is:
var $loading = $preview.parent().find('.preview-image');
$loading.show();
$.ajax({
}).always(function() {
$loading.hide();
});
Is the issue that it's hiding straight away? I think the hide needs to be within a success function of the AJAX call rather than being after it.
Eg.
$.ajax({
success: function() {
$loading.hide();
}
});
I have some jquery that looks like this,
$('.career_select .selectitems').click(function(){
var selectedCareer = $(this).attr('title');
$.ajax({
type: 'POST',
url: '/roadmap/step_two',
data: 'career_choice='+selectedCareer+"&ajax=true&submit_career=Next",
success: function(html){
$('.hfeed').append(html);
$('#grade_choice').SelectCustomizer();
}
});
});
My problem is that if the user keeps clicking then the .hfeed keeps getting data appended to it. How can I limit it so that it can only be clicked once?
Use the one function:
Attach a handler to an event for the elements. The handler is executed at most once per element
If you wanted the element to only be clicked once and then be re-enabled once the request finishes, you could:
A) Keep a state variable that updates if a request is currently in progress and exits at the top of the event if it is.
B) Use one, put your code inside a function, and rebind upon completion of request.
The second option would look like this:
function myClickEvent() {
var selectedCareer = $(this).attr('title');
var that = this;
$.ajax({
type: 'POST',
url: '/roadmap/step_two',
data: 'career_choice='+selectedCareer+"&ajax=true&submit_career=Next",
success: function(html){
$('.hfeed').append(html);
$('#grade_choice').SelectCustomizer();
},
complete: function() {
$(that).one('click', myClickEvent);
}
});
}
$('.career_select .selectitems').one('click', myClickEvent);
You can either use a global variable like
var added = false;
$('.career_select .selectitems').click(function(){
if(!added) {
// previous code here
added = true;
}
});
or use .one("click", function () { ... }) instead of the previous click function to execute the handler at most once per element. See http://api.jquery.com/one/ for more details.
$(document).ready(function() {
$(".delete_user_button").click(function(){
var username_to_delete = $(this).attr('rel');
$.ajax({
type:"POST",
url:"/delete/",
data:{'username_to_delete':username_to_delete},
beforeSend:function() {
$(this).val("Removing...");
},
success:function(html){
$("div.delete_div[rel=" + username_to_delete + "]").remove();
}
});
return false;
});
});
Why doesn't $(this).val() work?
I'm trying to change the text of the button when the user clicks remove.
In your event handler (beforeSend), this refers to the XMLHttpRequest object used for the ajax call, not your original this of the click event handler. You should "capture" it in a variable first:
$(document).ready(function() {
$(".delete_user_button").click(function(){
var element = $(this);
var username_to_delete = element.attr('rel');
$.ajax({
type:"POST",
url:"/delete/",
data:{'username_to_delete':username_to_delete},
beforeSend:function() {
element.val("Removing...");
},
success:function(html){
$("div.delete_div[rel=" + username_to_delete + "]").remove();
}
});
return false;
});
});
This mechanism is called "closures". For an interesting explanation of this, check this link:
http://www.bennadel.com/blog/1482-A-Graphical-Explanation-Of-Javascript-Closures-In-A-jQuery-Context.htm
Without more knowledge about the context or analysing the script itself: Keep in mind that, in certain environments, it might be possible that $ itself does not work and needs to be replaced with jQuery - I've seen this in Liferay.
I guess this is not your problem here, but it might come in handy for others looking for this problem from another context.