I have a fixed navbar on my site that I'm trying to tie functions to once it reaches a certain point on the page. I've done this successfully three times before on three sites but can't for the life of me get it to work on this one. The function is wrapped in a window ready so I know the page is fully loaded -- completely stumped for two days... Here the code:
jQuery:
function startchange() {
$('#ajax-frame').imagesLoaded().done(function(instance) {
var scroll_start = 0;
var startchange = $('.startchange');
var offset = startchange.offset();
if (startchange.length) {
$(document).on( 'scroll', function() {
scroll_start = $(this).scrollTop();
if (scroll_start > offset.top) {
$('nav').addClass('active');
console.log("startchange working");
} else {
$('nav').removeClass('active');
};
});
}
});
};
CSS:
body,
html {
height: 100% !important;
width: 100%;
margin: 0;
padding: 0;
overflow-x: hidden;
}
Thanks for any insight into this frustrating issue.
One quick approach that will sove the issue is to remove: overflow-x: hidden; from your css. Demo: https://jsfiddle.net/mrlew/ce8me3qk/
But here is what's happening: you're setting body and html to height 100%, and one is overlapping the other (html tag is a block element too). You're setting both to height: 100% and actually what you're scrolling is body, and not window/document.
Proof: look at both scrollbar there when setting overflow to scroll: https://jsfiddle.net/mrlew/ce8me3qk/8/ Note that you're scrolling the inner one. So, if you change $("document").on('scroll', function() { to $("body").on('scroll', function() {, it will work too.
Or, just don't set html height to 100%.
Related
I got a confusing bug inside my code and do not know how to fix it. I got to main functions, calling scripts depending on the current window size.
For mobile devices I got a slideToggle() function, which does work when viewing on a mobile device. But when opening above 600px, and scaling down the function is fired, but the slideToggle(); does not work anymore.
Its set to display: block; and immediately set to display: none; again. My slideToggle(); is embedded like this:
$('.box-header').on('click', function() {
$(this).parent().toggleClass('folded').toggleClass('unfolded');
$(this).next('div').stop().slideToggle();
console.log('clicked');
});
JSFIDDLE DEMO
When viewing the demo its important to load the page while the window size is above 600px and than scale down to recreate the problem. If it works please try again, as it does work sometimes.
What am I missing? And is there a better approach to kill and call scripts depending on the viewers viewport after resize events?
Put the if in the click event:
$('.box-header').on('click', function() {
if ($(window).width() < 600) {
$(this).parent().toggleClass('folded unfolded');
$(this).next('div').stop().slideToggle();
} else {
//for other code here for medium+large screens
}
});
https://jsfiddle.net/5puqn9ts/1/
even use a class to toggle between the mobile and large screen, bind a click event to each
$(document).ready(function() {
$('body').on('click', '.mobile', function() {
$(this).parent().toggleClass('folded').toggleClass('unfolded');
$(this).next('div').stop().slideToggle();
console.log('clicked');
});
// init scripts for smartphone or desktops
var initScripts = function() {
if ($(window).width() < 600) {
$('.box-header').addClass('mobile');
}
if ($(window).width() >= 600) {
$('.box-header').removeClass('mobile');
/add class for medium screen then bind event to ti
}
}
initScripts();
var id;
$(window).resize(function() {
initScripts()
});
});
https://jsfiddle.net/75186j96/5/
Your function set an event in every call. Try this correct alternative:
var smartphoneFunctions = $('.box-header').on('click', function() {
$(this).parent().toggleClass('folded').toggleClass('unfolded');
$(this).next('div').stop().slideToggle();
console.log('clicked');
});
https://jsfiddle.net/75186j96/8/
To answer your question, you need to adjust your slideToggle() target to be .box-content rather than the abstract div as this will instead apply the toggle on the .box-header. Also your class toggling could be bundled.
The resulting code would be the following:
$('.box-header').on('click', function() {
$(this).parent().toggleClass('folded unfolded');
$(this).next('.box-content').stop().slideToggle();
console.log('clicked');
});
That being said, there are better ways of doing this.
You could tie your classes to the appearance of .box-content, like this:
.box-content {
transition: height 300ms;
overflow: hidden;
}
.box.folded .box-content {
max-height: 0;
}
.box.unfolded .box-content {
max-height: 300px;
}
I have a script where I once I reach a specific point of the screen the div starts to scroll with the body by adding a fixed position, but it is not smooth and looks horrible. I have not been able to understand if I can add a pageoffset instead of adding a fixed class which causes the div to slightly jump instead of just picking up from where it is.
window.onload = function ()
{
var scrolledElement = document.getElementById('ID');
var top = scrolledElement.offsetTop;
var listener = function ()
{
var y = scrolledElement.scrollTop || scrolledElement.scrollTop || window.pageYOffset;
if (y >= top)
{
scrolledElement.classList.add('fixed');
} else {
scrolledElement.classList.remove('fixed');
}
};
window.addEventListener('scroll', listener, false);
}
but as I said, whenever the body scroll reaches the ID div it just jumps and adds the fixed css which is..
#ID.fixed {
position: fixed;
top:0;
width: 336px;
margin: 0px auto;
margin-top: 15px;
}
I can't understand if by adding offsettop to it instead of css it would make it not jump?
I am creating a timeline of events on my website, and I am trying to get each element (with a class '.event') to fade in as you scroll down through timeline. I am having issues - they all fade in together at the same time rather than individually.
Any ideas why? Thanks in advance!
$(document).ready(function() {
/* Every time the window is scrolled ... */
$(window).scroll( function(){
/* Check the location of each desired element */
$('.event').each( function(i){
var bottom_of_object = $(this).position().top + $(this).outerHeight();
var bottom_of_window = $(window).scrollTop() + $(window).height();
/* If the object is completely visible in the window, fade it it */
if( bottom_of_window > bottom_of_object ){
$(this).animate({'opacity':'1'},500);
}
});
});
});
Based on your JSFiddle this seems to be linked to a styling and/or markup issue.
Here's an updated version of your JSFiddle that works with your code and your markup: http://jsfiddle.net/2yMn4/2/. It messes up your layout a little bit, so you might need to rethink the structure, but hopefully that points you in the right direction. The main change that got it started working was switching your .event class to be relatively positioned. Then removing the second .posts-timeline article and .posts div.
.event {
position: relative;
opacity: 0;
left: 50%;
width: 210px;
z-index: 100;
min-height: 100px;
}
Let's say I have a single HTML page. 2000 pixels long for example. I want to detect if a visitor reaches a certain point on the page.
The page structure:
0px = begin of the page;
500px = about us page;
1000px = contactpage;
Is there a way with jQuery to detect if a user reaches the points described above?
You probably want jQuery's scroll event-binding function.
Yes, I would create three divs and then have a mouse over event on each. Example:
$("#begin").mouseover(function(){
alert("over begin");
});
$("#about").mouseover(function(){
alert("over about");
});
$("#contact").mouseover(function(){
alert("over contact");
});
You can see a working fiddle here: http://jsfiddle.net/ezj9F/
Try THIS working snippet.
Using this code you don't have to know position of the element you want to check if it is visible.
JQuery
var $window = $(window);
// # of pixels from the top of the document to the top of div.content
var contentTop = $("div.content").offset().top;
// content is visible when it is on the bottom of the window and not at the top
var contentStart = contentTop - $window.height();
// content is still visible if any part of his height is visible
var contentEnd = contentTop + $("div.content").height();
$window.scroll(function() {
var scrollTop = $window.scrollTop();
if(scrollTop > contentStart && scrollTop < contentEnd) {
console.log('You can see "HELLO"!');
} else {
console.log('You cannot see "HELLO"!');
}
});
HTML
<div class="scroll"></div>
<div class="content">HELLO</div>
<div class="scroll"></div>
CSS
div.scroll {
background-color: #eee;
width: 100px;
height: 1000px;
}
div.content {
background-color: #bada55;
width: 100px;
height: 200px;
}
EDIT: Now the algorithm is checking if any part of the div.content is visible (it is considering height of the element). If you are not interested in that change contentEnd to var contentEnd = contentTop.
I need that when I scroll down or up with mouse wheel or sidebar my div change incrementally the Y position (for example 50px up or down ). I need this in Javascript/Jquery.
I Try this code, but only works for scrolling down(The Scrolling Down and Up Function is working well, only the animate part is working wrong):
UPDATE:
var sidebarScrollTop = 0;
$(document).ready(function() {
sidebarScrollTop = $("body").offset();
$(window).scroll(function ()
{
var docScrollTop = $('body,html').scrollTop();
if(docScrollTop > sidebarScrollTop.top)
{
$("#legend").stop().animate({ marginTop: "+=50px",}, 'slow', "easeOutCirc" );
}
else
{
$("#legend").stop().animate({ marginTop: "-=50px",}, 'slow', "easeOutCirc" );
}
});
});
$(window).resize(function()
{
sidebarScrollTop = $("#legend").offset().top;
});
$(document).resize(function()
{
sidebarScrollTop = $("#legend").offset().top;
});
Thanks
You can use
$(window).scroll(function() {
// Your scroll code here
});
to grab whenever the user is scrolling on the page.
Next you want to change the div's y-value.
If the div is positioned absolute, this is just changing its top-value.
$('my-div').top = original-top-value + $(window).pageYOffset;
I believe you need is to keep the div always showing even when user scrolls down. If that is the case then it can be done with only CSS:
div {
position: fixed;
z-index: 100;
top: 100px;
left: 100px;
}
The values of z-index, top and left are dummy values. Change em with your ones.
UPDATE:
Since CSS Solution won't work for you, here is a working example writter in JS: http://jsfiddle.net/qCtt5/