Ways to create a self-contained video viewer

Is it possible to create a self-contained video player similar to jwplayer or the YouTube video player using just HTML, CSS, and JavaScript? I know that I can build a video player by utilizing the video tag along with some custom javascript and css, but how do I simplify the process so that only a few lines of code are needed to implement it like jwplayer and YouTube?

Upon exploring the jwplayer website, it appears that they only require the inclusion of a few lines of javascript to enable the player:

For the YouTube player, you simply need to embed the desired video in an iframe. Why does the video only show when embedded within an iframe? According to this explanation: https://www.w3schools.com/tags/tag_iframe.asp, isn't it meant to display the entire webpage rather than just the video player?

Example code snippet from jwplayer's website:

<div id="myElement"></div>

<script type="text/javascript">
    var playerInstance = jwplayer("myElement");
    playerInstance.setup({
        file: "//example.com/uploads/myVideo.mp4",
        mediaid: "xxxxYYYY"

    });
</script>

Instructions for embedding YouTube videos:

<iframe src="http://www.youtube.com/embed/W7qWa52k-nE"
width="560" height="315" frameborder="0" allowfullscreen></iframe>



How can I achieve this functionality using only html, css, and javascript?

Answer №1

Initially, the iframe on YouTube effectively displays the entire page content. However, upon inspecting the URL provided, you'll notice that it links to https://www.youtube.com/watch?v=W7qWa52k-nE (which shows the regular YouTube page) rather than https://www.youtube.com/embed/W7qWa52k-nE (note the "embed" in the URL). If you open https://www.youtube.com/embed/W7qWa52k-nE in your browser, only the video player will be visible. This explains why the iframe functions correctly and only displays the player.

Furthermore, when utilizing jwplayer, a minimal amount of code is required, but importing the necessary JavaScript and CSS library files into the page is essential. The lines of code written will invoke functions contained within the library.

To create a player using HTML5, one must incorporate and script certain JavaScript events and functions (refer to: https://www.w3schools.com/tags/ref_av_dom.asp).

/* LIB */

function MyPlayer(playerContainer) {

    let videoElement;
    let videoPoster;

    const instance = {};

    instance.stop = () => {
        return new Promise(resolve => {
            videoElement.pause();
            videoElement.src = null;


            setTimeout(() => {
                resolve();
            });
        });
    };

    instance.setUrl = async(url) => {
        await instance.stop();
        videoElement.src = url;
        videoElement.load();
    };

    instance.play = () => {
        videoElement.play();
    };

    instance.playUrl = async(url) => {
        await instance.setUrl(url);
        instance.play();
    };
    
    instance.pause = () => {
        videoElement.pause();
    };
    
    instance.setPoster = (url) => {
      if(url) {
        videoPoster.style.backgroundImage = 'url(' + url + ')';
      } else {
        videoPoster.style.backgroundImage = null;
      }
    };

    const onPlayerEvent = (eventName, event) => {
      playerContainer.setAttribute('data-state', eventName);
    };
    const onCoverClick = (event) => {
      event.preventDefault();
      event.stopPropagation();
      
      if(videoElement.paused) {
        instance.play();
      } else {
        instance.pause();
      }
    };


    /* Player init */
    playerContainer.className += ' MyPlayer';
    playerContainer.setAttribute('data-state', 'emptied');
    playerContainer.innerHTML = '<video class="videoElement" poster="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"></video><div class="videoPoster"></div><div class="videoIndicator"></div><div class="playerLogo">MyPlayer</div><div class="videoCover"></div>';
    
    videoElement = playerContainer.getElementsByClassName('videoElement')[0];
    videoElement.addEventListener('emptied', onPlayerEvent.bind(this, 'emptied'), false);
    videoElement.addEventListener('loadstart', onPlayerEvent.bind(this, 'loadstart'), false);
    videoElement.addEventListener('canplay', onPlayerEvent.bind(this, 'canplay'), false);
    videoElement.addEventListener('playing', onPlayerEvent.bind(this, 'playing'), false);
    videoElement.addEventListener('pause', onPlayerEvent.bind(this, 'pause'), false);
    videoElement.addEventListener('waiting', onPlayerEvent.bind(this, 'waiting'), false);
    videoElement.addEventListener('ended', onPlayerEvent.bind(this, 'ended'), false);
    videoElement.addEventListener('error', onPlayerEvent.bind(this, 'error'), false);
    
    videoPoster = playerContainer.getElementsByClassName('videoPoster')[0];
    
    const videoCover = playerContainer.getElementsByClassName('videoCover')[0];
    videoCover.addEventListener('click', onCoverClick, false);
    videoCover.addEventListener('touch', onCoverClick, false);

    return instance;
}



/* USAGE */

const playerInstance = MyPlayer(document.getElementById('myPlayer'));
playerInstance.setPoster('https://www.w3schools.com/html/pic_trulli.jpg');
playerInstance.playUrl('https://www.w3schools.com/html/mov_bbb.mp4');

const playerInstance2 = MyPlayer(document.getElementById('myPlayer2'));
playerInstance2.setPoster('https://www.w3schools.com/html/pic_trulli.jpg');
playerInstance2.setUrl('https://www.w3schools.com/html/mov_bbb.mp4');
@keyframes spin { 100% { -webkit-transform: rotate(360deg); transform:rotate(360deg); } }

.MyPlayer {
  position: relative;
}

.MyPlayer .videoElement {
  background-color: black;
  width: 100%;
  height: 100%;
  vertical-align: bottom;
}

.MyPlayer .videoPoster, .MyPlayer .videoCover {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
}

.MyPlayer .videoPoster {
  opacity: 0;
  background-size: cover;
  transition: opacity .2s;
}
.MyPlayer[data-state="emptied"] .videoPoster, .MyPlayer[data-state="loadstart"] .videoPoster, .MyPlayer[data-state="canplay"] .videoPoster, .MyPlayer[data-state="ended"] .videoPoster {
  opacity: 1;
}

.MyPlayer .videoIndicator::before {
  position: absolute;
  top: 10px;
  left: 10px;
  color: #fff;
  text-shadow: 0 0 5px #000;
}
.MyPlayer[data-state="emptied"] .videoIndicator::before {
  content: '';
}
.MyPlayer[data-state="loadstart"] .videoIndicator::before, .MyPlayer[data-state="waiting"] .videoIndicator::before {
  content: '\25CC';
  font-size: 1.6em;
  animation:spin 4s linear infinite;
}
.MyPlayer[data-state="canplay"] .videoIndicator::before {
  content: '\25B6';
  font-size: 3em;
  right: 10px;
  text-align: center;
}
.MyPlayer[data-state="playing"] .videoIndicator::before {
  content: '\25B6';
  font-size: 1.3em;
}
.MyPlayer[data-state="pause"] .videoIndicator::before {
  content: '\2590\A0\258C';
}
.MyPlayer[data-state="ended"] .videoIndicator::before {
  content: '\27F2';
  font-size: 1.3em;
}
.MyPlayer[data-state="error"] .videoIndicator::before {
  content: '\2716';
}

.MyPlayer .playerLogo {
  position: absolute;
  right: 10px;
  bottom: 10px;
  font-size: 1.4em;
  color: #fff;
  text-shadow: 0 0 5px #f00;
  transition: color .2s, text-shadow .2s;
}
.MyPlayer[data-state="playing"]:not(:hover) .playerLogo {
  color: rgba(255, 255, 255, 0.4);
  text-shadow: 0 0 5px rgba(255, 0, 0, 0.4);
}
<div id="myPlayer" style="display:inline-block;max-width:250px;"></div> <div id="myPlayer2" style="display:inline-block;max-width:225px;"></div><br />
Video files from https//www.w3schools.com<br />
Video from https://www.bigbuckbunny.org/

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Node.js is having trouble locating the JSON file for Ajax requests

Currently, I've developed a fun little game using the p5.js library and wanted to integrate a Leaderboard feature that pulls data from a JSON file acting as a database to store Usernames and scores. To achieve this, I've utilized a Node.js server ...

Adding dynamic HTML to the body in AngularJS based on URL alterations

I am currently developing a single-page application using Angular. I am trying to create a card stack made of divs, similar to this concept. https://i.stack.imgur.com/42M06.png The idea is that the app will have various URL links and a card should be app ...

What methods can I use to conceal #! from showing on the browser's address bar?

Imagine you have the below link: www.someurl.com/#!?page=index How would you convert it into one of these options: www.someurl.com/#!/index (using mod_rewrite) www.someurl.com/ajax/index (also using mod_rewrite, but replacing #! with ajax) www.someurl. ...

Tips for embedding a file within a text box in HTML and enabling users to make direct edits

I am currently working on a feature that allows users to open a .txt or .html file from their file explorer and paste the contents into a textarea for editing and saving purposes. My question is whether it's possible to read the file content and auto ...

How can I move a complete range of values up using the Google Sheets API in Node.JS?

I'm working with a Google Spreadsheet that is being accessed and modified by a Node.JS app. There's a specific situation where I need to shift an entire range up (moving A3:D up by one cell), but due to my limited experience with the Google Shee ...

Struggling to keep up with responsive behavior on a page featuring vertically and horizontally centered content that spans the full height

I'm working on a full-height website and the first section needs to have both vertical and horizontal centered content. The issue I'm facing is that there's an image included, which doesn't scale responsively when the screen size change ...

What is the best way to retrieve the data from this date object?

How can I access the date and time in the code below? I've attempted using functions within the Text block without success. It's unclear to me what mistake I'm making or how to correctly access this object, or transform it into an object th ...

How can you determine if a polymer element has been loaded or not?

element, I am interested in dynamically importing elements using the Polymer.import( elements, callback ) method. The callback is triggered only if the elements have not been imported yet, indicating they are already loaded. My query is: Is there a conve ...

PHP: Eliminating Line Breaks and Carriage Returns

My content entered into the database by CKEditor is adding new lines, which poses a problem as I need this data to be rendered in JavaScript as a single line of HTML. Within my PHP code, I have implemented the following steps: $tmpmaptext = $map['ma ...

Eliminating unnecessary white space while utilizing the first-letter CSS property

Is there a way to remove the extra whitespace added under the first line when making the first letter of a paragraph bigger than the rest of the text? I already tried adjusting padding and margins on p::first-line without success. p{ line-height: 1.4; } p ...

Showing particular URL text upon opening a new window using JavaScript

I've encountered an intriguing scenario. In my application, there's a feature that triggers a new window/tab to open when a button is clicked. Upon opening, a predefined HTML page is shown to the user with a specific URL set. I'm curious abo ...

Difficulty with Horizontal Mousewheel Scrolling

Struggling to implement a horizontal scrolling feature (via mousewheel) for both containers in the code below. I want this feature to be easily applied to any future container creations as well. <body> <style> #container { display: flex ...

utilize jQuery to load webpage with an HTML dropdown element

Querying the Campaigns: // Getting the campaigns $campaigns = $wpdb->get_results( "SELECT * FROM tbl_campaigns ORDER BY campaignID DESC", OBJECT_K ); // Displaying the Cam ...

When combining CSS grids, nesting them can sometimes cause issues with the height layout

Check out the code on jsFiddle .component-container { width: 800px; height: 200px; background-color: lightyellow; border: 1px solid red; padding: 10px; overflow: hidden; } .component-container .grid-container-1 { display: grid; grid-tem ...

Invoke `setState` function in contexts outside of React framework

Is the following approach guaranteed to work correctly within React v18 semantics? The "rules of hooks" only address calling the hook within the component, with no mention of whether it's acceptable to call the dispatcher returned from the ...

Adjust the height of the box based on the content within its flexbox

I have a flexbox div nested inside another div, and I'm trying to adjust the height of the outer box based on the content of the inner flexbox. Here is the link to the current fiddle. The issue I am facing is that the text in the second box overflows ...

Fetch response headers not being detected by Web Worker

Currently in my chrome extension, I'm utilizing web workers to collect response header cookies from a specific website. Interestingly, when I execute the request on the main thread, the response contains all the expected cookies. However, when the exa ...

Electron JS-powered app launcher for seamless application launching

Currently, I am working on a project to develop an application launcher using HTML, CSS, and JS with Electron JS. Each application is linked through an a href tag that directs users to the respective application path. If a normal link is used in the a hr ...

What is causing my anchor tags not to reflow properly?

I've been working on my new website and I'm facing a challenge that I just can't seem to solve. Here's the link: When I resize my browser to "mobile width", making it narrower than the row of oval "Tags" below my site menu, I want the ...

Utilizing Beautifulsoup to extract elements from Selenium

When utilizing BeautifulSoup with Selenium, I usually start by parsing the entire page using soup = BeautifulSoup(driver.page_source). But what if I only want to parse a specific element from Selenium in BeautifulSoup? If you try the following code snipp ...