I was wondering if I can create a subclass of HTMLDivElement. Like this.
MyDivElement.prototype.pickColor = function()
{
return this.picked;
}
function M
I'm experimenting with this a little bit. A big difficulty is that you need the context of a document to create an element. You can go with window.document as a default, but that's boring.
Here's the POC I'm working on:
function CustomNode(type, parent) {
if (type instanceof Node) {
// Decorate a preexisting node appropriately if called that way.
if (arguments.length === 2 && type.ownerDocument !== parent) {
// Import the node if it's not owned by the requested document.
type = parent.importNode(type, true);
}
return Object.assign(type, this.__proto__);
}
//Normal flow, e.g., new CustomNode("div");
var d = document;
if (parent) {
// Alt document flow, e.g., new CustomNode("div", xmlDoc);
if (parent.nodeType === 9) {
d = parent;
} else {
// Support for new CustomNode("div", parentElement);
// This doesn't append the element, just makes sure
// the documents match
d = parent.ownerDocument;
}
}
var inst;
// Creation flags
if (type[0] === '#') { //text
inst = d.createTextNode(type.substr(1));
} else if (type[0] === '?') { //Processing instruction
type = type.substr(1).split(' ');
inst = d.createProcessingInstruction(type.shift(), type.join(' '));
} else if (type[0] === '[') { // CDATA
inst = d.createCDATASection(type.substr(1));
} else if (type[0] === '/') { // Comment
inst = d.createComment(type.substr(1));
} else { //Everything else gets an element.
inst = d.createElement(type);
}
// DE-COR-ATE
Object.assign(inst, this.__proto__);
return inst;
}
// Decorator for customized NodeLists; probably inefficient. Decorates
// contents with CustomNode
function CustomNodeList(list) {
var Self = this.constructor,
CNode = this.Node;
return Object.assign([].map.call(list, function (node) {
return new CNode(node);
}), this.__proto__);
}
CustomNodeList.prototype = {
// so we know how to wrap...
Node: CustomNode,
text: function () {
return this[0].textContent;
}
};
CustomNode.prototype = {
// So we know how to decorate NodeLists
NodeList: CustomNodeList,
// So we know how to decorate Nodes
Node: CustomNode,
// Easy make-and-attach
new: function (type, attach) {
var CNode = this.Node;
var ret = new CNode(type, this.ownerDocument);
if (attach) {
this.appendChild(ret);
}
return ret;
},
// NodeLists with ES5 iterators!
find: function () {
var CNodeList = this.NodeList;
return new CNodeList(this.querySelectorAll.apply(this, arguments));
},
kids: function () {
var CNodeList = this.NodeList;
return new CNodeList(this.childNodes);
}
};
Mind, this is likely a bad idea: everything in the same scope of these functions (including the elements themselves) will never get garbage collected, as the GC in most browsers is dead-stupid when it comes to elements referencing objects. I'll never use it for production for that reason alone: it's a straight-up memory leak.