ungap/custom-elements-builtin

Safari Version 13.0.4

gertcuykens opened this issue ยท 7 comments

Works in chrome but, I get blank screen on Safari without error message.

<!doctype html>
<html>

<head>
  <title>a</title>
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
  <meta name="mobile-web-app-capable" content="yes">
  <style>
    html,
    body {
      width: 100%;
      height: 100%;
      padding: 0;
      margin: 0;
      font-family: sans-serif;
    }

    *:not(:defined) {
      display: none;
    }
  </style>
  <script src="https://unpkg.com/@ungap/custom-elements-builtin"></script>
  <script type="module">
    import('./a.js').then(m => customElements.define('confirm-link', m.default, { extends: 'a' }))
    customElements.whenDefined('confirm-link').then(() => {
      const a = document.createElement('a', { is: 'confirm-link' })
      a.href = './'
      a.innerText = 'test'
      document.body.appendChild(a)
    })
  </script>
</head>

</html>

a.js

export default class ConfirmLink extends HTMLAnchorElement {
  connectedCallback() {
    this.addEventListener('click', e => {
      const result = confirm(`Are you sure you want to go to '${this.href}'?`)
      if (!result) e.preventDefault()
    })
  }
}

hmm ok thanks, going to find out why using modules it stops working. But I have a other example that doesn't work https://codepen.io/gertcuykens/pen/JjoqoLe?editors=0010 not related to the previeus one but stil related to Safari :P

In the last example seems like you are facing a constructor caveat. Try replacing const a = new ConfirmLink(); with let a = document.createElement('a', {is: 'confirm-link'});.

P.S. not sure if const is appropriate either here.

@gertcuykens precisely what @WebrealizerZS said, it's part of the little README everyone should read before filing bugs:
https://github.com/ungap/custom-elements-builtin#constructor-caveat

Create new elements via document.createElement('button', {is: 'my-button'}) but do not use new MyButton or incompatible browsers will throw right away because they made HTMLButtonElement and all others not usable as classes.

Closing this, as it's a non issue.

Thank you PS I did read it, but once you start experimenting with different examples it's easy to forget a part you once read a week ago. Anyway going to include the Safari error message here, just in case somebody paste it in google.
TypeError: function is not a constructor (evaluating 'super(...args)')

@gertcuykens understandable, but there are workarounds, where my favorite is:

customElements.define = (function ($define, property) {
  return function define(name, Class, options) {
    var result = $define.apply(this, arguments);
    if (!Class.hasOwnProperty('new')) {
      if (options && options.extends) {
        var $name = options.extends;
        var $options = {is: name};
        property(Class, 'new', {value: function () {
          return document.createElement($name, $options);
        }});
      }
      else {
        property(Class, 'new', {value: function () {
          return document.createElement(name);
        }});
      }
    }
    return result;
  };
}(
  customElements.define,
  Object.defineProperty
));

This allows you to use ConfirmLink.new() instead of new ConfirmLink, and it works with any kind of custom element definition.

@gertcuykens module published as @ungap/custom-elements-new utility