Back to feed
ForumSpark Support Themes & Extensions Join

Insert Videos Based on Type

Cory · 7 months ago · 17 replies · 169

Preview

Selecting a service type and inserting a video URL will embed the video within the post you create.

This code currently supports the following services:

  • Dailymotion

  • Facebook

  • TikTok

  • Twitch

  • Vimeo

Change the width and height at the top of the script to your preference.

The width and height variables do not affect TikTok videos.

Admin CP → Themes → Board Templates → Below the board

<script>
const videoWidth = 560;
const videoHeight = 315;
const previewDIV = document.querySelector('.tiptap-toolbar');

if (previewDIV) {
    const insertVideo = document.createElement('button');
    insertVideo.type = 'button';
    insertVideo.id = 'insert-video';
    insertVideo.className = 'btn btn-secondary btn-sm';
    insertVideo.innerText = 'Insert Video';
    previewDIV.appendChild(insertVideo);

    document.querySelector('#insert-video').addEventListener("click", () => {

        if (document.querySelector('#video-container')) {
            document.querySelector('#video-container').remove();
        }

        const videoSelector = `<div id="video-container" class="panel" style="border-width: 1px; position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%)"><div class="panel__sub-header">Insert a Video:</div><div style="padding: 1rem">Video Type:<br><select><option value="-1">Select One</option><option>Dailymotion</option><option>Facebook</option><option>TikTok</option><option>Twitch</option><option>Vimeo</option></select><br><br>Video URL:<br><input type="text"></div><div class="panel__sub-header"><button type="button" class="btn btn-secondary btn-sm submit">Submit</button> <button type="button" class="btn btn-secondary btn-sm cancel">Cancel</button></div></div>`;
        document.body.insertAdjacentHTML('beforeend', videoSelector);

        document.querySelector('#video-container button.cancel').addEventListener("click", () => {
            document.querySelector('#video-container').remove();
        });

        document.querySelector('#video-container button.submit').addEventListener("click", () => {
            const type = document.querySelector('#video-container select').value;
            const video = document.querySelector('#video-container input').value;
            document.querySelector('#video-container').remove();

            if (type !== '-1') {
                document.querySelector('.tiptap-editor p').innerHTML = document.querySelector('.tiptap-editor p').innerHTML + '[VIDEO=' + type + ']' + video + '[/VIDEO]';
            }
        });
    });
}

const content = document.querySelectorAll('div.content');

if (content) {
    content.forEach(post => {
        post.innerHTML = post.innerHTML.replace(/\[VIDEO=(.+?)\](.+?)\[\/VIDEO\]/g, '<span class="video $1">$2</span>');
    });

    const video = document.querySelectorAll('span.video');
    const script = document.createElement('script');
    script.src = 'https://connect.facebook.net/en_US/sdk.js#xfbml=1&version=v21.0';
    document.body.appendChild(script);
    const script2 = document.createElement('script');
    script2.src = 'https://www.tiktok.com/embed.js';
    document.body.appendChild(script2);

    video.forEach(html => {
        const vType = html.getAttribute('class').split('video ')[1];
        let vID;

        if (vType === 'Dailymotion') {
            vID = html.innerText.split('/video/')[1];
            html.innerHTML = `<iframe src="https://geo.dailymotion.com/player.html?video=${vID}" style="width:${videoWidth}px; height:${videoHeight}px; overflow:hidden; border:none;" allowfullscreen title="Dailymotion Video Player" allow="web-share"></iframe>`;
        } else if (vType === 'Facebook') {
            vID = html.innerText.split('/videos/')[1].split('/?')[0];
            html.innerHTML = `<div class="fb-video" data-href="https://www.facebook.com/facebook/videos/${vID}/" data-width="${videoWidth}" data-height="${videoHeight}" ata-show-text="false"></div><div id="fb-root"></div>`;
        } else if (vType === 'TikTok') {
            vID = html.innerText.split('/video/')[1].split('?')[0];
            let channel = html.innerText.split('.com/')[1].split('/')[0];
            html.innerHTML = `<blockquote class="tiktok-embed" cite="https://www.tiktok.com/${channel}/video/${vID}" data-video-id="${vID}" data-embed-from="embed_page"><section></section></blockquote>`;
        } else if (vType === 'Twitch') {
            vID = html.innerText.split('/videos/')[1];
            let loc = location.href.split('https://')[1].split('/')[0];
            html.innerHTML = `<iframe src="https://player.twitch.tv/?video=v${vID}&parent=${loc}&autoplay=false" width="${videoWidth}" height="${videoHeight}" allowfullscreen></iframe>`;
        } else if (vType === 'Vimeo') {
            vID = html.innerText.substring(html.innerText.lastIndexOf('/') + 1, html.innerText.length);
            html.innerHTML = `<iframe src="https://player.vimeo.com/video/${vID}" width="${videoWidth}" height="${videoHeight}" frameborder="0" allow="autoplay; fullscreen; picture-in-picture" allowfullscreen></iframe>`;
        }
    });
}
</script>

17 replies
Steve · 7 months ago

Wow, this is certainly a great feature. I see a lot of forums have support for youtube video and they can be easily embedded, however, videos from other social sites only add up as links, they don't show preview.

Cory OP · 7 months ago

I originally included YouTube videos in this code, but I noticed the forum software already has them automatically embedded.

Speaking of "preview", I noticed this code doesn't work when you try to preview the post. I hope to have that fixed soon.

Empire · 7 months ago

Nice, perfect for many sites. I gonna edit and put it with the other BB buttons ;)

Cory OP · 7 months ago
empire said:

I gonna edit and put it with the other BB buttons

I considered that, but because of a specific runtime Forum Spark uses, when you click/change a BBCode function, it will remove the newly added button.

Ravenfreak · 7 months ago

Nice it's always a good idea to add support for other platforms outside of Youtube, thank you for this extension Cory I'll go add it to my forum since it definitely can benefit from it! :D I'm sure my members would appreciate this one too, Dailymotion is another platform I need to mention over there lol.

Cory OP · 7 months ago

I updated this code to work with the Tiptap editor. However, currently, instead of placing the BBCode where your cursor is, it adds it to the end of the text area. On the plus side, it now works in quick reply.

S
Shortie · 6 months ago

This is great and a feature that will be used a lot :)

Thanks!

Empire · 6 months ago

:)

B
Bright · 6 months ago

This one is a lifesaver 😄 embedding videos can boost the engagement well. I remember when I was copying long messy iframe codes on one forum, the stress was huge. This feature is a life saver honestly.

Daedalus · 6 months ago

Great work Cory as usual.

NeoMetallix · 5 months ago

Okay, not sure what I'm doing wrong. On templates it has blank boxes but you can't click on it to paste in the code. The actual name itself, "Below the board" is clickable but clicking on it does nothing. :/ This is on both Chrome and FireFox based browsers.

I was able to do this on my android browser however...

NeoMetallix · 5 months ago

This is great Cory. Do you think you could add functionality for Rumble/Odysee as well? Posting HTML with iframe doesn't seem to work on this software. 🤔

Cory OP · 5 months ago

On May 19, 2026, IntellectualLiberation said:

This is great Cory. Do you think you could add functionality for Rumble/Odysee as well? Posting HTML with iframe doesn't seem to work on this software. 🤔

I'm not sure you can embed Rumble videos the same way you do the other videos. It seems that when I view the URL vs the embed code, the ID is different.

NeoMetallix · 2 months ago

I modified the code so it includes Rumble. I figured someone else might like it. I’ve been thinking about having Odysee included too for more alternative platforms.

<script>
const videoWidth = 560;
const videoHeight = 315;
const previewDIV = document.querySelector('.tiptap-toolbar');

if (previewDIV) {
    const insertVideo = document.createElement('button');
    insertVideo.type = 'button';
    insertVideo.id = 'insert-video';
    insertVideo.className = 'btn btn-secondary btn-sm';
    insertVideo.innerText = 'Insert Video';
    previewDIV.appendChild(insertVideo);

    document.querySelector('#insert-video').addEventListener("click", () => {

        if (document.querySelector('#video-container')) {
            document.querySelector('#video-container').remove();
        }

        const videoSelector = `
        <div id="video-container" class="panel" style="border-width: 1px; position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%)">
            <div class="panel__sub-header">Insert a Video:</div>
            <div style="padding: 1rem">
                Video Type:<br>
                <select>
                    <option value="-1">Select One</option>
                    <option>Dailymotion</option>
                    <option>Facebook</option>
                    <option>TikTok</option>
                    <option>Twitch</option>
                    <option>Vimeo</option>
                    <option>Rumble</option>
                </select>
                <br><br>
                Video URL (iframe only for Rumble):<br>
                <input type="text">
            </div>
            <div class="panel__sub-header">
                <button type="button" class="btn btn-secondary btn-sm submit">Submit</button>
                <button type="button" class="btn btn-secondary btn-sm cancel">Cancel</button>
            </div>
        </div>`;
        document.body.insertAdjacentHTML('beforeend', videoSelector);

        document.querySelector('#video-container button.cancel').addEventListener("click", () => {
            document.querySelector('#video-container').remove();
        });

        document.querySelector('#video-container button.submit').addEventListener("click", () => {
            const type = document.querySelector('#video-container select').value;
            const video = document.querySelector('#video-container input').value;
            document.querySelector('#video-container').remove();

            if (type !== '-1') {
                document.querySelector('.tiptap-editor p').innerHTML += `[VIDEO=${type}]${video}[/VIDEO]`;
            }
        });
    });
}

const content = document.querySelectorAll('div.content');

if (content) {
    content.forEach(post => {
        post.innerHTML = post.innerHTML.replace(/\[VIDEO=(.+?)\](.+?)\[\/VIDEO\]/g, '<span class="video $1">$2</span>');
    });

    const video = document.querySelectorAll('span.video');
    const scriptFB = document.createElement('script');
    scriptFB.src = 'https://connect.facebook.net/en_US/sdk.js#xfbml=1&version=v21.0';
    document.body.appendChild(scriptFB);
    const scriptTikTok = document.createElement('script');
    scriptTikTok.src = 'https://www.tiktok.com/embed.js';
    document.body.appendChild(scriptTikTok);

    video.forEach(html => {
        const vType = html.getAttribute('class').split('video ')[1];
        let vID;

        if (vType === 'Dailymotion') {
            vID = html.innerText.split('/video/')[1];
            html.innerHTML = `<iframe src="https://geo.dailymotion.com/player.html?video=${vID}" style="width:${videoWidth}px; height:${videoHeight}px; overflow:hidden; border:none;" allowfullscreen title="Dailymotion Video Player" allow="web-share"></iframe>`;
        } else if (vType === 'Facebook') {
            vID = html.innerText.split('/videos/')[1].split('/?')[0];
            html.innerHTML = `<div class="fb-video" data-href="https://www.facebook.com/facebook/videos/${vID}/" data-width="${videoWidth}" data-height="${videoHeight}" ata-show-text="false"></div><div id="fb-root"></div>`;
        } else if (vType === 'TikTok') {
            vID = html.innerText.split('/video/')[1].split('?')[0];
            let channel = html.innerText.split('.com/')[1].split('/')[0];
            html.innerHTML = `<blockquote class="tiktok-embed" cite="https://www.tiktok.com/${channel}/video/${vID}" data-video-id="${vID}" data-embed-from="embed_page"><section></section></blockquote>`;
        } else if (vType === 'Twitch') {
            vID = html.innerText.split('/videos/')[1];
            let loc = location.href.split('https://')[1].split('/')[0];
            html.innerHTML = `<iframe src="https://player.twitch.tv/?video=v${vID}&parent=${loc}&autoplay=false" width="${videoWidth}" height="${videoHeight}" allowfullscreen></iframe>`;
        } else if (vType === 'Vimeo') {
            vID = html.innerText.substring(html.innerText.lastIndexOf('/') + 1);
            html.innerHTML = `<iframe src="https://player.vimeo.com/video/${vID}" width="${videoWidth}" height="${videoHeight}" frameborder="0" allow="autoplay; fullscreen; picture-in-picture" allowfullscreen></iframe>`;
        } else if (vType === 'Rumble') {
            // Only allow iframe URL, no direct URL
            // Example iframe URL: https://rumble.com/embed/v6vgexp
            if (html.innerText.includes('rumble.com/embed/')) {
                html.innerHTML = `<iframe src="${html.innerText}" width="${videoWidth}" height="${videoHeight}" frameborder="0" allowfullscreen allow="autoplay; encrypted-media"></iframe>`;
            } else {
                html.innerHTML = `<p style="color:red;">Rumble iframe URL required</p>`;
            }
        }
    });
}
</script>

?
Deleted user · 2 months ago

Inserting a video is awesome! no faffing about with tags.,paste and it’s done.. brilliant… thats what I like… things to be easy..no faffing… 🙂

Excalibur · 2 months ago

On Aug 19, 2026, NeoMetallix said:

I modified the code so it includes Rumble. I figured someone else might like it. I’ve been thinking about having Odysee included too for more alternative platforms.

<script>
const videoWidth = 560;
const videoHeight = 315;
const previewDIV = document.querySelector('.tiptap-toolbar');

if (previewDIV) {
    const insertVideo = document.createElement('button');
    insertVideo.type = 'button';
    insertVideo.id = 'insert-video';
    insertVideo.className = 'btn btn-secondary btn-sm';
    insertVideo.innerText = 'Insert Video';
    previewDIV.appendChild(insertVideo);

    document.querySelector('#insert-video').addEventListener("click", () => {

        if (document.querySelector('#video-container')) {
            document.querySelector('#video-container').remove();
        }

        const videoSelector = `
        <div id="video-container" class="panel" style="border-width: 1px; position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%)">
            <div class="panel__sub-header">Insert a Video:</div>
            <div style="padding: 1rem">
                Video Type:<br>
                <select>
                    <option value="-1">Select One</option>
                    <option>Dailymotion</option>
                    <option>Facebook</option>
                    <option>TikTok</option>
                    <option>Twitch</option>
                    <option>Vimeo</option>
                    <option>Rumble</option>
                </select>
                <br><br>
                Video URL (iframe only for Rumble):<br>
                <input type="text">
            </div>
            <div class="panel__sub-header">
                <button type="button" class="btn btn-secondary btn-sm submit">Submit</button>
                <button type="button" class="btn btn-secondary btn-sm cancel">Cancel</button>
            </div>
        </div>`;
        document.body.insertAdjacentHTML('beforeend', videoSelector);

        document.querySelector('#video-container button.cancel').addEventListener("click", () => {
            document.querySelector('#video-container').remove();
        });

        document.querySelector('#video-container button.submit').addEventListener("click", () => {
            const type = document.querySelector('#video-container select').value;
            const video = document.querySelector('#video-container input').value;
            document.querySelector('#video-container').remove();

            if (type !== '-1') {
                document.querySelector('.tiptap-editor p').innerHTML += `[VIDEO=${type}]${video}[/VIDEO]`;
            }
        });
    });
}

const content = document.querySelectorAll('div.content');

if (content) {
    content.forEach(post => {
        post.innerHTML = post.innerHTML.replace(/\[VIDEO=(.+?)\](.+?)\[\/VIDEO\]/g, '<span class="video $1">$2</span>');
    });

    const video = document.querySelectorAll('span.video');
    const scriptFB = document.createElement('script');
    scriptFB.src = 'https://connect.facebook.net/en_US/sdk.js#xfbml=1&version=v21.0';
    document.body.appendChild(scriptFB);
    const scriptTikTok = document.createElement('script');
    scriptTikTok.src = 'https://www.tiktok.com/embed.js';
    document.body.appendChild(scriptTikTok);

    video.forEach(html => {
        const vType = html.getAttribute('class').split('video ')[1];
        let vID;

        if (vType === 'Dailymotion') {
            vID = html.innerText.split('/video/')[1];
            html.innerHTML = `<iframe src="https://geo.dailymotion.com/player.html?video=${vID}" style="width:${videoWidth}px; height:${videoHeight}px; overflow:hidden; border:none;" allowfullscreen title="Dailymotion Video Player" allow="web-share"></iframe>`;
        } else if (vType === 'Facebook') {
            vID = html.innerText.split('/videos/')[1].split('/?')[0];
            html.innerHTML = `<div class="fb-video" data-href="https://www.facebook.com/facebook/videos/${vID}/" data-width="${videoWidth}" data-height="${videoHeight}" ata-show-text="false"></div><div id="fb-root"></div>`;
        } else if (vType === 'TikTok') {
            vID = html.innerText.split('/video/')[1].split('?')[0];
            let channel = html.innerText.split('.com/')[1].split('/')[0];
            html.innerHTML = `<blockquote class="tiktok-embed" cite="https://www.tiktok.com/${channel}/video/${vID}" data-video-id="${vID}" data-embed-from="embed_page"><section></section></blockquote>`;
        } else if (vType === 'Twitch') {
            vID = html.innerText.split('/videos/')[1];
            let loc = location.href.split('https://')[1].split('/')[0];
            html.innerHTML = `<iframe src="https://player.twitch.tv/?video=v${vID}&parent=${loc}&autoplay=false" width="${videoWidth}" height="${videoHeight}" allowfullscreen></iframe>`;
        } else if (vType === 'Vimeo') {
            vID = html.innerText.substring(html.innerText.lastIndexOf('/') + 1);
            html.innerHTML = `<iframe src="https://player.vimeo.com/video/${vID}" width="${videoWidth}" height="${videoHeight}" frameborder="0" allow="autoplay; fullscreen; picture-in-picture" allowfullscreen></iframe>`;
        } else if (vType === 'Rumble') {
            // Only allow iframe URL, no direct URL
            // Example iframe URL: https://rumble.com/embed/v6vgexp
            if (html.innerText.includes('rumble.com/embed/')) {
                html.innerHTML = `<iframe src="${html.innerText}" width="${videoWidth}" height="${videoHeight}" frameborder="0" allowfullscreen allow="autoplay; encrypted-media"></iframe>`;
            } else {
                html.innerHTML = `<p style="color:red;">Rumble iframe URL required</p>`;
            }
        }
    });
}
</script>

Nice, you mentioned adding Odysee too, would that be difficult to do?

NeoMetallix · 2 months ago

On Aug 19, 2026, Excalibur said:

Nice, you mentioned adding Odysee too, would that be difficult to do?

Not sure, I can see. Rumble was difficult because iframe URL is different from video URL. At first it was getting the wrong video and then it was rotating on every refresh. Finally got it to work right.

Create a free account to join the conversation.
Sign up free
ForumSpark © 2023 - 2026 · ForumSpark.net · Terms