Skip to content

Instantly share code, notes, and snippets.

@louisremi
Forked from 140bytes/LICENSE.txt
Created October 27, 2011 09:12
  • Star 11 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save louisremi/1319121 to your computer and use it in GitHub Desktop.
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(
eval('/ *\\b' + classname + '\\b/g')
// in production environment, replace with the following safer line (+9B)
//RegExp('(^| ) *'+ classname +' *( |$)','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",
"maettig"
],
"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
Copy link

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

@louisremi
Copy link
Author

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

@tsaniel
Copy link

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

@louisremi
Copy link
Author

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
Copy link

tsaniel commented Oct 27, 2011

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

@louisremi
Copy link
Author

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
Copy link

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
Copy link

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

@louisremi
Copy link
Author

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
Copy link
Author

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
Copy link

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

@louisremi
Copy link
Author

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
Copy link

atk commented Oct 27, 2011

Not bad at all ;-)

Update: would you mind renaming this gist?

@louisremi
Copy link
Author

@atk
Copy link

atk commented Oct 27, 2011

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

@autarc
Copy link

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

@louisremi
Copy link
Author

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

@maettig
Copy link

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.

@louisremi
Copy link
Author

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