Skip to content

Instantly share code, notes, and snippets.

@calvinf
Created July 1, 2017 02:07
Show Gist options
  • Save calvinf/b9b87dab5b340921bc3b0b868d1ea025 to your computer and use it in GitHub Desktop.
Save calvinf/b9b87dab5b340921bc3b0b868d1ea025 to your computer and use it in GitHub Desktop.
Add Classes (without using classList or jQuery)
<!doctype html>
<html>
<head>
<title>Add Classes (without using classList or jQuery)</title>
<meta charset="utf-8">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/mocha/3.4.2/mocha.css">
</head>
<body>
<div id="main" class="hello test"></div>
<div id="mocha"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/chai/4.0.2/chai.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mocha/3.4.2/mocha.min.js"></script>
<script>
/**
* Add classes to an element
*/
const addClass = function(el, classes) {
// if element isn't defined, throw error
if(!el) {
throw new Error('no element provided');
}
// if element is a string, assume it's an ID and grab from DOM
if(typeof el === 'string') {
el = document.getElementById(el);
}
// if element isn't a DOM object at this point, something has gone wrong
if(!el || typeof el !== 'object' || el.nodeType !== 1) {
throw new Error('element is not in DOM', el);
}
// turn className value into an array of classes
const originalClasses = el.className.split(' ');
console.log(`originals: ${originalClasses}`);
console.log(`classes: ${classes.split(' ')}`);
const updatedClasses = getClasses(originalClasses, classes.split(' '));
console.log(`updatedClasses: ${updatedClasses}`);
// set the className value to the updated classes
el.className = updatedClasses;
}
// get the updated class list
const getClasses = function(originalClasses, classes) {
// if there isn't a change, return the original class list
if(!classes || !classes.length) {
return originalClasses;
}
// concatenate the originals with the potential ones to add
const classList = originalClasses.concat(classes);
console.log('classList: ', JSON.stringify(classList));
// convert the whole thing to a map so we only have each class once
const classMap = classList.reduce((map, className) => {
map[className] = true;
return map;
}, {});
console.log('classMap:', JSON.stringify(classMap));
// turn the map back into a string of class names,
// sorted (since order doesn't normally matter and we didn't maintain it)
// and joined together with spaces
return Object.keys(classMap).sort().join(' ');
}
// test runner
const { expect } = window.chai;
mocha.setup('bdd');
// tests
describe('adds classes', () => {
beforeEach(() => {
const main = document.getElementById('main');
main.className = 'hello test';
});
it('our test element exists', () => {
const main = document.getElementById('main');
expect(_.isElement(main)).to.be.true;
expect(main.className == 'hello test');
});
it('handles adding a class based on a selector', () => {
const main = document.getElementById('main');
addClass('main', 'hello testing');
expect(main.classList.contains('hello test testing'));
});
it('handles adding a class', () => {
const main = document.getElementById('main');
const originals = 'hello test';
const newList = 'gorilla alphabet etc';
addClass('main', newList);
expect(main.classList.length).to.be.equal(5);
`${originals} ${newList}`.split(' ').forEach(className => {
expect(main.classList.contains(className));
});
expect(main.classList.contains('monkey'));
});
it('handles adding a class based on a selector', () => {
const main = document.getElementById('main');
addClass('main', 'hello testing');
expect(main.classList.contains('hello test testing'));
});
it('handles adding a class based on a element', () => {
const main = document.getElementById('main');
addClass(main, 'hello testing');
expect(main.classList.contains('hello test testing'));
});
it('errors on an invalid class', () => {
expect(() => {
addClass('main1', 'hello testing')
}).to.throw();
});
it('errors on an invalid element', () => {
expect(() => {
addClass(document.getElementById('main1'), 'hello testing')
}).to.throw();
});
});
// run tests
mocha.run();
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment