I'm currently working on my pfolio website and im quite far but not there yet...
http://thinkagain.nu/?page_id=2501 See this page I have this navigation bullets / dots on the right which you can navigate through the projects. I got it working for so far that if you click a bullet / dot it becomes selected (orange color) but what I want is that it also becomes selected state when you scroll down the sections, so without clicking on it.
So when your scrolling the 2nd project, the 2nd bullet / dot becomes selected, 3rd project makes the 3rd bullet / dot become selected and so on.
This is my code:
CSS:
#floatnav {
position: fixed;
right: -50px;
top: 50%;
width: 8em;
margin-top: -2.5em;
}
.bullit {
background-color:#242424;
-moz-border-radius:17px;
-webkit-border-radius:17px;
border-radius:17px;
border:0px solid #000000;
display:inline-block;
cursor:pointer;
color:#ffffff;
font-family:arial;
font-size:12px;
padding:5px 5px;
text-decoration:none;
text-shadow:0px 1px 0px #2f6627;
box-shadow: inset 1px 4px 9px -6px;
box-shadow: 2px 2px 1px #888888;
}
.bullit:hover {
background-color:#ebebeb;
box-shadow: inset 1px 4px 9px -6px;
}
.bullit.active {
position:relative;
top:1px;
background:orange;
}
HTML:
<ul id="floatnav">
</ul>
Jquery/javascript:
$('#floatnav a').click(function() {
$('#floatnav a').removeClass('active'); /*Remove previous*/
$(this).addClass('active'); /*Active clicked*/
})
If anyone could help me it would be greatly appreciated! Thanks in advance.
Nick
Try this (see example http://jsfiddle.net/shtrih/Z3BTd/)
$(window).on('scroll', function () {
var positions = [],
elements = [],
scrolltop = $(this).scrollTop()
;
$('> div', '#main').each(function() {
var pos = Math.abs($(this).position().top - scrolltop);
positions.push(pos);
elements[ pos ] = this.id;
});
var array_min = Math.min.apply(null, positions);
var current_element_id = elements[ array_min ];
console.log(current_element_id);
$('a', '#floatnav').removeClass('active');
$('a[href="#'+ current_element_id +'"]', '#floatnav').addClass('active');
});
Used materials:
JavaScript: min & max Array values?
How to know the end of scrolling event for a <div> tag
http://jqapi.com/
Here is some code that I hope it will help you understand and use on your website:
http://jsfiddle.net/dragulceo/KMnmb/1/
Notice that I included an external link to a jQuery plugin - jQuery throttle / debounce
You need to register a scroll handler and because the scroll handler is triggered many times you should use throttle method so that you don't affect the scrolling speed (avoid hiccups).
onScrollCallback = $.throttle(250, function () {
var el;
floatNavs.find('a.active').removeClass('active');
el = getVisibleElement();
if(el) {
floatNavs.find('a[href="#' + $(el).attr('id') + '"]').addClass('active');
}
});
$(document).on('scroll', onScrollCallback);
So now the browser triggers scroll event the code - moderately - will check to see which div is on screen and then add the active class for the a element that has the target the same with the id attribute.
The function that finds the element on screen is this one:
//gets the div on screen
getVisibleElement = function () {
var scrl = window.scrollY,
height = jQuery(window).height(),
elHeight,
i;
for (i = 0; i< numberEls; i++) {
item = $(targetEls[i]);
pos = item.position();
elHeight = item.height();
// the criteria if the element is on screen is that
// the topX position is greater then the scrolled pixels
// minus half of the element. There can be variations
// depending on the scrolled items
if (pos.top > scrl - elHeight / 2) {
return targetEls[i];
}
}
return false;
}
And as you can see in the comments you can play with or change the condition that determines when the element is on screen depending on the height of the scrolled elements.
Related
I'm trying to push up two buttons vertically displayed in order to put them above the footer content when I'm scrolling to it.
My two buttons are like this:
And I want them to be like that:
Any ways to make it with Javascript?
Thanks a lot !
Since you provided no code at all, here's my solution based on the assumption your buttons are in a parent div and that div has position: fixed and a right / bottom -property set to a certain amount of pixel.
window.onscroll = function (ev) {
if ((window.innerHeight + window.pageYOffset) >= document.body.offsetHeight - 2) {
document.getElementById("buttons").style.bottom = "100px";
} else {
document.getElementById("buttons").style.bottom = "20px";
}
}
/*
window.onscroll = function (ev) {
let footerHeight = document.getElementsByTagName("footer")[0].offsetHeight;
if ((window.innerHeight + window.pageYOffset) >= (document.body.offsetHeight - footerHeight)) {
document.getElementById("buttons").style.bottom = "100px";
} else {
document.getElementById("buttons").style.bottom = "20px";
}
}
*/
main {
height: 1000px;
}
#buttons {
position: fixed;
bottom: 20px;
right: 20px;
}
button {
background-color: grey;
border-radius: 50%;
display: block;
border: none;
padding: 15px;
margin-top: 10px;
}
<main></main>
<div id="buttons">
<button></button>
<button></button>
</div>
window.onscroll fires of at every scroll-event. It then checks, if the height of the window (window.innerHeight) and the distance scrolled so far (window.pageYOffset) are greater or equal to the total height of the body (document.body.offsetHeight)(- 2) is added because of an annoying mac-'feature'. For more look at this post). If thats the case, it moves the buttons up 100px instead of the 20px normally. If you dont add the else-statement, your buttons will stay at the position even if you scroll up again.
You can now get a bit creative. If you dont want to hit rock bottom of the page to make the buttons move, change the - 2. So you check for the height of your footer, and substract it from the total body height. Your buttons then start to move once the footer is it. Example of that in the javascript snippet, the part that is commented out.
I am trying to create a data-grid where I am not displaying all the records in the beginning and want to render them when scrolled. Is there a way I can set a scroll size based on the amount of data that I have and change the data in the dev when user scrolls.
I know there are grid's out there but I do not want to use them and want to know what are the different ways to do it.
I have tried looking into the scroll event and I did not find anything about the scroll direction or the current offset. Is there any documentation I can find. or even a technical name to search for would help me.
You can search for a "infinity scroll" with javascript and html.
EXAMPLE HTML: `<ul id='infinite-list'></ul>`
EXAMPLE CSS: `#infinite-list {
/* We need to limit the height and show a scrollbar */
width: 200px;
height: 300px;
overflow: auto;
/* Optional, only to check that it works with margin/padding */
margin: 30px;
padding: 20px;
border: 10px solid black;
}
/* Optional eye candy below: */
li {
padding: 10px;
list-style-type: none;
}
li:hover {
background: #ccc;
}`
EXAMPLE JAVASCRIPT: `var listElm = document.querySelector('#infinite-list');
// Add 20 items.
var nextItem = 1;
var loadMore = function() {
for (var i = 0; i < 20; i++) {
var item = document.createElement('li');
item.innerText = 'Item ' + nextItem++;
listElm.appendChild(item);
}
}
// Detect when scrolled to bottom.
listElm.addEventListener('scroll', function() {
if (listElm.scrollTop + listElm.clientHeight >= listElm.scrollHeight) {
loadMore();
}
});
// Initially load some items.
loadMore();
`
My navbar has a white background, but it should be transparent on the landing page and white when i scroll down and white on every other page.
I used the code from: Changing nav-bar color after scrolling?
EDIT:
So I added a fiddle with the answer below but somehow its not working
https://jsfiddle.net/jy6njukm/
Here's my code:
javascript:
$(document).ready(function(){
var scroll_start = 0;
var change_color = $('#change_color');
var offset = change_color.offset();
if (change_color.length){
$(document).scroll(function() {
scroll_start = $(this).scrollTop();
if(scroll_start > offset.top) {
// the white normal navbar
$(".navbar-add").removeClass("navbar-trans");
} else {
// what the users sees when he lands on the page
$(".navbar-add").addClass("navbar-trans");
}
});
}
});
Here is my navbar css:
.navbar-fixed {
position: fixed;
height: 70px;
padding: 0px 30px;
left: 0px;
top: 0px;
z-index: 50;
width: 100%;
background-color: white;
box-shadow: 0 1px 5px 0 rgba(0,0,0,0.07),0 1px 0 0 rgba(0,0,0,0.03);
}
.navbar-trans {
background-color: transparent !important;
box-shadow: none !important;
}
And I have my navbar html with only
<div class="navbar-fixed navbar-add">
.....
</div>
and my home.html.erb with
<div class="container-fluid banner bg-picture" id="change_color"
style="background-image: linear-gradient(-225deg, rgba(0,0,0,0.2) 0%,
rgba(0,0,0,0.35) 50%), url('<%= asset_path('banner_logo.jpeg') %>')">
</div>
It kind of works but the problem now is, that everytime I refresh the page, the navbar is still white and it only turns transparent when I scroll up, to the top of the page. It turns white when I scroll down though, like I want it to be.
I inspected the page and everytime I refresh it, the background-color of the class is still white even though I set this to be transparent in the javascript?
How can I make it possible that the background-color of my navbar is transparent on my landing page?
Using HTML
Your HTML should be:
<div class="navbar-fixed navbar-add navbar-trans">
.....
</div>
Since it already contains the navbar-trans class, it will remain transparent. Once the user scrolls, the javascript will kick in, and remove/add navbar-trans class as per the code.
Using JS
var landingPage = 'YOUR_LANDING_PAGE_URL';
function updateNavStyle() {
if(landingPage.length > 0 && location.href.toLowerCase().indexOf(landingPage.toLowerCase()) >= 0) {
var offset = $('#change_color').offset();
var scroll_start = $(document).scrollTop();
if (scroll_start > offset.top) {
// the white normal navbar
$(".navbar-add").removeClass("navbar-trans");
} else {
// what the users sees when he lands on the page
$(".navbar-add").addClass("navbar-trans");
}
}
}
$(document).ready(function() {
var scroll_start = 0;
var change_color = $('#change_color');
if (change_color.length) {
$(document).scroll(updateNavStyle);
updateNavStyle(); // Note this.
}
});
Here, in addition to binding the updateNavStyle function on scroll, I have added a call to it once the DOM is ready. As a result, as soon as the page loads, the function will be executed once and it will apply the styles based on scroll position.
Update:
If your landing page is 'index.html', where you want this function to work, write its value in variable landingPage. So the function will not run in other pages such as 'about.html' or 'contacts.html'.
There is a div, style fixed 60px from top. I want when I scroll down and the distance of div from top reached 10px, the div stop there for the rest of scrolling also when I scroll up it goes back to the old style 60px from top. I did a lot of search but I did not found anything like this. But there is a code which calculate distance from top:
var scrollTop = $(window).scrollTop(),
elementOffset = $('#my-element').offset().top,
distance = (elementOffset - scrollTop);
Here's one way to do it using pure javascript. You can replace some of the selectors like document.getElementById with jQuery selectors like $("id") if you like.
window.onscroll = function(){
var el = document.getElementById('sticky'),
s = window.pageYOffset || document.documentElement.scrollTop, // how much page is scrolled
t = document.getElementById('main').getBoundingClientRect().top; // top of main div
if(s > t){
el.style.position = 'fixed'; //make position fixed instead of absolute
}else{
el.style.position = ''; //clear styles if back to original position
}
}
body {
min-height: 200em;
margin: 0;
padding: 0;
}
header {
background: black;
color: white;
padding: .5em;
}
#main { position: relative; } /* important so the sticky box positions relative to this */
#sticky {
background: cornflowerblue;
padding: .5em;
position: absolute;
right: 1em;
top: 1em;
width: 10em;
color: white;
}
<header>This is just a page header or toolbar.</header>
<section id="main">
<div id="sticky">This should stick to the top when scrolled.</div>
</section>
Here's a jQuery solution. If we're more than 10px from the top of the page add a is-sticky class to the element which you can then style with CSS.
// store the element in a variable
var element = $('.item'),
visible = false;
// on scroll
$(window).scroll(function() {
/**
* store the scroll distance in px
* from the top of the viewport
*/
var scroll = $(window).scrollTop();
/**
* if the scroll is greater than or equal
* to 10px add a class of .is-sticky to the element
* otherwise we're less than 10px from the top
* of the document and therefore don't want
* the element to have the .is-sticky class
*/
if(scroll >= 10) {
if(!visible) {
element.addClass('is-sticky');
visible = true;
}
} else {
if(visible) {
element.removeClass('is-sticky');
visible = false;
}
}
});
I wrote an alert bar like this:
alertmsg{
font-family:Arial,Helvetica,sans-serif;
font-size:135%;
font-weight:bold;
overflow: hidden;
width: 100%;
text-align: center;
position: fixed;
top: 0px;
left: 0px;
background-color: #fff;
height: 56px;
color: #000;
font: 20px/40px arial, sans-serif;
display:none;
padding-top:12px;
-webkit-box-shadow: 3px 3px 5px #888;
-moz-box-shadow: 3px 3px 5px #888;
box-shadow: 3px 3px 5px #888;
}
function alertbar(m, timeout){
if(!timeout){
var timeout = 3000;
}
var $alertdiv = $('<div id = "alertmsg"/>');
$alertdiv.text(m);
$alertdiv.bind('click', function() {
$(this).slideUp(200);
});
$(document.body).append($alertdiv);
$("#alertmsg").slideDown("slow");
setTimeout(function() { $alertdiv.slideUp(200) }, timeout);
return false
}
Pretty simple. I call alertbar("Go go go!"); to have this alert drop down.
However, it covers the body's page. I want it to sort of "push down" on the entire page (all the elements)....sort of like StackOverflow does it I guess.
I think it's the position: fixed that is your problem. This will place your element relative to the window and take it out of the normal flow.
Use position:static (or relative) and make sure the alertmsg element is at the top of the markup.
There's a couple things you must do:
Change the position CSS attribute of the "alert bar" to not be fixed and just be normal (remove that property).
Change your JavaScript to prepend the alertdiv, rather than append it. This will make it the first thing in the body.
$('body').prepend($alertdiv);
Slide your $alertdiv down normally.
Now something that you didn't take into account in your code is what happens when you run alertbar more than once. You'll append more than one to the body. If this is a concern, try doing something like this:
var exists = $('#alertmsg').length > 0;
var $alertdiv = exists ? $('#alertmsg') : $('<div id="alertmsg" />');
Now only prepend to the body if it doesn't exist already.
if (!exists)
$('body').prepend($alertdiv);
If you want to keep the position: fixed then just expand the body's top padding to the size of the alertbox.
$("#alertmsg").slideDown("slow", function() {
var paddingTopStr = "+" + $(this).outerHeight().toString() + "px";
$('body').css({ paddingTop: paddingTopStr });
});
You will also have to return the padding after:
setTimeout(function() {
var paddingTopStr = "-" + $(this).outerHeight().toString() + "px";
$('body').css({ paddingTop: paddingTopStr });
$alertdiv.slideUp(200) }, timeout);
}
Same for the click event.
You could wrap the rest of your content (to be pushed down) in a separate div and then insert your alert bar before it