Trigger function with keydown only once? - javascript

I have a series of messages on my page that are triggered by a keydown event once people start typing in a textarea. However, I can't figure out how to trigger it only once. Since people are typing longer responses, the function runs every time a key is pressed :/
$(function() {
$(document).on('keydown', function() {
$('.three').delay(1000).fadeOut(1500);
$('.four').delay(2500).fadeIn(1500).delay(2000).fadeOut(1500);
$('.five').delay(7500).fadeIn(1500).delay(2000).fadeOut(1500);
$('.6').delay(12500).fadeIn(1500).delay(2000).fadeOut(1500);
$('.7').delay(17500).fadeIn(1500);
});
});

Instead of "on" use "one". This handles the event only once.
$(function() {
$(document).one('keydown', function() {
$('.three').delay(1000).fadeOut(1500);
$('.four').delay(2500).fadeIn(1500).delay(2000).fadeOut(1500);
$('.five').delay(7500).fadeIn(1500).delay(2000).fadeOut(1500);
$('.6').delay(12500).fadeIn(1500).delay(2000).fadeOut(1500);
$('.7').delay(17500).fadeIn(1500);
});
});
Here's the reference: http://api.jquery.com/one/

Related

How can I tell if an event is being fired by the same event that created it?

Let's say I have the following events:
$(button).on('mouseup', function (event1) {
$(something).show();
$(document).on('mouseup', function (event2) {
$(something).hide();
});
});
So, it shows "something" when button is clicked and hides it when the document is clicked. How can I make sure the second evnet doesn't trigger in the same event that created it? right now the something will show and hide instantly (at least on firefox).
I need to do this without any globals of any kind, preferably.
How about this:
$(button).on('mouseup', function (event1) {
$(something).show();
event1.stopPropagation();
$(document).one('mouseup', function (event2) {
$(something).hide();
});
});
stopPropagation() will stop the event from going past the button (to the document).
one() will only run the event once and then go away... can be recreated again with another click on the button.
JSFiddle
Here's another solution that doesn't rely on timestamps:
$("button").on('mouseup', function (event1) {
$("#something").show();
setTimeout(function () {
$(document).one('mouseup', function (event2) {
$("#something").hide();
});
}, 0);
});
demo
Using setTimeout with a delay of 0 will make it execute the code as soon as it's finished with this event. Also note I'm using one rather than on because you only need this event handler one time and without it you will end up attaching unlimited numbers of event handlers, every single one of which will need processing when a mouseup fires anywhere on your page.
A less silly solution might look like this:
$("button").on('mouseup', function (event1) {
$("#something").show();
});
$(document).on('mouseup', function (event2) {
if(event2.target != $("button")[0]) {
$("#something").hide();
}
});
demo
Why don't you isolate the event like so:
$(button).on('mouseup', function (event1) {
$(something).show();
});
$(document).on('mouseup', function (event2) {
$(something).hide();
});
I ended up using the event.timeStamp property to check if the two events are distinct. Also added an unbind and a namespace to the document event to prevent event stacking.
$(button).on('mouseup', function (event1) {
$(something).show();
$(document).on('mouseup.'+someIdentifier, function (event2) {
if(event1.timeStamp != event2.timeStamp) {
$(something).hide();
$(document).unbind('mouseup.'+someIdentifier);
}
});
});

why is jQuery click event firing multiple times

I have this sample code here
http://jsfiddle.net/DBBUL/10/
$(document).ready(function ($) {
$('.creategene').click(function () {
$('#confirmCreateModal').modal();
$('#confirmCreateYes').click(function () {
$('#confirmCreateModal').modal('hide');
var test = "123";
alert(test);
console.log(test);
});
});
});
If you click the create button 3 times and each time you click yes on the confirmation, the alert is fired multiple times for each click instead of just one time.
If you click the create button 3 times and each time you click no and on the 4th time you click yes the alert is fired for each of the previous clicks instead of just one time.
this behavior seems weird to me as i would expect the alert to be fired once per click. Do I have to use .unbind() or is there a better solution?
Could someone please tell me why this is happening and how to fix it?
Thanks
Because you are binding it multiple times. Click event inside a click event means every time you click, a new click event is being bound on top of the previously bound events. Do not bind click events inside of click events unless the click event creates the element. There's also no need to re-initialize the modal over and over.
$(document).ready(function ($) {
$('#confirmCreateModal').modal({show: false});
$('#confirmCreateYes').click(function () {
$('#confirmCreateModal').modal('hide');
var test = "123";
alert(test);
console.log(test);
});
$('.creategene').click(function () {
$('#confirmCreateModal').modal('show');
});
});
Demo
change the code like this
$(document).ready(function ($) {
$('.creategene').click(function () {
$('#confirmCreateModal').modal();
});
$('#confirmCreateYes').click(function () {
$('#confirmCreateModal').modal('hide');
var test = "123";
alert(test);
console.log(test);
});
});
fiddle
You dont have to bind $('#confirmCreateYes').click in each button click.
You can try this also -
$("#confirmCreateYes").unbind().click(function() {
//Stuff
});
Add this to your code:
$( "#confirmCreateYes").unbind( "click" );
Like this:
$(document).ready(function ($) {
$('.creategene').click(function () {
$('#confirmCreateModal').modal();
$('#confirmCreateYes').click(function () {
$('#confirmCreateModal').modal('hide');
var test = "123";
alert(test);
console.log(test);
$( "#confirmCreateYes").unbind( "click" );
});
});
});
It will unbind the event, so that it isn't bound on top of the previous event. This allows the event only to fire within the original click event.
This is not a good method. It will unbind all click events attached to the element. I will leave it here for learning purposes.
As of now its the below code worked for me,
$("#parentID").off("click", ".button").on("click", ".button", function(e){
e.preventDefault(); // stop probagation if its button or a href
// your code here
});

jQuery - triggering sequence of clicks won't work

hi this is my code http://jsfiddle.net/Xy4dF/1/
i have this part:
$('#top-user').on('click', function () {
alert('1');
});
$('.user').on('click', function () {
alert('2');
});
now out of this code i want to trigger in sequence the 2 elements clicks
so i do:
$('#top-user').click(function () {
$('.user').click();
});
What is wrong? :O
Is the following what you're after (I'm not 100% sure I've understood the question)
$(function () {
$('#top-user').on('click', function () {
alert('1');
});
$('.user').on('click', function () {
alert('2');
});
$('#top-user').click(function () {
$('.user').click();
}).click();
});
The reasons your original code didn't work is that:
You had defined the event handlers but not triggered any on page load.
You need to define an event handler before you trigger it. This is because when triggering an event, JQuery fakes it by immediately calling the bound event handlers rather than managing to genuinely trigger the event at browser level.
Hope this helps

Onload fires no matter where I place it

Right, I'm getting quite aggitated with this. I'm probably doing something wrong, but here's what I'm doing:
$(document).ready(function () {
$('#somebutton').click(function () {
openPage1();
});
$('#someotherbutton').click(function () {
openPage2();
});
});
var openPage1 = function () {
$('#iframe').attr('src', 'someurl');
$('#iframe').load(function () {
$('#button').click();
});
};
var openPage2 = function () {
$('#iframe').attr('src', 'anotherurl');
$('#iframe').load(function () {
$('#anotherbutton').click();
});
}
Whenever I click somebutton everything goes as expected. However when I click someotherbutton. The .load() from openPage1() is called first and I can't find a way to stop that. The .load() from openPage1() has a button with the same name, however on openPage2() I need to modify the contents before clicking the buttons.
I need to use .load() because I can't click the buttons before the document is ready.
Basically what I need is two seperate .load() instances on the same iframe, that don't fire off on each other.
Besides that, maybe my understanding of jQuery/JS is wrong, but shouldn't the .load() events only be listening after clicking the corresponding button?
Can someone help me out, this has been keeping me busy all afternoon.
Try using on, and once loaded, unbind
$("#iframe").on("load", function(){
$(this).off("load");
$('#button').click();
});
That way you remove the handler you put up before the second button is clicked?
By writing : $('#iframe').load(function (){ $('#button').click(); });, you are adding a listener on the load event, which will stay and be re-executed on each subsequent reload of the iframe.
Here is a jsfiddle to demonstrate this : click on the "reload" button, and see how many times the "loaded" message appears in your console.
in your case, if you click on #somebutton, then on #someotherbutton, after the second click, you will have two handlers bound on the load event, and both will be triggered.
If you click 5 times on #somebutton, you should end up calling 5 times $('#button').click().
If you want to execute it once, you can follow Fred's suggestion, or use jQuery .one() binder :
$('#iframe').one('load', function(){ $('#button').click() });
Here is the updated jsfiddle : 'loaded' should be displayed only once per click.
Maybe try and replace the lines in both functions like this:
$('#iframe').load(function() {
$('#anotherbutton').click();
};
$('#iframe').attr('src', 'anotherurl');
Otherwise it might be firing the event before the new event-handler has been set.
This isn't really an answer to your problem Now it is an answer, but I think utilizing functions as they were intended could be beneficial here, i.e.:
//Utilize a single function that takes arguments
var openPage = function (frame, src, eventEl) {
frame.attr('src', src); // If you pass frame as a jQuery object, you don't
frame.on("load", function(){ // need to do it again
$(this).off("load");
evEl.click(); //Same for your buttons
});
}
//Simplify other code
$(document).ready(function () {
$('#somebutton').click(function () {
openPage($("#iframe"),somehref,$("#buttonelement"));
});
$('#someotherbutton').click(function () {
openPage($("#iframe"),anotherhref,$("#someotherbuttonelement"));
});
});

Prevent keydown() from being captured by document binding

I'm not exactly sure how to phrase this, so I couldn't search it. Basically, I have a keydown() bind on $(document). I'd like to show() another div, and have all keydown events be rerouted to this div and prevented from firing off in the document handler. Is this even possible, or would I have to put all my main keybindings on another div and work from there?
e.stopPropagation, or
e.preventDefault (depending on the situation)
Where e is the event.
Ex:
function onKeyDown(e) {
doStuff();
e.preventDefault();
}
e.preventDefault() will prevent the default behaviour of an event. What you need is to use
e.stopPropagation(), so that the event does not bubble up the DOM structure.
$(element).keydown(function(e) {
// do the task
// allow the default behaviour also
e.stopPropagation();
//^. BUT stop the even bubbling up right here
});
e.stopProgation(), can be bit confusing to grasp on the first but I created a demo with click event to explain it.
Hope it helps!!
Try:
​$(document).on('keydown', function (evt) {
$('#foo').show().trigger(evt);
});​​​​​
$('#foo').on('keydown', function (evt) {
console.log(evt);
return false; // this is very important. Without it, you'll get an endless loop.
});
​
demo: http://jsfiddle.net/Z7vYK/
The only way I can think of to even have a keydown event run on something other than an input or document, is to manually trigger it. You could have a global variable keep track of whether or not your div is showing, then trigger the event on your div accordingly.
Here's one such solution
HTML
Show div
<div id="hiddendiv"></div>​
Javascript
var showing = false;
function showdiv()
{
showing = true;
$('#hiddendiv').show(200);
}
// Set up events on page ready
$(function() {
$(document).keydown(function(e) {
// If the div is showing, trigger it's keydown
// event and return
if(showing)
{
$('#hiddendiv').data('keydown_event', e).keydown();
return true;
}
alert('Document keydown! Keycode: ' + e.keyCode);
// Otherwise do the normal keydown stuff...
});
// Keydown for the hidden div
$('#hiddendiv').keydown(function() {
e = $(this).data('keydown_event');
alert('Hiddendiv keydown! Keycode: ' + e.keyCode);
// Make sure to stop propagation, or the events
// will loop for ever
e.stopPropagation();
return false;
});
});
​
As you can see, the #hiddendiv keydown event is being triggered by the document keydown event. I've also included a slight hack to get the event object to the hidden div using the jQuery data function.
Here's a demonstration of the code: http://jsfiddle.net/Codemonkey/DZecX/1/

Categories

Resources