From d88da2e241f6f53c09d7b91e615b6f7110d4bf2a Mon Sep 17 00:00:00 2001 From: Mark Boas Date: Sun, 14 Aug 2022 12:06:17 +0200 Subject: [PATCH 01/12] refactor - abstract player code (native, soundcloud, youtube) --- js/hyperaudio-lite.js | 234 +++++++++++++++++++++++++----------------- 1 file changed, 141 insertions(+), 93 deletions(-) diff --git a/js/hyperaudio-lite.js b/js/hyperaudio-lite.js index 237e109..5d19678 100644 --- a/js/hyperaudio-lite.js +++ b/js/hyperaudio-lite.js @@ -1,8 +1,127 @@ /*! (C) The Hyperaudio Project. MIT @license: en.wikipedia.org/wiki/MIT_License. */ -/*! Version 2.0.14 */ +/*! Version 2.0.17 */ 'use strict'; +function nativePlayer(playerElement, instance) { + this.player = playerElement; + + this.player.addEventListener('pause', instance.clearTimer, false); + this.player.addEventListener('play', instance.checkPlayHead, false); + + this.getTime = () => { + console.log("native player getTime"); + return new Promise((resolve) => { + resolve(this.player.currentTime); + }); + } + + this.setTime = (seconds) => { + console.log("native player setTime"); + this.player.currentTime = seconds; + } + + this.play = () => { + console.log("native player play"); + this.player.play(); + } + + this.pause = () => { + console.log("native player pause"); + this.player.pause(); + } +} + +function soundcloudPlayer(playerElement, instance) { + this.player = playerElement; + + this.player = SC.Widget(this.player.id); + this.player.bind(SC.Widget.Events.PAUSE, instance.clearTimer); + this.player.bind(SC.Widget.Events.PLAY, instance.checkPlayHead); + + this.getTime = () => { + console.log("soundcloud player getTime"); + return new Promise((resolve) => { + this.player.getPosition(ms => { + console.log("got the time"); + resolve(ms / 1000); + }); + }); + } + + this.setTime = (seconds) => { + console.log("soundCloud player setTime"); + this.player.seekTo(seconds * 1000); + } + + this.play = () => { + console.log("soundCloud player play"); + this.player.play(); + } + + this.pause = () => { + console.log("native player pause"); + this.player.pause(); + } +} + +function youtubePlayer(playerElement, instance) { + + this.player = playerElement; + + const tag = document.createElement('script'); + tag.id = 'iframe-demo'; + tag.src = 'https://www.youtube.com/iframe_api'; + const firstScriptTag = document.getElementsByTagName('script')[0]; + firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); + + const previousYTEvent = window.onYouTubeIframeAPIReady; + window.onYouTubeIframeAPIReady = () => { + + if (typeof previousYTEvent !== 'undefined') { // used for multiple YouTube players + previousYTEvent(); + } + + this.player = new YT.Player(this.player.id, { + events: { + onStateChange: onPlayerStateChange, + }, + }); + }; + + let onPlayerStateChange = event => { + if (event.data === 1) { + // playing + instance.checkPlayHead(); + } else if (event.data === 2) { + // paused + instance.clearTimer(); + } + }; + + this.getTime = () => { + console.log("youtube player getTime"); + return new Promise((resolve) => { + resolve(this.player.getCurrentTime()); + }); + } + + this.setTime = (seconds) => { + console.log("youtube player setTime"); + this.player.seekTo(seconds, true); + } + + this.play = () => { + console.log("youtube player play"); + this.player.playVideo(); + } + + this.pause = () => { + console.log("youtube player pause"); + this.player.pauseVideo(); + } +} + class HyperaudioLite { constructor(transcriptId, mediaElementId, minimizedMode, autoscroll, doubleClick, webMonetization) { this.transcript = document.getElementById(transcriptId); @@ -10,6 +129,7 @@ class HyperaudioLite { } init = (mediaElementId, m, a, d, w) => { + const windowHash = window.location.hash; const hashVar = windowHash.substring(1, windowHash.indexOf('=')); @@ -45,6 +165,8 @@ class HyperaudioLite { this.webMonetization = w; this.highlightedText = false; this.start = null; + + this.myPlayer = null; if (this.autoscroll === true) { @@ -60,7 +182,6 @@ class HyperaudioLite { this.parentTag = words[0].parentElement.tagName; this.parentElements = this.transcript.getElementsByTagName(this.parentTag); - this.player = document.getElementById(mediaElementId); if (this.player.tagName == 'VIDEO' || this.player.tagName == 'AUDIO') { @@ -72,44 +193,14 @@ class HyperaudioLite { } if (this.playerType === 'native') { - this.player.addEventListener('pause', this.clearTimer, false); - this.player.addEventListener('play', this.checkPlayHead, false); + // native + this.myPlayer = new nativePlayer(this.player, this); } else if (this.playerType === 'soundcloud') { // SoundCloud - this.player = SC.Widget(mediaElementId); - this.player.bind(SC.Widget.Events.PAUSE, this.clearTimer); - this.player.bind(SC.Widget.Events.PLAY, this.checkPlayHead); + this.myPlayer = new soundcloudPlayer(this.player, this); } else { // assume YouTube - const tag = document.createElement('script'); - tag.id = 'iframe-demo'; - tag.src = 'https://www.youtube.com/iframe_api'; - const firstScriptTag = document.getElementsByTagName('script')[0]; - firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); - - const previousYTEvent = window.onYouTubeIframeAPIReady; - window.onYouTubeIframeAPIReady = () => { - - if (typeof previousYTEvent !== 'undefined') { // used for multiple YouTube players - previousYTEvent(); - } - - this.player = new YT.Player(mediaElementId, { - events: { - onStateChange: onPlayerStateChange, - }, - }); - }; - - let onPlayerStateChange = event => { - if (event.data === 1) { - // playing - this.checkPlayHead(); - } else if (event.data === 2) { - // paused - this.clearTimer(); - } - }; + this.myPlayer = new youtubePlayer(this.player, this); } this.parentElementIndex = 0; @@ -151,7 +242,7 @@ class HyperaudioLite { } } } - }; + }; // end init createWordArray = words => { let wordArr = []; @@ -261,18 +352,7 @@ class HyperaudioLite { if (!isNaN(parseFloat(timeSecs))) { this.end = null; - - if (this.playerType === 'native') { - this.player.currentTime = timeSecs; - this.player.play(); - } else if (this.playerType === 'soundcloud') { - this.player.seekTo(timeSecs * 1000); - this.player.play(); - } else { - //assume YouTube - this.player.seekTo(timeSecs, true); - this.player.playVideo(); - } + this.myPlayer.setTime(timeSecs); } }; @@ -282,46 +362,21 @@ class HyperaudioLite { checkPlayHead = () => { - this.clearTimer(); - - if (this.playerType === 'native') { - this.currentTime = this.player.currentTime; - if (this.highlightedText === true) { - this.currentTime = this.start; - this.player.currentTime = this.currentTime; - this.highlightedText = false; - } - this.checkStatus(); - } else if (this.playerType === 'soundcloud') { - - this.player.getPosition(ms => { - this.currentTime = ms / 1000; - if (this.highlightedText === true) { - this.currentTime = this.start; - this.player.seekTo(this.currentTime * 1000); - this.highlightedText = false; - } - - this.checkStatus(); - }); - } else { - // assume YouTube + console.log("checkPlayHead"); - // Note – there is an issue when the video is already cached - // and we're attempting to play a highlighted section, - // where it jumps to the buffered point before seeking to - // the correct place – but doesn't play. - // May have to detect a suitable event before seeking. + this.clearTimer(); - this.currentTime = this.player.getCurrentTime(); + (async (instance) => { + instance.currentTime = await instance.myPlayer.getTime(); - if (this.highlightedText === true) { - this.currentTime = this.start; - this.player.seekTo(this.start, true); - this.highlightedText = false; + if (instance.highlightedText === true) { + instance.currentTime = instance.start; + instance.myPlayer.setTime(instance.currentTime); + instance.highlightedText = false; } - this.checkStatus(); - } + instance.checkStatus(); + })(this); + } scrollToParagraph = (currentParentElementIndex, index) => { @@ -370,14 +425,7 @@ class HyperaudioLite { //check for end time of shared piece if (this.end && this.end < this.currentTime) { - if (this.playerType === 'native') { - this.player.pause(); - } else if (this.playerType === 'soundcloud') { - this.player.pause(); - } else { - // assume YouTube - this.player.pauseVideo(); - } + this.myPlayer.pause(); this.end = null; } else { let newPara = false; From 8779a957cf7a9eb859d399c20227dc2d2aabc881 Mon Sep 17 00:00:00 2001 From: Marco Scarselli Date: Mon, 15 Aug 2022 10:56:53 +0200 Subject: [PATCH 02/12] strategyPlayer interface and options --- js/hyperaudio-lite.js | 42 +++++++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/js/hyperaudio-lite.js b/js/hyperaudio-lite.js index 5d19678..eb1ad33 100644 --- a/js/hyperaudio-lite.js +++ b/js/hyperaudio-lite.js @@ -3,9 +3,14 @@ 'use strict'; + +function strategyPlayer(concretePlayer, playerElement, instance) { + return new concretePlayer(playerElement, instance) +} + function nativePlayer(playerElement, instance) { this.player = playerElement; - + this.player.addEventListener('pause', instance.clearTimer, false); this.player.addEventListener('play', instance.checkPlayHead, false); @@ -34,7 +39,7 @@ function nativePlayer(playerElement, instance) { function soundcloudPlayer(playerElement, instance) { this.player = playerElement; - + this.player = SC.Widget(this.player.id); this.player.bind(SC.Widget.Events.PAUSE, instance.clearTimer); this.player.bind(SC.Widget.Events.PLAY, instance.checkPlayHead); @@ -81,7 +86,7 @@ function youtubePlayer(playerElement, instance) { if (typeof previousYTEvent !== 'undefined') { // used for multiple YouTube players previousYTEvent(); } - + this.player = new YT.Player(this.player.id, { events: { onStateChange: onPlayerStateChange, @@ -122,6 +127,13 @@ function youtubePlayer(playerElement, instance) { } } +let strategyPlayerOptions = { + "native": nativePlayer, + "soundcloud": soundcloudPlayer, + "youtube": youtubePlayer + +} + class HyperaudioLite { constructor(transcriptId, mediaElementId, minimizedMode, autoscroll, doubleClick, webMonetization) { this.transcript = document.getElementById(transcriptId); @@ -167,7 +179,7 @@ class HyperaudioLite { this.start = null; this.myPlayer = null; - + if (this.autoscroll === true) { this.scroller = window.Velocity || window.jQuery.Velocity; @@ -181,7 +193,7 @@ class HyperaudioLite { this.parentTag = words[0].parentElement.tagName; this.parentElements = this.transcript.getElementsByTagName(this.parentTag); - + this.player = document.getElementById(mediaElementId); if (this.player.tagName == 'VIDEO' || this.player.tagName == 'AUDIO') { @@ -192,16 +204,8 @@ class HyperaudioLite { this.playerType = this.player.getAttribute('data-player-type'); } - if (this.playerType === 'native') { - // native - this.myPlayer = new nativePlayer(this.player, this); - } else if (this.playerType === 'soundcloud') { - // SoundCloud - this.myPlayer = new soundcloudPlayer(this.player, this); - } else { - // assume YouTube - this.myPlayer = new youtubePlayer(this.player, this); - } + + this.myPlayer = strategyPlayer(strategyPlayerOptions[this.playerType], this.player, this) this.parentElementIndex = 0; @@ -221,7 +225,7 @@ class HyperaudioLite { if (!isNaN(parseFloat(this.start))) { this.highlightedText = true; - + let indices = this.updateTranscriptVisualState(this.start); let index = indices.currentWordIndex; @@ -280,7 +284,7 @@ class HyperaudioLite { if (selection.toString() !== '') { let fNode = selection.focusNode.parentNode; let aNode = selection.anchorNode.parentNode; - + if (aNode.tagName === "P") { aNode = selection.anchorNode.nextElementSibling; } @@ -499,7 +503,7 @@ class HyperaudioLite { checkPaymentPointer = element => { let paymentPointer = null; - + if (typeof(element) != "undefined") { paymentPointer = element.getAttribute('data-wm'); } @@ -616,4 +620,4 @@ if (typeof module !== 'undefined' && module.exports) { module.exports = { HyperaudioLite }; } -//export default HyperaudioLite; +//export default HyperaudioLite; \ No newline at end of file From 2031133614df0e7e4aebdfbb52d1935675b35453 Mon Sep 17 00:00:00 2001 From: Mark Boas Date: Mon, 15 Aug 2022 15:52:18 +0200 Subject: [PATCH 03/12] renaming and function order --- js/hyperaudio-lite.js | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/js/hyperaudio-lite.js b/js/hyperaudio-lite.js index eb1ad33..56e319e 100644 --- a/js/hyperaudio-lite.js +++ b/js/hyperaudio-lite.js @@ -3,11 +3,6 @@ 'use strict'; - -function strategyPlayer(concretePlayer, playerElement, instance) { - return new concretePlayer(playerElement, instance) -} - function nativePlayer(playerElement, instance) { this.player = playerElement; @@ -127,11 +122,14 @@ function youtubePlayer(playerElement, instance) { } } -let strategyPlayerOptions = { +const hyperaudioPlayerOptions = { "native": nativePlayer, "soundcloud": soundcloudPlayer, "youtube": youtubePlayer +} +function hyperaudioPlayer(playerType, playerElement, instance) { + return new playerType(playerElement, instance) } class HyperaudioLite { @@ -205,7 +203,7 @@ class HyperaudioLite { } - this.myPlayer = strategyPlayer(strategyPlayerOptions[this.playerType], this.player, this) + this.myPlayer = hyperaudioPlayer(hyperaudioPlayerOptions[this.playerType], this.player, this) this.parentElementIndex = 0; From d4928256994331d33bc25ad826f98c9d0d9f2054 Mon Sep 17 00:00:00 2001 From: Mark Boas Date: Wed, 17 Aug 2022 20:03:36 +0200 Subject: [PATCH 04/12] remove logging and adapt test --- __TEST__/hyperaudio-lite.test.js | 9 ++++++--- js/hyperaudio-lite.js | 16 ---------------- 2 files changed, 6 insertions(+), 19 deletions(-) diff --git a/__TEST__/hyperaudio-lite.test.js b/__TEST__/hyperaudio-lite.test.js index c641ed8..9f8a4e9 100644 --- a/__TEST__/hyperaudio-lite.test.js +++ b/__TEST__/hyperaudio-lite.test.js @@ -1,7 +1,7 @@ /** * @jest-environment jsdom * - * Tests updated for version 2.0.8 + * Tests updated for version 2.1.7 */ const { test } = require("@jest/globals"); @@ -153,7 +153,10 @@ test("instantiation - webMonetization true", () => { test("media playback - payment pointer inserted", () => { simulateClick(document.getElementsByTagName("span")[4], "click"); - const paymentPointer = document.querySelector('[name="monetization"]'); - expect(paymentPointer.content).toStrictEqual("payment-pointer"); + jest.setTimeout(() => { + const paymentPointer = document.querySelector('[name="monetization"]'); + expect(paymentPointer.content).toStrictEqual("payment-pointer"); + }, "100") + }); diff --git a/js/hyperaudio-lite.js b/js/hyperaudio-lite.js index 56e319e..b8e719c 100644 --- a/js/hyperaudio-lite.js +++ b/js/hyperaudio-lite.js @@ -10,24 +10,20 @@ function nativePlayer(playerElement, instance) { this.player.addEventListener('play', instance.checkPlayHead, false); this.getTime = () => { - console.log("native player getTime"); return new Promise((resolve) => { resolve(this.player.currentTime); }); } this.setTime = (seconds) => { - console.log("native player setTime"); this.player.currentTime = seconds; } this.play = () => { - console.log("native player play"); this.player.play(); } this.pause = () => { - console.log("native player pause"); this.player.pause(); } } @@ -40,27 +36,22 @@ function soundcloudPlayer(playerElement, instance) { this.player.bind(SC.Widget.Events.PLAY, instance.checkPlayHead); this.getTime = () => { - console.log("soundcloud player getTime"); return new Promise((resolve) => { this.player.getPosition(ms => { - console.log("got the time"); resolve(ms / 1000); }); }); } this.setTime = (seconds) => { - console.log("soundCloud player setTime"); this.player.seekTo(seconds * 1000); } this.play = () => { - console.log("soundCloud player play"); this.player.play(); } this.pause = () => { - console.log("native player pause"); this.player.pause(); } } @@ -100,24 +91,20 @@ function youtubePlayer(playerElement, instance) { }; this.getTime = () => { - console.log("youtube player getTime"); return new Promise((resolve) => { resolve(this.player.getCurrentTime()); }); } this.setTime = (seconds) => { - console.log("youtube player setTime"); this.player.seekTo(seconds, true); } this.play = () => { - console.log("youtube player play"); this.player.playVideo(); } this.pause = () => { - console.log("youtube player pause"); this.player.pauseVideo(); } } @@ -364,8 +351,6 @@ class HyperaudioLite { checkPlayHead = () => { - console.log("checkPlayHead"); - this.clearTimer(); (async (instance) => { @@ -378,7 +363,6 @@ class HyperaudioLite { } instance.checkStatus(); })(this); - } scrollToParagraph = (currentParentElementIndex, index) => { From 9e4155be136e48ef5aef1d7b8123d466d3edb2cc Mon Sep 17 00:00:00 2001 From: Mark Boas Date: Thu, 18 Aug 2022 12:05:16 +0200 Subject: [PATCH 05/12] semi colons and spacing --- js/hyperaudio-lite.js | 30 ++---------------------------- 1 file changed, 2 insertions(+), 28 deletions(-) diff --git a/js/hyperaudio-lite.js b/js/hyperaudio-lite.js index b8e719c..3c8e7aa 100644 --- a/js/hyperaudio-lite.js +++ b/js/hyperaudio-lite.js @@ -5,7 +5,6 @@ function nativePlayer(playerElement, instance) { this.player = playerElement; - this.player.addEventListener('pause', instance.clearTimer, false); this.player.addEventListener('play', instance.checkPlayHead, false); @@ -30,7 +29,6 @@ function nativePlayer(playerElement, instance) { function soundcloudPlayer(playerElement, instance) { this.player = playerElement; - this.player = SC.Widget(this.player.id); this.player.bind(SC.Widget.Events.PAUSE, instance.clearTimer); this.player.bind(SC.Widget.Events.PLAY, instance.checkPlayHead); @@ -57,9 +55,7 @@ function soundcloudPlayer(playerElement, instance) { } function youtubePlayer(playerElement, instance) { - this.player = playerElement; - const tag = document.createElement('script'); tag.id = 'iframe-demo'; tag.src = 'https://www.youtube.com/iframe_api'; @@ -68,7 +64,6 @@ function youtubePlayer(playerElement, instance) { const previousYTEvent = window.onYouTubeIframeAPIReady; window.onYouTubeIframeAPIReady = () => { - if (typeof previousYTEvent !== 'undefined') { // used for multiple YouTube players previousYTEvent(); } @@ -126,7 +121,6 @@ class HyperaudioLite { } init = (mediaElementId, m, a, d, w) => { - const windowHash = window.location.hash; const hashVar = windowHash.substring(1, windowHash.indexOf('=')); @@ -165,20 +159,15 @@ class HyperaudioLite { this.myPlayer = null; - if (this.autoscroll === true) { this.scroller = window.Velocity || window.jQuery.Velocity; } //Create the array of timed elements (wordArr) - const words = this.transcript.querySelectorAll('[data-m]'); - this.wordArr = this.createWordArray(words); - this.parentTag = words[0].parentElement.tagName; this.parentElements = this.transcript.getElementsByTagName(this.parentTag); - this.player = document.getElementById(mediaElementId); if (this.player.tagName == 'VIDEO' || this.player.tagName == 'AUDIO') { @@ -189,14 +178,10 @@ class HyperaudioLite { this.playerType = this.player.getAttribute('data-player-type'); } - - this.myPlayer = hyperaudioPlayer(hyperaudioPlayerOptions[this.playerType], this.player, this) - + this.myPlayer = hyperaudioPlayer(hyperaudioPlayerOptions[this.playerType], this.player, this); this.parentElementIndex = 0; - words[0].classList.add('active'); this.parentElements[0].classList.add('active'); - let playHeadEvent = 'click'; if (this.doubleClick === true) { @@ -222,7 +207,6 @@ class HyperaudioLite { this.end = this.hashArray[1]; //TODO convert to binary search for below for quicker startup - if (this.start && this.end) { for (let i = 1; i < words.length; i++) { const wordStart = parseInt(words[i].getAttribute('data-m')) / 1000; @@ -297,7 +281,6 @@ class HyperaudioLite { } // 1 decimal place will do - aNodeTime = Math.round(aNodeTime / 100) / 10; aNodeDuration = Math.round(aNodeDuration / 100) / 10; fNodeTime = Math.round(fNodeTime / 100) / 10; @@ -328,7 +311,6 @@ class HyperaudioLite { this.highlightedText = false; // clear elements with class='active' - let activeElements = Array.from(this.transcript.getElementsByClassName('active')); activeElements.forEach(e => { @@ -350,7 +332,6 @@ class HyperaudioLite { }; checkPlayHead = () => { - this.clearTimer(); (async (instance) => { @@ -401,7 +382,6 @@ class HyperaudioLite { } newPara = true; - this.parentElementIndex = currentParentElementIndex; } return(newPara); @@ -409,7 +389,6 @@ class HyperaudioLite { checkStatus = () => { //check for end time of shared piece - if (this.end && this.end < this.currentTime) { this.myPlayer.pause(); this.end = null; @@ -425,7 +404,6 @@ class HyperaudioLite { } //minimizedMode is still experimental - it changes document.title upon every new word - if (this.minimizedMode) { const elements = transcript.querySelectorAll('[data-m]'); let currentWord = ''; @@ -462,9 +440,7 @@ class HyperaudioLite { if (this.webMonetization === true) { //check for payment pointer - let activeElements = this.transcript.getElementsByClassName('active'); - let paymentPointer = this.checkPaymentPointer(activeElements[activeElements.length - 1]); if (paymentPointer !== null) { @@ -531,6 +507,7 @@ class HyperaudioLite { this.wordArr.forEach((word, i) => { let classList = word.n.classList; + if (i < index) { classList.add('read'); classList.remove('unread'); @@ -544,7 +521,6 @@ class HyperaudioLite { this.parentElements = this.transcript.getElementsByTagName(this.parentTag); //remove active class from all paras - Array.from(this.parentElements).forEach(el => { if (el.classList.contains('active')) { el.classList.remove('active'); @@ -552,7 +528,6 @@ class HyperaudioLite { }); // set current word and para to active - if (index > 0) { this.wordArr[index - 1].n.classList.add('active'); @@ -562,7 +537,6 @@ class HyperaudioLite { } // Establish current paragraph index - let currentParentElementIndex; Array.from(this.parentElements).every((el, i) => { From 5e0568d2f281b62aa103153c6e2e86610c8ca5a3 Mon Sep 17 00:00:00 2001 From: Mark Boas Date: Thu, 18 Aug 2022 12:25:08 +0200 Subject: [PATCH 06/12] removed redundancy from players --- js/hyperaudio-lite.js | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/js/hyperaudio-lite.js b/js/hyperaudio-lite.js index 3c8e7aa..3e83d42 100644 --- a/js/hyperaudio-lite.js +++ b/js/hyperaudio-lite.js @@ -3,8 +3,8 @@ 'use strict'; -function nativePlayer(playerElement, instance) { - this.player = playerElement; +function nativePlayer(instance) { + this.player = instance.player; this.player.addEventListener('pause', instance.clearTimer, false); this.player.addEventListener('play', instance.checkPlayHead, false); @@ -27,9 +27,8 @@ function nativePlayer(playerElement, instance) { } } -function soundcloudPlayer(playerElement, instance) { - this.player = playerElement; - this.player = SC.Widget(this.player.id); +function soundcloudPlayer(instance) { + this.player = SC.Widget(instance.player.id); this.player.bind(SC.Widget.Events.PAUSE, instance.clearTimer); this.player.bind(SC.Widget.Events.PLAY, instance.checkPlayHead); @@ -54,8 +53,7 @@ function soundcloudPlayer(playerElement, instance) { } } -function youtubePlayer(playerElement, instance) { - this.player = playerElement; +function youtubePlayer(instance) { const tag = document.createElement('script'); tag.id = 'iframe-demo'; tag.src = 'https://www.youtube.com/iframe_api'; @@ -68,7 +66,7 @@ function youtubePlayer(playerElement, instance) { previousYTEvent(); } - this.player = new YT.Player(this.player.id, { + this.player = new YT.Player(instance.player.id, { events: { onStateChange: onPlayerStateChange, }, @@ -110,8 +108,8 @@ const hyperaudioPlayerOptions = { "youtube": youtubePlayer } -function hyperaudioPlayer(playerType, playerElement, instance) { - return new playerType(playerElement, instance) +function hyperaudioPlayer(playerType, instance) { + return new playerType(instance); } class HyperaudioLite { @@ -178,7 +176,7 @@ class HyperaudioLite { this.playerType = this.player.getAttribute('data-player-type'); } - this.myPlayer = hyperaudioPlayer(hyperaudioPlayerOptions[this.playerType], this.player, this); + this.myPlayer = hyperaudioPlayer(hyperaudioPlayerOptions[this.playerType], this); this.parentElementIndex = 0; words[0].classList.add('active'); this.parentElements[0].classList.add('active'); @@ -507,7 +505,7 @@ class HyperaudioLite { this.wordArr.forEach((word, i) => { let classList = word.n.classList; - + if (i < index) { classList.add('read'); classList.remove('unread'); From 29a8a8c9270ccff02b7830f4f9147998c6db06f9 Mon Sep 17 00:00:00 2001 From: Mark Boas Date: Thu, 18 Aug 2022 19:09:18 +0200 Subject: [PATCH 07/12] replace substr with substring --- js/hyperaudio-lite.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/hyperaudio-lite.js b/js/hyperaudio-lite.js index 3e83d42..6dca4bc 100644 --- a/js/hyperaudio-lite.js +++ b/js/hyperaudio-lite.js @@ -123,7 +123,7 @@ class HyperaudioLite { const hashVar = windowHash.substring(1, windowHash.indexOf('=')); if (hashVar === this.transcript.id) { - this.hashArray = windowHash.substr(this.transcript.id.length + 2).split(','); + this.hashArray = windowHash.substring(this.transcript.id.length + 2).split(','); } else { this.hashArray = []; } From aaf12acef1b010dd009fd0d9706d96020a5757bc Mon Sep 17 00:00:00 2001 From: Mark Boas Date: Tue, 23 Aug 2022 15:30:07 +0100 Subject: [PATCH 08/12] fix for media slection pause (#119) --- js/hyperaudio-lite.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/hyperaudio-lite.js b/js/hyperaudio-lite.js index 6dca4bc..ef8da14 100644 --- a/js/hyperaudio-lite.js +++ b/js/hyperaudio-lite.js @@ -387,7 +387,7 @@ class HyperaudioLite { checkStatus = () => { //check for end time of shared piece - if (this.end && this.end < this.currentTime) { + if (this.end && parseInt(this.end) < parseInt(this.currentTime)) { this.myPlayer.pause(); this.end = null; } else { From e7f73b4aa80e460d29bab0caa5e3b36540b42784 Mon Sep 17 00:00:00 2001 From: Mark Boas Date: Wed, 24 Aug 2022 09:15:11 +0100 Subject: [PATCH 09/12] fix media playback test --- __TEST__/hyperaudio-lite.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/__TEST__/hyperaudio-lite.test.js b/__TEST__/hyperaudio-lite.test.js index 9f8a4e9..3614cb8 100644 --- a/__TEST__/hyperaudio-lite.test.js +++ b/__TEST__/hyperaudio-lite.test.js @@ -157,6 +157,6 @@ test("media playback - payment pointer inserted", () => { jest.setTimeout(() => { const paymentPointer = document.querySelector('[name="monetization"]'); expect(paymentPointer.content).toStrictEqual("payment-pointer"); - }, "100") + }, 0) }); From 3ce12ccaee0272e47b952dcfc0d8ad94443e60d7 Mon Sep 17 00:00:00 2001 From: Mark Boas Date: Wed, 24 Aug 2022 17:00:59 +0100 Subject: [PATCH 10/12] reflect correct text selection on reload #120 --- js/hyperaudio-lite.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/hyperaudio-lite.js b/js/hyperaudio-lite.js index ef8da14..2a22ad6 100644 --- a/js/hyperaudio-lite.js +++ b/js/hyperaudio-lite.js @@ -208,7 +208,7 @@ class HyperaudioLite { if (this.start && this.end) { for (let i = 1; i < words.length; i++) { const wordStart = parseInt(words[i].getAttribute('data-m')) / 1000; - if (wordStart > this.start && this.end > wordStart) { + if (wordStart > parseFloat(this.start) && parseFloat(this.end) > wordStart) { words[i].classList.add('share-match'); } } From a9084598d081f2a445f34c25d9ce1f3f8a542b04 Mon Sep 17 00:00:00 2001 From: Mark Boas Date: Thu, 8 Sep 2022 11:24:59 +0200 Subject: [PATCH 11/12] final changes --- js/hyperaudio-lite.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/js/hyperaudio-lite.js b/js/hyperaudio-lite.js index 2a22ad6..23be4ac 100644 --- a/js/hyperaudio-lite.js +++ b/js/hyperaudio-lite.js @@ -274,6 +274,10 @@ class HyperaudioLite { let fNodeDuration; if (fNode != null && fNode.getAttribute('data-m') != null) { + // if the selection ends in a space then we want the previous element + if(selection.toString().slice(-1) == " ") { + fNode = fNode.previousElementSibling; + } fNodeTime = parseInt(fNode.getAttribute('data-m'), 10); fNodeDuration = parseInt(fNode.getAttribute('data-d'), 10); } From 9fb1b83f5d4940dbe48c75f0d43051c39a20ed85 Mon Sep 17 00:00:00 2001 From: Mark Boas Date: Thu, 8 Sep 2022 12:04:36 +0200 Subject: [PATCH 12/12] more precise selection playback --- js/hyperaudio-lite.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/js/hyperaudio-lite.js b/js/hyperaudio-lite.js index 23be4ac..7b6c9e5 100644 --- a/js/hyperaudio-lite.js +++ b/js/hyperaudio-lite.js @@ -268,18 +268,27 @@ class HyperaudioLite { fNode = fNode.previousElementSibling; } + // if the selection starts with a space we want the next element + if(selection.toString().charAt(0) == " ") { + aNode = aNode.nextElementSibling; + } + let aNodeTime = parseInt(aNode.getAttribute('data-m'), 10); let aNodeDuration = parseInt(aNode.getAttribute('data-d'), 10); let fNodeTime; let fNodeDuration; if (fNode != null && fNode.getAttribute('data-m') != null) { - // if the selection ends in a space then we want the previous element + // if the selection ends in a space we want the previous element if(selection.toString().slice(-1) == " ") { fNode = fNode.previousElementSibling; } + fNodeTime = parseInt(fNode.getAttribute('data-m'), 10); fNodeDuration = parseInt(fNode.getAttribute('data-d'), 10); + + // if the selection starts with a space we want the next element + } // 1 decimal place will do