12

I am nearly there, just a little unsure as to my code setup, I basically want to remove a class on click, and add it back again onclick, then remove onclick, then add onclick. And so on! Here's what I have, it's nearly there, but if there is a nicer way to do this then please help! Thank you.

document.getElementById('myButton').onclick = function() {
    myButton.className = myButton.className.replace(/(?:^|\s)active(?!\S)/g, '') ? 'active': jbar.className.replace(/(?:^|\s)active(?!\S)/g, '') ;
}

Any help much appreciated!

5 Answers5

76

I am really surprised nobody mentioned classList here. So just to be complete: Alternative solution would be to use classList method toggle().

Your case would then simply be:

document.getElementById('myButton').onclick = function() {
    this.classList.toggle('active');
}

e.classList.toggle() has good support (except for, ehm, IE, It's there since IE10). Click here for complete browser compatibility.

kecer
  • 3,031
  • 2
  • 21
  • 24
14

If you want to use a ternary operator, use this:

document.getElementById('myButton').onclick = function() {

    var className = ' ' + myButton.className + ' ';

    this.className = ~className.indexOf(' active ') ?
                         className.replace(' active ', ' ') :
                         this.className + ' active';
}

For clarity, I'd use a regular if/else:

document.getElementById('myButton').onclick = function() {

    var className = ' ' + myButton.className + ' ';

    if ( ~className.indexOf(' active ') ) {
        this.className = className.replace(' active ', ' ');
    } else {
        this.className += ' active';
    }              
}

Here's the fiddle: http://jsfiddle.net/ttEGY/

Joseph Silber
  • 214,931
  • 59
  • 362
  • 292
  • Brill! Thank you very much. Howcome you didn't need the RegEx? –  Jan 30 '13 at 23:34
  • @Toddo - Because I wrapped it in spaces, I can just search for an exact string match. Old trick I learnt from the jQuery source. – Joseph Silber Jan 30 '13 at 23:36
  • Clever, much cleaner than RegEx. Can I trouble you for one extra piece of advice? If I wanted to remove the class from two different divs, at once? How would that be done without writing it twice. Assuming the id is #myButton1 and #myButton2 both containing the class to toggle. –  Jan 30 '13 at 23:42
  • @Toddo - You can't. You should abstract this functionality into a function, and call it for both elements separately. – Joseph Silber Jan 30 '13 at 23:42
  • How would you run the function then on each item? or do you mean setup an onclick for each of them? –  Jan 30 '13 at 23:45
  • Something like this? document.getElementById('myButton').onclick = toggleClass(myButton); with the function above like so: function toggleClass(element) {...} –  Jan 30 '13 at 23:50
  • @Toddo - Yep. Don't forget to replace `this.className` with `myButton.className`. – Joseph Silber Jan 30 '13 at 23:59
2

If JQuery is okay for you it really is as simple as

$(myButton).toggleClass('active')

http://jsfiddle.net/bikeshedder/eRJB4/

bikeshedder
  • 7,337
  • 1
  • 23
  • 29
0

Suggest common realization of toggleClass method:

function toggleClass(element, tClass) {
    tClass = tClass.replace(/\s/g, "");

    var classes =  element.className;
    element.className = classes.indexOf(tClass) !== -1 
        ? classes.replace(" " + tClass, "")
        : classes + " " + tClass;
}

using:

var element = document.getElementById('myId');
toggleClass(element, 'active');
BotanMan
  • 1,357
  • 12
  • 25
0

Implementation using Array methods:

const toggleClass = (element, className) => {
  let classNames = element.className.split(' ');
  let index = classNames.indexOf(className);
  if (index === -1) {
    classNames.push(className);
  } else {
    classNames.splice(index, 1);
  }
  element.className = classNames.filter(item => item !== '').join(' ');
}

Usage:

let body = document.getElementsByTagName('body')[0];
toggleClass(body, 'ready');

Plunker

Steve Brush
  • 2,911
  • 1
  • 23
  • 15