I am trying to add a button click event in JW Player to seek 10 seconds forward from current frame. But default getCurrent() function is not working.
Here is my code -
jwplayer('#myElement');
const forwardDisplayButton = (<HTMLElement>forwardContainer.querySelector('.jw-icon-rewind'));
const forwardControlBarButton = (<HTMLElement>forwardContainer.querySelector('.jw-icon-rewind'));
[forwardDisplayButton, forwardControlBarButton].forEach(button => {
button.onclick = () => {
player.seek((player.getPosition() + 10));
}
})
And Here is my error -
player.getPosition is not a function
Thank you in advance
Related
I have 12 boxes I need to have turn on one after another after I press the 'MOVE' button in Javascript. The CSS and HTML I already have written for the program.
This is the code I've written so far to turn on each box individually, but I need them all to turn on automatically and consecutively after 1 second with a single click of a button.
on = () => {
const element = document.getElementById('s1');
element.classList.toggle('on');
}
let timer = null;
start = () => {
timer = setTimeout(() => {
toggle();
start();
}, 1000);
}
stop = () => {
clearTimeout(timer);
}
I have a long infinite scroll page full of videos that I am refreshing a sticky ad on. On each scroll to a new video the URL is updated. Each URL update fires a callback that calls the refresh function. I would like to rate limit how fast the function can be fired so that refresh calls don't happen too fast if the user scrolls too quickly.
I have been able to get throttle working in a test environment while using an event listener for a button click instead of the URL change callback, but have been unable to find a way to make it work without an event listener.
Here's the base code, as you can see I need to rate-limit how fast refreshFirstSlot is called.
// Function which refreshes the first slot
var refreshFirstSlot = function () {
googletag.cmd.push(function () {
googletag.pubads().refresh([adSlot1]);
});
};
// UrlUpdate is called each time the URL updates
UrlUpdate = function (url, type) {
refreshFirstSlot();
};
// throttle code
const throttle = (callback, delay) => {
let throttleTimeout = null;
let storedEvent = null;
const throttledEventHandler = (event) => {
storedEvent = event;
const shouldHandleEvent = !throttleTimeout;
if (shouldHandleEvent) {
callback(storedEvent);
storedEvent = null;
throttleTimeout = setTimeout(() => {
throttleTimeout = null;
if (storedEvent) {
throttledEventHandler(storedEvent);
}
}, delay);
}
};
return throttledEventHandler;
};
// adding the refresh call
var returnedFunction = throttle(function () {
refreshFirstSlot();
}, 5000);
// final call
UrlUpdate = function (url, type) {
returnedFunction();
};
Where am I going wrong here?
You could do something like this :
load your page => call your ad
scroll your page => refresh your ad unless previous call has not been rendered / ended
and so on...
To do so, you can use Google Publisher Tag's events (see here). Here is a simple example :
var refreshReady = false;
//slotRequested
googletag.pubads().addEventListener('slotRequested', function(event) {
var slotId = event.slot.getSlotElementId();
if(slotId === adSlot1.getSlotElementId()) {
//every time adSlot1 is requested, we disable the refresh variable
refreshReady = false;
}
});
//slotRenderEnded
googletag.pubads().addEventListener('slotRenderEnded', function(event) {
var slotId = event.slot.getSlotElementId();
if(slotId === adSlot1.getSlotElementId()) {
//every time adSlot1 has been rendered, we enable the refresh variable
refreshReady = true;
}
});
var refreshFirstSlot = function () {
if(refreshReady) {
googletag.cmd.push(function () {
googletag.pubads().refresh([adSlot1]);
});
}
else {
console.log('not yet !');
}
};
UrlUpdate = function (url, type) {
refreshFirstSlot();
};
You could add a timeout to make sure the ad is not refreshed as soon as rendered (improve viewability)
for a one-page portfolio, I have some repetition code for each button that control some video players populated by CMS.
I’ll have 15 to 20 players to control with each one is own button on the page to launch it , and return button to stop (1 on each section). I use Webflow which limit the number of characters for the code.
I would love to find the shorter/smarter way to write this for each player without 20 repetition in the code.
///////// for Player 0 //
// Play on click .titre
on('#titre-2', 'click', () => {
players[0].play();
});
// Stop and back to 0 at end
players[0].on('ended', function(event) {
players[0].pause();
players[0].currentTime = 0;
////////// for Player 1 //
// play on click .titre
on('#titre-3', 'click', () => {
players[1].play();
});
// stop at end
players[1].on('ended', function(event) {
players[1].pause();
players[1].currentTime = 0;
});
/////// for player 3 ////
...
... and so on for 15 to 20 players, until last player
(number of players is subject to change when updating the portfolio with CMS)
EDIT : here is the full code from the beginning, with the part of the code for each player at the end, that need to be improved :
<script src="https://cdn.plyr.io/3.5.6/plyr.js"></script>
<script>
document.addEventListener('DOMContentLoaded', () => {
const controls = [
'play-large','restart','play','progress',
'current-time','mute','volume','fullscreen'
];
//init PLAYERS
const players = Array.from(document.querySelectorAll('.player_js')).map(p => new Plyr(p,{ controls }));
// Expose player so it can be used from the console
window.players = players;
// Bind event listener
function on(selector, type, callback) {
document.querySelector(selector).addEventListener(type, callback, false);
}
///////// for Player 0 //
// Play on click .titre
on('#titre-2', 'click', () => {
players[0].play();
});
// Stop and back to 0 at end
players[0].on('ended', function(event) {
players[0].pause();
players[0].currentTime = 0;
////////// for Player 1 //
// play on click .titre
on('#titre-3', 'click', () => {
players[1].play();
});
// stop at end
players[1].on('ended', function(event) {
players[1].pause();
players[1].currentTime = 0;
});
/////// for player 3 ////
/// AND SO ON ...
});
You can loop the code :
for(let x = 0 ; x < 20 ; x ++){
// Play on click .titre
on('#titre-' + (x + 2), 'click', () => {
players[x].play();
});
// Stop and back to 0 at end
players[x].on('ended', function(event) {
players[x].pause();
players[x].currentTime = 0;
}
But the best solution is create a class of players
I'm aware that I need a user action to start Web Audio on mobile. However I have followed the recommendation to resume (in the case of Tone.js call Tone.start()) on user action but it still don't work.
Here are the relevant parts of my code:
keyElement.addEventListener("touchstart", notePressed, false);
keyElement.addEventListener("touchend", noteReleased, false);
function notePressed(event) {
let dataset = event.target.dataset;
if (!dataset["pressed"]) {
let octave = +dataset["octave"];
oscList[octave][dataset["note"]] = playTone(dataset["frequency"]);
dataset["pressed"] = "yes";
}
event.preventDefault(); event.stopPropagation();
}
function noteReleased(event) {
let dataset = event.target.dataset;
if (dataset && dataset["pressed"]) {
let octave = +dataset["octave"];
oscList[octave][dataset["note"]].triggerRelease();
delete oscList[octave][dataset["note"]];
delete dataset["pressed"];
}
}
function playTone(freq) {
let synth = new Tone.Synth().toDestination();
let now = Tone.now();
Tone.start();
synth.triggerAttack(freq, now);
return synth;
}
It works fine on the second touch, but after the first touch I get a warning about the audio context being suspended, even though the standard is that it is resumed when start() is called by a user action. I'm stumped here.
That Tone code looks correct. I simplified it in a CodePen and it worked on mobile on first click (iOS).
var keyElement = document.getElementById("play");
keyElement.addEventListener("touchstart", notePressed, false);
keyElement.addEventListener("touchend", noteReleased, false);
// Added mouse ELs to test on non-mobile.
keyElement.addEventListener("mousedown", notePressed, false);
keyElement.addEventListener("mouseup", noteReleased, false);
var pressedTone;
function notePressed(event) {
console.log("notePressed");
pressedTone = playTone(440);
event.preventDefault();
event.stopPropagation();
}
function noteReleased(event) {
pressedTone.triggerRelease();
}
function playTone(freq) {
console.log("playTone", freq);
let synth = new Tone.Synth().toDestination();
let now = Tone.now();
Tone.start();
synth.triggerAttack(freq, now);
return synth;
}
Here's the link to the CodePen: https://codepen.io/joeweiss/pen/gOmeQVW
I'm trying to play videos one after the other in the same Vimeo player, without success.
This is the code I'm working on. I can't find any example on how to do that.
I'm sure I'm wrong but I don't know how to go further...
var iframe = document.querySelector('iframe.main-player');
var player = new Vimeo.Player(iframe);
var video_ids = ['123456789', '987654321'];
video_ids.forEach(function(item, index) {
player.pause();
player.loadVideo(item);
player.on('loaded', function() {
player.play();
});
})
I'm not sure about this, because can't test it right now , but you can try something like this:
var iframe = document.querySelector('iframe.main-player');
var player = new Vimeo.Player(iframe);
var video_ids = ['123456789', '987654321'];
var index = 0;
var playNext = function(data){
player.pause();
if(index<=video_ids.length)
player.loadVideo(video_ids[index++])
}
player.pause();
player.loadVideo(video_ids[index++]);
player.on('loaded', function() {
player.play();
});
player.on('ended', playNext);
The idea is pretty simple by listen to the ended event then moving to the next item.
First of all, we just create a class to hold some information such as the list & current playing index:
import Player from "#vimeo/player";
class Playlist {
constructor(playlist) {
this.playlist = playlist;
this.currentIdx = 0;
}
init() {
this.player = new Player("app", {
id: this.currentItem,
width: 640
});
this.player.on("ended", this.onEnded.bind(this));
}
onEnded() {
if (this.currentIdx < this.playlist.length) {
this.currentIdx++;
const nextId = this.currentItem;
this.player.loadVideo(nextId);
// Check next item has loaded then play it automatically
// you might not receive any error in case of having to interact with document
this.player.on("loaded", () => {
this.player.play();
});
}
}
get currentItem() {
return this.playlist[this.currentIdx];
}
}
// Try to run 2 items
const pl = new Playlist([59777392, 28582484]);
pl.init();
NOTE: I also created a codesandbox link for you here https://codesandbox.io/s/focused-firefly-ej0fd?file=/src/index.js