Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
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 commented Oct 27, 2011

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,''))}

Owner

louisremi commented Oct 27, 2011

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

tsaniel commented Oct 27, 2011

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)}
Owner

louisremi commented Oct 27, 2011

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 commented Oct 27, 2011

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

Owner

louisremi commented Oct 27, 2011

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 commented Oct 27, 2011

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 commented Oct 27, 2011

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:''))}

Owner

louisremi commented Oct 27, 2011

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"?

Owner

louisremi commented Oct 27, 2011

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 commented Oct 27, 2011

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:'')}

Owner

louisremi commented Oct 27, 2011

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 commented Oct 27, 2011

Not bad at all ;-)

Update: would you mind renaming this gist?

atk commented Oct 27, 2011

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

Autarc commented Nov 6, 2011

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 (^_^)

Owner

louisremi commented Nov 6, 2011

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

maettig commented Nov 11, 2011

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.

Owner

louisremi commented Jan 30, 2012

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