Floating JQuery menu issues on slower connection - javascript

I'm trying to create a floating menu (#quickmenu in left hand sidebar of bottom link) that stops at #weather whilst also re-calculating the bottom = $(\'#weather\').offset().top; every 0.5 seconds...
Page to test: Bristol International Jazz & Blues Festival 2014 | Festival Archive
The recalculation is key as I use expandable content in the main body and because without recaculating on slower connections it doestn't work. I need only #weather.offset.top to be recalculated every 5 seconds, not the whole script otherwise it refreshes and flickers...
I've tried to do code it myself and it's not working, it's 99% not coded correctly but can't figure out what's going wrong? The logic seems to be correct though... if (y >= top && z <= bottom) { ....
<script type="text/javascript">
$(document).ready(function () {
top = $('#quickmenu').offset().top;
var didScroll = false;
$(window).scroll(function() {
didScroll = true;
});
setInterval(function() {
if ( didScroll ) {
didScroll = false;
bottom = $('#weather').offset().top;
y = $(this).scrollTop();
z = y + $('#quickmenu').height();
if (y >= top && z <= bottom) {
// if so, add the fixed class
$('#quickmenu').addClass('fixed');
} else if(z > bottom) {
// otherwise remove it
$('#quickmenu').removeClass('fixed').addClass('absolute');
} else {
// otherwise remove it
$('#quickmenu').removeClass('fixed');
}
}
}, 500);
});
</script>

Thanks for the input, and apologies for lack of clarity within the question. I have fixed my issue by taking another approach. I hope that this is less resource heavy?
<script type="text/javascript">
(function () {
var s = document.querySelector(\'#event-info\').style;
s.overflow = \'inherit\';
s.height = \'auto\';
})();
window.updateQuickMenuPos = function () {
var menu = document.querySelector(\'#quickmenuwrapper\');
var scroll_pos = document.body.scrollTop;
var menu_pos = menu.offsetTop + 10;
var weather = document.querySelector(\'#weather\');
var pos = (scroll_pos - menu_pos);
// min height
if (pos < 0) {
pos = 0;
}
// max height
if (menu_pos + menu.offsetHeight + pos > weather.offsetTop) {
pos = weather.offsetTop - menu.offsetHeight - menu_pos;
}
var s = menu.style;
s[\'webkitTransform\'] = s[\'mozTransform\'] = s[\'transform\'] = \'translateY(\' + pos + \'px)\';
};
jQuery(document).scroll(window.updateQuickMenuPos);
</script>

Related

How to disable a jquery function from executing for a certain amount of time

I have a jQuery function that calculates the distance between two slideshows and detects to see if they have been scrolled past yet and tells it to display the first slide with important information on it.
However, it displays it once, but then the if statement loops and keeps displaying it, which would be expected.
I am wondering if there is a way to force the function to wait 25-ish seconds before it executes again? Any help would be much appreciated.
Here is the jQuery code:
$(window).scroll(function() {
$('.infoIdentifier').each(function() {
var scroll = $(window).scrollTop();
var objectpos = $(this).offset().top - 600;
var nextobject = $(this).parent().nextAll('.slideshow').children(".infoIdentifier")
if (nextobject.length === 0) {
var nextobjectpos = 10000;
} else {
var nextobjectpos = nextobject.offset().top - 600;
}
if (scroll > objectpos && scroll < nextobjectpos) {
var $this = $(this).parent('.slideshow');
var $currentSlide = $this.find('.active');
var $nextSlide = $this.children('.jumbotron').first();
$nextSlide.fadeIn(500).addClass('active');
$currentSlide.fadeOut(500).removeClass('active');
}
});
});
As for HTML, the slideshows are held in a main container, and each slide show with important information is tagged as class = 'infoIdentifier'. This part of the function does its job. The calculations are fine and the application of classes is fine, however, how do I disable the if (scroll > objectpos && scroll < nextobjectpos){ statement for x amount of seconds. Any help would be much appreciated. Thank you!
Here's one way to achieve this. I added a boolean outside of your scroll function called wait, which is set to false initially.
Then I added !wait as a condition to your if logic, which means it will only validate if wait is currently false.
Then inside that block, I set wait to true, and started a setTimeout for 25 seconds, after which wait is set back to false.
During those 25 seconds, that slideshow code will not run.
var wait = false;
$(window).scroll(function() {
$('.infoIdentifier').each(function() {
var scroll = $(window).scrollTop();
var objectpos = $(this).offset().top - 600;
var nextobject = $(this).parent().nextAll('.slideshow').children(".infoIdentifier")
if (nextobject.length === 0) {
var nextobjectpos = 10000;
} else {
var nextobjectpos = nextobject.offset().top - 600;
}
if (!wait && scroll > objectpos && scroll < nextobjectpos) {
var $this = $(this).parent('.slideshow');
var $currentSlide = $this.find('.active');
var $nextSlide = $this.children('.jumbotron').first();
$nextSlide.fadeIn(500).addClass('active');
$currentSlide.fadeOut(500).removeClass('active');
wait = true;
setTimeout(function() {
wait = false;
}, 25000);
}
});
});

jQuery animation works with only one element

I need to make it working for all my elements under Which nothing should fade (images).
Currently works only for the div.logo tag
I guess at the moment the reason mine <h1> element is now allowing animations underneath is that when I am getting the .top(), .left() and so on, you are doing it for the last element in the list.
I need to get the borders of each element in the resulting list.
Any help would be much appreciated
Demo: http://jsfiddle.net/z9b8S/
JS:
function displayThese(selectorString) {
var $heading = $(selectorString);
var h1top = $heading.position().top;
var h1bottom = h1top + $heading.height();
var h1left = $heading.position().left;
var h1right = h1top + $heading.width();
var divs = $('li').filter(function () {
var $e = $(this);
var top = $e.position().top;
var bottom = top + $e.height();
var left = $e.position().left;
var right = left + $e.width();
return top > h1bottom || bottom < h1top || left > h1right || right < h1left;
});
return divs;
}
(function fadeInDiv() {
var divsToChange = displayThese('h1, div.logo');
var elem = divsToChange.eq(Math.floor(Math.random() * divsToChange.length));
if (!elem.is(':visible')) {
elem.prev().remove();
elem.animate({
opacity: 1
}, Math.floor(Math.random() * 1000), fadeInDiv);
} else {
elem.animate({
opacity: (Math.random() * 1)
}, Math.floor(Math.random() * 1000), function () {
window.setTimeout(fadeInDiv);
});
}
})();
$(window).resize(function () {
// Get items that do not change
var divs = $('li').not(displayThese());
divs.css({
opacity: 0.3
});
});

Get static value from variable (scroll function)

I have a "follow scroll" function, but I want it to turn off when it returns to a certain point. My code is as follows:
scrollSidebar: function(scroll) {
var elemPos = $('#bestvideos-2').offset().top,
scroll2 = scroll;
if(scroll2 >= elemPos) {
$('#bestvideos-2').animate({
'margin-top':(scroll - 315)+'px'
},0);
} else {
$('#bestvideos-2').css('margin-top','0');
}
}
$(window).scroll(function() {
var scrollHeight = $(window).scrollTop();
Scroll.scrollSidebar(scrollHeight);
})
The problem is - every time I get up, it goes way up, not following scroll. What I'm thinking is storing a variable elemPos somewhere and keep it static (now it's changing each time I scroll).
What can I do with this?
Pass the value to the scrollSidebar function - make sure that the var elemPos = $('#bestvideos-2').offset().top is executed on dom ready
scrollSidebar: function (elemPos, scroll) {
var scroll2 = scroll;
if (scroll2 >= elemPos) {
$('#bestvideos-2').animate({
'margin-top': (scroll - 315) + 'px'
}, 0);
} else {
$('#bestvideos-2').css('margin-top', '0');
}
}
var elemPos = $('#bestvideos-2').offset().top
$(window).scroll(function () {
var scrollHeight = $(window).scrollTop();
Scroll.scrollSidebar(elemPos, scrollHeight);
})

how to check if the scrollbar has reached at the end of div?

function yHandler () {
var show = document.getElementById('show');
var contentHeight = show.offsetHeight;
var yOffset = show.pageYOffset;
var y = yOffset + show.innerHeight;
if(y >= contentHeight) {
alert("ok")
}
}
show.onscroll = yHandler;
how to check if the scrollbar has reached the end of div?
Some code for you to work on:
var scroll = document.getElementById('scroll');
var content = document.getElementById('content');
scroll.onscroll = function(){
var total = scroll.scrollTop + scroll.clientHeight;
if(total == content.clientHeight)
alert('Reached bottom!');
}
http://jsfiddle.net/EY6qP/
Thor's method works perfectly well (+1), but you could also rely on scrollHeight.
(function(scroll){
scroll.onscroll = function(){
if (scroll.scrollTop + scroll.clientHeight == scroll.scrollHeight) {
console.log('hither!');
}
}
})(document.getElementById('scroll'));
Use scrollHeight, scrollTop and clientHeight attributes to detect the scroll bar reached bottom end or not.
function handleScroll() {
var div = document.getElementById("div-id");
if(Math.abs(Math.round(div.scrollHeight - div.scrollTop) - div.clientHeight) > 3) {
console.log("Scroll bar reached bottom end");
return true;
}
return false;
};

jQuery Scroll Current Position and Next-Prev Navigator

I need a bit of advice as I can't get my noob head around the following, please see this fiddle: http://jsfiddle.net/NtUpw/
The code works as intended, but when the current div offset goes > 41 and prev is hit, I'd like the page to return to the beginning of the current div, not to one before that. Any idea how can I add this condition?
I realise the current code isn't the cleanest (actually it's a combination of two fiddles), but I hope someone could take a look at it anyway. Thanks.
$('a.buttons').on('click', function (e) {
e.preventDefault();
var t = $(this).text(),
that = $(this);
if (t === 'next' && $('.current').next('div.post').length > 0 ) {
var $next = $('.current').next('.post');
var top = $next.offset().top;
$('body').animate({
scrollTop: $('.current').next('div.post').offset().top - 40
});
} else if (t === 'prev' && $('.current').prev('div.post').length > 0 ) {
var $prev = $('.current').prev('.post');
var top = $prev.offset().top;
$('body').animate({
scrollTop: $('.current').prev('div.post').offset().top - 40
});
}
$(window).bind('scroll', function () {
$('.post').each(function () {
var post = $(this);
var position = post.position().top - $(window).scrollTop();
if (position <= 40) {
post.addClass('current');
post.prev().removeClass("current");
} else {
post.removeClass('current');
}
});
});
The prev action works by moving always the div to the previous; the solution is to check the current position of the navigator respect to the current div:
var $prev;
var top;
var firstElem = true;
if ($('.current').prev('div.post').length > 0) {
$prev = $('.current').prev('.post');
top = $prev.offset().top;
firstElem = false
}
var currTop = $('.current').offset().top;
var navBottom = $('.navigation').offset().top + 40;
if (currTop == navBottom && !firstElem) {
$('body,html').animate({
scrollTop: $('.current').prev('div.post').offset().top - 40
});
with this the navigator jumps to the previous div only if is not at the top of the current; alternatively jumps to the previous.
The firefox issue depends on how Firefox places the overflow, it places it at the html level not at body like other browsers.
To let it work you must define the scrolling action with:
$('body,html').animate({
});
Working fiddle: http://jsfiddle.net/IrvinDominin/2QYgR/3/

Categories