Search code examples
custom-element

Identifying a Customized Built-In Element without an is= attribute


In my Chessly.github.io project I use Customized Built-In IMG Elements to define SVG chesspieces:

Question: How can I distinguish a regular IMG from a customized IMG?

document.body.append(
  document.createElement("IMG", { 
    is: "white-queen"
  });
);

This creates a chesspiece, but does not set the is= attribute

I now explicitly set the is= attribute myself, but since this attribute does nothing and can be set to any value (I use is as an observed attribute in my Custom Element code) it is not a solid way to distinguish IMG elements from Customized IMG elements when walking the DOM.

If I promote a pawn (replace the img src)

<img is=white-pawn/>

with element.setAttribute("is","white-queen")

How can I determine the piece originally was the white pawn?
It still is a white-pawn in the Custom Elements registry.

Am I overlooking something?

Simplified code (with basic SVG shape) in JSFiddle: https://jsfiddle.net/dannye/k0va2j76/

Update: Code (based on correct answer below)

let isExtendedElement = x => 
      Object.getPrototypeOf(x).__proto__.constructor.name !== 'HTMLElement';

note! This does NOT catch Autonomous Custom Elements!

maybe better:

let isBaseElement = x =>
    Object.getPrototypeOf(Object.getPrototypeOf(x)).__proto__.constructor.name=='Element';

Solution

  • I think adding explicitly the is attribute is the best solution for now.

    Else you'll have to deal with the class reference. In your case:

    yourElement.constructor === customElements.get( 'circle-image' )
    yourElement.constructor === CircleImage //if it's the named class
    

    This supposes that you know the name of the custom elements you want to check.

    Else you'll have to go through the protoype chain:

    CircleImage --> HTMLImageElement --> HTMLElement --> Element --> Node

    If HTMLElement is only the father, it's a built-in element. If HTMLElement is the grandfather (or grand-grand...), it's probably an extended build-in element.

    update

    If you use a named class you can also retrieve its name:

    elem.constructor.name