Scroll animation doesn't work on IE and Mozilla - javascript

I have an element that fills the screen, under that is another element but this one is hidden so you can't scroll to it manually.
My CSS stylesheet looks like this for that:
body {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
}
#page1, #content {
height: 100%;
width: 100%;
position: absolute;
}
#content {
top: 100%;
display:none;
}
#page1 stands for the element that fills the screen and #content stands for the element which is underneath that.
When I click on a button on the first element (which fills the screen), it shows the element under that and smoothly scrolls down to that.
I was using this piece of code in the first place:
$(document).ready(function() {
$('#exploreBtn').on('click', function() {
$('#content').fadeIn(500);
console.log($("#content").offset().top)
$('html, body').animate({
scrollTop: $("#content").offset().top
}, 1000, function(){
$("#page1").css('display','none');
$('#content').css('top',0);
$(document).scrollTop(0);
});
});
});
Which works in IE and Mozilla, but I've tried to improve it...
Now I'm using this code:
$(function() {
var headerLoaded = true,
contentLoaded = false,
header = "#fitScreen",
exploreBtn = "#exploreBtn",
scrollBackBtn = "#scrollBackBtn",
content = "#content";
$(exploreBtn).on('click', function() {
if (!contentLoaded && headerLoaded) {
showScrollHide(content, header, function() {zit
var sum = ($('nav').height()) + parseInt($('nav').css('margin-bottom'));
$('#panelContent').css('margin-top', sum);
$('#content').css('top', 0);
$('html, body').css('overflow-y', 'auto');
$(window).scrollTop(0);
headerLoaded = false;
contentLoaded = true;
});
}
});
var showScrollHide = function(element, hide, func) {
$(element).fadeIn(500, function() {
$('body').animate({
scrollTop: $(element).offset().top
}, 1000, function() {
$(hide).fadeOut(100, func);
});
});
};
});
And for some reason, it doesn't work on IE and Mozilla.
It just gives me a slight delay, and then it fades in the screen I'm scrolling to.
Can anyone help me with this?

In your new code, you have this part :
$(element).fadeIn(500, function() {
$('body').animate({
scrollTop: $(element).offset().top
}, 1000, function() {
$(hide).fadeOut(100, func);
});
});
The difference between your working code and your not working code is which element you animate the scroll.
In you working code, you are animating 'body, html'. Depending on browser, the scrollbar is not on the same element. Hence, that's why you should target both html and body element :
$(element).fadeIn(500, function() {
$('html, body').animate({ //HERE!
scrollTop: $(element).offset().top
}, 1000, function() {
$(hide).fadeOut(100, func);
});
});

Related

How Do I Use Scrollspy when I have links on the page and off the page?

I have an application with a landing page that has many sections, and use Scrollspy for the smooth scrolling effect in the page. At the end of my navigation items I have a call to action button that takes the user to another page. However, because it's in my navigation items, when the page loads, Scrollspy is throwing an error on the link to another page.
Uncaught Error: Syntax error, unrecognized expression: https://example.com/page2
Is there anything I can do to tell scrollspy to ignore that link or is there some other way to get rid of that error? Thanks!
Here is the code I am using to initialize scrollspy:
(function ($) {
'use strict';
// SmoothLink
function initSmoothLink() {
$('.nav-item a').on('click', function(event) {
var $anchor = $(this);
$('html, body').stop().animate({
scrollTop: $($anchor.attr('href')).offset().top - 0
}, 1500, 'easeInOutExpo');
event.preventDefault();
});
}
// StickyMenu
function initStickyMenu() {
$(window).on('scroll',function() {
var scroll = $(window).scrollTop();
if (scroll >= 50) {
$(".sticky").addClass("stickyadd");
} else {
$(".sticky").removeClass("stickyadd");
}
});
}
// Scrollspy
function initScrollspy() {
$("#navbarCollapse").scrollspy({
offset: 70
});
}
//MFPVideo
function initMFPVideo() {
$('.video_play').magnificPopup({
disableOn: 700,
type: 'iframe',
mainClass: 'mfp-fade',
removalDelay: 160,
preloader: false,
fixedContentPos: false
});
}
// Back To Top
function initBackToTop() {
$(window).on('scroll',function(){
if ($(this).scrollTop() > 100) {
$('.back_top').fadeIn();
} else {
$('.back_top').fadeOut();
}
});
$('.back_top, .footer_logo_link').on('click',function(){
$("html, body").animate({ scrollTop: 0 }, 1000);
return false;
});
}
function init() {
initSmoothLink();
initStickyMenu();
initScrollspy();
initMFPVideo();
initBackToTop();
}
$(document).on('turbolinks:load', function(){
init();
});
})(jQuery);
You can add in if statement to check if the href has a hash. If it doesn't have one, then it will just proceed as normal.
function initSmoothLink() {
$('.nav-item a').on('click', function(event) {
var $anchor = $(this);
if (this.hash !== "") {
$('html, body').stop().animate({
scrollTop: $($anchor.attr('href')).offset().top - 0
}, 1500, 'easeInOutExpo');
event.preventDefault();
}
});
}
Scrollspy looks for all a tags in given container, takes href attribute and uses it's value as jQuery selector. Here is the possible solution using JS:
Page 2
Setting href and id is required in your case if you don't want to add additional checks in initSmoothLink() function.

Add a loading gif when element fades out and remove it when new element fades in

I have this pagination set up so that when users click on the next arrow (.paging-navigation a), the current set of blog posts fade out and the new set fades in. Sometimes there is a delay while the new set loads in and I want to insert a loading gif there so users know nothing went wrong.
Here is how I have it set up:
$('#article-list').on('click', '.paging-navigation a', function(e){
e.preventDefault();
var link = $(this).attr('href');
$('html, body').animate({
scrollTop: $('#news').offset().top - 60
}, 500);
$('#article-list').fadeOut(500, function(){
// I would like to put in the animation gif here
and fade it away when the new set of posts
fade in.
$(this).load(link + ' #article-list', function() {
$(this).find('#article-list > *').unwrap().end().fadeIn(500);
});
});
});
Here is the HTML:
<div id="news">
<div id="article-list">
<img class="loading-list" src="loading.gif" style="display:none">
(blog posts here)
<div class="paging-navigation">
<div class="nav-previous">
Prev
</div>
<div class="nav-next">
Next
</div>
</div>
</div>
</div>
I've tried showing/hiding the .loading-list img like this but it didn't work:
$('#article-list').on('click', '.paging-navigation a', function(e){
e.preventDefault();
var link = $(this).attr('href');
$('html, body').animate({
scrollTop: $('#news').offset().top - 60
}, 500);
$('#article-list').fadeOut(500, function(){
$('.loading-list').show(); <// added
$(this).load(link + ' #article-list', function() {
$(this).find('#article-list > *').unwrap().end().fadeIn(500);
});
$('.loading-list').hide(); <// added
});
});
Can someone help me out?
Also, while the first set of posts fade out and the new posts are getting ready to load in, the height of the container div reduces suddenly to account for the lack of content and then the height shifts back when the new posts fade in. Is there any way to make the height of the div transition smoother?
Edit: CSS for #article-list
#news #article-list {
overflow: hidden;
text-align: center;
}
<div id="news">
<img class="loading-list" src="loading.gif" style="display:none">
<div id="article-list">
(blog posts here)
<div class="paging-navigation">
<div class="nav-previous">
Prev
</div>
<div class="nav-next">
Next
</div>
</div>
</div>
</div>
Script:
$('#article-list').on('click', '.paging-navigation a', function(e){
e.preventDefault();
var link = $(this).attr('href');
$('html, body').animate({
scrollTop: $('#news').offset().top - 60
}, 500);
$('#article-list').fadeOut(500, function(){
$('.loading-list')[0].show(); <// added
$(this).load(link + ' #article-list', function() {
$(this).find('#article-list > *').unwrap().end().fadeIn(500);
});
$('.loading-list')[0].hide(); <// added
});
});
this would work as long as you remove image a step up , you cant hide a parent and keep the child visible.
Edit:
selecting class will return a node list , so have to specify element,or use loading -list as id instead of class.
Edit (2)
Actually i dont know what is wrong with your source code , but jquery hide and show doesnt work for me.
However this worked :
document.getElementsByClassName("loading-list")[0].style.display="block";
so new code should be:
$('#article-list').on('click', '.paging-navigation a', function(e){
e.preventDefault();
var link = $(this).attr('href');
$('html, body').animate({
scrollTop: $('#news').offset().top - 60
}, 500);
$('#article-list').fadeOut(500, function(){
document.getElementsByClassName("loading-list")[0].style.display="block";; <// added
$(this).load(link + ' #article-list', function() {
$(this).find('#article-list > *').unwrap().end().fadeIn(500);
});
document.getElementsByClassName("loading-list")[0].style.display="none";; <// added
});
});
You need to move the $('.loading-list').hide() into the callback function of the .load().
$('#article-list').on('click', '.paging-navigation a', function (e) {
e.preventDefault();
var link = $(this).attr('href');
$('html, body').animate({
scrollTop: $('#news').offset().top - 60
}, 500);
$('#article-list').fadeOut(500, function () {
$('.loading-list').show();
$(this).load(link + ' #article-list', function () {
$('.loading-list').hide(); //moved here
$(this).find('#article-list > *').unwrap().end().fadeIn(500);
});
//from here
});
});
So you show the gif, start loading the new content, then when the content is done loading, the callback function hides the gif and fades in the new content.
As for the height, you can use CSS transition to smooth out the changes. But since you can't transition to and from height: auto, you need a workaround. Something like:
CSS:
#article-list {
min-height: 0;
-webkit-transition: min-height 0.5s;
transition: min-height 0.5s;
}
JS (jQuery):
$('#article-list').on('click', '.paging-navigation a', function (e) {
e.preventDefault();
var link = $(this).attr('href');
$('html, body').animate({
scrollTop: $('#news').offset().top - 60
}, 500);
$('#article-list').css('min-height', 400); //change min-height here
$('#article-list').fadeOut(500, function () {
$('.loading-list').show();
$(this).load(link + ' #article-list', function () {
$('.loading-list').hide();
$(this).find('#article-list > *').unwrap().end().fadeIn(500);
$('#article-list').css('min-height', 0); //change min-height here
});
});
});
So right before you start to fade out the old content, you set the min-height, so the div doesn't collapse. When right after the new content starts to fade in, so it's already filling some of the div's height, you set the min-height back to 0, allowing the transition to smoothly shrink the div to the new content's height.
Let me know if something doesn't work, since it's a little hard for me to test this code.
Edit, updated
Try
v3
$('#article-list')
.on('click', '.paging-navigation a', function (e) {
e.preventDefault();
var link = $(this).attr('href');
$('html, body').animate({
scrollTop: $('#news').offset().top - 60
}, 500, "linear");
$('#article-list *:not(img.loading-list)')
.fadeOut({
duration: 500,
start: function (promise) {
$("img.loading-list")
.fadeIn(0);
}
}).promise().done(function(el) {
$(el).siblings("img.loading-list")
.fadeOut(1500, function() {
// substituted `e.target` for `this`
$(e.target).load(link + ' #article-list', function() {
$('#article-list *:not(img.loading-list)')
.fadeIn(500);
});
})
});
});
jsfiddle http://jsfiddle.net/guest271314/7mvrdzcj/

Fixing nav to top, then add margin to body

Currently using this:
$(function(){ // document ready
var stickyTop = $('.navigation-wrap').offset().top; // returns number
$(window).scroll(function(){ // scroll event
var windowTop = $(window).scrollTop(); // returns number
if (stickyTop < windowTop) {
$('.navigation-wrap').addClass('sticky');
}
else {
$('.navigation-wrap').removeClass('sticky');
}
});
});
And that sticks the navigation to the top of the screen perfectly, however... when using the following:
$(document).ready(function () {
$(document).on("scroll", onScroll);
//smoothscroll
$('a[href^="#"]').on('click', function (e) {
e.preventDefault();
$(document).off("scroll");
$('a').each(function () {
$(this).removeClass('navactive');
});
$(this).addClass('navactive');
var target = this.hash,
menu = target;
$target = $(target);
$('html, body').stop().animate({
'scrollTop': $target.offset().top+2
}, 500, 'swing', function () {
window.location.hash = target;
$(document).on("scroll", onScroll);
});
});
});
To highlight the current button depending on how far down the page you have scrolled. The problem is now that the 50px navigation is covering the top of the content. If you click on one of the buttons, the page scrolls down and covers the title.
Is there any way of adding a 50px margin to the code so the nav doesn't get in the way? I did try using offset, but couldn't get it to work.
Yeah, add more pixels in this line:
'scrollTop': $target.offset().top+2
For example:
'scrollTop': $target.offset().top+52
You can take a look at a similar solution I proposed.

how to animate height of a div back-jquery

I'm trying to show some part of a div and animate it to 100% when the div is clicked.
and I want to animate it back to the initial height of the div if it's clicked again.
this is what i have so far,but it doesn't work. can anyone help?
#mydiv {
height:150px;
width: 100%;
overflow:hidden;
}
<script type="text/javascript">
$(document).ready(function(){
$("#mydiv").click(function(){
$(this).animate({height: '100%'}, 300);
}, function() {
$(this).animate({height: '150px'}, 300);
});
});
</script>
click() doesn't accept two function arguments, previously there was a toggle() function that performed how you need it but it has now been deprecated and removed from jQuery.
Since your use case is pretty simple, I believe something like this would be enough:
$("#mydiv").click(function () {
var $this = $(this);
$this.animate({
height: $this.height() == 150 ? '100%' : 150
}, 300);
});
Demo fiddle
This should do the job for you.
jQuery:
$(document).ready(function() {
$("#mydiv").toggle(
function() {
$(this).animate({height: '100%'}, 300);
};
function() {
$(this).animate({height: 150}, 300);
});
});

Tool bar JavaScript Pin to / Onmouseover event conflict

I'm making a tool bar with JavaScript. This tool bar's regular height is 50px. On mouse over, it's height changes to 500px. On this toolbar however, there's a little pin to image. My intention is to make this image change the tool bar div's height to 500px and let it stay that way. Currently I can change the tool bar div with the image, but onmouseout it changes back to its original 50px height.
How can I make it so that when the pin image is clicked, the onmouseout functions stops working until the image is clicked again?
If it helps, this is my code:
//Pin to Image
<img class="pin" onClick = "document.getElementById('toolbar').style.height
= '500px';" src="images/pin.png" width="20px" height="20px" />
//JavaScript for mouseoverevent
$(document).ready(function() {
$("#toolbar").hover(
//on mouseover
function() {
$("#toolbar").animate({
height: '550'
}, 'slow');
},
//on mouseout
function() {
$(this).animate({
height: '-=500px'
}, 'slow');
}
);
});
The following code should do the trick (i have not tested if it works for sure). It can be done for sure with a better way (maybe with toggle):
<img class="pin" height="20px" src="images/pin.png" width="20px"/>
//JavaScript for mouseoverevent
$(document).ready(function() {
var isPinned = false;
$(".pin").click(function(){
$("#toolbar").css('height', '500px');
isPinned = true;
});
$("#toolbar").hover(
//on mouseover
function() {
if(!isPinned) {
$("#toolbar").animate({
height: '550'
}, 'slow');
}
},
//on mouseout
function() {
if(!isPinned) {
$(this).animate({
height: '-=500px'
}, 'slow');
}
}
);
});
remove the onclick from the image and add this:
$('.pin').click(function(){
$(this).toggleClass('.pinned');
if(parseInt($('#toolbar').css('height')) < 500) $("#toolbar").animate({
height: '550'
}, 'slow');
});
and edit the #toolbar hover function:
$("#toolbar").hover(
function() {
// return if its pinned
if($('#toolbar .pin').hasClass('pinned')) return;
$("#toolbar").animate({
height: '550'
}, 'slow');
},
function() {
// return if its pinned
if($('#toolbar .pin').hasClass('pinned')) return;
$(this).animate({
height: '-=500px'
}, 'slow');
}
);
});
now you can use the .pinned class to visualize the state of the toolbar.
Create a flag variable that stores the toolbar's state. Write a condition inside the mouseout function that bypasses the height change if the state is 'pinned'.

Categories

Resources