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

Better embed, YT #138

Open
jensens opened this issue Oct 7, 2022 · 0 comments
Open

Better embed, YT #138

jensens opened this issue Oct 7, 2022 · 0 comments

Comments

@jensens
Copy link
Member

jensens commented Oct 7, 2022

To not forget about it I create this issue.
FTR:

I wrote an alternative embed tile for a customer last year and now I need it again. The current embed tile was not sufficient in both case.
It is very simple and provides a tile with 100% width in its row, aspect ration kept, settings kept. You just need to paste the Youtube embed code into a text field.

This could be extended for similar video embeds (Iframe based).

Here is the code

from plone.supermodel.model import Schema
from plone.tiles import Tile
from zope import schema
from lxml import etree
from lxml import html

import logging

logger = logging.getLogger(__name__)


class IYTEmbedTile(Schema):
    """Youtube Embed tile."""

    media_embed = schema.Text(title="Youtube Media Embed code", required=True)


class YTEmbedTile(Tile):
    """A tile that embeds Youtube."""

    def __call__(self):
        # parse embed code
        embed_code = self.data.get("media_embed")
        try:
            parsed = html.fromstring(
                '<div class="youtube-responsive-wrapper">{}</div>'.format(embed_code)
            )
        except Exception:
            logger.exception(f"Embed parsing problem with:\n{embed_code}")
            return "<div>Malformated embed code</div>"
        children = parsed.getchildren()
        if not (
            children
            and len(children) == 1
            and children[0].tag == "iframe"
            and "src" in children[0].attrib
            and "youtube" in children[0].attrib["src"]
        ):
            return "<div>Invalid embed code (no iframe)</div>"
        iframe = children[0]
        if not ("height" in iframe.attrib and "width" in iframe.attrib):
            return "<div>Invalid embed code (measures missing)</div>"
        try:
            height, width = int(iframe.attrib["height"]), int(iframe.attrib["width"])
        except Exception:
            return "<div>Invalid embed code (measure no numbers)</div>"
        del iframe.attrib["height"]
        del iframe.attrib["width"]
        parsed.attrib["style"] = f"padding-bottom: {(height/width)*100}%"
        new_iframe = etree.tostring(parsed, pretty_print=True).decode("utf8")
        return f"<html><body>{new_iframe}</body></html>"

ZCML:

  <!-- ytembed tile  -->
  <plone:tile
      name="kup.tiles.ytembed"
      title="YT Embed"
      description="Paste an Youtube embed code and get an tile-width video"
      for="*"
      schema=".ytembed.IYTEmbedTile"
      class=".ytembed.YTEmbedTile"
      permission="zope2.View"
      add_permission="cmf.ModifyPortalContent"
      />

Styles:

      .youtube-responsive-wrapper {
        position: relative;
        padding-top: 0;
        height: 0;
        overflow: hidden;
        iframe {
          position: absolute;
          top: 0;
          left: 0;
          width: 100%;
          height: 100%;
        }
      }

Also some registry.xml was needed:

  <record name="plone.app.tiles">
    <field type="plone.registry.field.List">
      <title>Tiles</title>
      <value_type type="plone.registry.field.TextLine" />
    </field>
    <value purge="false">
      <element>kup.tiles.ytembed</element>
    </value>
  </record>
  <records interface="plone.app.mosaic.interfaces.ITile"
           prefix="plone.app.mosaic.app_tiles.kup_tiles_ytembed"
  >
    <value key="name">kup.tiles.ytembed</value>
    <value key="label">YT Embed</value>
    <value key="category">media</value>
    <value key="tile_type">app</value>
    <value key="default_value" />
    <value key="read_only">false</value>
    <value key="settings">true</value>
    <value key="favorite">false</value>
    <value key="rich_text">false</value>
    <value key="weight">21</value>
  </records>
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

1 participant