@@ -15,6 +15,12 @@ var plyrPlayer;
15
15
var youTubeDataApiKey = "AIzaSyCxVxsC5k46b8I-CLXlF3cZHjpiqP_myVk" ;
16
16
var currentVideoID ;
17
17
18
+ // global playlist, this is populated with an ajax call
19
+ var tags = [ ] ;
20
+ var playList = new Set ( ) ;
21
+ var autoplayState = false ;
22
+ const MAX_TAGS = 10 ;
23
+
18
24
var errorMessage = {
19
25
init : function ( ) {
20
26
// nothing for now
@@ -137,6 +143,7 @@ var ZenPlayer = {
137
143
that . setupTitle ( ) ;
138
144
that . setupVideoDescription ( videoID ) ;
139
145
that . setupPlyrToggle ( ) ;
146
+ that . setupAutoplayToggle ( ) ;
140
147
} ) ;
141
148
142
149
plyrPlayer . addEventListener ( "playing" , function ( ) {
@@ -165,6 +172,17 @@ var ZenPlayer = {
165
172
updateTweetMessage ( ) ;
166
173
} ) ;
167
174
175
+ // when player has finished playing
176
+ plyrPlayer . addEventListener ( "ended" , function ( ) {
177
+ if ( autoplayState ) {
178
+ if ( playList . length === 0 || playList . size === 0 ) {
179
+ fetchSuggestedVideoIds ( ) ;
180
+ }
181
+ var newId = getNewVideoID ( ) ;
182
+ that . playNext ( newId ) ;
183
+ }
184
+ } ) ;
185
+
168
186
plyrPlayer . addEventListener ( "timeupdate" , function ( ) {
169
187
// Nothing is playing
170
188
if ( ! plyrPlayer . plyr || ! plyrPlayer . plyr . embed ) {
@@ -223,6 +241,11 @@ var ZenPlayer = {
223
241
} ) ;
224
242
}
225
243
} ,
244
+ // play next song from autoplay
245
+ playNext : function ( videoID ) {
246
+ $ ( "#v" ) . val ( videoID ) ;
247
+ $ ( "#form" ) . submit ( ) ;
248
+ } ,
226
249
show : function ( ) {
227
250
$ ( "#audioplayer" ) . show ( ) ;
228
251
// Hide the demo link as some video is playing
@@ -258,6 +281,24 @@ var ZenPlayer = {
258
281
toggleElement ( event , ".plyr__video-wrapper" , "Player" ) ;
259
282
} ) ;
260
283
} ,
284
+ setupAutoplayToggle : function ( ) {
285
+ // toggle auto next song playing
286
+ $ ( "#toggleAutoplay" ) . click ( function ( event ) {
287
+ var toggleTextElement = $ ( "#" + event . currentTarget . id ) ;
288
+ if ( autoplayState ) {
289
+ toggleTextElement . text ( "Start autoplay" ) ;
290
+ autoplayState = false ;
291
+ window . sessionStorage . removeItem ( "autoPlay" ) ;
292
+ window . sessionStorage . removeItem ( "playList" ) ;
293
+ }
294
+ else {
295
+ toggleTextElement . text ( "Stop autoplay" ) ;
296
+ autoplayState = true ;
297
+ window . sessionStorage . setItem ( "autoPlay" , true ) ;
298
+ }
299
+ } ) ;
300
+ } ,
301
+
261
302
getVideoDescription : function ( videoID ) {
262
303
var description = "" ;
263
304
@@ -275,6 +316,7 @@ var ZenPlayer = {
275
316
}
276
317
else {
277
318
description = data . items [ 0 ] . snippet . description ;
319
+ tags = data . items [ 0 ] . snippet . tags ;
278
320
}
279
321
} ,
280
322
function ( jqXHR , textStatus , errorThrown ) {
@@ -524,6 +566,79 @@ function pickDemo() {
524
566
return demos [ Math . floor ( Math . random ( ) * demos . length ) ] ;
525
567
}
526
568
569
+ function updateAutoplayToggle ( state ) {
570
+ if ( state ) {
571
+ $ ( "#toggleAutoplay" ) . text ( "Stop autoplay" ) ;
572
+ }
573
+ else {
574
+ $ ( "#toggleAutoplay" ) . text ( "Start autoplay" ) ;
575
+ }
576
+ }
577
+
578
+ function getNewVideoID ( ) {
579
+ var nextID = null ;
580
+ nextID = playList . pop ( ) ;
581
+ while ( currentVideoID === nextID ) {
582
+ nextID = playList . pop ( ) ;
583
+ }
584
+ window . sessionStorage . setItem ( "playList" , JSON . stringify ( playList ) ) ;
585
+ return nextID ;
586
+ }
587
+
588
+ function fetchSuggestedVideoIds ( ) {
589
+ if ( tags . length ) {
590
+ // get similar videos, populate playList
591
+ if ( ! isFileProtocol ( ) ) {
592
+ for ( let index = 0 ; index < tags . length && index < MAX_TAGS ; index ++ ) {
593
+ $ . ajax ( {
594
+ url : "https://www.googleapis.com/youtube/v3/search" ,
595
+ dataType : "json" ,
596
+ async : false ,
597
+ data : {
598
+ key : youTubeDataApiKey ,
599
+ part : "snippet" ,
600
+ type : "video" ,
601
+ order : "relevance" ,
602
+ q : tags [ index ] ,
603
+ maxResults : 2
604
+ } ,
605
+ success : onRelatedVideoFetchSuccess
606
+ } ) . fail ( function ( jqXHR , textStatus , errorThrown ) {
607
+ logError ( jqXHR , textStatus , errorThrown , "Related video lookup error" ) ;
608
+ } ) ;
609
+ }
610
+ playList = Array . from ( playList ) ;
611
+ window . sessionStorage . setItem ( "playList" , JSON . stringify ( playList ) ) ;
612
+ }
613
+ }
614
+ }
615
+
616
+ function onRelatedVideoFetchSuccess ( data ) {
617
+ // push items into playlist
618
+ for ( var i = 0 ; i < data . items . length ; i ++ ) {
619
+ playList . add ( data . items [ i ] . id . videoId ) ;
620
+ }
621
+ }
622
+
623
+ function loadAutoPlayDetails ( ) {
624
+ // load playList from session storage on reload
625
+ if ( window . sessionStorage . getItem ( "playList" ) ) {
626
+ playList = JSON . parse ( window . sessionStorage . getItem ( "playList" ) ) ;
627
+ }
628
+
629
+ // fetch autoPlay from session storage on reload
630
+ if ( window . sessionStorage . getItem ( "autoPlay" ) ) {
631
+ autoplayState = window . sessionStorage . getItem ( "autoPlay" ) ;
632
+ updateAutoplayToggle ( autoplayState ) ;
633
+ }
634
+ }
635
+
636
+ function resetAutoPlayList ( ) {
637
+ playList = new Set ( ) ;
638
+ tags = [ ] ;
639
+ window . sessionStorage . removeItem ( "playList" ) ;
640
+ }
641
+
527
642
$ ( function ( ) {
528
643
if ( / A n d r o i d | w e b O S | i P h o n e | i P a d | i P o d | B l a c k B e r r y | I E M o b i l e | O p e r a M i n i / i. test ( navigator . userAgent ) ) {
529
644
$ ( "#container" ) . hide ( ) ;
@@ -534,6 +649,8 @@ $(function() {
534
649
535
650
errorMessage . init ( ) ;
536
651
652
+ loadAutoPlayDetails ( ) ;
653
+
537
654
// How do we know if the value is truly invalid?
538
655
// Preload the form from the URL
539
656
var currentVideoID = getCurrentVideoID ( ) ;
@@ -608,20 +725,22 @@ $(function() {
608
725
data : {
609
726
key : youTubeDataApiKey ,
610
727
part : "snippet" ,
611
- fields : "items/snippet/description" ,
612
728
id : videoID
613
729
} ,
614
730
success : function ( data ) {
615
731
if ( data . items . length === 0 ) {
616
732
window . location . href = makeSearchURL ( formValue ) ;
617
733
}
618
734
else {
735
+ tags = data . items [ 0 ] . snippet . tags ;
619
736
window . location . href = makeListenURL ( videoID , formValueTime ) ;
620
737
}
621
738
}
622
739
} ) . fail ( function ( jqXHR , textStatus , errorThrown ) {
623
740
logError ( jqXHR , textStatus , errorThrown , "Lookup error" ) ;
624
741
} ) ;
742
+ // fetching next videoIds for auto play
743
+ fetchSuggestedVideoIds ( ) ;
625
744
}
626
745
}
627
746
else {
@@ -654,6 +773,8 @@ $(function() {
654
773
// Handle demo link click
655
774
$ ( "#demo" ) . click ( function ( event ) {
656
775
event . preventDefault ( ) ;
776
+ resetAutoPlayList ( ) ;
777
+
657
778
gtag ( "send" , "event" , "demo" , "clicked" ) ;
658
779
659
780
// Don't continue appending to the URL if it appears "good enough".
@@ -670,13 +791,22 @@ $(function() {
670
791
// Handle focus link click
671
792
$ ( "#focus-btn" ) . click ( function ( event ) {
672
793
event . preventDefault ( ) ;
794
+ resetAutoPlayList ( ) ;
795
+
673
796
gtag ( "send" , "event" , "focus" , "clicked" ) ;
674
797
// Redirect to the favorite "focus" URL
675
798
window . location . href = makeListenURL ( focusId ) ;
676
799
} ) ;
677
800
801
+ // handle click on search icon
802
+ $ ( "#submit" ) . click ( function ( ) {
803
+ resetAutoPlayList ( ) ;
804
+ } ) ;
805
+
678
806
// Check if the current ID is the focus ID
679
807
$ ( window ) . on ( "load" , function ( ) {
808
+ loadAutoPlayDetails ( ) ;
809
+
680
810
// Show Focus Button
681
811
if ( window . location . href . indexOf ( focusId ) === - 1 ) {
682
812
$ ( "#focus-btn" ) . show ( ) ;
0 commit comments