Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to inherit from the DOM element class

I want to write some Javascript classes which extend DOM nodes (so that I can then insert instances of my class directly into the DOM), but am having difficulty finding out which class/prototype I should inherit from.

E.g.:

function myExtendedElement() {
       this.superclass = ClassA;
       this.superclass();
       delete this.superclass;
} 

But what should ClassA be?

like image 378
wheresrhys Avatar asked Sep 28 '09 22:09

wheresrhys


2 Answers

In 2020, you can easily create a custom element by extending HTML elements.

class AppDrawer extends HTMLElement {...}
window.customElements.define('app-drawer', AppDrawer);

// Or use an anonymous class if you don't want a named constructor in current scope.
window.customElements.define('app-drawer', class extends HTMLElement {...});

More info and reference: Custom Elements

like image 74
Reza Avatar answered Oct 13 '22 01:10

Reza


Old Q but there's a better answer than "Do" or "Don't" now that IE6 is mostly defunct. First of all prototyping core ECMA endpoint-inheritance constructors like 'Array' is pretty harmless and useful if you do it properly and test to avoid breaking existing methods. Definitely stay away from Object and think real hard before messing with Function, however.

If you're sharing code between a lot of people/authors, or dealing with DOM uncertainty, however, it's typically better to create adapter/wrapper objects with a new factory method to use in an inheritance-scheme.

In this case I wrote document.createExtEl to create wrapped DOM elements whose accessible properties are all available via prototype.

Using the following, your "superclass" for divs would be HTMLExtDivElement (in this case globally available - ew, but it's just an example). All references to the original HTMLElement instance's available properties live inside the wrapper's prototype. Note: some old IE properties can't be passed as references or even accessed without throwing errors (awesome), which is what the try/catch is for.

You could normalize common properties by adding logic to put missing or standardized properties in right after the loop wraps instance-available properties but I'll leave that to you.

Now for the love of Pete, don't ever use my code to write some cascading 16-times inheritance foolishness and then implement in some ironically popular library we're all forced to deal with or I will hunt you down and loudly quote "Design Patterns" at you while throwing rotten fruit.

//Implementation just like document.createElement()
//document.createExtEl('div').tagName === 'DIV'

document.createExtEl = ( function(){  //returns a function below

            var htmlTags = ['div','a'], //... add all the element tags you care to make extendable here
            constructorMap = {},
            i = htmlTags.length;

            while(i--){
                thisTag = htmlTags[i].toLowerCase();
                constructorMap[ thisTag ] = function(){
                    var elObj = document.createElement(thisTag),
                    thisProto = this.constructor.prototype,
                    constructorName = 'HTMLExt' + thisTag.charAt(0).toUpperCase() + thisTag.slice(1) + 'Element';

                    alert(constructorName);

                    window[constructorName] = this.constructor; //adds a global reference you can access the new constructor from.

                    for(var x in elObj){ try{ thisProto[x] = elObj[x]; } catch(e){} }
                }
            }

            //all of the above  executes once and returned function accesses via closure
            return function(tagName){
                return new constructorMap[tagName.toLowerCase()]();
            }



    } )()

    //Now in the case of a superclass/constructor for div, you could use HTMLExtDivElement globally
like image 24
Erik Reppen Avatar answered Oct 13 '22 01:10

Erik Reppen