Disable button until function is done - javascript

I am trying to disable the button until the code is successfully executed. Unfortunately, the button is activated too early, the function is still running. How can I prevent this?
$("#myButton").click(function() {
$(this).prop("disabled", true)
doSomethingFunction()
$(this).prop("disabled", false)
});
Edit:
Thank you all for your help. I have adjusted my code. Can you do it this way or are there better ways?
class TestClass
{
static doSomethingFunction() {
return new Promise(function (resolve, reject) {
setTimeout(function () { console.log("function is done"); resolve(self); }, 5000);
})
}
}
$("#myButton").click(function() {
$(this).prop("disabled", true)
TestClass.doSomethingFunction().then(r => $(this).prop("disabled", false))
});
The second solution does not work for me, because "completely done" is output before "function is done"
class TestClass
{
static doSomethingFunction(callback) {
setTimeout(function () { console.log("function is done");}, 2000);
if(callback !== undefined){
callback();
}
}
}
$("#myButton").click(function() {
$(this).prop("disabled", true)
TestClass.doSomethingFunction(function(){
console.log("completely done")
});
});
What am I doing wrong?

Consider the following.
var myData;
function doSomethingFunction(callback){
$.get("someplace.php", function(data){
myData = data;
if(callback !== undefined){
callback();
}
});
}
$("#myButton").click(function() {
var $self = $(this);
$self.prop("disabled", true);
doSomethingFunction(function(){
console.log(myData);
$self.prop("disabled", false);
});
});
This allows you to pass in code to run once the function is complete. In this example, maybe it's getting data from the server. This may take almost no time, or maybe the report takes 1.2 seconds to generate. Either way it will not be run until the AJAX is successful.
Update
Here is an example, based on the following: How do I use jQuery promise/deffered in a custom function?
$(function() {
function doSomething() {
var deferred = new $.Deferred();
setTimeout(function() {
deferred.resolve(10);
}, 10 * 1000);
return deferred;
}
$("button").click(function() {
var $self = $(this);
console.log("Disabled");
$self.prop("disabled", true);
doSomething().then(function() {
$self.prop("disabled", false);
console.log("Enabled");
});
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button>Start</button>
This will run for 10 seconds and then enable the button. Applying it to your example.
class TestClass {
static doSomethingFunction() {
var deferred = new $.Deferred();
setTimeout(function() {
deferred.resolve(10);
}, 5 * 1000);
return deferred;
}
}
$("#myButton").click(function() {
var $self = $(this);
$self.prop("disabled", true);
TestClass.doSomethingFunction().then(r => $self.prop("disabled", false));
});

Related

how to judge imgs is all loaded

I have a project to know the imgs' height when the document is loading,but at first i got the height is zero So is there any tips to know whether the imgs is already loaded? I tried to use $.deferred inside jQuery; here is my code:
$(function() {
var imgdefereds = [];
$('img').each(function() {
var dfd = $.Deferred();
$(this).bind('load', function() {
dfd.resolve();
}).bind('error', function() {
//error callback
})
if (this.complete) {
setTimeout(function() {
dfd.resolve();
}, 1000);
}
imgdefereds.push(dfd.promise());
})
$.when.apply(null, imgdefereds).done(function() {
console.log('complete');
});
})
It didn't work. How can I fix it?
Try this:
$("img").one("load", function() {
// do stuff
}).each(function() {
if(this.complete) {
// do stuff
}
});

jquery when / then for recursive ajax calls

function getFriends(url) {
return FB.api(url, function(response) {
if (response && !response.error) {
if (response.paging && response.paging.next) {
$.each(response.data, function() {
friends.push(this);
});
return getFriends(response.paging.next);
} else {
console.error(friends);
}
} else {
console.error("facebook friends couldn't been retrieved ");
}
});
}
$.when(getFriends("/me/friends")).then(
function() {
console.log('getFriends finished');
});
i want to make sure that fb calls finished when the then() block executed but had no chance. is there a way to implement this ?
thanks
The Facebook JS SDK does not implement jQuery style promise objects / $.Deferreds but you can easily create an instance on your own like:
function getFriends(url) {
var dfd = $.Deferred();
FB.api(url, function(response) {
if (response && !response.error) {
if (response.paging && response.paging.next) {
$.each(response.data, function() {
friends.push(this);
});
return getFriends(response.paging.next);
} else {
console.log(friends);
}
dfd.resolve();
} else {
console.error("facebook friends couldn't been retrieved ");
dfd.reject();
}
});
return dfd;
}
getFriends("/me/friends").done(
function() {
console.log('getFriends finished');
}
);
Not really an answer, but a working example that demo's how to go about it:
Demo JSFiddle
function doStuff() {
var dfd = new jQuery.Deferred();
alert ("loaded");
setTimeout(function(){
dfd.resolve("response - success");
}, 5000);
return dfd.promise();
}
$.when(doStuff()).then(function(status) {
alert(status);
});

alert when value changed setinterval

When there is an update from getjson, the textbox text changed!
No allert is comminh up.. some one can help me with this allert??
The textbox:
<input id="your_textbox" />
setInterval(function () {
$.getJSOg('/api/my_apiurl', function (Payload) {
$(Payload).each(function (i, item) {
$("#your_textbox").val(item.CR_DateTime);
});
});
}, 3000);
and the script to allert "haai:
setInterval(function () {
jQuery('#your_textbox').on('input', function () {
alert('haai');
});
}, 3000);
Change to (not working):
setInterval(function () {
var check;
$(function(checkForMessages) {
$.getJSON('/api/myapiurl', function (data) {
if(data == 1) {
//There are new messages
clearInterval(check);
alert("You have mail!");
}
}
);
check = setInterval(checkForMessages, 3000);
});
}, 3000);
You keep adding an even to the textbox over and over and over again! That is really bad.
It should just be
jQuery('#your_textbox').on('input', function () {
alert('haai');
});
Now JavaScript does not trigger the event when you change the textbox with code, so you need to do the triggering.
var previousValue = $("#your_textbox").val(),
newValue = item.CR_DateTime;
if (previousValue !== newValue ) {
$("#your_textbox").val(newValue).trigger("input");
}

Detect Mousemovent inside of blur function Jquery

I am trying to create a neat way to stop an AJAX called based upon if the browser is in focus, and if the mouse moves.. So here's what I want it to do:
If the user goes to a different tab in their browser, minimized the window, or goes somewhere else other than the web app, I want it to kill the AJAX calls in 1 minute. If the user moves the mouse anywhere in the web app, it should consider the user "focused" on the app, and thus continue the ajax calls. I put a timeout called "st" in there to take care of the "timeout" portion, but adding in a mouse detector is a little more advanced. Here's what I have:
var window_focus = true;
$(document).ready(function () {
$('#alertbox').click(function () {
$('#alertbox').slideUp("slow");
});
// Check focal point
$(window).focus(function () {
if (window_focus) {
return
}
window_focus = true;
waitForMsg();
}).blur(function () {
if (!window_focus) {
return
}
console.log('Init Suspension...');
// Set Timeout
$(function () {
st = setTimeout(function () {
clearTimeout(setTimeoutConst);
window_focus = false;
document.title = 'Timed Out | WEBSITE';
console.log('Suspended');
}, 60000);
});
});
waitForMsg();
});
I was going to try adding in something like this:
$(function () {
$().mousemove(function () {
console.log('Reinitialize');
clearTimeout(st);
waitForMsg();
});
});
But it didn't work. Thanks for your help.
http://jsfiddle.net/popnoodles/5mqMm/
You probably want this using .one(). This will see the mouse move, run your procedure and not run it again, until the window is reloaded or it's on another page.
Putting it inside of blur means blurring sets it up again.
}).blur(function () {
$(document).one('mousemove', function(){
// i react ONCE to the mouse being moved
console.log('Reinitialize');
clearTimeout(st);
waitForMsg();
// focus the window again as desired
$(window).trigger('focus');
});
if (!window_focus) {
return
}
console.log('Init Suspension...');
// Set Timeout
$(function () {
st = setTimeout(function () {
clearTimeout(setTimeoutConst);
window_focus = false;
document.title = 'Timed Out | WEBSITE';
console.log('Suspended');
}, 60000);
});
});
Try this jsfiddle
var window_focus = true, lastMouseMoveTime;
$(document).ready(function () {
lastMouseMoveTime = new Date().getTime();
$('#alertbox').click(function () {
$('#alertbox').slideUp("slow");
});
// Check focal point
$(window).focus(function () {
if (window_focus) {
return
}
window_focus = true;
waitForMsg();
}).blur(function () {
if (!window_focus) {
return
}
window_focus = false;
console.log('Init Suspension...');
// Set Timeout
});
waitForMsg();
$(document).mousemove(function(){
lastMouseMoveTime = new Date().getTime();
if(!window_focus ){
waitForMsg(); // restarting ajax if it stopped because of mousemove.
}
});
});
in your ajax call method
if( !window_focus){
if( new Date().getTime() - lastMouseMoveTime > 60*1000 ){
return;
}
}

Order function in JS

I have the following code in main.js:
(function($) {
// Code goes here
$.fn.switcher=function(opts)
{
var defaults={
btn:'.info_btn', //Класс кнопки
block:'.details_info', //Класс блока, который нужно скрыть
hideifout:false, //Если true то скроект блок когда мышь его покент
classActive:'open' //Класс который ставится активной кнопке
//classNotActive:'close'
};
var options=$.extend(defaults, opts);
this.each(
function(){
var $this=$(this);
var btn=$this.find(options.btn);
var block=$this.find(options.block);
var plaing=false;
var click=function(e){
if (e.type=='mouseleave')
{
e.stopPropagation();
}
if (plaing) return;
plaing=true;
if (block.is(':visible'))
{
block.hide('blind',function(){
btn.removeClass(options.classActive);
btn.css('z-index',0);
plaing=false;
});
} else {
btn.addClass(options.classActive);
btn.css('z-index',2);
block.show('blind',function(){
plaing=false;
});
}
}
btn.click(click);
if (options.hideifout){
block.mouseleave(click);
}
}
);
}
})(jQuery);
And js code in my aspx file:
<script type="text/javascript">
$(document).ready(function () {
$('#listInfoBlock').load('/cinema/filmlist'); // load films by default
$(".title").click(function (e) {
e.preventDefault();
loadFilmList($(this));
});
$("#buttonFindFilmByName").click(function (e) {
e.preventDefault();
loadFilmList($(this));
});
// load films by criteria
function loadFilmList(id) {
$('#listInfoBlock').load('/cinema/filmlist?id=' + $(id).attr("id"));
$(".tabs").find("a").removeClass("active");
$(id).parent().addClass("active");
};
});
</script>
The function loadFilmList fills listInfoBlock.
The problem in that function in main.js executes first and there are no div called .details_info (it will be there when loadFilmList is executed)
How can I solve this problem?
Thanks.
SOLUTION:
I rewrite like that:
function loadFilmList(id) {
$('#listInfoBlock').load('/cinema/filmlist?id=' + $(id).attr("id"), function () {
$('.infoBlock').switcher();
$('div.widgets').switcher(
{
btn: '.expand',
block: '.voice_block',
hideifout: true
// classActive:'expand'
});
});
if (id !== undefined) {
$(".tabs").find("a").removeClass("active");
$(id).parent().addClass("active");
}
};
now it's work.
Thanks Nate.
The problem is that you're declaring $.fn.switcher but aren't ever calling it anywhere. I think you need to call it in two places, in a callback function on both of your .load() AJAX calls.
$('#listInfoBlock').load('/cinema/filmlist', function() { $.fn.switcher({ }); });
and
$('#listInfoBlock').load('/cinema/filmlist?id=' + $(id).attr("id"), function() { $.fn.switcher({ }); });

Categories