PageSourceSearch

https://www.carmel.ac.uk/wp-content/plugins/carbonneutral/assets/video/vimeo-lite.js?ver=3.7.0

js carmel.ac.uk collected 2026-10-04 13:33:47 UTC 6,141 bytes, 161 lines download raw bytes

1/**
2 * Ported from https://github.com/paulirish/lite-youtube-embed
3 *
4 * A lightweight vimeo embed. Still should feel the same to the user, just MUCH faster to initialize and paint.
5 *
6 * Thx to these as the inspiration
7 *   https://storage.googleapis.com/amp-vs-non-amp/youtube-lazy.html
8 *   https://autoplay-youtube-player.glitch.me/
9 *
10 * Once built it, I also found these:
11 *   https://github.com/ampproject/amphtml/blob/master/extensions/amp-youtube (👍👍)
12 *   https://github.com/Daugilas/lazyYT
13 *   https://github.com/vb/lazyframe
14 */
15class LiteVimeo extends HTMLElement {
16    constructor () {
17        super();
18        // TODO: support dynamically setting the attribute via attributeChangedCallback
19    }
20
21    connectedCallback () {
22        // Gotta encode the untrusted value
23        // https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html#rule-2---attribute-escape-before-inserting-untrusted-data-into-html-common-attributes
24        this.videoId = encodeURIComponent(this.getAttribute('videoid'));
25
26        this.secret  = encodeURIComponent(this.getAttribute('h'));
27
28        let playBtn = this.querySelector('.ltv-playbtn');
29
30        /**
31         * Lo, the vimeo placeholder image!  (aka the thumbnail, poster image, etc)
32         * We have to use the Vimeo API.
33         */
34        let { width, height } = getThumbnailDimensions(this.getBoundingClientRect());
35        const devicePixelRatio = window.devicePixelRatio || 1;
36        width *= devicePixelRatio;
37        height *= devicePixelRatio;
38
39        // let thumbnailUrl = `https://lite-vimeo-embed.now.sh/thumb/${this.videoId}`;
40        // thumbnailUrl += `.${canUseWebP() ? 'webp' : 'jpg'}`;
41        // thumbnailUrl += `?mw=${width}&mh=${height}&q=${devicePixelRatio > 1 ? 70 : 85}`;
42
43        // this.style.backgroundImage = `url("${thumbnailUrl}")`;
44
45        if (!playBtn) {
46            const playBtn = document.createElement('button');
47            playBtn.type = 'button';
48            playBtn.classList.add('ltv-playbtn');
49            this.appendChild(playBtn);
50        }
51        playBtn.removeAttribute('href');
52
53        // On hover (or tap), warm up the TCP connections we're (likely) about to use.
54        this.addEventListener('pointerover', LiteVimeo._warmConnections, {
55            once: true
56        });
57
58        // Once the user clicks, add the real iframe and drop our play button
59        // TODO: In the future we could be like amp-youtube and silently swap in the iframe during idle time
60        //   We'd want to only do this for in-viewport or near-viewport ones: https://github.com/ampproject/amphtml/pull/5003
61        this.addEventListener('click', () => this._addIframe());
62    }
63
64    // // TODO: Support the the user changing the [videoid] attribute
65    // attributeChangedCallback() {
66    // }
67
68    /**
69     * Begin pre-connecting to warm up the iframe load
70     * Since the embed's network requests load within its iframe,
71     *   preload/prefetch'ing them outside the iframe will only cause double-downloads.
72     * So, the best we can do is warm up a few connections to origins that are in the critical path.
73     *
74     * Maybe `<link rel=preload as=document>` would work, but it's unsupported: http://crbug.com/593267
75     * But TBH, I don't think it'll happen soon with Site Isolation and split caches adding serious complexity.
76     */
77    static _warmConnections () {
78        if (LiteVimeo.preconnected) return;
79
80        // The iframe document and most of its subresources come right off player.vimeo.com
81        addPrefetch('preconnect', 'https://player.vimeo.com');
82        // Images
83        addPrefetch('preconnect', 'https://i.vimeocdn.com');
84        // Files .js, .css
85        addPrefetch('preconnect', 'https://f.vimeocdn.com');
86        // Metrics
87        addPrefetch('preconnect', 'https://fresnel.vimeocdn.com');
88
89        LiteVimeo.preconnected = true;
90    }
91
92    _addIframe () {
93        const iframeHTML = `
94<iframe width="640" height="360" frameborder="0"
95  allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen
96  src="https://player.vimeo.com/video/${this.videoId}?h=${this.secret}
96&autoplay=1"
97></iframe>`;
98        this.insertAdjacentHTML('beforeend', iframeHTML);
99        this.classList.add('ltv-activated');
100    }
101}
102// Register custome element
103customElements.define('lite-vimeo', LiteVimeo);
104
105/**
106 * Add a <link rel={preload | preconnect} ...> to the head
107 */
108function addPrefetch(kind, url, as) {
109    const linkElem = document.createElement('link');
110    linkElem.rel = kind;
111    linkElem.href = url;
112    if (as) {
113        linkElem.as = as;
114    }
115    linkElem.crossorigin = true;
116    document.head.appendChild(linkElem);
117}
118
119function canUseWebP() {
120    var elem = document.createElement('canvas');
121
122    if (elem.getContext && elem.getContext('2d')) {
123        // was able or not to get WebP representation
124        return elem.toDataURL('image/webp').indexOf('data:image/webp') === 0;
125    }
126
127    // very old browser like IE 8, canvas not supported
128    return false;
129}
130
131/**
132 * Get the thumbnail dimensions to use for a given player size.
133 *
134 * @param {Object} options
135 * @param {number} options.width The width of the player
136 * @param {number} options.height The height of the player
137 * @return {Object} The width and height
138 */
139function getThumbnailDimensions({ width, height }) {
140    let roundedWidth = width;
141    let roundedHeight = height;
142
143    // If the original width is a multiple of 320 then we should
144    // not round up. This is to keep the native image dimensions
145    // so that they match up with the actual frames from the video.
146    //
147    // For example 640x360, 960x540, 1280x720, 1920x1080
148    //
149    // Round up to nearest 100 px to improve cacheability at the
150    // CDN. For example, any width between 601 pixels and 699
151    // pixels will render the thumbnail at 700 pixels width.
152    if (roundedWidth % 320 !== 0) {
153        roundedWidth = Math.ceil(width / 100) * 100;
154        roundedHeight = Math.round((roundedWidth / width) * height);
155    }
156
157    return {
158        width: roundedWidth,
159        height: roundedHeight
160    };
161}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.