Looping through Video Sources slows Chrome - javascript

I have two video sources that are outputted to my page via ajax (the second is hidden). I play the first one and bind an event onto it so that when it has ended the next video is played and shown whilst the first is then paused, rewinded back to 0, and the process continues.
here is my code.
function queueVideos(num, amount) {
if (num < amount) {
document.getElementById('video-element-'+num).addEventListener('ended', playNextClip, false);
function playNextClip() {
var nextVid = num + 1;
$( '#video-element-' + nextVid ).show().get(0).play();
$( '#video-element-' + num ).hide();
document.getElementById( 'video-element-' + num ).pause();
document.getElementById( 'video-element-' + num ).currentTime = 0;
queueVideos(nextVid, amount)
}
}
if (num == amount) {
document.getElementById('video-element-'+num).addEventListener('ended', playFirst, false);
function playFirst() {
$( '#video-element-1' ).show().get(0).play();
$( '#video-element-' + num ).hide();
document.getElementById( 'video-element-' + num ).pause();
document.getElementById( 'video-element-' + num ).currentTime = 0;
queueVideos(1, amount);
}
}
}
The code is called within an ajax function that feeds it the num and amount from data i get elsewhere, for arguments sake let's say i'm running it like so:
queueVideos(1, 2);
My problem is that after around 1 minute the transitions between the clips get laggy, the clips pause unexpectedly, and ultimately the browser (chrome) performs slowly.
How can I fix this?
Thanks!

I found that changing the function playFirst() to not include queueVideos(1, amount); fixed the problem! I didn't realize that i only needed to add the event listener once. Woohoo!

Related

how to add up the current score, jquery, javascript

I am trying to get a current score to add up every time an answer is correct, what is happening is that I have the questions in a pagination set up and when this answer is correct it give me the score but then when it goes to the next page it refresh the score and if I got that one right it just give me the score for that one again but it doesn't add up.
JS code:
$(function() {
$('#author').on('change', function(event) {
var opt = this.options[ this.selectedIndex ];
var correct = $(opt).text().match (arr2);
var score = 0;
if (correct){
alert('Good job ' + arr2,);
score += 2;
alert (score);
currentScore = score++;
alert(currentScore);
display(currentScore);
}
else {
alert ('nice try ' + arr2);
}
});
});
Here is another option - local storage.
Here is a reference W3School Web storage
It's not the most ideal solution, but it can meet your criteria.
let score = localStorage.getItem('score')
score++;
localStorage.setItem('score', score);
Your pages will be able to access the localStorage so you can get the value of score and re-set it.
Hopefully the reference can answer further questions, else leave a comment!
Con: It may not be supported by all browsers.
EDIT:
Here is an example with your code.
$(function() {
let currentScore = localStorage.getItem('score'); // get score
if (currentScore === null){ // if score doesnt exist yet
localStorage.setItem('score', 0); // set score
currentScore = 0; // make currentScore 0
}
$('#author').on('change', function(event) {
var opt = this.options[ this.selectedIndex ];
var correct = $(opt).text().match (arr2);
if (correct){
alert('Good job ' + arr2);
currentScore += 2; //increment current score by 2
alert (currentScore);
localStorage.setItem('score', currentScore); // set the item again with new value
alert(currentScore);
display(currentScore);
}
else {
alert ('nice try ' + arr2);
}
});
});
Edit 2:
let currentScore = localStorage.getItem('score'); // get score
currentScore = parseInt(currentScore);
it give me the score but then when it goes to the next page it refresh the score and if I got that one right it just give me the score for that one again but it doesn't add up.
I think your problem is there.
If I understand correctly, when the answer is good, the page refresh and passes to the next question. Your problem is that the score doesn't add up to the previous one.
The score variable is only stored in the current page, like a temporary one. Without saving the score on the server, via ajax or another method, and getting it on the next page, it will not add up. Indeed, score will have a value of 0 due to the refresh.
A simple schema :
score = 0 -> correct answer -> +50 point -> score = 50 -> next page -> score = 0
As you can see, because the javascript you wrote is not assuring the persistance of your information, the previously stored score is lost.
You need to send the score on the server and then get it back when the new page is loaded or to avoid changing page and make your quizz on one and only page, without refreshing.
Keep in mind that everytime you are refresing a page, the javascript is starting again and therefore everything done before is lost.
I hope this was helpful.
Ps: You should place your code in the $( document ).ready(); block just like this :
$( document ).ready(function() {
console.log( "ready!" );
});
It will make your code start when the html DOM (the structure of the html file) is loaded and ready to be manipulated. It can avoid a lot of errors.
Edit2 : What it will look like in your code :
$( document ).ready(function() {
$('#author').on('change', function(event) {
var opt = this.options[ this.selectedIndex ];
var correct = $(opt).text().match (arr2);
var score = 0;
if (correct){
alert('Good job ' + arr2,);
score += 2;
alert (score);
currentScore = score++;
alert(currentScore);
display(currentScore);
}
else {
alert ('nice try ' + arr2);
}
});
});
Or, to make this more readable and to avoird having a lot of things in the document.ready block (when you will have a lot of lines/functions) :
$( document ).ready( myNiceFunction() );
var myNiceFunction = function(){
$('#author').on('change', function(event) {
var opt = this.options[ this.selectedIndex ];
var correct = $(opt).text().match (arr2);
var score = 0;
if (correct){
alert('Good job ' + arr2,);
score += 2;
alert (score);
currentScore = score++;
alert(currentScore);
display(currentScore);
}
else {
alert ('nice try ' + arr2);
}
}
Ps2 : I know this is not the best website to explain it but I think it is simple enough to make you understand the principle of ajax without losing you into a bunch of technical stuff : here and here
Edit : Grammar and second post-scriptum.
Not sure how you're doing pagination but it should be ajaxed, instead of a full postback, so you don't lose the values on your page.

Javascript: Countdown by animation.width()

I am currently trying to make a visual countdown for my user for when the animation is finished. My current attempt looks somewhat like this:
function setClassAndFire(){
timer = setInterval(function () {
t--;
$(this).attr('class', 'timerAnimation');
countdownTimer();
if (t === 0) {
clearInterval(timer);
timer = undefined;
funcForCall();
}
}, 1000);
}
function countdownTimer(){
var timerCurrentWidth = $('.timerAnimation').width(),
timerMaxWidth = $("#awardQueueText").width(),
pxPerSecond = timerMaxWidth / 60,
currentCountdown = timerCurrentWidth / pxPerSecond;
currentCountdown = Math.round(currentCountdown);
document.getElementById("timer").innerHTML = "<span style='white-space : nowrap;'>Animation ends in:</br></span>"+
"<span style='white-space : nowrap;'>" + currentCountdown + " sec.</span>";
}
Important to know is that the animation only displays the time until we may be able to send an API call. So the animation will be re-engaged if we have something in queue.
So as you can see my current attempt works, but is some-what cluncky:
The countdown sometimes fails to subtract a second and "fixes"
that with a 2 seconds subtract in the next attempt.
This is probably caused by the Math.round() for currentCountdown, but is there a work around for that? I mean I have the max possible width of the animation object and can seperate it from the current width.
Is there a way to bring it to work? We need to relate the timer to the animation to achive desired behavior. So when the animation count hits 25, I want that the displayed number is 25 as well!
You got this problem because you got the number from the width andh the width can't have decimals (or better, they can be but they are gonna be truncated sometimes).
So my suggestion is to use a differente variable for the number you will show and the width of the DOM element.
It seems to me that the variable t is what I am talking about, so just try to use it.
function setClassAndFire(){
timer = setInterval(function () {
t--; //What is t?
$(this).attr('class', 'timerAnimation');
countdownTimer(t);
if (t === 0) {
clearInterval(timer);
timer = undefined;
funcForCall();
}
}, 1000);
}
function countdownTimer(t){
document.getElementById("timer").innerHTML = "<span style='white-space : nowrap;'>Animation ends in:</br></span>"+
"<span style='white-space : nowrap;'>" + t+ " sec.</span>";
}

Having trouble getting my HTML onload to call my JS function

I have a function that should be called whenever my html page loads. The <body> tag should call the startAdPage() function. However, nothing at all happens. I am not completely sure why. Any suggestions? Here is the <body> call in my HTML page
<body onload="startAdPage();">
Next, here is my startAdPage() function, as well as the two functions it calls. Those two aren't completely finished yet. One of them is supposed to create a small image gallery slide show. The other is supposed to create a countdown from 10 - 1 before displaying a separate web page. Neither work yet, so any advice on them would also be appreciated, though they aren't my main focus yet.
function startAdPage(){
setInterval(changeAd(), 2000);
setInterval(startCountdown(), 1000);
}
Here is changeAd()
function changeAd() {
for(var i = 1; i < 4; i++){
document.images[0].src = "images/pic" + intNumber + ".jpg";
}
}
Lastly, startCountdown(). I haven't made the webpage that I said this function calls yet
function startCountdown() {
window.alert('Test');
for(var i = 10; i >= 1; i++){
document.getElementById("countdown").value = i;
}
}
Your problem is right here:
document.images[0].src = "images/pic" + intNumber + ".jpg";
You refer to intNumber but you should be using i instead. So change the above to
document.images[0].src = "images/pic" + i + ".jpg";
and your function will be called.
You should consider removing the onload in the body tag and do a
window.onload = startAdPage;
instead - to keep your html and Js logic separate.
Also, your countdown logic is wrong - you want to decrement i, not increment:
var i = 10; i>0; i--

Iterating Ajax load selector

I am trying to create an 'infinite scroll' using Ajax (or rather specifically using Jquery's .load function), the function fires perfectly and in the instances where it has worked it spits out a comical amount of articles, so I figured that I should create a unique, iterating div (id1,id2,id3 etc) but when using an iterating selector to load the Ajax content into unique div ids, by iterating it, it .load fails or doesn't fire.
var busy = false;
var i = 1;
var x = 0;
function content(){
if($(document).height() * 0.7 < $(document).scrollTop() && !busy) {
var offset = i++ * 6;
$("#expand").after("<section id='expand" + x++ + "' class='gridWrapper'></section>");
$("#expand" + x).load("/ajaxcontent/", {section: 'articles', category: '', limit: '6', offset: offset, form: 'grid', action: 'article'}, function(){
busy = true;
});
x++
} else {
busy = false;
}
}
window.onscroll = content;
document.ready = content;
My question is how do I get the selector $("#expand" + x) to work correctly? In the variations (for loops, while loops, .each) I have tried where it does output articles it goes utterly bananas and essentially regurgitates all articles. Any help would be hugely appreciated!
(As it is a an Ajax load, I don't think that I can create a JsFiddle)
This is working
$('#expand' + x)
try to remove the ++ in this line
$("#expand").after("<section id='expand" + x++ + "' class='gridWrapper'></section>");
to
$("#expand").after("<section id='expand" + x + "' class='gridWrapper'></section>");

How can I optimize this recursive function which calls setTimeout()

The following function is using 100% of a CPU core on my computer. Is there a way I could rewrite it to be non-recursive? Would that fix it or is it because my CPU sucks? Are others seeing the same performance problems on their computer?
Code:
<html>
<head>
<script type="text/javascript" src="jquery-1.7.1.js"></script>
<script type="text/javascript">
function timeMsg(n,max,delay)
{
writeToLog(n + "th: &#" + n,n);
var temp = n + 1;
if(n < max){
var t=setTimeout("timeMsg(" + temp + "," + max + "," + delay + ")",delay);
}
}
function writeToLog(text,n){
$("#log").html($("#log").html() + text + "<br/>");
//autoscrolling: doesn't work...'
}
</script>
</head>
<body>
<form>
<input type="button" value="Display alert box in 3 seconds" onClick="timeMsg(0,100000,100)" />
</form>
<div id="log"></div>
</body>
Instead of repeatedly calling setTimeout with slightly-different values, you could setup a global variable to track the current iteration, and use one call to setInterval() instead. setInterval is like setTimeout, except it will keep running indefinitely - you don't have to call it over and over again. That might help, a bit.
That should not be using 100% CPU. (But the actual performance is dependent on the size of your document.) However, one obvious improvement is to get rid of the implicit eval in setTimeout:
function timeMsg(n, max, delay) {
writeToLog(n + "th: &#" + n, n);
var temp = n + 1;
if(n < max) {
var t = setTimeout(function() {
timeMsg(temp, max, delay);
}, delay);
}
}
You should also use append in place of the double-html (anti-)pattern you're currently employing:
function writeToLog(text,n){
$("#log").append(text + "<br/>");
}
There's no need to search for #log twice (reading its html both times).
Use setInterval() to start and clearInterval() when you reach your max.
Demo: http://jsfiddle.net/ThinkingStiff/PwASf/
Script:
var timer;
function startMsg( n, max, delay ) {
timer = window.setInterval( function() {
timeMsg( n++, max );
}, delay );;
};
function timeMsg( temp, max ) {
writeToLog(temp + "th: &#" + temp, temp);
if( temp == max ){
window.clearInterval( timer );
}
}
function writeToLog(text,n){
$(' #log' ).append( text + '<br/>' );
}
startMsg( 1, 10, 1000 );
HTML:
<div id="log"></div>
No, even as written, it doesn't use 100% CPU for me.
First thing you should do is change your writeToLog function. It is must faster to append an HTML block than to 1) read the existing HTML, 2) add the text+BR, 3) write the whole thing back in.
function writeToLog(text,n){
$("#log").append(text + "<br/>");
//autoscrolling: doesn't work...'
}
Other than that, if you want to not block other JS from running, then you need to use the setTimeout/setInterval method of implementing this loop. Otherwise a regular for loop is faster.

Categories