fadeIn() does not make web page scroll at the right position - javascript

I use jQuery to implement the slide show animation.
The html looks like:
<div class="slideshow pointer">
<img class="next" src="img1">
...
</div>
I use jQuery to find the next image, fadeOut the previous one and fadeIn the next one. This slideshow part is made visible by a click action of a image thumb. When the first image is loaded, the webpage will scroll to the right place (a proper position to show the image).
But when I click to show the next image, the webpage scroll to a different place, and click next, the webpage scroll to a second different place. The address stays at 'www.xxx.home.html#/books/01/'. And I use another javascript function to make this address display the webpage at the right position.
I have checked that when I click to show next image, there is only this function used, no other function that would cause a slideDown or scroll action (not 100% sure). I am wondering if fadeIn() action does something more than I expect, e.g. some scroll action?
The javascript code:
$('body').on('click', '.slideshow img', function(e){
var thisimg = $(this);
var thisss = thisimg.parent();
var totimgs = thisss.find("img").length;
if (totimgs > 1){
var thisindex = thisimg.index();
var x = e.pageX - 240;
if (x < 240 || x > 600) {
if (x < 240) {
var nextindex = thisindex - 1;
if (nextindex < 0) {
nextindex = totimgs - 1;
}
} else if (x > 600) {
var nextindex = thisindex + 1;
if (nextindex > totimgs - 1) {
nextindex = 0;
}
} else {
nextindex = thisindex;
}
thisimg.fadeOut(500);
var nextss = thisss.find("img:nth-child(" + (nextindex + 1) + ")");
nextss.fadeIn(500);
}
}
});
Can anyone give the reason why? Or there is something else I need to check what makes this scroll?

Related

How to change sticky element depending on scrolling through several section on JS/jQuery?

I need to change the sticky image (by changing class or changing URL attr) while scrolling past several text sections.
Asana on their home page has an exact example
check the gif animation here
In front of text section 1 - image 1,
while we scroll near text section 2 - image changes to 2nd, and so on.
When scrolling back to the top, the same logic, each image appear in front of it's text section.
If there would be only 1 breakpoint, I used code like this:
$(window).scroll(function () {
if ($(window).scrollTop() >= offset) {
$(".image").addClass("active");
} else {
$(".image").removeClass("active");
}
});
But since there could be much more sections I need another solution.
Any ideas? Thanks in advance.
I think this is the pattern you are looking for:
$(window).scroll(function () {
image1();
image2();
image3();
});
function image1() {
var min = 0;
var max = 400;
if(window.scrollY >= min && window.scrollY < max) {
$("img").attr("src","https://cdn.picpng.com/head/head-the-dummy-avatar-man-tie-72756.png");
}
}
function image2() {
var min = 400;
var max = 800;
if(window.scrollY >= min && window.scrollY < max) {
$("img").attr("src","https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRlfO4xTPtZVZfQCZqpaoOV4_c3G-OMUJ00IU0fy8wnDOZzud3N2xYnMrzJbXLCs7vlmWM&usqp=CAU");
}
}
function image3() {
var min = 800;
var max = 10000;
if(window.scrollY >= min && window.scrollY < max) {
$("img").attr("src","https://www.unite2canada.com/images/dummy-user.png");
}
}
You can see this piece of code at work right here
Maybe for somebody, it will be helpful, so I will post my solution.
Thanks to Alex, I changed logic: I left only one image and on scroll, I change src attr.
$(window).scroll(function () {
let index, txtPosition, imgPosition;
$('.text-item').each(function () {
index = $(this).index();
txtPosition = $(this).offset().top;
imgPosition = $('.image-item').offset().top + 50;
if (txtPosition < imgPosition) {
$('.image-item img').attr('src', $(this).attr('data-image'));
}
});
});

Caught on a persistent issue with JS, nav bar active class not switching properly

I've been using this code snippet to add in a vertical dot nav to a one page site, which smooth scrolls to a section when one of the links are clicked, and keeps a highlight on the active section. I did a lot of tweaking to the css to make it look how I wanted, and then replaced the sections.
So this is my code in a jsfiddle, and the main issue I am having is the active class not changing properly, and making the side nav bar mess up. I've posted the JS below.
$(document).ready(function(){
$('.awesome-tooltip').tooltip({
placement: 'left'
});
$(window).bind('scroll',function(e){
dotnavigation();
});
function dotnavigation(){
var numSections = $('section').length;
$('#side-nav li a').removeClass('active').parent('li').removeClass('active');
$('section').each(function(i,item){
var ele = $(item), nextTop;
console.log(ele.next().html());
if (typeof ele.next().offset() != "undefined") {
nextTop = ele.next().offset().top;
}
else {
nextTop = $(document).height();
}
if (ele.offset() !== null) {
thisTop = ele.offset().top - ((nextTop - ele.offset().top) / numSections);
}
else {
thisTop = 0;
}
var docTop = $(document).scrollTop();
if(docTop >= thisTop && (docTop < nextTop)){
$('#side-nav li').eq(i).addClass('active');
}
});
}
/* get clicks working */
$('#side-nav li').click(function(){
var id = $(this).find('a').attr("href"),
posi,
ele,
padding = 0;
ele = $(id);
posi = ($(ele).offset()||0).top - padding;
$('html, body').animate({scrollTop:posi}, 'slow');
return false;
});
It works fairly well on the jsfiddle, but I am putting this code into squarespace, and on there it ends up like this where all of the buttons highlight when you try to change active classes.
I have tried to isolate the bug by going through the html, css, and the js, but I don't have enough knowledge of JS to be able to edit the script to fix it.
I would really appreciate any help. Thanks in advance.
EDIT: Link to broken squarespace
In the code snippet, the sample page is designed with continuous sections, so the method ele.next() will return next sections. In your squarespace page, the sections is not continuous, so method ele.next() will return empty and the code is not working.
Your could try to modify function dotnavigation like this
function dotnavigation(){
var numSections = $('section').length;
$('#side-nav li a').removeClass('active').parent('li').removeClass('active');
var sections = $('section');
var i = 0;
for (i = 0; i < sections.length; i++) {
var ele = $(sections[i]), nextTop;
//console.log(ele.next().html());
if (i < sections.length - 1) {
nextTop = $(sections[i + 1]).offset().top;
}
else {
nextTop = $(document).height();
}
if (ele.offset() !== null) {
thisTop = ele.offset().top - ((nextTop - ele.offset().top) / numSections);
}
else {
thisTop = 0;
}
var docTop = $(document).scrollTop();
console.log(thisTop);
if(docTop >= thisTop && (docTop < nextTop)){
$('#side-nav li').eq(i).addClass('active');
}
}
}
I've updated your code sample here.

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);
}
});
});

Floating JQuery menu issues on slower connection

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>

JS slideshow works one way

My slideshow is suffering from erratic behaviour. it's driven by pagers which the user clicks. when the corresponding pager is clicked, the next image is made visible (opacity/filter) and set as z-index 5 so that it should sit beneath the present image (z-index 10). The current image is then faded-out and finally, the next image is set to current and the image that has faded out is set to z-index 0. However, this only works when clicking back to a previous image (in Chrome, ie is behaving even more strangely.) in the order of images. That is to say,
chrome:
"list_slide1" to "list_slide3" instant jump with no fade
"list_slide3" to "list_slide1" fade behaves correctly
then...
"list_slide1" to "list_slide3" instant jump no fade "list_slide3" to
"list_slide2" fade behaves correctly
or...
"list_slide1" to "list_slide6" instant jump no fade
"list_slide6" to any preceding list-slide1-5 fade behaves correctly
IE:
"list_slide1" to "list_slide3" instant jump with no fade
"list_slide3" to "list_slide1" a second pause then jump
The pagers and the images are dynamically generated from a database (hence the little piece of PHP at the bottom of the code). it contains as many items as are listed for the page in the database.
a few notes:
1) the fade function is my own take on
http://javascript.info/tutorial/animation and has worked just fine in
another slideshow elsewhere on the site.
2) getElementsByClass is from http://www.robertnyman.com and returns
parent and child elements of the requested class in an array (hence
why I call current[0] etc.)
thanks.
<script type="text/javascript">
var pager = document.getElementById('pager1');
var list_pagers = document.getElementById('pagers')
var i = 0;
var next_slide = function(next) {
if (next.className !== 'slide_current') {
if (getElementsByClassName('slide_pending').length === 0) {
var current = getElementsByClassName('slide_current');
next.className = 'slide_pending';
next.style.zIndex = 5;
next.style.opacity = 1;
next.style.filter = 'alpha(opacity = 100)';
next.style.display = 'block';
fade(current[0], linear, 1000);
var fadeSlide = switcher(next, current);
}
}
}
var switcher = function(now, then) {
setTimeout(function() {
now.className = 'slide_current';
now.style.zIndex = 10;
now.style.opacity = 1;
now.style.filter = 'alpha(opacity = 100)';
then[0].className = 'slide_hide';
then[0].style.zIndex = 0;
then[0].style.opacity = 0;
then[0].style.filter = 'alpha(opacity = 0)';
then[0].style.display = 'none';
}, 1001);
}
<?php
// dynamically build event for each pager/slide in the show.
for ($k = 1; $k <= $i; $k++) {
echo 'var next_slide' .$k. ' = document.getElementById("list_slide" +' .$k. '); ',
'addEvent(list_pagers.childNodes[' .($k - 1). '], "click", function () {next_slide(next_slide' .$k. ')}); ';
}
?>
Forgive me for not posting an answer to your exact problem, but I would steer away from writing Javascript plugins yourself for the following reasons:
Hundreds of them exist on the Web already, some of which are developed on GitHub as open source, preventing potential issues through collaborative development.
There is no need to reinvent the wheel; simply spend 20 minutes googling javascript sliders and find one that you can customise to your needs.
A couple I like using are 'caroufredsel', which is responsive and offers a few nice features (dynamically adding items, callbacks etc).
Another is 'flexslider'.
SOLUTION:
the problem was that the <div> tags i was trying to fade each contained an <img> and another <div>... the CSS being applied was either working inconsistently/erratically or - as is IE's wont - not-at-all.... The solution was - rather than animating the fade of the parent <div> - animating the respective child components separately. At first, it looked like the IE solution was completely unto itself; in fact, it was insightful to creating a neat, lightweight non-JQuery slideshow for all the browsers. One trade-off was that I had to incorporate all the styling into the element tags rather than a separate CSS. This seemed like the only viable option in this instance by virtue of the nature of the DOM requests being made...
Questions/feedback gratefully received:
<script type="text/javascript">
var list_pagers = document.getElementById('pagers')
var i = 0;
<?php
// dynamically build event for each pager/slide in the show.
for ($k = 1; $k <= $i; $k++) {
echo 'var next_slide' .$k. ' = document.getElementById("list_slide" +' .$k. '); ',
'addEvent(list_pagers.childNodes[' .($k - 1). '], "click", function () {next_slide(next_slide' .$k. ')}); ';
}
?>
var next_slide = function(next) {
if (next.className !== 'slide_current') {
if (navigator.appName === 'Microsoft Internet Explorer') {
//IE 7 & 8
if ((navigator.appVersion.search('MSIE 8.0') >= 1) || (navigator.appVersion.search('MSIE 7.0') >= 1)) {
var current = getElementsByClassName('slide_current')[0].childNodes[0];
var currentBar = getElementsByClassName('slide_current')[0].childNodes[1];
var nextBar = next.childNodes[1];
var nextSlide = next.childNodes[0];
} else {
//IE 9
var current = getElementsByClassName('slide_current')[0].childNodes[1];
var currentBar = getElementsByClassName('slide_current')[0].childNodes[2];
var nextBar = next.childNodes[2];
var nextSlide = next.childNodes[1];
}
// give the next slide and its header (nextBar) a temporary status of zIndex 5/6
nextSlide.style.zIndex = 5;
nextBar.style.zIndex = 6;
nextSlide.style.filter = "alpha(opacity=100)";
nextBar.style.filter = "alpha(opacity=85)";
fade(currentBar, linear, 500); // fade currentBar out
fade(current, linear, 500); // fade current out
//once we've faded out current slides, it's time to replace them with th
setTimeout(function() {
getElementsByClassName('slide_current')[0].className = 'slide_hide';
next.className = 'slide_current';
nextSlide.style.opacity = 1; // IE 9 includes opacity...
nextBar.style.opacity = 1; // IE 9 includes opacity...
nextSlide.style.filter = "alpha(opacity=100)";
nextBar.style.filter = "alpha(opacity=85)";
nextSlide.style.zIndex = 10;
nextBar.style.zIndex = 11;
}, 500);
} else {
// NON IE TAGS
var current = getElementsByClassName('slide_current')[0];
current.childNodes[1].style.zIndex = 10; // [1] the child <img> tag
current.childNodes[2].style.zIndex = 11; // [2] the child <div> tag
current.childNodes[1].style.opacity = 1;
current.childNodes[2].style.opacity = 0.85;
next.childNodes[1].style.zIndex = 5;
next.childNodes[2].style.zIndex = 6;
next.childNodes[1].style.opacity = 1;
next.childNodes[2].style.opacity = 0.85;
fade(current.childNodes[1], linear, 600); // fade current out
fade(current.childNodes[2], linear, 600); // fade current out
var fadeSlide = setTimeout(function() {switcher(next, current)}, 500);
var switcher = function(now, then, nowBar, thenBar) {
then.className = 'slide_hide';
then.childNodes[1].style.opacity = 0;
then.childNodes[2].style.opacity = 0;
now.className = 'slide_current';
now.childNodes[1].style.opacity = 1;
now.childNodes[2].style.opacity = 0.85;
now.style.opacity = 1;
}
}
}
}
</script>

Categories