public
Last active — forked from 140bytes/LICENSE.txt

c, an expressive className manipulation lib: c( elem, 'has/add/remove/toggle', class_name )

  • Download Gist
LICENSE.txt
1 2 3 4 5 6 7 8 9 10 11 12 13
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.
annotated.js
JavaScript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
// 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;
}
package.json
JSON
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
{
"name": "c",
 
"description": "An expressive className manipulation lib: c( elem, 'has/add/remove/toggle', class_name )",
 
"contributors": [
"louisremi",
"atk",
"tsaniel"
],
 
"keywords": [
"class",
"className",
"DOM"
]
}
test.html
HTML
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
<!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>

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

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

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

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!

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

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 ;^)

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.

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

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

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...

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

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!

Not bad at all ;-)

Update: would you mind renaming this gist?

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

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

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

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.

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

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.