3

I am trying to add this custom element to YouTube.

at first, I wrote in the console:

const script1 = document.createElement("script")
script1.type = "module"
script1.src = "https://unpkg.com/pose-viewer@0.0.4/dist/pose-viewer/pose-viewer.esm.js"
document.head.appendChild(script1)

and then:

document.createElement('pose-viewer')

but I got this error:

Uncaught TypeError: Class constructor a cannot be invoked without 'new' at new g (custom-elements-es5-adapter.js:11) at :1:10

so I compiled to es5:

const script1 = document.createElement("script")
script1.src = "https://unpkg.com/pose-viewer@0.1.2/dist/pose-viewer/pose-viewer.js"
document.head.appendChild(script1)

but I got this error:

Uncaught TypeError: Illegal invocation at n.f (pose-viewer.js:15) at Function.getOwnPropertyDescriptor (pose-viewer.js:15) at pose-viewer.js:44 at pose-viewer.js:58 at pose-viewer.js:130

What I am doing wrong? Why is this not working specifically on YouTube, but does work everywhere else?

Community
  • 1
  • 1
israelk
  • 61
  • 5
  • I assume that the script you are trying to add from `unpkg.com` is not written by you? Can you provide more information on that script? – Philipp Jul 20 '21 at 14:59
  • @Philipp The script was written by me. It is a custom element (web component) named `pose-viewer` written with Stencil. – Amit Jul 20 '21 at 16:08
  • Well, then the bug seems to be in your own script. Did you try to upload a non-minified version and debug it? – Philipp Jul 20 '21 at 16:16
  • The script runs just fine in other websites, just like OP said, not in YouTube. From further debugging, seems like YouTube are using some sort of script `custom-elements-es5-adapter` which messes up proper custom elements, – Amit Jul 20 '21 at 16:19
  • Looks like it's a polyfill used in Polymer: https://polymer-library.polymer-project.org/2.0/docs/polyfills – Thomas Jul 22 '21 at 08:49

1 Answers1

1

If you look at the source of the https://unpkg.com/pose-viewer@0.1.2/dist/pose-viewer/pose-viewer.js you'll see that is transpiled to ES5, however the custom elements should be defined in ES6, ex:

class MyElement extends HtmlElement {}

more info about the adapter here :

https://www.npmjs.com/package/@webcomponents/webcomponentsjs#custom-elements-es5-adapterjs

You just need to follow the error message and add this to your html before you run your script:

<script src="https://unpkg.com/@webcomponents/webcomponentsjs@2.5.0/custom-elements-es5-adapter.js"></script>

Update

If you are using the esm script, you don't need the adapter as the script is using es6 syntax.

you can load the script as a module:

<!DOCTYPE html>
 <html>
<head>
      <meta charset="utf-8">
      <meta name="viewport" content="width=device-width">
      <title>pose viewer example</title>
</head>
<body>
<script src="https://unpkg.com/pose-viewer@latest/dist/pose-viewer/pose-viewer.esm.js" type="module"></script>
<pose-viewer></pose-viewer>
</body>
</html>

Or if you want to import it from another js script you just need to add an import statement

Where the html might look like this:

<!DOCTYPE html>
 <html>
<head>
      <meta charset="utf-8">
      <meta name="viewport" content="width=device-width">
      <title>pose viewer example</title>
</head>
<body>
<script src="./index.js" type="module"></script>
</body>
</html>

And the script like this :

  import "https://unpkg.com/pose-viewer@latest/dist/pose-viewer/pose-viewer.esm.js";
 const x = document.createElement('pose-viewer');
 document.body.appendChild(x);

Update

To load it into the youtube website via the console you need to use the new operator, using the esm module the loading part looks like this

 const script = document.createElement('script')
 script.setAttribute('type', 'module');
 script.setAttribute('src', 'https://unpkg.com/pose-viewer@0.0.4/dist/pose-viewer/pose-viewer.esm.js' );
 document.body.appendChild(script);

Then get the class from the customElement registry and invoke it with new:

 const PoseViewer = customElements.get('pose-viewer');
 new PoseViewer();
Tiberiu C.
  • 3,365
  • 1
  • 30
  • 38
  • Thanks. When including the es6 bundle with `esm`, one gets an "Illegal invocation" on the `attachShadow` call. However, it works on any other website not including that adapter. – Amit Jul 26 '21 at 09:34
  • There is a note that this adapter doesn't need to be transpiled, the script must be loaded as is into the page. on our corporate project we still use es5 bundles transpiled from typescript. I added the script to the bundle and it works without issues – Tiberiu C. Jul 26 '21 at 11:40
  • I'm not sure I understand - sorry. I added the unpkg script you noted before loading, and tried loading the transpiled es5 `pose-viewer` or the original `esm` version of `pose-viewer`, but both fail, and I'm not sure what you are suggesting we should do. – Amit Jul 26 '21 at 11:54
  • In which browser are you tring to make it work? – Tiberiu C. Jul 26 '21 at 14:14
  • I'm trying to make it work in the latest Chrome – Amit Jul 26 '21 at 17:43
  • https://jsbin.com/fediyav/edit?html it seems to initialize the component with both document.createElement and directly into the htnl – Tiberiu C. Jul 30 '21 at 07:57
  • Thanks. I know it works by itself, the problem is that I'm trying to inject this element to YouTube, and they are using this polyfill. How can I inject my element to YouTube despite having that polyfill there? – Amit Jul 30 '21 at 09:18
  • What do you mean adding it to YouTube, are you trying to add the script to https://youtube.com via the console ? – Tiberiu C. Aug 02 '21 at 06:44
  • 1
    Now I understood your question,, I have updated my answer – Tiberiu C. Aug 02 '21 at 06:59