Last active
July 8, 2019 19:41
-
-
Save jjspace/a370212cee9dae27e5c1313654553ed0 to your computer and use it in GitHub Desktop.
Better DOM createElement and style
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
/** | |
* Add a new stylesheet to this page with the provided rules | |
* Rules should be an array of the form: | |
* [['selector string', { *rules object* }]] | |
* where rules object is: | |
* { property: 'value', ...} | |
* property names are camelCase versions of css properties | |
* for example the prop 'background-color' would become 'backgroundColor' | |
* @param {Array} rules | |
* @example | |
addStylesheet([ | |
['h2', { | |
color: 'red', | |
backgroundColor: 'green !important', | |
}], | |
['.myclass', { | |
backgroundColor: 'yellow' | |
}] | |
]); | |
*/ | |
const addStylesheet = (rules) => { | |
const styleEl = document.createElement('style'); | |
styleEl.id = 'customSheet'; | |
document.head.appendChild(styleEl); | |
const styleSheet = styleEl.sheet; | |
rules.forEach((rule) => { | |
const [selector, props] = rule; | |
let propStr = Object.entries(props).reduce((acc, [prop, val]) => { | |
return acc + prop.replace(/[A-Z]/g, (m) => '-'+m.toLowerCase()) + `:${val};`; | |
}, ''); | |
styleSheet.insertRule(`${selector}{${propStr}}`, styleSheet.cssRules.length); | |
}); | |
return styleSheet; | |
} | |
// Add ability to style elements with an object of styles | |
const styleElem = (elem, style) => { | |
let newElem = elem.cloneNode(true); | |
Object.entries(style).forEach((prop) => { | |
let [name,val] = prop; | |
// convert kebab to camelCase | |
name = name.replace(/\-(\w)/g, (m)=>`${m[1].toUpperCase()}`); | |
// set val | |
if (name in elem.style) { | |
newElem.style[name] = val; | |
} else { | |
throw new Error(`${name} is not a valid style property`); | |
} | |
}); | |
return newElem; | |
} | |
// replace document.creatElement with function inspired by emmet | |
// to quickly set class, id, and inner text | |
const createElement = (emmetLike) => { | |
// extract element type, default to div | |
let elemTypeMatch = emmetLike.match(/^[a-zA-Z0-9-]+/); | |
let elemType = elemTypeMatch ? elemTypeMatch[0] : 'div'; | |
// extract text | |
let textContext = ''; | |
let textContextMatch = emmetLike.match(/\{(.+)\}/); | |
if (textContextMatch) { | |
textContext = textContextMatch[1]; | |
emmetLike = emmetLike.replace(textContextMatch[0], ''); | |
} | |
// extract id | |
let idMatch = emmetLike.match(/#([^\s\.\{\}]+)/); | |
let id = idMatch ? idMatch[1] : ''; | |
// extract classes | |
let classMatch = emmetLike.match(/\.-?[_a-zA-Z]+[_a-zA-Z0-9-]*/g); | |
let className = classMatch ? classMatch.join('').replace(/\./g, ' ').trim() : ''; | |
let elem = document.createElement(elemType); | |
if (id) { elem.id = id; } | |
if (className) { elem.className = className; } | |
if (textContext) { elem.appendChild(document.createTextNode(textContext)); } | |
return elem; | |
} | |
console.log(createElement(`.class.class-2#id-the-second{${'hello'}}.extra`)); | |
console.log(createElement(`{${'hello'}}.class.class-2#id-the-second.extra`)); | |
console.log(createElement(`.class.class-2{${'hello'}}#id-the-second.extra`)); | |
console.log(createElement(`button.submit`)) | |
console.log(createElement(`ul`)) | |
console.log(createElement('p{this is some text. I like talking about things. docs are fun like object.entries}')) | |
console.log(createElement(`.class-1#item.class-2`)) | |
let itemName = document.createElement('div'); | |
itemName.className = 'item-name'; | |
itemName.innerText = 'testing; | |
console.log(itemName); | |
console.log(createElement(`.item-name{testing}`)) | |
let itemName2 = styleElem(itemName, { | |
position: 'absolute', | |
background: 'red', | |
'font-family': 'monospace', | |
flex: 1, | |
top: '30px', | |
}); | |
console.log(itemName2); | |
console.log(itemName2.style); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment