1- import Vue , { PropType , VNode } from 'vue'
2- import type { LoadIframeEventPayload } from './types'
1+ import Vue , { VueConstructor , PropType , VNode } from 'vue'
2+ import type { LoadIframeEventPayload , Refs } from './types'
33import { startsWith } from './helpers'
4- import { PREVIEW_IMAGE_SIZES , DEFAULT_IFRAME_ATTRIBUTES } from './constants'
4+ import {
5+ PREVIEW_IMAGE_SIZES ,
6+ DEFAULT_IFRAME_ATTRIBUTES ,
7+ PLAYER_SCRIPT_SRC ,
8+ } from './constants'
59
6- export default Vue . extend ( {
10+ export default ( Vue as VueConstructor < Vue & { $refs : Refs } > ) . extend ( {
711 name : 'VueLazyYoutubeVideo' ,
812 props : {
913 src : {
@@ -52,10 +56,24 @@ export default Vue.extend({
5256 thumbnailListeners : {
5357 type : Object as PropType < Record < string , Function | Function [ ] > > ,
5458 } ,
59+ enablejsapi : {
60+ type : Boolean ,
61+ default : false ,
62+ } ,
63+ playerOptions : {
64+ type : Object as PropType < YT . PlayerOptions > ,
65+ default : ( ) => ( { } ) ,
66+ } ,
67+ injectPlayerScript : {
68+ type : Boolean ,
69+ default : false ,
70+ } ,
5571 } ,
5672 data ( ) {
5773 return {
5874 activated : this . autoplay ,
75+ playerInstance : null as YT . Player | null ,
76+ __interval__ : null as NodeJS . Timeout | null ,
5977 }
6078 } ,
6179 computed : {
@@ -72,7 +90,9 @@ export default Vue.extend({
7290 srcAttribute ( ) : string {
7391 const hasQuestionMark =
7492 typeof this . src === 'string' && this . src . indexOf ( '?' ) !== - 1
75- return `${ this . src } ${ hasQuestionMark ? '&' : '?' } autoplay=1`
93+ return `${ this . src } ${ hasQuestionMark ? '&' : '?' } autoplay=1${
94+ this . enablejsapi ? '&enablejsapi=1' : ''
95+ } `
7696 } ,
7797 styleObj ( ) : object {
7898 return {
@@ -113,10 +133,62 @@ export default Vue.extend({
113133 onIframeLoad ( ) {
114134 const payload : LoadIframeEventPayload = { iframe : this . getIframe ( ) }
115135 this . $emit ( 'load:iframe' , payload )
136+
137+ if ( this . enablejsapi ) {
138+ try {
139+ window . YT . Player
140+ this . initPlayerInstance ( )
141+ } catch ( e ) {
142+ if ( this . injectPlayerScript ) {
143+ this . doInjectPlayerScript ( )
144+ } else {
145+ console . error (
146+ '[vue-lazy-youtube-video]: window.YT.Player is not defined. Make sure you either included the IFrame Player API or passed `injectPlayerScript` prop'
147+ )
148+ throw e
149+ }
150+ }
151+ }
116152 } ,
117153 getIframe ( ) {
118154 return this . $refs . iframe as HTMLIFrameElement | undefined
119155 } ,
156+ checkPlayer ( ) {
157+ if ( YT . Player ) {
158+ if ( this . __interval__ ) {
159+ clearInterval ( this . __interval__ )
160+ }
161+
162+ this . initPlayerInstance ( )
163+ return true
164+ }
165+ return false
166+ } ,
167+ initPlayerInstance ( ) {
168+ const { iframe } = this . $refs
169+ if ( ! iframe )
170+ throw new Error (
171+ '[vue-lazy-youtube-video]: YT.Player can not be instantiated without iframe element'
172+ )
173+ this . playerInstance = new YT . Player ( iframe , this . playerOptions )
174+ this . $emit ( 'init:player' , this . playerInstance )
175+ return this . playerInstance
176+ } ,
177+ getPlayerInstance ( ) {
178+ return this . playerInstance
179+ } ,
180+ doInjectPlayerScript ( ) {
181+ const script = document . createElement ( 'script' )
182+ script . setAttribute ( 'src' , PLAYER_SCRIPT_SRC )
183+
184+ script . onload = ( ) => {
185+ this . __interval__ = setInterval ( ( ) => {
186+ this . checkPlayer ( )
187+ } , 32 )
188+ }
189+
190+ document . head . appendChild ( script )
191+ } ,
120192 warn ( message : string ) {
121193 console . warn ( `[vue-lazy-youtube-video]: ${ message } ` )
122194 } ,
0 commit comments