I need to recognize a long click in a JavaScript bookmarklet.
So, I cannot use jQuery, neither onclick() event and similar. Is it possible, and how?
onmousedown, call setTimeout() for the duration of your long click. If the timeout is allowed to expire, it will call its function to do whatever you hoped to do on the long click. However, onmouseup you cancel the setTimeout() if it has not yet expired.
<script type='text/javascript'>
// t will hold the setTimeout id
// Click for 1 second to see the alert.
var t;
</script>
<button onmousedown='t=setTimeout(function(){alert("hi");}, 1000);' onmouseup='clearTimeout(t);'>Clickme</button>
Here it is in action in jsfiddle
Isn't a long click just a click where mousedown and mouseclick events are considerably long away from each other? In order to solve that you could just measure the time it takes from a mousedown event to the click event and check if it is, e.g. longer than two seconds (or whatever you desire).
You can access the current milliseconds since 01.01.1970 via new Date().getTime(). Given that I would intuitively check a "long click" like that.
$(".selector").mousedown(function() {
$(this).data("timestamp", new Date().getTime());
}).click(function(event) {
var e = $(this);
var start = e.data("timestamp");
e.removeData("timestamp");
if (start && new Date().getTime() - start > YOUR_DESIRED_WAIT_TIME_IN_MILLISECONDS) {
// Trigger whatever you want to trigger
} else {
event.preventDefault();
event.stopPropagation();
}
});
Late reply, but instead of click / long click to provide two different actions, you might want to consider click / double click.
First click: Record time and then timer to perform action1 in 500 miliseconds.
Second click: If time since last click is short, cancel timer and perform action2. If time since last click is long, then this is a first click.
Nothing stops you from using triple click, etc.
Related
I have an input type="number" and am using the up/down arrows within the field to change the value of the input. I want to trigger a function after the final click/change of the input.
By final I mean after the input hasn't been changed for 1000ms (my assumption that the user has now stopped clicking).
I've set up a 1000ms setTimeout() that runs the function, but even though I'm calling clearTimeout() .on('change') of the input, the function runs 1000ms after the first change, rather than the last.
I've set up a simple JSFiddle to illustrate what I mean. The div with "Hello World!" in it should not appear until after the final click.
If you rapidly click the up arrow on the input (at least once every 999ms) then the div should never appear.
I have looked through a lot of other similar questions on here but they're almost all about the scope of the timer variable, which I don't think applies here.
What am I doing wrong?
onchange, is triggered when input loses its focus, try on input.. btw. jquery is not required here.
var timeOut;
document.getElementById("foo").addEventListener("input", function() {
clearTimeout(timeOut);
timeOut = setTimeout(function() {
document.getElementById("bar").style.display = "block";
}, 1000);
});
I am making an incremental game in javascript, so I am replacing some links in the page all the time, this links are showing a really weird behavior. I am attaching the click events with .on(, and some times the click event is fired and some times not, is very random.
Here is a clear example of the beheavior. I can imagine that is something related with the time interval, because if I set the interval in 1000 millis, the event always is fired. Of course that I can make some changed in the code in order to don't replace the link and only update it, but I want to know if this is fixable first.
HTML:
<div id="container"><a id="link" href="#">test</a></div>
JS:
$(document).ready(function(){
$("#container").on("click","#link",function(){
alert("clicked");
});
setInterval(function(){
var newA = $("#link").clone();
$("#link").remove();
$("#container").append(newA);
},100);});
Example in jsFiddle:
http://jsfiddle.net/MtR6b/1/
Thanks!!
Your setInterval code is very fast 100 ms that's why when then event is about to trigger element is replaced with new one so click event is not triggered.
Try clicking on the link many times you will see the alert.
DEMO with 1000ms=1s setInterval
I have 3 textboxes within a div and I need to raise an event when focus leaves one of those inputs and doesn't go to another one of these 3 inputs.
As long as the user is editing one of these 3 controls, the event wont raise. The event will only raise when the focus has changed to a control which isn't one of these inputs.
I tried using focusout on all 3 inputs and checking if document.ActiveElement is one of the 3 inputs but focusout of one control occurs before focusin on another so document.ActiveElement is always empty.
Anyone has any idea how to get around this?
I would consider using a timer to solve this tricky dilemma.
When focus is lost, start the timer. Then you can cancel the timer if focus is then set upon another "safe" input.
Something like this:
var timeoutID;
$("#TheSafeZone input").focus(function () {
if (timeoutID) {
clearTimeout(timeoutID);
timeoutID = null;
}
});
$("#TheSafeZone input").blur(function () {
releaseTheHounds();
});
function releaseTheHounds() {
timeoutID = setTimeout(function () {
alert("You're all going to die down here");
}, 1);
}
Here is a working example
NOTE: I have set the timeout to just 1ms, this seems to work reliably for me but it may be worth doing a few tests in other browsers (I am using Chrome). I guess it is down to how the JS engine handles events, but I don't know enough about that to confidently say all browsers will work the same
Put "Blur" and "Focus" events with opposite logic so that when ever user leaves group of controls specified in DIV only "Blur" event will be fired.
$(document).on("blur","#edit-area .form-control", function (event) {
$('.editButtons').show();
});
$(document).on("focus","#edit-area .form-control", function (event) {
$('.editButtons').hide();
});
I have some animation in my code and I have faced a problem: When the user clicks the button more than once my animation will become faster and faster. To deal with this I have included the refresh page function (location.reload()) inside the function below.
Now I have a major problem: when I execute the button supposed the reload page function will be executed first then follow by day2 function then day1 function... the problem is now only the refresh page function is been executed.
How do I overcome this problem?
Javascript:
function day()
{
location.reload().then(day2).then(day1);
}
HTML:
<input type="button" id="buttonThree" value="Day" onclick="day()"/>
What you're doing doesn't work
Now I have a major problem: when I execute the button supposed the reload page function will be executed first then follow by day2 function then day1 function... the problem is now only the refresh page function is been executed.
Well, yeah. You refreshed the page. That involves leaving the page then re-entering it. Leaving the page means your JavaScript ends everything it's doing, and re-entering it means your JavaScript starts anew. JavaScript does not transcend page loads.
If you want your JavaScript to communicate with JavaScript on other pages, do so via other means: an #anchor in the URI, a query string in the URI, form data, sessionStorage, localStorage, or cookies - those are arranged in order of permanence and appropriateness, with cookies completely overdoing it, and #anchors and query strings being completely appropriate.
But that's completely unnecessary and inappropriate here. You shouldn't be doing what you're doing in the first place.
Let's address the actual problem of multiple button presses
I have some animation in my code and I have faced a problem: When the user clicks the button more than once my animation will become faster and faster.
Simply put, you shouldn't be doing what you're doing and this problem has a much simpler solution: disable the button, or set a boolean flag, in order to prevent the animation from running multiple times. Simply, don't allow the animation to run multiple times.
Option 1: Disabling the button
Disabling the button prevents it from sending onclick events, and signals to your user the button won't do anything for now. I recommend doing this if your button should not do anything longer whilst the animation is running, or whilst something else is happening.
The approach is to disable the button as soon as it's clicked. Later, once the tasks that button fired off (such as the animation) are finished, and it's OK to click the button again, you re-enable the button.
<input type="button" id="animateButton" value="Animate" onclick="animate()"/>
function animate() {
// 'this' refers to the button, when the button's click event
// calls this function
this.disabled = true;
startAnimation();
}
function startAnimation() {
// run the animation
// ...
// once the animation is completed, via whatever means you want
// (such as by jQuery's animate.complete callback),
// re-enable the button like this:
document.getElementById("animateButton").disabled = false;
// or address the button some other appropriate way.
}
Option 2: Boolean flag, leaving the button enabled but doing nothing
This approach involves using a boolean flag to ignore clicks when the animation is running, instead of disabling the button outright.
This lets the user click the button still. It's useful if you want the button enabled for whatever reason, such as if you want the button doing other things on click - just without starting the animation every time.
If it's not going to do anything except start the animation, however, you probably should use option 1 instead to disable it, signalling the button won't do anything for now.
If you want this button to do other things, I suggest you have it call a different function - for example, doStuff() - and have that function call the animate() function below.
<input type="button" id="animateButton" value="Animate" onclick="animate()"/>
var canAnimate = true;
function animate() {
if (!canAnimate) return; // do nothing if we're not allowed to animate yet
canAnimate = false;
startAnimation();
}
function startAnimation() {
// run the animation
// ...
// once the animation is completed, via whatever means you want
// (such as by jQuery's animate.complete callback),
// set the flag to say we can animate again, like this:
canAnimate = true;
}
There are a couple of things that really trouble me with regards to how jQuery handles nested functions (not to the point that I can't sleep but it's getting there) and I wish a jQuery expert could explain how things work to bring me piece of mind.
Let's say you have the below HTML code:
<button id="first">click me first</button>
<button id="second">click me next</button>
And the following jQuery code:
$(document).ready(function() {
$('#first').click(function() {
$('#second').click(function() {
alert('test');
});
});
});
A dialog box will popup if you click the first button and then the second button.
I understand jQuery instantiates the $('#first').click() function when the DOM is ready and calls it when someone clicks on the first button.
However what I am puzzled with is the following:
[Q1] is the $('#second').click() function also instantiated on DOM ready or only when $('#one').click() is called?
Now, when you look at the jQuery code, there is nothing that "keeps us" in the $('#first').click() function, that is once the user clicks on the first button, the $('#second').click() function should be instantiated and we should exit the $('#one').click() function straight away. However after clicking the first button, jquery must somehow keep $('#second').click() indefinitely in memory in case the user clicks on the second button.
[Q2] how does jquery know to keep the $('#second').click() function in memory until the user clicks on the second button after clicking the first button?
Finally let's say you wanted to modify your code so that the user had to click the second button within 10 seconds of clicking the first button for the dialog box to appear:
[Q3] how would you implement this so that jQuery would know to stop listening for click events on the second button after 10 seconds?
Q1 - JS will simply load function definitions. It won't run it unless they are explicitly triggered/called. In this case, it will simply attach the event handler to #first and wait until someone clicks the button to fire the event. This will make the second function attach itself to the second button.
Q2 Again, it's not jQuery, it's JavaScript doing all the work. The method is simply attached to the DOM element and is triggered on the event it is attached to. JS is like any programming language and will keep all methods and variables in its memory.
The second click function isn't actually attached to the second button until after someone clicks on the first button. This is because, when the first button is clicked, JS knows to trigger the first method which does all the work of attaching the second method to the second button.
Q3 You could use setTimeout to unbind that method from the DOM element.
$(document).ready(function() {
$('#first').click(function() {
$('#second').click(function() {
alert('test');
setTimeout(function(){$('#second').unbind('click');}, 10000);
});
});
});
Note This unbinds all click event handlers from this DOM element. You can also unbind that particular method by passing it as a parameter. Check out the API docs for usage.
setTimeout : https://developer.mozilla.org/en/DOM/window.setTimeout
unbind : http://api.jquery.com/unbind/
[A1] The second function is only instantiated when #first is clicked as it is part of the execution of the first method. This also means that if you click #first n times you should get n alerts for every click on #second.
[A2] The function is rooted by the #second element. So long as that element is alive javascript knows to keep the function around.
[A3] You would need to save off the function pointer and do a setTimeout to clear it.
$(document).ready(function() {
$('#first').click(function() {
var secondFunction = function() {
alert('test');
};
$('#second').click(secondFunction);
setTimeout(function(){ $('#second').unbind('click', secondFunction); }, 10000);
});
});
A better implementation is probably something like:
$(document).ready(function() {
var enabled = false;
$('#first').click(function() {
enabled = true;
setTimeout(function(){ enabled = false; }, 10000);
});
$('#second').click(function() {
if(enabled) {
alert('test');
};
});
});
The answer to your first question: Yes, the second button will bind to click event only when a user clicks on the first button.
The second question: I'm not sure what you're asking.
The third one: Assuming the button one has nothing to do except bind the event to second button once clicked, you can set a timeout on document ready for 10 seconds. Now when the timer expires it must unbind the button one's click event hence blocking second button's event. I guess you understand now. e.g.
$(document).ready(function(){
setTimeout(removeEvent, 10000);
$('#first').click(function() {
$('#second').click(function() {
alert('test');
});
});
});
function removeEvent(){
$('#first').unbind('click');
}