Jumping effect for scroll fixed scrollTop() - javascript

I am referring to the following tutorial:
http://www.webdeveloperjuice.com/2011/08/07/how-to-fix-element-position-after-some-scroll-using-jquery/
While the demo in the page looks fine, but when I implement it on my site, I get the "jumping" effect. Often, the 1st item gets jumped, and straight to half of the 2nd item.
How do I fix this?
Below is my HTML:
<div id="map_container">
<div id="map" class="well"></div>
</div>
<ul>
<li>1. Many contents here...</li>
<li>2. Many contents here...</li>
<li>3. Many contents here...</li>
<li>4. Many contents here...</li>
<li>5. Many contents here...</li>
<li>6. Many contents here...</li>
<li>7. Many contents here...</li>
</ul>
The following is the Javascript:
$(document).ready( function(){
$('#map_container').css("width", $('#map').width());
$("#map_container").scrollFixed({hideBeforeDiv:'footer'});
});
(function($){
$.fn.scrollFixed = function(params){
params = $.extend( {appearAfterDiv: 0, hideBeforeDiv: 0}, params);
var element = $(this);
if(params.appearAfterDiv)
var distanceTop = element.offset().top + $(params.appearAfterDiv).outerHeight(true) + element.outerHeight(true);
else
var distanceTop = element.offset().top;
if(params.hideBeforeDiv)
var bottom = $(params.hideBeforeDiv).offset().top - element.outerHeight(true) - 10;
else
var bottom = 200000;
$(window).scroll(function(){
if( $(window).scrollTop() > distanceTop && $(window).scrollTop() < bottom )
element.css({'position':'fixed', 'top':'0'});
else
element.css({'position':'static'});
});
};
})(jQuery);

When Javascript dynamically adds a position: fixed to the #map_container, just use CSS to apply the same #map_container height to the first item of ul. The following solution is done using SCSS:
#map_container {
&.fixed {
position: fixed;
top: 0;
& ~ .ul .li:first-child {
margin-top: 210px;
}
}

Related

Animate div detect top or bottom of it

I want my div to animate when that div is almost half while scrolling.
How can I do it? It's not on a fixed div but its like sticky sidebar
Just like on this website sample
this is my code
$(function(){ // document ready
if ($('.filter-container').length) { // make sure ".filter-container" element exists
var el = $('.filter-container');
var stickyTop = $('.filter-container').offset().top; // returns number
var stickyHeight = $('.filter-container').height();
$(window).scroll(function(){ // scroll event
var limit = $('#footer').offset().top - stickyHeight - 100;
var windowTop = $(window).scrollTop(); // returns number
if (stickyTop < windowTop){
el.css({ position: 'fixed', top: 0, width: 280 });
}
else {
el.css({ position: 'static', width: 280 });
}
if (limit < windowTop) {
var diff = limit - windowTop;
el.css({top: diff});
}
});
}
});
You could write a jQuery function using Waypoints.
Or more easily (in my opinion) but with higher payload cost use Bootstrap affix. In this case you keep your current css but then add some Bootstrap properties to the div, in your case:
<div class="filter-container" data-spy="affix" data-offset-top="60" data-offset-bottom="200">
This will add the classes .affix-top to the div UNTIL the user scrolls past 60px. Then if will change to .affix when the user gets 200px from the bottom it will change to .affix-bottom to the class.
This jsfiddle shows it quite well:
http://jsfiddle.net/skelly/df8tb/
This shows the appropriate css to get the sticky effect.

Finding position of element within scrollable div

I have these "pages" aka div's inside a scrollable container. On command, I am trying to find out what part of the div in question, is touching the top of .pageContent.
So for example, right when the page loads, no part of #page_1 is touching the top of pageContent, but as I scroll down. #page_1 hits the top of .pageContent and I now want to figure out where that is.
I know I can get the position of .pageContent using $("#pageContent").scrollTop() but these page's could be different sizes and I am not sure how to go about figuring it out.
Could anyone put me in the right direction?
jsfiddle
HTML
<div id="pageContent">
<div id="page_1" class="content"></div>
<div id="page_2" class="content"></div>
<div id="page_3" class="content"></div>
</div>
CSS
#pageContent {
overflow: auto;
width:500px;
height:300px;
padding:10px;
border:1px solid black;
background-color:grey;
}
.content {
height:400px;
width:300px;
margin:0 auto;
background-color:red;
margin-bottom:10px;
}
You can use the jQuery .position() function to compute where each page is in relation to the top of the container. See this Fiddle.
For example, for #page_1,
var page1 = $('#page_1');
$('#pageContent').scroll(function() {
// page1.position().top gives the position of page_1 relative to the
// top of #pageContent
});
ScrollTop can be used, be I wouldn't recommend it.
Attach a scroll event to your main div and listener for all the objects inside:
$('#pageContent').scroll(function(){
var pages = $("#pageContent > .content");
for (var i = 0; i < pages.length; i++)
{
if ($(pages[i]).position().top < 0 && ( $(pages[i]).position().top + $(pages[i]).outerHeight() ) > 0)
{
var outerHeight = $(pages[i]).outerHeight();
var pixels = (outerHeight - (outerHeight + $(pages[i]).position().top));
console.log("These pixels are in view between: " + pixels + " and " + outerHeight );
}
}
})
Every time the div scroll a loop is performed checking the position of all elements. If the elements scroll out of view a the top the if is triggered, calculating the remaining visible pixels of the page currently visible.
This uses jQuery's: position() and outerHeight() and JavaScript's native offsetTop.
http://jsfiddle.net/q5aaLo9L/4/
I tried something like this
$(document).ready(function () {
var divs = $('.content').map(function (i, el) {
return $(el).offset().top - $(el).parent().offset().top;
});
$('#pageContent').scroll(function () {
var index = findIndex($(this).scrollTop(), divs) - 1;
if (index > -1) {
console.log($(this).children().eq(index).attr('id'));
} else {
console.log('outside');
}
});
});
function findIndex(pos, divs) {
return (divs.filter(function (el, et) {
return et <= pos
}).length);
}
It's not super clean code because I had to do it quickly.
DEMO
I hope this helps
I mocked this up, it uses JQuery's each() function to iterate through the pages and return the information of the page that has breached the top of the box.
I wasn't sure from your question exactly what you wanted returned, so I got it to return either the percentage of the page that has cleared the top border, the position (as negative value of pixels) of the top of the "page " in relation to the content container, and also just the ID of that div.
var getCurrentPage = function(){
var page;
var position;
var percentageRead;
$('.content').each(function(){
if($(this).position().top <= 0){
page = $(this);
position = $(this).position().top;
}
});
percentageRead = ((position *-1)/ $(page).height()* 100);
console.log(page.attr('id'));
console.log(position);
console.log(percentageRead + '%');
}
$('#pageContent').on('scroll', getCurrentPage);
You could fire this on any event but I used scroll to build it.

Get the first Element that is floating on next line

I have a list of Elements that are floating left:
<style>
ul {
overflow: hidden;
width: 100%;
}
ul li {
float: left;
width: 100px;
}
</style>
<ul>
<li id="#one">One</li>
<li id="#two">Two</li>
<li id="#three">Three</li>
...
</ul>
...having a window width of 200px the first Element that is floating on the second line would be #three... having a window width of just 100px that would be #two.
Now on every <li> there is a click-event bound, that should tell me which Element is the first Element on the next Line, seen by itself.
Clicking on #one with a window width of 200px I want to get #three, and with a window width of 100px I want to get #two.
I tried to solve this by getting the position of the Element that is clicked on, query the Position inside the window using .getBoundingClientRect(), get the height of the Element (taking 20px here), and then get the Element by using document.elementFromPoint(y,x)...something like this:
y = clicked_element.getBoundingClientRect().left
x = clicked_element.getBoundingClientRect().top + 21
first_element_on_next_line = document.elementFromPoint(y,x)
so far, so good... but of course this is just working if the first element on the next line is really inside the window! :-\
and this is where I'm stuck...if I have a window width of 200px and a window height of just 20px (just for the example), I just can't select #three with document.elementFromPoint() because its position is outside the window.
I could also use jQuery, it's included anyways, but everything came across was using document.elementFromPoint()
Any Ideas??
You could use following logic using jQuery .position() method: {as suggested by maja}
$(function () {
var $lis = $('ul li').on('click', function(){
var $nextFirstElement = $(this).nextAll('.first').first();
console.log($nextFirstElement);
});
$(window).on('resize', function () {
var initialLeft;
$lis.each(function(i){
if (i === 0) { // this could be put out of the loop, but...
initialLeft = $(this).position().left;
}
$(this).toggleClass('first', i === 0 || $(this).position().left === initialLeft);
});
}).resize();
});
-jsFiddle-
The Solution I'm using now (which in fact is the Solution charlietfl brought up in the Comments) is this:
$(function(){
var list = $("ul"),
lis = list.children(),
first_li = lis.first(),
list_width, first_li_width, items_per_line
var set_vars = function(){
list_width = list.width()
first_li_width = first_li.width()
items_per_row = Math.floor(list_width / first_li_width)
}
set_vars()
lis.click(function(){
index = lis.index(this)
next_first_index = index + (items_per_row - (index % items_per_row))
console.log(next_first_index)
})
$(window).resize(function(){
set_vars()
})
})

How to make text appear on scroll in html

Hello, I want a certain text to appear when I scroll past it or when I scroll until the point where the text is. The effect when appearing should be somewhat like the first effect on the top of the website http://namanyayg.com/.
I want the effect in minimal code with pure CSS and JS i.e no jQuery.
I was thinking that maybe I would use something like a display:none property for a span and then when you scroll past it the display becomes block but I dont know how to trigger the effect using javascript.
Any help would be appreciated.
First wrap whatever your text or content that you want to show on scroll, in one div so that you can show hide the div depending upon the scroll. Write two classes for your target div.
Your CSS:
/*Use this class when you want your content to be hidden*/
.BeforeScroll
{
height: 100px; /*Whatever you want*/
width: 100%; /*Whatever you want*/
.
.
display: none;
}
/*Use this class when you want your content to be shown after some scroll*/
.AfterScroll
{
height: 100px; /*Whatever you want*/
width: 100%; /*Whatever you want*/
.
.
display: block;
}
Your HTML:
<!--Set class BeforeScoll to your target div-->
<div id = "divToShowHide" class = "BeforeScroll">Content you want to show hide on scroll</div>
Your Script:
<!--include these script in head section or wherever you want-->
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.10.1/jquery-ui.min.js" type="text/javascript"></script>
<script type = "text/javascript">
$(document).ready(function(){
//Take your div into one js variable
var div = $("#divToShowHide");
//Take the current position (vertical position from top) of your div in the variable
var pos = div.position();
//Now when scroll event trigger do following
$(window).scroll(function () {
var windowpos = $(window).scrollTop();
//Now if you scroll more than 100 pixels vertically change the class to AfterScroll
// I am taking 100px scroll, you can take whatever you need
if (windowpos >= (pos.top - 100)) {
div.addClass("AfterScroll");
}
//If scroll is less than 100px, remove the class AfterScroll so that your content will be hidden again
else {
s.removeClass("AfterScroll");
}
//Note: If you want the content should be shown always once you scroll and do not want to hide it again when go to top agian, no need to write the else part
});
});
</script>
Hope it will solve your problem.
I would recommend this plugin
http://johnpolacek.github.io/superscrollorama/
Edit:
I don't know how no one noticed that the solution had to be made without using external libraries like jQuery. However, the solution is extremely easy with basic functionality. Find it here
HTML:
<div id="parent-div">
<div id="child-div">
Psst .. I am here!!
</div>
</div>
CSS:
#parent-div
{
position:relative;
height:3000px;
width:300px;
background-color:red;
}
#child-div
{
color:white;
position:relative;
top:1000px;
width:300px;
display:none;
text-align:center;
}
JS:
var body=document.getElementsByTagName("body")[0];
var parent=document.getElementById("parent-div");
var child=document.getElementById("child-div");
body.onscroll = function(){
//console.log(documenhttps://fiddle.jshell.net/3urv0tp0/#tidyt.getElementById("child-div").style.top)
if(document.documentElement.scrollTop>=child.offsetTop)//Adjust Tolerance as you want
{
child.style.display="block"
}
};
I was looking for this either. Here i was trying to make "show text after scrolling to (number)px with fade effect". I wish it will work as it works for me :) The animation will be playing again if u scroll back to it, idk how to make it just one like in web u showed xd (i will edit if I find out)
window.addEventListener("scroll", function() {showFunction()});
function showFunction() {
if (document.body.scrollTop > 900 || document.documentElement.scrollTop > 900) {
document.getElementById("toptexts2").style.display = "block";
} else {
document.getElementById("toptexts2").style.display = "none";
}
}
.toptexts2 {
animation: fadeEffect 3s; /* fading effect takes 3s */
}
#keyframes fadeEffect { /* from 0 to full opacity */
from {opacity: 0;}
to {opacity: 1;}
}
<div class="toptexts2" id="toptexts2">
<div>Hi!</div>
<div>↓ go down ↓</div>
</div>
I like this:
var doc = document, dE = doc.documentElement, bod = doc.body;
function E(e){
return doc.getElementById(e);
}
function xy(e, d){
if(!d)d = 'Top';
d = 'offset'+d;
var r = e[d];
while(e.offsetParent){
e = e.offsetParent; r += e[d];
}
return r;
}
function x(e){
return xy(e, 'Left');
}
function y(e){
return xy(e);
}
var txt = E('theId'), txtS = txt.style;
onscroll = function(){
var left = dE.scrollLeft || bod.scrollLeft || 0;
var top = dE.scrollTop || bod.scrollTop || 0;
var w = innerWidth || dE.clientWidth || bod.clientWidth;
var h = innerHeight || dE.clientHeight || bod.clientHeight;
if(top > y(txt)-h){
txtS.display = 'none';
}
else{
txtS.display = 'block';
}
}
I left the left stuff in there, just in case, but you can probably remove it.
var div=$("#divtochange");
$(window).scroll(function () {
var windowpos = $(window).scrollTop();
//---check the console to acurately see what the positions you need---
console.log(windowpos);
//---------------------
//Enter the band you want the div to be displayed
if ((windowpos >= 0) && (windowpos <= 114)){
div.addClass("AfterScroll");
}
else{
div.removeClass("AfterScroll");
}

DIV stick to top till pushed offscreen by next DIV

I am trying to get a similar effect to the Instagram timeline on a project I am doing. My HTML is:
<div class="item">
<div class="title">
<h1>Some title</h1>
<span>Time here</span>
</div>
<div class="content"></div>
</div>
Which is repeated many times down the page, and my CSS is:
* {
margin: 0;
padding: 0;
}
.item {
width: 100%;
background-color: red;
}
.item h1, span{
padding: 2px 0 5px 5px;
}
.item span{
display: inline;
}
.title {
background-color: blue;
}
.content {
height: 200px;
background-color: green;
}
What I want to happen is when a user scrolls, <div class="title"> sticks to the top when a user is scrolling, but when the next <div class="title"> comes up it 'pushes' the previous one off screen and then fixes it's self to the top.
Screenshots:
Picture 1 - Look at the two headers, one for withhearts the other for brenton_clarke.
Picture 2 - brenton_clarke's header has reached the bottom of withheart's
Picture 3 - brenton_clarke's header is pushing withheart's offscreen
Picture 4 - brenton_clarke's headers is now stuck to the top till pauloctavious pushes it off
My Fiddle
Can anyone give me some help with this?
With the link suggested below I was able to get it sort-of working, but not great: http://jsfiddle.net/reb6X/1/
Having modified the jQuery to use .html() rather than .text() it works not to badly now: http://jsfiddle.net/reb6X/2/
You might want to check out this jsfiddle.
http://jsfiddle.net/kennis/JTvFZ/
I think it could get you in the right direction.
// Index of the currently 'active' section
var activeCache = null;
// Actual rendered height of a header element
var cloneHeight = function(){
var $clone = $('<div class="clone"></div>').appendTo('body'),
cloneHeight = $clone.outerHeight();
$clone.remove();
return cloneHeight;
}();
// Top offsets of each header
var offsets = [];
// Figure out which section is 'active'
var activeHeaderIndex = function(){
var scrollTop = document.body.scrollTop;
for ( var i = 0; i < offsets.length; i++ )
if ( offsets[i] - cloneHeight > scrollTop )
return Math.max( i - 1, 0 );
}
// Build the 'offsets' array
$('.header').each(function(i, obj){
offsets.push( $(this).offset().top );
});
// Listen to scroll events
$(window).on('scroll', function(){
var active = activeHeaderIndex(),
scroll = document.body.scrollTop,
clone = $('.clone').length,
$active = $('.header').eq(active),
prevTitle = $('.header').eq(active - 1).text(),
title = $active.text(),
$fixed = $('.fixed');
// Hide fixed header
if ( offsets[active] > scroll ){
if ( !clone ){
$('.header').eq(0).hide();
$('<li class="clone">' + prevTitle + '</li>').insertBefore($active);
}
$fixed.hide();
// Show fixed header
} else {
if ( clone ){
$('.header').eq(0).show();
$('.clone').remove();
}
$fixed.show();
}
// If we're not changing headers, exit
if ( active == activeCache ) return;
// Update active index
activeCache = active;
// Remove old fixed header (if any)
$('.fixed').remove();
// Add a new fixed header
$fixed = $('<div class="fixed">' + title + '</div>').appendTo('body');
}).trigger('scroll');

Categories

Resources