Using setInterval, But want to disable it when user input detected - javascript

I am calling a function with setInterval that is loading my page through an ajax get request and is outputting the response to the page sort of like a "live updates" page, I have comments being pulled and input boxes for comment submission but the problem is that when the user is inputting data into the form it's resetting meanwhile because the page is refreshing in the background with the ajax call.
My question is: How can I make it so that if there is any user input on the form (by form id maybe) to then disabled the timer, until they have left focus of the form element?
I hope this makes sense,

I think you need to use focus and blur functions of jquery
var my_interval;
function start_interval(){
my_interval = setInterval(function(){
my_ajax_function()}, 2000);
}
$('input').focus( function() {
clearInterval(my_interval);
});
$('input').blur( function() {
start_interval();
});

You just need to use clearInterval
$(function() {
var AtlassTimer,
i = 0;
function oncommententer()
{
console.log('Clear');
clearInterval(AtlassTimer);
}
function oncommentleave()
{
console.log('Start');
AtlassTimer = setInterval(loadactiveusers, 1000);
}
function loadactiveusers() {
$('#result').html(i++);
}
$('#formId input').on({
'keypress change': oncommententer,
blur: oncommentleave
});
//Init
oncommentleave();
});

Simply use the clearInterval method as well.
//start the routine
var myRoutine = setInterval(blah);
//stop the routine
clearInterval(myRoutine);
You'll probably need to attach event listeners to your form <input> elements using your favorite web framework, and in those event listeners, call clearInterval.

Please use setTimeout instead, you can
var t;
t = setTimeout(function(){
//whatever you like
}, 1000);
$('input').one('click', function(){
clearTimeout(t);
});
Reading - http://www.w3schools.com/jsref/met_win_cleartimeout.asp

Related

Universal code that disables buttons onclick

I have a next issue:
My application contains many buttons that make async requests to the server, currently if user is fast enough to click button more than one time - same request gets executed twice or more and data on the server gets duplicated.
Is there a way to disable clicked button, until the request is executed?
Someone suggested this solution:
$("input[type='button']")
.each(function () {
var el = $(this);
var onclickFunction = el.attr('onclick'), alreadyChecked = el.attr('clickHandler');
if (typeof onclickFunction != 'undefined' && typeof alreadyChecked == 'undefined')
{
el.removeAttr("onclick");
el.removeAttr("onclickFunction", onclickFunction);
el.attr('clickHandler', 'true');
el.on('click', function()
{
el.attr("disabled", "disabled");
$.when(eval(onclickFunction)).then(function () { el.removeAttr('disabled'); })
})
}
});
But if i understood correctly, this code runs only once. So if my application contains many views, this code should be executed on each view load.
Is there any more apropriate solution?
Two ways.
1) Use a flag(let's call it requestInProgress) in the page scope that is turned on once the request is made. Once the request is completed, turn off the flag.
2) Disable the button once the button is request is getting processing so as to prevent user from hitting it a second time. Enable the button once the request processing is complete.
Try using .one()
function handleClick(e) {
// not necessary, though notifies user button is disabled
$(this).attr("disabled", true);
// do ajax stuff
$.ajax().then(function() {
$(e.target).removeAttr("disabled")
// reattach `click` when ajax completes
.one("click", handleClick)
})
}
$("input[type='button']").one("click", handleClick)
What I would recommend is using a CSS class to prevent the user from multiple submissions. This also provides you the flexibility of easily styling the appearance for disabled buttons as well, say for their color or opacity in your stylesheet.
Something like this:
function onClickHandler() {
var myButton = $(this);
// check to see if it's already disabled
if (myButton.hasClass('disabled')) {
// if so, just exit out
return;
}
// add the disabled class
myButton.addClass('disabled');
// continue with your processing...
}
If browser compatibility is not an issue, you could also check out the disabled attribute, but I'm personally a bigger fan of using a class.

:visible doesn't work after submit event

Code http://jsfiddle.net/Z9qP5/1/
I want to fadeOut my form after the user submitted their email. There is the next problem. I just can't catch the submit event, so what I want, if the success message appears, then the form should be hidden. I use :visible like this:
$('#mc-embedded-subscribe-form').submit(function (e) {
if($('#mce-success-response').is(':visible')){
$("#mc_embed_signup").hide();
}
});
#mce-success-response is the success dialog.
I also tried:
if( $("#mce-success-response").css('display') == 'block') {
}
but it doesn't work. What's wrong?
yes, I think the submit event is just a one way, you just submit, and you don't want to get response when you do like that way. maybe you can use ajax that can handle the result. actually, you just submit your form, then fade out your form I think.
This is more of a workaround, and not an effective solution.
But it works!
function checkSuccess() {
if ($('#mce-success-response').is(':visible')) {
$("#mc_embed_signup").hide();
}
}
window.setInterval(checkSuccess, 100);
You could also use the code below to add a delay to the hideing:
function checkSuccess() {
function successAction(){
$("#mc_embed_signup").hide();
}
if ($('#mce-success-response').is(':visible')) {
setTimeout(successAction, 2500);
}
}
window.setInterval(checkSuccess, 100);
One possible solution is to use a custom event in this case(because as I explained in the comment the success-respone element is displayed in an ajax success handler).
So in your mce_success_cb method
if (resp.result == "success") {
$('#mce-' + resp.result + '-response').show();
$('#mce-' + resp.result + '-response').html(resp.msg);
$('#mc-embedded-subscribe-form').each(function () {
this.reset();
});
$("#mc-embedded-subscribe-form").trigger('submitsuccess');
// If the form has errors, display them, inline if possible, or appended to #mce-error-response
} else {
//rest of your code
}
then
$(document).ready(function () {
$('#mc-embedded-subscribe-form').on('submitsuccess', function (e) {
$("#mc_embed_signup").hide();
});
});
Are you getting the success response from AJAX after the submit? As per your code snippet, I am assuming that to be the case and that the success boz appears once your Ajax request is completed. Since its going to be for a short while, you can try the following piece of code.
function waitForIt(){
if(!$('#mce-success-response').is(':visible')){
setTimeout(waitForIt(),500);
} else{
$("#mc_embed_signup").hide();
}
$('#mc-embedded-subscribe-form').submit(function (e) {
setTimeout(waitForIt(),500);
}
});
Alternatively, if its not the AJAX response that pops up the success message, you can try putting an interface between your form submit and the user action. Change your input type from submit to button or use a plain image as a button, i.e <img>. Use a click() instead of submit(), check if the container is visible, if yes, then hide the required container and trigger submit.
Hope it helps!

JQuery "undo" an action by calling another function when back clicked

Is there a way to "undo" a function executed by jQuery when the back button is clicked? For example, my function that I want to execute is named doSomething:
function doSomething(button) {
...clicking the button does something...
}
And I have an undo function that undoes the above function, undoDoSomething:
function undoDoSomething(button) {
....undoes the doSomething function...
}
How do I call the function for the button and then if the back button is clicked right after I execute the function, I can call the undoDoSomething function to undo that function?
I know jQuery History goes back to a previous page saved in history but how do I use that to call a function?
the history api makes this easy: http://jsfiddle.net/Z9dRY/
html:
<button>Increase</button>click back button to decrease
<span id="counter">0</span>
js:
$("button").click(function(){
var count = +$("#counter").text() + 1;
history.pushState({count:count});
$(counter).text(count);
})
$(window).on("popstate",function(e){
if (e.originalEvent.state)
$(counter).text(e.originalEvent.state.count);
})
On each action, add to the history, and then each back button click will undo each change (of course, you have to develop the undo part. In this case, i just stored what the count should be changed to at that point and changed it.)
https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Manipulating_the_browser_history
Take note of the browser support, this code will work in all modern browsers and IE10+. oldIE will need a workaround either using an iframe or a hash in the url.
Here's the same example with an added decrease button to show that it doesn't really change anything: http://jsfiddle.net/Z9dRY/1/ it even inherantly supports the forward button(redo).
Update: fixed losing initial state: http://jsfiddle.net/Z9dRY/2/
You could call your undo function on the window.unload event
window.onbeforeunload = function(e) {
undoDoSomething();
};
You can usue beforeunload that is executed when leaving the page
var called = false;
function doSomething(button) {
called = true;
}
$(window).on('beforeunload',function(e){
if(called){
//call your function here
undoDoSomething()
}
});

AJAX/JS: Echoing value of a div without page refresh or button click

I am currently working with an wmd editor that i will later implement to my website. I have been able to get the value of the #wmd-preview div by changing the settings to markdown and adding a hidden input field. The issue is with the JS/AJAX function. When I type something in the text area I get the result echoed but when i go back and apply bold to the word it doesnt echo the change until i actually type something again.
How can i get the div value echoed when a font style change has been applied to a word without having to type again? Here is my EXAMPLE
<script>
$(document).ready(function() {
var timer = null;
var dataString;
function submitForm(){
$.ajax({ type: "POST",
url: "test1.php",
data: dataString,
success: function(result){
$('#wmd_result').html( $('#resultval', result).html());
}
});
return false;
}
$('#wmd-input').on('keyup click', function() {
clearTimeout(timer);
timer = setTimeout(submitForm, 1000);
var wmdVal = $("#wmd-preview").html();
dataString = 'wmdVal='+ wmdVal;
});
});
</script>
You could try
$('#wmd-button-bar').click(function() {
clearTimeout(timer);
timer = setTimeout(submitForm, 1000);
var wmdVal = $("#wmd-preview").html();
dataString = 'wmdVal='+ wmdVal;
});
It does work if you e.g. click on the word, it just that you only have keyup and click as event handlers. Try adding change as well and see if that works.
Maybe try using the change event instead?
$('#wmd-input').change(function() {
clearTimeout(timer);
timer = setTimeout(submitForm, 1000);
var wmdVal = $("#wmd-preview").html();
dataString = 'wmdVal='+ wmdVal;
});
You're only listening for events on the #wmd-input textarea. Clicking the bold button might change the contents of that text area, but it's not an editing event and no events are triggered in the browser. You aren't changing the text area, some function tied to the button you pressed is changing it.
Add a click listener to .wmd-button and you'll be able to capture that event.
Here's a jsfiddle demonstrating how it might work.
Edit: Added code example.
All you need to do is add the .wmd-button class to your jQuery listener, like this:
$('#wmd-input, .wmd-button').on('keyup click', function() {...
You would usually want to pay attention to listener order to make sure your code is executed after the wmd styling code, but because you've got a timeout in your function it likely won't matter.
I would like to suggest another way you might want to consider.
Handling events can turn to a monster. for example - someone offered the following code line
$('#wmd-input, .wmd-button').on('keyup click', function() {...
This will cause an event every time you click on the input field!! ( you click on input field every time you want to focus it for editing ).
Don't forget that there can be many events every second - which might get the server exploded with requests.
A better way might be to set an interval function, this method will read the value from the input field and compare it to last value it has.
If something changes - go ahead and make an Ajax request, otherwise, do nothing.
This way you control the rate in which the Ajax request is made, and you don't have to worry about any event ever! If suddenly you have a new set of buttons, or input fields, or popus to insert images or whatever... life is simply easier this way.
On the down side - as the interval is bigger - you get a delay between typing and previewing.
pseudo-code for this interval method looks like this
$(function(){
var lastValue = null;
setInterval( function(){
var newValue = $("#wmd-preview").html();
if ( lastValue == null || newValue.localeCompare( lastValue ) == 0 ){
lastValue = newValue;
// preview code here
}
// else do nothing
}, 1000 );
});

Call a function after form reset

Is there a method for me to call a function after click on the reset button in form, and I mean after, so that the form is first reset and then my function called. Normal event bubbling would call my function and only then reset the form. Now I would like to avoid setTimeout in order to do this.
What I need is to call a function when a form is reset because I use uniform and uniform needs to be updated when values change.
At the moment I do it like this:
//Reset inputs in a form when reset button is hit
$("button[type='reset']").live('click', function(){
elem = this;
//Sadly we need to use setTimeout to execute this after the reset has taken place
setTimeout(function(){
$.each($(elem).parents('form').find(":input"), function(){
$.uniform.update($(this));
});
}, 50);
});
I tried to do al this on $(':input').change() but reseting an element does not seem to trigger the change event.
Thank you in advance for any help.
HTML forms do have an onReset event, you can add your call inside there:
function updateForm()
{
$.each($('form').find(":input"), function(){
$.uniform.update($(this));
});
}
<form onReset="updateForm();">
As pointed out in the comment by Frédéric Hamidi you can also use bind like so:
$('form').bind('reset', function() {
$.each($(this).find(":input"), function(){
$.uniform.update($(this));
});
});
After some testing it appears both ways fire before the reset takes place and not after. The way your doing it now appears to be the best way.
The same conclusion was found in this question here
I haven't yet tested in all browsers, but you can do your own ordering within a click event:
http://jsfiddle.net/vol7ron/9KCNL/1/
$(document).ready(function() {
$("input:reset").click(function() { // apply to reset button's click event
this.form.reset(); // reset the form
window.alert($("input:text").val()); // call your function after the reset
return false; // prevent reset button from resetting again
});
});
Time ago I worked debugging a Google IE related plugin and I solved the main error with a bubbling trick. That's why I think immediately in this solution for your problem (of course should be cross-browser):
<form>
<div id="capture_bubble">
<input type="text"><input type="reset">
</div>
</form>
In this way you can capture the bubbling with $('#capture_bubble') after reset event be triggered.
You can make a quick test with:
(function($) {
$(function() {
$('#capture_bubble').live('click', function(){
console.debug('capture_bubble');
alert('capture_bubble')
})
$("input[type='reset']").live('click', function(){
this.form.reset(); // forcing reset event
console.debug('reset');
alert('reset')
});
});
})(jQuery);
Please note: this.form.reset(); (change made due to a jeff-wilbert observation)
you shouldn't need to wait 50 milliseconds. If you use setTimeout with a timeout of zero, it effectively means "push this code onto the event stack". Since the form-reset is guaranteed to have fired first, the code in the setTimeout is guaranteed (in well behaved javascript interpreters) to have access to the form values you want (post-reset). You should be able to use the code below, guilt-free.
var afterReset = function(){
var pushMeOntoTheEventStack = window.setTimeout(function(){
$("#form input").each(function(){
console.log( this.name + ' = ' + this.value );
});
},0);
};
$("#form").on("reset",afterReset);
Try this solution
Goal:
add on "click" event
prevent the default action (reset)
trigger "reset"
run desired code
Example:
$("button[type='reset']").on('click', function(evt) {
evt.preventDefault();
$(evt.target).trigger('reset');
// enter code to run after reset
$.each($(this).find(":input"), function(){
$.uniform.update($(this));
});
});

Categories