Is there a way to only allow the active video to play while disabling the others in this Vue 3 and Bootstrap 5 carousel?

I'm currently developing a Single Page Application (SPA) using Vue 3, TypeScript, and The Movie Database (TMDB). Additionally, I'm incorporating Bootstrap 5 for the UI.

To showcase movie trailers on the movie details page, I've created the TrailerCarousel.vue component:

<template>
  // Component code here
</template>

<script lang="ts">
  // Script code here
</script>

<style scoped lang="scss">
  // Styling code here
</style>

I utilize this component in src\components\MovieDetails.vue:

<div v-if="movieTrailers.length" class="mb-3">
    // Movie Details code here
</div>

Stackblitz

For a demonstration, I've created a Stackblitz with the code.

Please note that the "www.youtube.com refused to connect" issue only occurs on Stackblitz for reasons unknown.

The Issue

While transitioning between trailers and playing them, the previously playing one does not stop, resulting in sound overlap. I'm struggling to find a solution to this problem.

What would be the most effective approach to achieve the desired outcome?

Answer №1

There are various methods to tackle this issue, in my opinion. One approach could involve pausing the video iframe. While I haven't personally attempted it, I believe something like the following could be effective:

const previousActiveIframe = document.querySelectorAll('.carousel-item.active iframe') as HTMLIFrameElement

previousActiveIframe?.contentWindow?.postMessage('{"event":"command","func":"pauseVideo","args":""}', '*')

Alternatively, a simpler solution could be to refresh the iframe whenever the slide changes:

  data() {
    return {
      maxCarouselItems: 5,
      iframeRendererCount: 0, // 👈
    }
  },

  methods: {
    onSlideChange() {
      this.iframeRendererCount++
    }
}
<iframe
  :key="iframeRendererCount"
  :src="`https://www.youtube.com/embed/${video.key}`"
  frameborder="0"
  allowfullscreen
></iframe>

Answer №2

If you're looking to address this issue effectively, consider utilizing the Youtube IFrame Player API. This API enables you to manage Youtube videos in a standardized manner.

To begin, incorporate the youtube-player package into your project:

npm install youtube-player

Next, update the content of your component TrailerCarousel.vue with the following code:

<template>
  <div id="trailersCarousel" class="carousel slide" data-bs-interval="false">
    <ol v-if="movieTrailers.length > 1" class="carousel-indicators">
      <li v-for="(video, index) in movieTrailers.slice(0, maxCarouselItems)" :key="video.id"
        data-bs-target="#trailersCarousel" :data-bs-slide-to="`${index}`" :class="{ active: index === 0 }">
        {{ index + 1 }}
      </li>
    </ol>

    <div class="carousel-inner">
      <!-- Add `ref` to div element to get reference to it in script -->
      <div v-for="(video, index) in movieTrailers.slice(0, maxCarouselItems)" :key="video.id" class="carousel-item"
        :class="{ active: index === 0 }" :ref="el => itemRefs.push(el)" :data-id="video.key">
        <!-- <iframe class="embed-responsive-item" :src="`https://www.youtube.com/embed/${video.key}`"></iframe> -->
      </div>
    </div>
  </div>
</template>

<script lang="ts">
import { defineComponent } from "vue";
import YT from "youtube-player";

export default defineComponent({
  name: "TrailerCarousel",

  props: {
    movieTrailers: {
      type: Array,
      required: true,
    },
  },

  // Additional code and explanations provided within the script

</script>

<style scoped lang="scss">
.carousel-indicators {
  margin-bottom: 10px;

  // Updated styling information

</style>

I've clarified the code changes made and provided insights into the modifications. While the code currently works, it could benefit from enhanced typing, error handling, and event management.

Additional Points:

  • For vue3, it's encouraged to use vite as the build tool.
  • Utilize setup in <script lang='ts'> and composition API to reduce boilerplate code.

Answer №3

This is the way in which it has been put into action.

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

Are there any comparable features in Angular 8 to Angular 1's $filter('orderBy') function?

Just starting out with Angular and curious about the alternative for $filter('orderBy') that is used in an AngularJS controller. AngularJS example: $scope.itemsSorted = $filter('orderBy')($scope.newFilteredData, 'page_index&apos ...

Include the HTTP header in a GET request for an HTML hyperlink

Within my HTML code, I am using an <a> tag that will trigger a 302 redirect when clicked. However, I need to incorporate some HTTP headers into this GET request. Is there a way to achieve this without including the headers in the href attribute? Tha ...

Tips for transferring an array from a form to a URL using JavaScript?

My form uses a get method, and includes a select element allowing users to choose multiple options. However, when the user submits the form, the URL does not neatly display these selections. Is there a way for me to pass the array in a more organized manne ...

Utilizing jQuery Methods within Node.js

Recently delved into the world of node.js and created multiple pages (such as login, signup, blog, etc). If I desire an effect in which: 1. Hovering over the "News" button triggers a slider to appear downwards, To make adjustments to an image within ...

What is the best way to record and share a video with jquery and laravel?

Is there a way to grant users access to record videos within an application and then upload them after previewing? I've been able to successfully record and download a video, but now I'm unsure of how to proceed with uploading it to the server. ...

Steps to creating a nested function

I'm still learning the ropes of Javascript, and I've been working on creating a personal library to streamline my coding process. Here's the code snippet I've come up with. function myLibrary() { let _this = this; this.addString = ...

Retrieve information from a URL using an Express API

Every 45 minutes, my API receives a request: GET http://MyHost/mediciones/sigfox_libelium/{device}/{data}/{time}/{customData#trama} I need to extract {device}, {data}, {time}, and {customData#trama} from the URL and store them in separate variables. This ...

Scrollmagic - Creating dynamic effects by animating body and div backgrounds using multiple tweens

I'm currently developing a website that utilizes scrollmagic to smoothly transition the color of the active div (each set to size of the screen) from black back to white as you scroll down. The issue I am facing is that the body background color does ...

Ways to align div elements

I am currently in the process of developing my own custom animation player. Utilizing Three.js for object rendering has been successful so far. However, the challenge lies in incorporating control options at the bottom of the player interface (such as play ...

Mastering the art of debugging a mongoose action in node.js

I am utilizing mongoose for connecting my node.js app with mongoDB. However, I am facing an issue where the database does not get updated when I create or update a model instance. How can I effectively debug and identify what goes wrong in the create or up ...

How come my JavaScript regular expression doesn't function properly when applied to elements in an array?

let numbers = new Array('1','2','3'); let letters = new Array('a','b','c'); let length = numbers.length; let str = 'abcdefgabcdefg'; for (let i=0; i<length; i++) { let regex = new ...

Appending a forward slash at the end of a URL seamlessly directs the user to a serendipitous webpage experience, while

I'm currently developing a project on this website: Interestingly, when you append a forward slash to the end of the URL, all the images mysteriously disappear. Consequently, I am unable to include Google AdWords tracking code at the end of any URLs: ...

Ways to showcase Firebase information with multi-tiered keys in an HTML table?

I am struggling to showcase information from a Firebase database with a multi-level key onto an HTML table using Angular. Here is the structure of the data: https://i.sstatic.net/qQ6RZ.jpg https://i.sstatic.net/PIaUZ.jpg When attempting to display using ...

Creating a Three by Three Grid with HTML and CSS

I have a total of 20 elements to display in a grid view. However, I specifically want a 3x3 grid view, where only 9 elements will be visible in the view window. The remaining elements should be placed on the right side of the window in a scrollable manner. ...

Can you explain the inner workings of the sort function in JavaScript, including how it utilizes the compare

I'm curious about how the sort function operates in JavaScript, specifically in conjunction with the compare function. According to what I've read, if you have an array and use the code array.sort(compare), it's stated that if the compare fu ...

The functionality of ng-click and ng-submit seems to be malfunctioning

I am currently facing an issue with my Angular application and PhoneGap. I have a login form along with a login controller set up, but for some reason, the ng-submit function is not working as expected. When the submit button calls the formConnexion() func ...

Issue with displaying Vue.js page within iframe in Firefox

We are facing an issue where a Vue.js page with an Echarts pie chart is not displaying in Firefox, even though it shows up perfectly in Chrome and IE. Replacing the Echarts page with basic numbers did not solve the problem in Firefox. Here is how i ...

Using Jquery for a Second Timer

I have a jQuery function that looks like the one below. The result is displayed in a span, but when the page is reloaded, this span briefly disappears and then reappears. Is there a way to prevent this from happening? I need it to stay visible at all tim ...

Enhancing Material UI KeyboardDatePicker with personalized CSS design

Material UI KeyboardDatePicker is the component I'm currently using. https://i.sstatic.net/It50L.png In order to remove the black line visible in the datepicker (as shown in the screenshot), what steps should I take? Displayed below is the code ...

Utilizing an external type definition in JSDoc @typedef

I'm encountering an issue with reducing redundancy when defining my imported types. I am trying to streamline the process, but unfortunately I am running into errors. /** @typedef {import("../types/util")} util @typedef {util.mapBehaviors} m ...