# Simplifying multiple click events into something more extendable

I have the following code which changes the text in a certain element on click depending on the text value present in the element at the time the event is fired.

http://jsfiddle.net/TNDhL/

$('#left').on('click', function (){ if ($("#textContainer:contains('something')").length) {
$('#textContainer').text('third text replacement');$('.elsewhere').text('more here');
}
else if ($("#textContainer:contains('third text replacement')").length) {$('#textContainer').text('now the next item');
$('.elsewhere').text('something new here'); } else if ($("#textContainer:contains('now the next item')").length) {
$('#textContainer').text('new text here');$('.elsewhere').text('something else here');
}
else if ($("#textContainer:contains('new text here')").length) {$('#textContainer').text('something');
$('.elsewhere').text('text here'); } });$('#right').on('click', function (){
if ($("#textContainer:contains('something')").length) {$('#textContainer').text('new text here');
$('.elsewhere').text('something else here'); } else if ($("#textContainer:contains('new text here')").length) {
$('#textContainer').text('now the next item');$('.elsewhere').text('something new here');
}
else if ($("#textContainer:contains('now the next item')").length) {$('#textContainer').text('third text replacement');
$('.elsewhere').text('more here'); } else if ($("#textContainer:contains('third text replacement')").length) {
$('#textContainer').text('something');$('.elsewhere').text('text here');
}
});


Please see fiddle above for working version.

In this instance clicking on 'Left' or 'Right' would change the text above.

Is there a better way to handle this case? Main goal is to allow for easier extension of these simple functions into something more complex that involves several similar click events. Something less error prone and easier to maintain/grow. Any suggestions?

• do you need that fuzzy match? – Ven Sep 16 '13 at 18:31
• Ah... hadn't thought about it until you mention it but no I actually don't want :contains but instead an exact match for the string. – jessback Sep 16 '13 at 18:36

Displaying lots of content? This is not a job for Javascript, this is a Job for HTML. Keep the content in HTML, where non-programmers can maintain it:

<div id="textContainer">
<div class="t1">something</div>
<div class="t2">third text replacement</div>
<div class="t3">now the next item</div>
<div class="t4">new text here</div>
</div>
<hr />
<div id="left">Left</div>
<div id="right">Right</div>
<hr />
<div class="elsewhere">
<div class="t1">text here</div>
<div class="t2">more here</div>
<div class="t3">something new here</div>
<div class="t4">something else here</div>
</div>


and use JS only to display/hide it:

var cursor = 1;
var max = $('#textContainer div').length; function redisplay() {$('#textContainer div').hide();
$('#textContainer div.t'+cursor).show();$('.elsewhere div').hide();
$('.elsewhere div.t'+cursor).show(); }$('#left').on('click', function (){
cursor--;
if(cursor < 1) cursor = max ;
redisplay();
});

$('#right').on('click', function (){ cursor++; if(cursor > max) cursor = 1; redisplay(); }); redisplay();  (you might want to move the variables cursor + max from the global namespace to something more private) working demo at http://jsfiddle.net/bjelline/KV63M/ • You are correct, it was becoming too much to maintain all the content in JavaScript. Your method requires I do a bit more on the front end to extend a few functions I had planned but overall its much easier. Thanks – jessback Sep 17 '13 at 15:48 The easier (imho) solution would be to store what you want in an nested object containing the matches : var selectors = { left: { 'something': ['third text replacement', 'more here'], 'third text replacement': ['now the next item', 'something new here'], } }; var$textContainer = $('#textContainer') ,$elsewhere = $('.elsewhere'); for (var sel in selectors) { void function(sel, matches) {$('#'+sel).click(function() {
for (var i = 0; i < matches.length; ++i) {
// change "this.value" if it's not an input
if (this.value == matches[i]) {
// we found a match, let's update the value
$textContainer.text(matches[i][0]);$elseWhere.text(matches[i][1]);
// and return early
break;
}
}
});
}(sel, selectors[sel]);
}

• Just for information: void is used here to create an IIFE. One could also use parentheses around the function. – Aegis Sep 16 '13 at 18:53