document.createElement('div');
Returns:
<div></div>
document.createElement('div#id.class1.class2');
document.createElement('div', {
id: 'id',
className: 'class1 class2'
});
Both Return:
<div id="id" class="class1 class2"></div>
Passing the { id: 'id', className: 'class1 class2' }
overrides the string passed div#id.class1.class2
.
So DON'T USE BOTH
document.createElement('div', {
'attributes': {
'id': 'id',
'class': 'class1 class2',
'data-index': 1
},
'dataset': {
'num': 5
},
'style': {
'color': 'lightblue',
'background': 'lightgrey',
'fontSize': '20px'
},
'innerHTML': '<h1 class="text">Hello World</h1>',
'onclick': function() {...}
// etc
});
Returns:
<div id="id" class="class1 class2" data-index="1" data-num="5" style="color: rgb(173, 216, 230); font-size: 20px; background: rgb(211, 211, 211);">
<h1 class="text">Hello World</h1>
</div>
var cachedCreateElement = Document.prototype.createElement;
Document.prototype.createElement = function(tagName, props) {
var splitTagName = tagName.match(/(^|[\.\#])[^\.\#]*/g);
var element = cachedCreateElement.call(this, splitTagName[0]);
for(var i = 0, l = splitTagName.length; i < l; i++ ) {
var str = splitTagName[i];
if(str[0] === '#') {
element.id = str.slice(1);
} else if(str[0] === '.') {
element.classList.add(str.slice(1));
}
}
for(var prop in props) {
switch(prop) {
case 'attributes':
for(var attr in props[prop]) element.setAttribute(attr, props[prop][attr]);
break;
case 'dataset':
case 'style':
for(var key in props[prop]) element[prop][key] = props[prop][key];
break;
default:
element[prop] = props[prop];
break;
}
}
return element;
}
This would not have to be like this if the one property attributes
on the Element.prototype
was changed to work differently:
As of right now the following is not possible:
document.body.attributes.index = 1;
And have the body look like this:
<body index="1"></body>
Why? because the attributes
property is the only one that I can find on Elements that return this:
document.body.attributes;
//returns:
NamedNodeMap {0: index}
Meaning there indexed for some weird reason.
Now if that were changed we could have document.createElement()
work like this:
var cachedCreateElement = Document.prototype.createElement;
Document.prototype.createElement = function(tagName, props) {
var splitTagName = tagName.match(/(^|[\.\#])[^\.\#]*/g);
var element = cachedCreateElement.call(this, splitTagName[0]);
for(var i = 0, l = splitTagName.length; i < l; i++ ) {
var str = splitTagName[i];
if(str[0] === '#') {
element.id = str.slice(1);
} else if(str[0] === '.') {
element.classList.add(str.slice(1));
}
}
for(var prop in props) {
var p = props[prop];
if(p.constructor === Object) {
for(var key in p) element[prop][key] = p[key];
} else if(p.constructor === Array) {
for(var i = 0, l = p.length; i < l; i++) element[prop][i] = p[i];
} else {
element[prop] = p;
}
}
return element;
}
Well this is the way I'd do it, I'm not sure how browsers would natively do it.
What you'd have to keep in mind is if a property is not settable normally:
var div = document.createElement('div'); // Using original method
div.parentElement = document.body; // This doesn't work
// So no point in doing this:
document.createElement('div', {
parentElement: document.body,
// or
parentNode: document.body
});
Properties that aren't natively settable will not be set.