Skip to content

Embed URL

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
c, an expressive className manipulation lib: c( elem, 'has/add/remove/toggle', class_name )
// class manipulation library
function( elem, verb, classname, attr, result ) {
// systematically remove class name from className attribute
result = elem[
attr = 'className'
].replace(
// equivalent to: new RegExp('\\b' + class + '\\b')
eval('/\\b' + classname + '\\b/g')
, '' );
return 'has' == verb ? result != elem[attr]:
// all other verbs modify className attribute
elem[attr] = {
add: 1,
toggle: result == elem[attr]
}[ verb ] ?
// verb is 'add' or ( verb is 'toggle' and class name wasn't already present in className attribute)
result + ' ' + classname:
// verb is anything else ('remove', 'getRidOf') or ( verb is 'toggle' and class name was already present in className attribute)
result;
}
function(e,v,n,c,r){r=e[c='className'].replace(eval('/\\b'+n+'\\b/g'),'');return'has'==v?r!=e[c]:e[c]={add:1,toggle:r==e[c]}[v]?r+' '+n:r}
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Copyright (C) 2011 @louis_remi <http://louisremi.com>
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.
{
"name": "c",
"description": "An expressive className manipulation lib: c( elem, 'has/add/remove/toggle', class_name )",
"contributors": [
"louisremi",
"atk",
"tsaniel"
],
"keywords": [
"class",
"className",
"DOM"
]
}
<!DOCTYPE html>
<title>Foo</title>
<div id="elem" class="banana"></div>
<pre><code>&lt;div id="elem" class="banana"&gt;&lt;/div&gt;</code></pre>
<div>elem has banana?: <b id=t1>undefined</b></div>
<div>elem has chocolate?: <b id=t2>undefined</b></div>
<div>elem add cacao: <b id=t3>undefined</b></div>
<div>elem remove banana: <b id=t4>undefined</b></div>
<div>elem has banana?: <b id=t5>undefined</b></div>
<div>elem toggle iceCream?: <b id=t6>undefined</b></div>
<div>elem toggle cacao?: <b id=t7>undefined</b></div>
<script>
var c = function(e,v,n,c,r){r=e[c='className'].replace(eval('/\\b'+n+'\\b/g'),'');return'has'==v?r!=e[c]:e[c]={add:1,toggle:r==e[c]}[v]?r+' '+n:r},
$ = function(id) { return document.getElementById(id) },
elem = $("elem");
$("t1").innerHTML = !!c( elem, "has", "banana" );
$("t2").innerHTML = !!c( elem, "has", "chocolate" );
$("t3").innerHTML = c( elem, "add", "cacao" );
$("t4").innerHTML = c( elem, "remove", "banana" );
$("t5").innerHTML = !!c( elem, "has", "banana" );
$("t6").innerHTML = c( elem, "toggle", "iceCream" );
$("t7").innerHTML = c( elem, "toggle", "cacao" );
</script>
@atk

Does not work in ie yet (due to v[0]), but saves some bytes:

function(e,v,n,c,r){c='className';v=v[0];r=eval('/\\b'+n+'\\b/g');return'h'==v?r.test(e[c]):(e[c]=v=='a'?e[c]+' '+n:e[c].replace(n,''))}

@louisremi
Owner

@atk nope, c({className:"atest test"}, "remove", "test") would fail. And keeping "add" and "has" is actually shorter.

@tsaniel

Save 8 bytes.

function(a,b,c,d){var e=" ",f=e+a[d="className"]+e,g=e+c+e;return"has"==b?~f.indexOf(g):b=="add"?a[d]+=e+c:a[d]=f.split(g).join(e)}
@louisremi
Owner

I kept your idea of flipping verb=="has" and factorizing elem[c]=, saving 2bytes.
I won't factorize ( s+ elem[c] +s ) and ( s+ cName +s ) because assigning them isn't necessary for add, and conditional assignment is longer.
137bytes!

@tsaniel

I don't quite understand the meaning of 'conditional assignment is longer'.

@louisremi
Owner

if @tsaniel factorizes a[d]= then his code is 130bytes
If someone saves another 2bytes then we can add .slice(1,-1) and I'd accept to factorize ( s+ elem[c] +s ) and ( s+ cName +s ). Otherwise it's not worth it ;^)

@tsaniel

What about

function(a,b,c,d){var e=" ",f=e+a[d="className"]+e,g=e+c;return"has"==b?~f.search(g):a[d]=b=="add"?a[d]+g:f.split(g+e).join(e).slice(1,-1)}

Update: 139 bytes.

@atk

My mistake, replace(r,'') not replace(n,'') - now it works:

function(e,v,n,c,r){c='className';v=v[0];r=eval('/\\b'+n+'\\b/g');return'h'==v?r.test(e[c]):(e[c]=v=='a'?e[c]+' '+n:e[c].replace(r,''))}

But here's one even shorter (126bytes):

function(e,v,n,c,r){r=e[c='className'].replace(eval('/\\b'+n+'\\b/g'),'');return'has'==v?r!=e[c]:(e[c]=r+('add'==v?' '+n:''))}

@louisremi
Owner

function(e,v,n,c,r){r=e[c='className'].replace(eval('/\\b'+n+'\\b/g'),'');return'has'==v?r!=e[c]:(e[c]=r+('add'==v?' '+n:''))}

Wow, I like that one very much! It filters duplicate values when using add, perfect.
You guys are impressive.
Now using v=v[0], can we add the verb "toggle"?

@louisremi
Owner

function(e,v,n,c,r){r=e[c='className'].replace(eval('/\\b'+n+'\\b/g'),'');return'h'==(v=v[0])?r!=e[c]:e[c]=r+('a'==v||'t'==v&&r==e[c]?' '+n:'')}
142 with toggle...

@atk

that's 144, not 142.

We can save four more bytes by replacing

'a'==v||'t'==v&&r==e[c] with
v in{a:1,t:r==e[c]}

Voila:

function(e,v,n,c,r){r=e[c='className'].replace(eval('/\\b'+n+'\\b/g'),'');return'h'==(v=v[0])?r!=e[c]:e[c]=r+({a:1,t:r==e[c]}[v]?' '+n:'')}

Update: damn, toggle not yet working...

Better try (works now, 139 bytes only):

function(e,v,n,c,r){r=e[c='className'].replace(eval('/\\b'+n+'\\b/g'),'');return'h'==(v=v[0])?r!=e[c]:e[c]=r+({a:1,t:r==e[c]}[v]?' '+n:'')}

@louisremi
Owner

I came up with
function(e,v,n,c,r){r=e[c='className'].replace(eval('/\\b'+n+'\\b/g'),'');return'h'==(v=v[0])?r!=e[c]:e[c]='a'==v||'t'==v&&r==e[c]?r+' '+n:r}
which was still 1 byte too long. Let's see if merging the two can save some bytes...
function(e,v,n,c,r){r=e[c='className'].replace(eval('/\\b'+n+'\\b/g'),'');return'h'==(v=v[0])?r!=e[c]:e[c]={a:1,t:r==e[c]}[v]?r+' '+n:r}
136 bytes :^)
No wait, we can have IE compat back:
function(e,v,n,c,r){r=e[c='className'].replace(eval('/\\b'+n+'\\b/g'),'');return'has'==v?r!=e[c]:e[c]={add:1,toggle:r==e[c]}[v]?r+' '+n:r}
That's 138 bytes. I love this game!

@atk

Not bad at all ;-)

Update: would you mind renaming this gist?

@atk

No, thank you. It was really fun to help you golfing this one down :-)

@Autarc

Like the idea and the coverage (add,has,remove, including toggle) of this modifing class function :)

If you still like to enhance it, there is this odd thing with a space - as you "add/toggle" a new class to an element. It's not really a problem, but perhaps this could somehow be considered too (^_^)

@louisremi
Owner

Thanks Autarc. There are only two characters left so it's a tricky problem ;^)

@maettig

Besides @tsaniel's abusing regular expressions to find prime numbers this is one of my favorite 140byt.es snippets. It's incredible how much functionality is compressed in this toolkit.

I have a suggestion what to do with the remaining 2 bytes: Change eval('/\\b'+n+'\\b/g'),'') into eval('/ *\\b'+n+'\\b/g'),''). This will at least remove some of the spaces. Toggling the same class on and off will not add more and more spaces.

@louisremi
Owner

Thanks maettig, I should have applied your suggestion earlier. The output is now much cleaner.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.