6 ms·
Instead of the loop, you can just use: Object.assign(elem, props). I found I wanted a more data-driven style that matched the element types themselves, so I
by akira2501 6y ago
Instead of the loop, you can just use: Object.assign(elem, props). I found I wanted a more data-driven style that matched the element types themselves, so I use the somewhat more cumbersome:
// data driven HTMLElement creation
var $element = function(type, p={}) {
let h, elem = document.createElement(type);
if (!p || (typeof(p) !== "object")) {
elem.innerHTML = p || '';
return(elem);
}
h = p.attributes; delete p.attributes; if (h) for (let e of Object.entries(h)) { elem.setAttribute(e[0],e[1]) }
h = p.classList; delete p.classList; if (h) for (let c of h) { elem.classList.add(c) }
h = p.dataset; delete p.dataset; if (h) Object.assign(elem.dataset, h);
h = p.style; delete p.style; if (h) Object.assign(elem.style, h);
h = p.innerHTML; delete p.innerHTML; if (h) elem.innerHTML = h;
h = p.children; delete p.children; if (h) for (let ch of h) { if (ch) elem.appendChild(ch) }
h = p.parentNode; delete p.parentNode; if (h) h.appendChild(elem);
h = p.event; delete p.event; if (h) for (let e of Object.entries(h)) { elem.addEventListener(e[0],e[1]) }
return(Object.assign(elem, p));
};
- ryanbrunner 6y agoNeat solution - out of curiosity though, why remove the properties from the passed options? If I called that function, I wouldn't normally expect it to mutate my arguments like that.
- hombre_fatal 6y agoAt a glance, they do it so that at the end they can merge in any remaining props they didn't handle after all their work building `elem` is done. This can be accomplished non-destructively with destructuring. const { attributes, classList, style, ...rest } = p // elem = ...consume attributes, classList, style... return Object.assign(elem, rest)
- enlyth 6y agoThis approach with destructuring is great but you will need to transpile the code if you're targeting IE11 which is still often the case in enterprise settings unfortunately.
- CodesInChaos 6y agoUsing innerHTML as default if the second argument isn't an object risks XSS vulnerabilities. I'd prefer innerText for as default.
- codemonkey-zeta 6y agoWhat XSS vulnerability? Any user can set the innerHTML of any element at any time.
- doomslice 6y agohttps://portswigger.net/web-security/cross-site-scripting/stored https://portswigger.net/web-security/cross-site-scripting/st... You protect against someone else abusing it on other users.
- reificator 6y ago> What XSS vulnerability? Any user can set the innerHTML of any element at any time. This mindset right here is exactly why XSS is still an issue. If you pull user generated content and put it in the DOM like this, you will open your users to XSS from other users. Basing your personal use DOM APIs on setting `el.innerHTML` will lead to a slip-up. Use `textContent` by default.
- cptskippy 6y agoOften times you write code to defend against other developers who don't know any better.
- fardelian 6y agoMost of the time I write code to defend against future me, because I know that in a few days I'll have forgotten half of the code along with all the optimization hacks in it.
- codemonkey-zeta 6y agoOh my, of course. My assumption was that this function would not be used with dynamic, possibly user-defined input. This is small-scale thinking, and obviously if you intend for this code to be reused then this case must be accounted for. I'm pretty terrified that I was able to look at this code and have that assumption, even though I know better. I've even caught and resolved a couple XSS vulnerabilities at companies I've worked for. What does this say about me? Maybe another question to ask is, what does this say about the value of a web framework?