Reputation: 511
I am attempting to create an onclick function which has 1 of 2 outcomes on each click. In other words, when the user clicks the onclick element for the first time the outcome 1 occurs; then the user clicks the same element a second time, outcome 2 occurs. When the user clicks on the element a third time, outcome 1 happens again; forth click, outcome 2 occurs; and so on, like a loop. Below is some pseudo jQuery to give an illustration...
$(function(){
var hits = 0;
$('#myButton').click(function(){
if (var hits = pos )
{
$('#content1').fadeIn("slow");
$('#content2').fadeOut("slow");
}
else
{
$('#content1').fadeOut("slow");
$('#content2').fadeIn("slow");
}
return false;
});
});
I have had a hard time searching for an answer because the terminology can vary tremendously. From 'variable' to 'trigger' to 'array' to 'listener' to 'handler' to 'conditional' to 'bind'.... where do I begin to search? I know there are multiple ways to create my function, but I know this is the best site to go to find the easiest, most efficient way. So on top of helping me out syntactically, I'd also like some terminology help with the cluster of words I listed. I know the general meaning of each term, but when applying them to the scenario/function I am trying to create, where do they each play a part? I think this will help straighten things out for a lot of people. Thanks in advance.
Thank you all for the quick and elaborate, professional feedback. I will use this new knowledge to its advantage. JQuery really does make things simple, almost too easy. However, the main reason I asked this question was to apply it to a keydown function, instead of a click function. I thought I could find an answer and swap some code around, maybe with normal javascript this would have worked. I have posted a new question that uses the knowledge and feedback you all have provided and come up with a different scenario involving the keydown function. I think I have the syntax pretty close thanks to your help, but however, only almost. If you would like to see, here is the url: bind event handler on keydown listen function JavaScript jQuery You guys truly rock.
Upvotes: 0
Views: 9150
Reputation: 25289
May I suggest you have a look into jQuery's toggle() method which would be used like:
$(function() {
$('#myButton').toggle(function(){...}, function(){...});
});
I also give you a modified version of the DIY way:
$(function(){
var hits = 0;
$('#myButton').click(function(){
hits ^= 1;
if ( hits ) {
$('#content1').fadeIn("slow");
$('#content2').fadeOut("slow");
} else {
$('#content1').fadeOut("slow");
$('#content2').fadeIn("slow");
}
return false;
});
});
Upvotes: 0
Reputation: 3280
As you want to know some terminology etc. I will provide you with some language-independent one.
Basically, I would call your requirement a 'state machine'.
In it's very basic, a state machine contains of "states", "events", and "transition functions". In your case you've got 2 states (let's call them "visible" and "hidden"), one event ("click") and 2 transition functions (we can call them "showContentOne" and "showContentTwo").
Two clarify terminology:
Following, I will provide you with very basic (too basic in fact) explanation of concept, but keep in mind that I oversimplify things here - read appropriate articles in books or even wikipedia to get more precise information.
A state machine can be best described with a graph, in your case:
So how to implement this thing properly?
you must have some variable to store state of your element. In your code snippet you have used global variable called "hits". As you use jQuery I would instead use it's "data" function which let's you bind arbitrary data to your DOM element (this way you will be able to install many independent state machines in single DOM tree). Then you need to bind event handlers (this is easy as you have only one event to consider - click) and define your state transition functions. Finally you need a function that will check state of an element, analyse incoming event and call appropriate state transition function.
Some basic implementation could look like this (I will not test this code, treat it as pseudo-code to help you get executable solution)
function showContentOne($element) {
$('#content1').fadeIn("slow");
$('#content2').fadeOut("slow");
$element.data('state', 'hidden');
}
function showContentTwo($element) {
$('#content1').fadeOut("slow");
$('#content2').fadeIn("slow");
$element.data('state', 'visible');
}
function transitState($element, event) {
var state = $element.data('state');
if (state == 'visible' && event == 'click') {
showContentTwo($element);
} else if (state == 'hidden' && event == 'click') {
showContentOne($element);
} else {
//unsupported transition - do nothing or raise error
}
}
$(function(){
$('#myButton')
.data('state', 'visible') //initialize a state
.click(function() { //install event handler
transitState($(this), 'click');
}
//here you can possibly install more event handlers
});
});
Now if you reimplement "transitState" to use some array or objects like state machine definition you can get quite robust solution to add/remove events and other state transition functions. You can install a state machine on any element, perhaps wrap this with jquery plugin.
Note: in your case my solution is serious over-engineering of this task. I provided it to give you some terminology. Your very basic problem (2 states, 2 transitions, one event) can be easily implemented in very similiar way you showed in original question, only change I would make is not using global variable, but data function to maintain state. Because you have got exactly two states, boolean variable to hold it will be perfectly fine.
$(function(){
$('#myButton')
.data('isVisible', true)
.click(function(){
if ($(this).data('isVisible')) {
$('#content1').fadeIn("slow");
$('#content2').fadeOut("slow");
} else {
$('#content1').fadeOut("slow");
$('#content2').fadeIn("slow");
}
$(this).data('isVisible', !$(this).data('isVisibile'));
return false;
});
});
And as others stated for changing visibility of elements on consecutive clicks you can use toggle functions.
sorry for my poor english :/
Upvotes: 2
Reputation: 15129
Try:
$(function(){
var hits = 0; //->variable
// Everything below this line is called "binding" a handler to an event (click event)
$('#myButton').click(function(){ // --> This whole function is the handler or listener
if (hits % 2 !== 0) //for hits 2,4,6,8 etc. Also the condition
{
$('#content1').fadeIn("slow");
$('#content2').fadeOut("slow");
}
else
{ // for hits 1,3,5,7
$('#content1').fadeOut("slow");
$('#content2').fadeIn("slow");
}
hits++;
return false;
});
});
Upvotes: 1
Reputation: 70209
jQuery has .toggle(handlers)
for alternating clicks functionality:
$('#myButton').toggle(function() {
$('#content1').fadeIn("slow");
$('#content2').fadeOut("slow");
}, function() {
$('#content1').fadeOut("slow");
$('#content2').fadeIn("slow");
});
Now if all you want to do is switch 2 elements by fading them in/out respectively, you can use .fadeToggle()
:
$('#myButton').click(function() {
$('#content1, #content2').fadeToggle("slow");
});
Upvotes: 5
Reputation: 4118
One way to easily achieve this, and perhaps make it somewhat more elegant, would be to write this simple plugin:
(function ($) {
$.fn.rollerClick = function (handlers) {
this.each(function () {
this.hits = 0;
$(this).click(function () {
handlers[this.hits ++](this);
if (this.hits == handlers.length) {
this.hits = 0;
}
});
});
};
)(jQuery);
Now you can use it like this:
$("selector").rollerClick([
function (element) {
alert('1');
},
function (element) {
alert('2');
},
function (element) {
alert('3');
}
]);
Then by clicking repeatedly over the selected item you will roll through the handlers, seeing alerts popping up showing "1", "2", "3", "1", "2", ... .
Upvotes: 0