Created
July 1, 2017 02:07
-
-
Save calvinf/b9b87dab5b340921bc3b0b868d1ea025 to your computer and use it in GitHub Desktop.
Add Classes (without using classList or jQuery)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!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