Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Permit retrieval of registered classes from window.customElements #445

Closed
JanMiksovsky opened this issue Mar 16, 2016 · 26 comments
Closed

Comments

@JanMiksovsky
Copy link

Following up on issue #431, I'd like to propose that window.customElements allow a dev to retrieve information about the custom elements which have been registered. It sounds like @domenic was supportive of this idea, so as a strawman, I propose adding the following:

  • window.customElements.get(name). Returns the class which was previously registered with define(name), or undefined if no element has yet been registered with that name.
  • window.customElements[@@iterator](). This returns a new Iterator object that enumerates the [name, class] pairs registered. I don't particularly care in what order the entries are returned. For consistency with Map.prototype[@@iterator](), it would be nice to return these in the order in which they were defined.

This, at least would meet the needs I've encountered, chiefly being able to: 1) easily verify that a particular custom element has in fact been registered, 2) conditionally define an element if it hasn't already been registered. E.g.:

if (!window.customElements.get('my-element')) {
  window.customElements.define('my-element', MyElement);
}
@domenic
Copy link
Collaborator

domenic commented Mar 16, 2016

A couple questions:

  1. What is the use case for iteration?
  2. Is it a problem that get(name) returns only the constructor, and not any of the other relevant information? Most interestingly, I imagine, whether or not it's a type extension and if so of what.

@annevk
Copy link
Collaborator

annevk commented Mar 17, 2016

It should probably also return the callbacks stored by the user agent... Or at least we should have the option to do that if we think it's useful at some point.

@domenic
Copy link
Collaborator

domenic commented Mar 17, 2016

Maybe .get() just gets the constructor, and .getDefinition() gets an object representing the definition?

Anyway, who's interested in implementing this if I spec it? @rniwa @kojiishi ... trying to Will Chen's GitHub handle...

@rniwa
Copy link
Collaborator

rniwa commented Mar 17, 2016

I don't want to support customElements[@@iterator] but providing a mechanism to get the definition seems fine to me.

@JanMiksovsky
Copy link
Author

To answer @domenic's question: I think the iterator would be generally useful for tools/extensions that want to list the elements which have been registered. But I don't have a pressing need for it right now. If the iterator is hard, it's by no means required for v1.

@rianby64
Copy link
Contributor

Let's consider an example for the iterator:

// somewhere else were defined MyElement1, MyElement2... and so on
window.customElements.define('my-element1', MyElement1);
window.customElements.define('my-element2', MyElement2);

// then, let's play with Iterator...
var alreadyDefined = window.customElements; // 
for (var customElement of alreadyDefined) {
  console.dir(customElement);   // should I see here MyElement1, MyElement2?
}

What about if somewhere else we've imported a custom element that registers some new custom elements?

<link rel="import" href="myExamples.html"> <!-- here we define more custom elements? -->

Remember that all imports don't have context.

What are the pros and cons if have a table with all registered custom elements?
If it's needed I'd like to check this table from a clear place... for example

var defined = window.customElements.definitions;
for (var customElement in defined) {
   console.dir(customElement);
}

And if check if an element already was registered.

if (!window.customElements.definitions.getItem('my-element1')) { 
  // ...
}

The above is following the convention given for Attributes.

@annevk
Copy link
Collaborator

annevk commented Mar 21, 2016

I don't think we can consider HTML imports as a use case given that nobody but Chrome wants to implement it.

@rianby64
Copy link
Contributor

@annevk Let's not consider HTML imports, but let's consider what @JanMiksovsky proposed: window.customElements[@@iterator]()
What about if manipulate the defined custom elements via window.customElements.definitions?
I think that the existing structure for Element.attributes fits good to window.customElements.definitions. Here we've the possibility to define functions like hasDefinition(), getDefinition() and so on. I hope that has sense.

@rianby64
Copy link
Contributor

@annevk Thanks a lot.
By the way. I found that the example about how to import html via link looks simple. But also I see that HTML import draft offers different ways to import html. I'll read the manuals and take your advice in count.

@domenic
Copy link
Collaborator

domenic commented Mar 21, 2016

I don't see any reason to create anything as complex as Element.prototype.attributes when nobody so far has stated a use case. (Although @JanMiksovsky gave a "tools/extensions" use case, that's probably better served by extensions APIs, not web platform APIs.)

@rianby64
Copy link
Contributor

@domenic I see you noticed that Element.prototype.attributes is a complex thing. Let me write some ideas.

A CustomElementsRegistry's list of defined local names is the list containing all of the local names of the custom element definitions in the registry.

  1. As mentioned at "2.4 The CustomElementsRegistry interface" the window.customElements is a list.
  2. As mentioned at "3.1 HTML+: The Window object" I see that window.customElements is an instance of "2.4 The CustomElementsRegistry interface".

Then,

  1. Is it necessary to expose the list from the registry?
  2. If expose it, should be used the root element window.customElements?

I think that to expose the list of defined custom elements should be used an extra attribute... something like

window.customElements.definitions
// or
window.customElements.elements
// or something similar

But...
The same name window.customElements states that we're working with custom elements.
So. We've an object window.customElements that

  1. defines new custom elements
  2. behaves like a list

@domenic
Copy link
Collaborator

domenic commented Mar 21, 2016

I am supremely uninterested in the API shape. What I am interested in is use cases. It's probably not worth your time bikeshedding the former.

@rianby64
Copy link
Contributor

Ok. The use cases will drive us to this conversation at some point.

@jarek-foksa
Copy link

In case every standard element gets its own constructor as discussed in whatwg/html#896, wouldn't it make more sense to have a registry that includes both standard and custom elements? Sample use cases:

const SUPPORTS_PICTURE = document.elements.has("picture");
const SUPPORTS_SMIL = document.elements.has("animate");
const SUPPORTS_MATHML = document.elements.has("math");
const SUPPORTS_MESH_GRADIENTS = document.elements.has("mesh");

@domenic
Copy link
Collaborator

domenic commented Mar 24, 2016

@jarek-foksa can you explain what the use case for that is? If it's about figuring out support, you can do that just as easily by testing for 'HTMLPictureElement' in window etc.

@jarek-foksa
Copy link

@domenic This looks rather inconsistent to me:

if (window.HTMLPictureElement) {
  let picture = document.createElement("picture");
}

I would prefer to have a choice of either constructor-based or name-based APIs that I could use consistently:

// Name-based approach
if (document.elements.has("picture")) {
  let picture = document.elements.create("picture");
}

// Constructor-based approach
if (window.HTMLPictureElement) {
  let picture = new HTMLPictureElement();
}

@domenic
Copy link
Collaborator

domenic commented Mar 24, 2016

I don't see any need to introduce an entire new registry API surface just to fix some aesthetic inconsistency.

@rianby64
Copy link
Contributor

I think that @domenic desires to see a very short way to check if a custom element was defined or not. What about if

var check = document.querySelector('my-custom-element');
if (check) {
  console.log('my-custom-element already defined');
}

@annevk
Copy link
Collaborator

annevk commented Apr 4, 2016

Is this needed for v1?

@rniwa
Copy link
Collaborator

rniwa commented Apr 4, 2016

It seems like this is a v2 feature although it has a very high benefit-to-cost ratio so I'd consider adding this earlier than other v2 features.

@domenic
Copy link
Collaborator

domenic commented Apr 5, 2016

Untagging needs-consensus as it seems like this has consensus at least in its basic form. I'll spec .get(name) soon.

@rianby64
Copy link
Contributor

rianby64 commented Apr 5, 2016

Please, let's summary. I'd like to understand the thread 😄
.get(name) means window.get(name) or document.get(name)?

The current documentation states:

window.define('name', ClassName)

So,

window.get('name') should return ClassName. Right?

Should you consider to name that function in a more specific way?
I see that window has already some getters

window.getComputedStyle;
window.getSelection;
window.getMatchedCSSRules;

Does have sense to name the function to getDefinition ? It's just an opinion... If getDefinition is too long then get sounds good too.
Thanks!

@domenic
Copy link
Collaborator

domenic commented Apr 5, 2016

It's window.customElements, not document or window.

There's no getDefinition for now, just get.

@rianby64
Copy link
Contributor

rianby64 commented Apr 5, 2016

Ah 😄 excelente!
So, window.customElements.get('name') returns ClassName. Understood. Thanks a lot.

domenic added a commit to whatwg/html that referenced this issue Apr 8, 2016
@domenic
Copy link
Collaborator

domenic commented Apr 8, 2016

This is included in whatwg/html#1012.

@annevk
Copy link
Collaborator

annevk commented Apr 16, 2016

\o/

@annevk annevk closed this as completed Apr 16, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants