Search code examples
javascripthtmlcodepen

How to dynamically add codepen embed and ensure it is rendered?


Desired Behaviour

Show embedded codepen in an environment where registered users can edit page content.

There may be more than one codepen added to a page.

Actual Behaviour

When adding a pen to the DOM, the pen does not display, only a link to the pen is displayed.

Steps To Reproduce

Note: the steps below are just to demonstrate the logic that would take place in my own environment, ie a registered user editing content on a website.

01) Go to this randomly selected pen
02) Click on the Embed link at the bottom right of the page
03) Copy contents from the HTML (recommended) tab
04) Go to https://blog.codepen.io/documentation/features/embedded-pens
05) Open Chrome developer tools, and replace a paragraph element with the embed code
06) The pen will not be displayed, only a link like:

See the Pen [pen_name] by [pen_author] on CodePen  

Question

What additional steps do I need to make to ensure the codepen is rendered?

Given that the format of the embed code is:

<p class="codepen" data-height="300" data-theme-id="37516" data-default-tab="css,result" data-user="ste-vg" data-slug-hash="oKYjKV" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="Clip Clop Clippity Clop">
    <span>See the Pen <a href="https://codepen.io/ste-vg/pen/oKYjKV/">
            Clip Clop Clippity Clop</a> by Steve Gardner (<a href="https://codepen.io/ste-vg">@ste-vg</a>)
        on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

it does seem a bit presumptuous to expect the script will just do its job when pasted in the page.

If that is the case, how do I dynamically add the contents (including the script tag) and ensure it is executed?

EDIT

I just came across this answer from 2010, which suggests this format:

$.getScript("https://static.codepen.io/assets/embed/ei.js", function(){
    console.log("running new js!");
});

and when I run that in Chrome dev tools, after pasting the embed code in the DOM, the pen is rendered.

  • Is there anything wrong with this approach?
  • Why doesn't pasting the embed code in the DOM 'just work'?
  • Is the script file referenced in the embed code unique to the pen?
  • Or could you just add the script to your page once and it would handle all embedded pens (both existing and those dynamically added)?

I tried adding this to <head>:

<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

and having it there doesn't seem to parse existing or dynamically added embed code.

They still just display the message:

See the Pen [pen_name] by [pen_author] on CodePen    

EDIT AGAIN

With script referenced in <head>, I tried calling this after dynamically adding the HTML to the DOM:

__CPEmbed()

And it renders the codepens!

I'm not sure if it is a legitimate way to do it, but I came across __CPEmbed at the end of the article here:

https://blog.codepen.io/documentation/prefill-embeds


Solution

  • I see you've figured it out! Yes, __CPEmbed() is the official API for triggering the iframe insertion. You can even feed it a specific selector if there are certain embeds you want to target: __CPEmbed('.my-codepen-embed')

    It's triggered by default when the document.readyState !== 'loading', but you can call it at any time. Multiple calls should not affect already converted embeds.

    I couldn't find this in our regular Embed documentation anymore, so I'm making a note to update that.

    Thanks!