I have a page with a series of (HTML 5) videos whose audio needs to fade in or out depending on your position on the page (and it may be different for each video). I'm using jQuery Waypoints with the InView plugin to detect when an element is in the viewport. I'm not sure how to do it consistently, so that you don't cause unexpected behavior when you trip a waypoint while the volume is still decreasing or increasing.
var waypoint = new Waypoint.Inview({
element: $('#element')[0],
enter: function() {
$('#element')[0].volume = 0;
$('#ielement')[0].play();
incVol($('#element')[0]);
},
entered: function() {},
exit: function() {},
exited: function() {
decVol($('#element')[0]);
}
});
function incVol(e) {
setTimeout(function() {
if ((e.volume + .05) < 1) {
e.volume += .05;
incVol(e);
} else {
e.vol = 1;
}
}, 100)
}
function decVol(e) {
setTimeout(function() {
if ((e.volume - .05) > 0) {
e.volume -= .05;
decVol(e);
} else {
e.volume = 0;
e.pause();
}
}, 100)
}
This is an inconsistent attempt, if you trigger 'enter' while 'decVol' is still running you lose volume completely and have to trigger an 'exit', wait, and then trigger 'enter' again.
I've also tried something with jQuery's animate on volume. But that doesn't seem consistent either.
var waypoint = new Waypoint.Inview({
element: $('#element')[0],
enter: function() {
$('#element')[0].volume = 0;
$('#element')[0].play();
$('#element').animate({
volume: 1
}, 1000);
},
entered: function() {},
exit: function() {},
exited: function() {
$('#element').animate({
volume: 0
}, 1000, function() {
$('#element')[0].pause();
});
}
});
If I scroll up and down too fast, especially if I have multiple waypoints of this type in the page, then the queue of events becomes extensive and I have fade ins/outs happening far after the events have triggered (though, I prefer this implementation for the moment).
Any suggestions on how to achieve what I want a little better?
Prefacing the animate() function with stop() is the answer.
Something like:
$('#element').stop(true, false).animate({
volume: 1
}, 1000);
Related
I have used fullpage.js on my website's homepage, and I have made it so that it scrolls automatically every 10 seconds.
I have used the function as it is below:
$( '#fullpage' ).fullpage({
continuousVertical: true,
loopHorizontal: false,
resize: false,
afterRender: function() { // so that it applies to first section too
forceScroll();
}
});
slideTimeout = setInterval( function() {
$.fn.fullpage.moveSectionDown();
}, 10000);
function forceScroll() {
var slideTimeout;
}
However, I'd like to use clearInterval(slideTimeout) when the user slides down or sideways using his mouse, as when I want to browse afterwards it keeps going up and down... which is really annoying.
But I can't seem to find the trigger for it, or any workaround really!
How am I able to make this work?
Documentation for Fullpage.js on GitHub;
The website I am speaking about
Thank you a lot in advance,
Filipe
If I understand true, you want to unbind your interval when user scrolls.
$('body').on('mousewheel', function(e) {
if (e.originalEvent.wheelDelta > 0) {
if (typeof slideTimeout !== "undefined") {
clearInterval(slideTimeout); //case for scroll up
alert("Timeout clear");
}
} else {
if (typeof slideTimeout !== "undefined") {
clearInterval(slideTimeout); //case for scroll down
alert("Timeout clear");
}
}
});
Here is an example version of the system
var slideInterval = setInterval(function() {
$("#counter").text(parseInt($("#counter").text()) + 1);
}, 1000);
$('body').on('mousewheel', function(e) {
if (e.originalEvent.wheelDelta > 0) {
clearInterval(slideInterval);
alert("Timeout clear");
} else {
clearInterval(slideInterval);
alert("Timeout clear");
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="counter" style="height:6000px;">0</div>
fullpage.js doesn't provide any callback for mouse wheel /trackpad events I'm afraid.
You would have to do it by yourself as #Ahmet Can Güven indicates. But I would recommend you to look for a more cross browser solution mousewheel won't work in all browsers.
I have the following countdown timer function:
jQuery.fn.countDown = function(settings,to) {
settings = jQuery.extend({
startFontSize: "46px",
endFontSize: "18px",
duration: 1000,
endNumber: 0,
callBack: function() { }
},
settings);
return this.each(function() {
//where do we start?
if(!to && to != settings.endNumber) { to = settings.startNumber; }
//set the countdown to the starting number
jQuery(this).text(to).css("fontSize",settings.startFontSize);
//loopage
jQuery(this).animate({fontSize: settings.endFontSize},
settings.duration,
"",
function() {
if(to > settings.endNumber + 1) {
jQuery(this).css("fontSize",
settings.startFontSize).text(to - 1).countDown(settings, to - 1);
} else {
settings.callBack(this);
}
});
});
};
To start a countdown on my page, I initialize it like so:
(This will make it count down from 5 to 0, shown in element #countdown)
jQuery("#countdown").countDown({
startNumber: 5,
callBack: function(me) { }
});
Now I sometimes need to cancel a running countdown and start a new one.
For example, stop the countdown at 3 and initialize again to start over.
Can somebody tell me how I can extend this code to do that?
(the original timer script was taken from http://davidwalsh.name/jquery-countdown-plugin)
V.
Given that you have some access to the settings, and you execute your timer as such:
var settings = {
startNumber: 5,
callBack: function(me) {}
};
jQuery("#countdown").countDown(settings);
You can stop and restart your timer like this:
function stopAndRestart() {
jQuery("#countdown").stop().countDown(settings);
}
.stop() stops the animation on a given element (which happens to, terribly, be the method of timing here)
I have the following code setup to display the canvas duplicate of the video when paused so it can display a greyscale version of the paused image. As you'll notice the paused frame is always behind the video.
I've tried setting pixelScan() to only happen when the video is paused or ended, and I've experimented with the setTimeout() and requestAnimationFrame() all with no luck. But, that's most likely due to my own lack of skill with JavaScript haha
I just seem to keep getting caught up with this issue and I know there has to be plenty fixes to this simple issue
http://coreytegeler.com/ethan/
var processes={
timerCallback:function() {
if (this.v2.paused || this.v2.ended) {
return;
}
this.ctxIn.drawImage(this.v2,0,0,this.width,this.height);
this.pixelScan();
var self=this;
},
doLoad:function(){
this.v2=document.getElementById("video");
this.cIn=document.getElementById("cIn");
this.ctxIn=this.cIn.getContext("2d");
this.cOut=document.getElementById("cOut");
this.ctxOut=this.cOut.getContext("2d");
var self=this;
setTimeout(function() {
self.timerCallback();
}, 34);
this.v2.addEventListener("playing", function() {
self.width=v.videoWidth;
self.height=v.videoHeight;
cIn.width=v.videoWidth;
cIn.height=v.videoHeight;
cOut.width=v.videoWidth;
cOut.height=v.videoHeight;
self.timerCallback();
}, false);
this.v2.addEventListener('ended', function() {
openInfo();
v2.pause();
v2.loop = true;
stateAnimate.animate({path: playBtn, fill:"white"}, 300, "ease-in-out");
loopAnimate.animate({path: loopOn, fill:"white"}, 200, "back-in");
});
},
pixelScan: function() {
var frame = this.ctxIn.getImageData(0,0,this.width,this.height);
for(var i=0; i<frame.data.length;i+=4) {
var grayscale=frame.data[i]*.3+frame.data[i+1]*.59+frame.data[i+2]*.11;
frame.data[i]=grayscale;
frame.data[i+1]=grayscale;
frame.data[i+2]=grayscale;
}
this.ctxOut.putImageData(frame,0,0);
return;
}
}
You can use the pause event:
this.v2.addEventListener('pause', function() {
// process frame here
}, false);
The idea is simple: I have buttons which refer to another website. Whenever the user has clicked more than two links I want to refresh some content (through Ajax). For that to work I need to detect if my window is active or not, since I only want the event to start when the user is BACK on my page.
Without further ado this is my code:
$(document).on("click", "a", function() {
numberOfClicks += 1;
if (numberOfClicks >= 2)
{
userOnWebsiteOrNot();
numberOfClicks = 0;
}
});
function userOnWebsiteOrNot()
{
if (focusedOrNot == 0)
{
$('#resultaat').hide().fadeIn(5000);
}
}
window.addEventListener('focus', function() {
document.title = 'focused';
focusedOrNot = 0;
});
window.addEventListener('blur', function() {
document.title = 'not focused';
focusedOrNot = 1;
});
It DOES detect whenever the user is on the page or not, but somehow the fade always happens.
Could anybody explain me what I'm doing wrong or give me any ideas?
Thanks
Yenthe
ANSWER:
I needed a setTimeOut on three functions because they would otherwise check too fast. Thank you for that help Romo! ;) All credit goes to Romo to be honest.
$(document).on("click", "a", function() {
numberOfClicks += 1;
if (numberOfClicks >= 2)
{
haallinks();
setTimeout(function() {
userOnWebsiteOrNot();
}, 2000);
numberOfClicks = 0;
}
});
function userOnWebsiteOrNot()
{
if (focusedOrNot === 0)
{
$('#resultaat').hide().fadeIn(5000);
}
else
{
controlerenActiefOfNiet();
}
}
function controlerenActiefOfNiet()
{
setTimeout(function() {
userOnWebsiteOrNot();
}, 2000);
}
window.addEventListener('focus', function() {
setTimeout(function() {
focusedOrNot = 0;
}, 0);
});
window.addEventListener('blur', function() {
setTimeout(function() {
focusedOrNot = 1;
}, 1000);
});
I think the problem is that when you click a link the second time the window will always be focused. JS runs pretty fast. To overcome this, I think you should do a setTimeout() and delay it 200ms or so to give the window time to "lose" focus
setTimeout(function() {userOnWebsiteOrNot(); },2000);
http://jsfiddle.net/xVHgE/
Edit: Adding delay to event listener. I don't think you can "delay" an event though, just the function it runs.
window.addEventListener('focus', function() {
setTimeout( function() {
$('#test').html('focus');
focusedOrNot = 0;
} , 5000);
});
I'm testing my webpage in browsers and it seems that some bits are not working in firefox and opera. I assume it's caused by jQuery used on my page.
This is my website: http://freshbeer.lv/ht/index.html
At the bottom of the source code you can find all jQuery code used (mainly to call and apply plugins). I'm having trouble to determine what is wrong, as there are no errors shown in console (firefox 20.0) Main dysfunctions are
player, just compare how it works in chrome and than check it out in firefox or opera, first of all it doesn't show "..." which signifies loading, secondly once you click play on another player, both songs keep playing, where as in other browsers first song would pause, so there would be only one song playing.
advertisement should have margins on top and bottom calculated by jQuery, it doesn't in opera and firefox.
So Am I missing something? Maybe I need to apply certain code standards?
That seems to be all, however I can't be sure.
I'll put code written by me here (most likely issue is in it), note, there are several jQuery plugins included above it.
<script type="text/javascript">
//Audio Player
audiojs.events.ready(function () {
var as = audiojs.createAll();
$('audio').each(function () {
var myAudio = this;
this.addEventListener('play', function () {
$('audio').each(function () {
if (!(this === myAudio)) {
this.pause();
}
});
});
});
});
$(document).ready(function() {
//Responsive add margins
function addMargin () {
var add = $(".advert");
var addMargin = add.css("margin-left");
add.css({
"margin-top": addMargin,
"margin-bottom": addMargin
});
}
addMargin();
$(window).resize(addMargin);
//Responsive Grid
var MusicGrid = (function() {
var $musicGridContainer = $('.grid'),
init = function() {
changeMusicGrid();
initEvents();
initPlugins();
},
changeMusicGrid = function() {
var w_w = $(window).width();
if (w_w <= 765) n = 1;
else if (w_w <= 1180) n = 2;
else n = 3;
},
initEvents = function() {
$(window).on('smartresize.MusicGrid', function(event) {
changeMusicGrid();
});
},
initPlugins = function() {
$musicGridContainer.imagesLoaded(function() {
setTimeout(function() {
$musicGridContainer.masonry({
itemSelector: '.article',
columnWidth: function(containerWidth) {
return containerWidth / n;
},
isAnimated: true,
animationOptions: {
duration: 150
}
});
}, 500);
});
};
return {
init: init
};
})();
MusicGrid.init();
});
//Preload Content
function preloadCode() {
if (preloadCode.done) return;
preloadCode.done = true;
clearTimeout(t);
$(".preloader").css("display", "none");
$(".grid").css({ opacity: 0, visibility: 'visible', marginTop: 20 }).animate({ marginTop: 0, opacity: 1 }, 550);
$('.article[id^="article-"]').each(function () {
if (parseInt(this.id.replace('article-', '')) % 3 === 0) {
$('#' + this.id).css({ marginTop: 50 }).animate({ marginTop: 0 }, 350);
} else if (parseInt(this.id.replace('article-', '')) % 2 === 0) {
$('#' + this.id).css({ marginTop: 100 }).animate({ marginTop: 0 }, 400);
} else {
$('#' + this.id).css({ marginTop: 150 }).animate({ marginTop: 0 }, 450);
}
});
$(".footer").css("display", "block");
}
var t = setTimeout(preloadCode, 6000);
$(window).load(preloadCode);
</script>
1. advertisement should have margins on top and bottom calculated by jQuery, it doesn't in opera and firefox. So Am I missing something? Maybe I need to apply certain code standards?
Your element has auto margins, so, depending on the browser, .css('margin-left') might return different values, including 0.
I recommend using the JsSizes library which is a lightweight plugin that will allow you to get the actual margins in pixels.
2. player, just compare how it works in chrome and than check it out in firefox or opera, first of all it doesn't show "..." which signifies loading, secondly once you click play on another player, both songs keep playing, where as in other browsers first song would pause, so there would be only one song playing.
Firefox and Opera don't support mp3 in their audio element, so it gets replaced by a flash object. Therefore you can't listen to those DOM events anymore.
Although, according to their annotated source code, the flash object has public methods play(), pause(), and isPlaying.
I'd recommend listening a click event on the 'play-pause' button and use these functions. Like this :
var as = ''; // You're going to have to make your as variable global to access it outside of your function.
audiojs.events.ready(function () {
as = audiojs.createAll();
$('.audiojs .play-pause').click(function(){ //Listening to the click event
var thisIndex = $(this).parents('.audiojs').index('.audiojs'); // When you create several players, as is an array of instances of players. Here we're finding the DOM index of the player so it reflects its position in the as array.
$.each(as, function(index,val){ //then, for each instance of players in the as array
if ( index != thisIndex && as[index].playing ) as[index].pause(); //If the player is already playing, and its index is different than the one we just clicked on, pause it !
});
});
});