Why can I not save currentTime() to a variable? - javascript

I try to automatically get the currentTime()on button click, but the issue I have at the moment is that I cannot access player when the button "create" is clicked. It returns undefinied
How can I get access to player.currentTime() when create is clicked?
var player;
$('.start').on('click', function (event) {
initializePlayer("test.mp4");
$('.create').show();
});
$('.create').on('click', function (event) {
var start = player.currentTime();
// start is always undefined
console.log("start is ".start);
startConverting(start);
});
function startConverting(start) {
// converting
}
function initializePlayer(src) {
player = videojs('media', {
fluid: true,
controls: true,
});
player.src({
type: "video/mp4",
src: src,
});
}
I have been looking at this for a long time and can't see where my problem is. Any help would be great!
Thanks!
Edit:
I realized that if I console.log(player.currentTime()) it would output the time. Now, why can I not pass the value to var start and it is being undefined?

Related

Get data attr value on hover

I have a few links. When I hover mouse over the links I would like to get the values stored in data attributes. I need to pick the t values and pass them into function
HTML
<a href="#" data-lat="23.333452" data-lon="-97.2234234">
JS
var loc = document.querySelectorAll("a[data-lat]");
loc.addEventListener("mouseover", locOver);
loc.addEventListener("mouseout", locOut);
function locOver() {
// do something
}
function locOut() {
// do something else
}
It's been a while since I used vanilla JS and it's been a long day so I'm sure it's pretty close but I'm stuck. I keep getting:
Uncaught TypeError: loc.addEventListener is not a function
What am I missing here?
You need to loop through the nodes that you obtained with document.querySelectorAll("a[data-lat]") for adding events.
Working example.
Node
<script>
var loc = document.querySelectorAll("a[data-lat]");
loc.forEach(node => {
node.addEventListener("mouseover", locOver);
node.addEventListener("mouseout", locOut);
})
function locOver(event) {
// do something
console.log('mouseover', event.target.dataset)
}
function locOut() {
// do something
console.log('locOut')
}
</script>
const loc = document.querySelector("a[data-lat]");
const locOver = () => {
console.log("Mouse is over the link");
}
const locOut = () => {
console.log("Mouse is out of the link");
}
loc.addEventListener("mouseover", locOver);
loc.addEventListener("mouseout", locOut);
Link
Explanation:
I target the link using .querySelector method that returns a single node.
After that i created two event handler for mouseOver and mouseOut and than i added the eventListener to the link.

Bodymovin hover playing animation only once

Got my animation to trigger play on hover. I got everything to work but when I try to hover to play again, nothing seems to work.
Any ideas what I wrote wrong?
var squares = document.getElementById("test");
var animation = bodymovin.loadAnimation({
container: test,
renderer: "svg",
loop: false,
autoplay: false,
path: "https://dl.dropboxusercontent.com/BodyMovin/squares.json"
});
squares.addEventListener("mouseenter", function () {
animation.play();
});
function playAnim(anim, loop) {
if(anim.isPaused) {
anim.loop = loop;
anim.goToAndPlay(0);
}
}
function pauseAnim(anim) {
if (!anim.isPaused) {
anim.loop = false;
}
}
When the animation reaches it's final frame, it doesn't go back to the first one. That's why if you call play, nothing happens since it has already ended and there is no more to play.
You should do:
squares.addEventListener("mouseenter", function () {
animation.goToAndPlay(0);
});
And if you only want it to replay once it has reached it's final frame, this should work:
var isComplete = true;
svgContainer.addEventListener('mouseenter', function(){
if(isComplete){
squares.goToAndPlay(0);
isComplete = false;
}
})
squares.addEventListener('complete', function(){
isComplete = true;
})
I'm giving a shot on this, although my experience about Bodymovin (and Lottie) is only from React Native world.
This should be quite straight forward to stop animation and restart it when cursor leaves the element:
squares.addEventListener("mouseenter", function () {
animation.play();
});
squares.addEventListener("mouseleave", function () {
animation.gotoAndStop(0);
});

How to have multiple instances of a jQuery plugin

I am trying to create a SoundCloud music player. It can play any track from SoundCloud, but this plugin is only working if there is only one instance of it in the page. So it wont work if two of the same plugin are in the page.
Here is an example of having two players in the page: JSFiddle
var trackURL = $(".player").text();
$(".player").empty();
$(".player").append("<div class='playBTN'>Play</div>");
$(".player").append("<div class='title'></div>");
var trackId;
SC.get('/resolve', { url: trackURL }, function (track) {
var trackId = track.id;
//var trackTitle = track.title;
$(".title").text(track.title);
$(".playBTN").on('click tap', function () {
//trackId = $(".DSPlayer").attr('id');
stream(trackId);
});
// first do async action
SC.stream("/tracks/" + trackId, {
useHTML5Audio: true,
preferFlash: false
}, function (goz) {
soundToPlay = goz;
sound = soundToPlay;
scTrack = sound;
//updater = setInterval( updatePosition, 100);
});
});
var is_playing = false,
sound;
function stream(trackId) {
scTrack = sound;
if (sound) {
if (is_playing) {
sound.pause();
is_playing = false;
$(".playBTN").text("Play");
} else {
sound.play();
is_playing = true;
$(".playBTN").text("Pause");
}
} else {
is_playing = true;
}
}
If you remove any of these div elements that hold the .player class, the other element will work. So it only doesn't work because there are two instances of the same plugin.
How can I fix it? to have multiple instances of the player in one page?
I have identified the problem. It has to do with the fact that you are trying to load multiple tracks at the same time, but have not separated the code to do so.
As #Greener mentioned you need to iterate over the .player instances separately and execute a SC.get() for each one of them.
Here is what I see happening that is causing the problem:
var trackURL = $(".player").text();
^The code above returns a string that contains both of the URLs you want to use back-to-back without spaces. This creates a problem down the road because of this code:
SC.get('/resolve', { url: trackURL }, function (track) {...
That is a function that is trying to load the relevant song from SoundCloud. You are passing it a variable "trackURL" for it to try and load a specific URL. The function gets a string that looks like "URLURL" what it needs is just "URL".
What you can do is iterate over all the different ".player" elements that exist and then call the sounds that way. I modified your script a little to make it work using a for loop. I had to move the "empty()" functions into the for loop to make it work correctly. You have to use .eq(index) when referring to JQuery array of elements.
Like this:
var trackURL
var trackId;
for(index = 0; index < $(".player").length; index++){
trackURL = $(".player").eq(index).text();
//alert(trackURL);
$(".player").eq(index).empty();
$(".player").eq(index).append("<div class='playBTN'>Play</div>");
$(".player").eq(index).append("<div class='title'></div>");
SC.get('/resolve', { url: trackURL }, function (track) {
var trackId = track.id;
alert(track.id);
//var trackTitle = track.title;
$(".title").eq(index).text(track.title);
$(".playBTN").eq(index).on('click tap', function () {
//trackId = $(".DSPlayer").attr('id');
stream(trackId);
});
// first do async action
SC.stream("/tracks/" + trackId, {
useHTML5Audio: true,
preferFlash: false
}, function (goz) {
soundToPlay = goz;
sound = soundToPlay;
scTrack = sound;
//updater = setInterval( updatePosition, 100);
});
});
}
This is not a completely finished code here, but it will initiate two separate songs "ready" for streaming. I checked using the commented out alert what IDs SoundCloud was giving us (which shows that its loaded now). You are doing some interesting stuff with your streaming function and with the play and pause. This should give you a good idea on what was happening and you can implement your custom code that way.

Only run a JavaScript function if it is not run again after a set amount of time

I have an input which controls the state of an element changing very rapidly. This causes that element to flicker as parts of it change.
I am trying to store these state changes and then providing nothing has changed for a set amount of time (an arbitrary 500ms) change the state.
I have tried to solve this using timeouts as demonstrated in the code below (the same code as in the fiddle.):
var changingToHappy = false;
// Original no attempts to fix functions.
//var ifHappy = function () {
// $("#face").text(':)');
//};
//
//var ifNotHappy = function () {
// $("#face").text(':(');
//};
var ifHappy = function () {
changingToHappy = true;
setTimeout(function () {
if (changingToHappy) {
$("#face").text(':)');
}
}, 500);
};
var ifNotHappy = function () {
changingToHappy = false;
setTimeout(function () {
if (!changingToHappy) {
$("#face").text(':(');
}
}, 500);
};
$("#textBox").keypress(
function (event) {
if (event.which == 49) {
ifHappy();
$("#flickerFace").text(':)');
}
if (event.which == 50) {
ifNotHappy();
$("#flickerFace").text(':(');
}
}
);
If you rapidly press 1, 2, 1, 2 and so on in the fiddle the face will remain not flickery for a moment and then the timeouts will catchup and it will begin to change state.
This fiddle http://jsfiddle.net/9w70wxgz/4/ simulates the problem.
To clarify I only want the face to change if nothing has tried to change its state for a set amount of time.
What you're looking for is called a debounced function, here is an example with a piece of your code (you're almost there):
//storage for timer
var notHappyTimer;
var ifNotHappy = function () {
changingToHappy = false;
//removes timer if event fires in less than 500ms
clearTimeout(notHappyTimer);
//resets it to attempt again in 500ms
notHappyTimer = setTimeout(function () {
if (!changingToHappy) {
$("#face").text(':(');
}
}, 500);
};
As you can see, you just assign the timeout to a variable that clears itself every time the function is fired, then starts the timer again. This ensures that the text change only happens if the function hasn't been fired in 500ms.

Javascript: Setting track position form soundcloud api

I've been trying to play a track from Soundcloud at a specific position.
I have used the code from the following question as a reference
Soundcloud API: how to play only a part of a track?
below is the code that I have used
function playTrack(id) {
SC.whenStreamingReady(function() {
var sound = SC.stream(id);
sound.setPosition(240000); // position, measured in milliseconds
console.log(sound.position)
sound.play()
});
}
The console.log returns 0 and the track plays from the beginning.
alternative code I have tried and had the same result with is below
SC.stream("/tracks/" + id, function(sound){
console.log("playing")
console.log(sound)
sound.setPosition(120000)
console.log(sound.position)
sound.play()
})
Since soundcloud no longer uses soundmanager. the above methods will no longer work.
What must be done is to use a function called "seek()" instead of "setPosition()"
sound.seek(1500);
Here's a better example:
SC.stream(
"/tracks/[trackID]",
function(sound){
sound.seek(1500)
});
And if you wanted to access the seek function outside of the callback I would do this:
var soundTrack;
SC.stream(
"/tracks/[trackID]",
function(sound){
soundTrack = sound;
});
var buttonClickEvent = function(){
soundTrack.seek(1500);
}
According to SoundCloud's docs they are using SoundManager2 to handle playback, so you should be able to use any of its methods or settings. Try this:
function playTrack(id) {
SC.whenStreamingReady(function() {
var sound = SC.stream(id, {
from: 120000, // position to start playback within a sound (msec)
autoLoad: true,
autoPlay: true,
onplay: function(){ console.log(this.position) }
});
});
}
If that doesn't work you can try this instead:
function playTrack(id) {
SC.whenStreamingReady(function() {
var sound = SC.stream(id, { autoPlay: false }, function(sound){
sound.setPosition(240000); // position, measured in milliseconds
console.log(sound.position);
sound.play();
});
sound.load();
});
}
This should work-
var play_sound = function(id) {
SC.whenStreamingReady(function() {
var sound = SC.stream("/tracks/"+id,{autoPlay: false}, function(sound) {
sound.play({
whileplaying: function() {
console.log( this.position );
}
});
});
});
}

Categories