2

I have a div that can display 3 images (in the background) each indicating the 'state' of some variable: i.e., partial, full and none. For each of these states I have images: partial.gif, full.gif and none.gif (i.e., these are background images of that div)

Need: Circular queue like toggling effect for changing the images in this order partial -> full -> none -> partial

So if the current image is 'partial.gif' and the user clicks the div the background image changes to the next one in the sequence i.e., full.gif (and if it is currently full.gif it changes to none.gif and that to partial.gif and so on).

Naive solution: have a bunch of if/else's or switch-case and check the current one (image) and then decide based on array look up which is the next one. Is this the best way of doing it? Can I leverage jQuery's toggle function somehow?

(PS: It need not be restricted to images, but could also be for different background color sequences etc., I'd like to know what it is a good 'generic' way of doing it i.e., The example may be specific for background images but if I changed part of that code for background-color or font it should still work. I don't want it to be purely generic, but just enough so it is easy to modify for other attributes. If not, that's fine too. Just a thought :)

PhD
  • 11,202
  • 14
  • 64
  • 112

2 Answers2

5

http://api.jquery.com/toggle-event/

To be precise http://api.jquery.com/toggle-event/#example-0 does exactly what you wanted...

$("#div1").toggle(
  function() {
    $(this).css("background-image","url(full.png)")
  },   
  function() {
    $(this).css("background-image","url()")
  },   
  function() {
    $(this).css("background-image","url(partial.png)")
  }
});

UPDATE fn.toggle was removed from jQuery

Here are relevant posts

Community
  • 1
  • 1
mplungjan
  • 169,008
  • 28
  • 173
  • 236
  • Neat!! I looked up the api reference too. But a lingering question: Can this _list of functions_ be made arbitrarily long? I mean having 4-5 `function(){...}`s? – PhD Jul 10 '11 at 12:54
  • 1
    Yes. Any length but they will be executed in the order entered. – mplungjan Jul 10 '11 at 12:56
  • 1
    Nevermind, found it :) Here's what the api doc says "_If more than two handlers are provided, .toggle() will cycle among all of them. For example, if there are three handlers, then the first handler will be called on the first click, the fourth click, the seventh click, and so on._" – PhD Jul 10 '11 at 12:57
  • Excellent answer, but unfortunately the feature seems to have [been removed in JavaScript 1.9](http://api.jquery.com/toggle-event/). And the three-way example is gone from the docs. Groan. – Bob Stein Jul 19 '13 at 13:28
1

As long as it's a CSS-based solution (where you can just switch classes), you could do something like this (untested code):

$('#element').click(function() {
  // get current css class value.
  var class = $(this).attr('class');

  // determine/increment number.
  var nextNumber = parseInt(class.charAt(class.length - 1)) + 1;

  // if too high, reset to first one.
  if (nextNumber > 3) {
    nextNumber = 1;
  }

  // remove old class and add new class.
  $(this).removeClass(class).addClass('my_class' + nextNumber);
});

Assumption being made here that you only have one CSS class applied to the element at a time. But if that's not the case, I'm sure you can find a workaround/tweak for this.

And this is just generic enough where you can swap out your CSS class definitions without impacting the script functionality.

Kon
  • 27,113
  • 11
  • 60
  • 86
  • makes sense, but IMO @mplungjan's solution is much cleaner and is a part of the jQuery api - I wasn't aware of that :) But it prevents from algorithmic reinvention :) – PhD Jul 10 '11 at 12:58
  • 1
    Ah, you know what.. I didn't know that toggle could have more than two states. That's an oversight on my part. However, I'd still rather class names instead of specific styles themselves. So if I were you, I'd use @mplungjan's solution but do remove/add class instead. – Kon Jul 10 '11 at 13:01
  • It's helpful to think of a custom solution in the event that jQuery's toggle doesn't solve your problem, for example when using keydown instead of click or delegating the toggle from another event. – Marcy Sutton Jan 17 '13 at 21:12