stellar.js - configuring offsets / aligning elements for a vertical scrolling website? - javascript

I have found, and am trying to use, a plugin called stellar.js. Primarily it is for creating a parallax effect for websites, but, I am not after this effect - I am after the other effect it offers:
Stellar.js' most powerful feature is the way it aligns elements.
All elements will return to their original positioning when their
offset parent meets the edge of the screen—plus or minus your own
optional offset.
An example of the offset positioning: http://markdalgleish.com/projects/stellar.js/#show-offsets . When you scroll over a div it snaps/realigns to the edge of the browser. I am trying to get this to work for a vertical website.
I am not having much luck - due to my novice knowledge of Javascript and jQuery. I thought it would just be a case of swapping around the horizontals to verticals.
Has anyone played with this plugin before, or used it for a similar scenario, and got any tips?
The jsFiddle with all the code: http://jsfiddle.net/2SH2T/
And the Javascript code:
var STELLARJS = {
init: function() {
var self = this;
$(function(){
self.$sections = $('div.section').each(function(index){
$(this).data('sectionIndex', index);
});
self.highlightSyntax();
self.handleEvents();
self.debugOffsets.init();
self.debugOffsetParents.init();
self.initParallax();
});
},
initParallax: function() {
var isHomePage = $('body').hasClass('home'),
$main = $('div.main');
if (isHomePage) {
$main.height($main.height() + $(window).height() - 1000);
}
if ($.browser.msie) {
$('body').removeAttr('data-stellar-background-ratio').append('<div class="ie-bg" />');
}
$(window).stellar({
horizontalOffset: !isHomePage,
verticalScrolling: 40
});
},
highlightSyntax: function() {
$('pre').addClass('prettyprint');
if (window.prettyPrint !== undefined) prettyPrint();
},
handleEvents: function() {
var self = this,
//Debounce function from Underscore.js
debounce = function(func, wait) {
var timeout;
return function() {
var context = this, args = arguments;
var later = function() {
timeout = null;
func.apply(context, args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
}
},
handleScroll = function() {
var scrollTop = $(window).scrollTop(),
sectionIndex = Math.round((scrollTop - 40) / self.$sections.first().outerHeight()),
$activeSection = self.$sections.eq(sectionIndex);
if ($activeSection.length === 0) {
$activeSection = self.$sections.last();
}
if ($activeSection.length === 0) return;
$(window).unbind('scroll.stellarsite');
if (scrollLeft === 0) {
$(window).unbind('scroll.stellarsite').bind('scroll.stellarsite', debounce(handleScroll, 500));
} else {
$('html,body').animate({
scrollLeft: $activeSection.offset().left - 40
}, 600, 'easeInOutExpo', function() {
setTimeout(function(){
$(window).unbind('scroll.stellarsite').bind('scroll.stellarsite', debounce(handleScroll, 500));
}, 10);
});
}
$(window).bind('mousewheel', function(){
$('html,body').stop(true, true);
});
$(document).bind('keydown', function(e){
var key = e.which;
if (key === 37 || key === 39) {
$('html,body').stop(true, true);
}
});
};
if (window.location.href.indexOf('#show-offset-parents-default') === -1) {
$(window).bind('scroll.stellarsite', debounce(handleScroll, 500));
}
},
debugOffsets: {
init: function() {
this.$debug = $('#debugOffsets');
if (window.location.href.indexOf('#show-offsets') > -1) {
this.show();
}
},
show: function() {
this.$debug.fadeIn();
$('body').addClass('debugOffsets');
$('h2').append('<div class="debug-h2-label">Offset Parent (All parallax elements align when this meets the offsets)</div>');
},
hide: function() {
this.debug.fadeOut;
$('body').removeClass('debugOffsets');
}
},
debugOffsetParents: {
init: function() {
this.$debug = $('#debugOffsets');
if (window.location.href.indexOf('#show-offset-parents-default') > -1) {
this.removeOffsetParents();
}
if (window.location.href.indexOf('#show-offset-parents') > -1) {
this.show();
}
},
show: function() {
this.$debug.fadeIn();
$('body').addClass('debugOffsetParents');
$('h2').append('<div class="debug-h2-label">New Offset Parent (All parallax elements align when this meets the offsets)</div>');
$('h2').each(function(){
$(this).find('div.constellation:last').append('<div class="debug-constellation-label">Default Offset Parents</div>');
});
$('body').addClass('debug');
},
removeOffsetParents: function() {
$('body').addClass('debugOffsetParentsDefault');
$('h2[data-stellar-offset-parent]').removeAttr('data-stellar-offset-parent');
}
}
};
STELLARJS.init();

After searching for a good solution for a while, I found this jQuery plugin- Snappoint!
https://github.com/robspangler/jquery-snappoint

I modified the original code and came up with exact effect like in stellarjs.com. Instead it's vertical :)
Take a look: http://jsfiddle.net/E4uVD/38/

I think I have achieved what you are describing with the code below. Here is a JsFiddle: http://jsfiddle.net/E4uVD/7/
JQuery:
$(function(){
var _top = $(window).scrollTop();
var individualDivHeight = 300;
$(window).mousedown(function() {
$('html, body').stop();
});
$(window).mouseup(function(){
var _cur_top = $(window).scrollTop();
var totalHeight = $('#container').height();
var posToScroll = Math.round(_cur_top / individualDivHeight) * individualDivHeight;
$('html, body').stop().animate({scrollTop: posToScroll}, 2000);
});
});
HTML:
<div id="container">
<div class="box">300px</div>
<div class="box">300px</div>
<div class="box">300px</div>
<div class="box">300px</div>
<div class="box">300px</div>
<div class="box">300px</div>
<div class="box">300px</div>
<div class="box">300px</div>
<div class="box">300px</div>
<div class="box">300px</div>
</div>
CSS:
body {
height:2000px;
}
.box
{
color: #fff;
height: 300px;
width: 300px;
border: 1px solid white;
}
#container {
height:3000px;
width:300px;
background-color:blue;
}

Related

Event on scrolling up or down

I wanna detect when the user scrolls. I saw there are some questions about this but those answers didn't help me.
Here is my code:
var up = document.getElementById('up');
var down = document.getElementById('down');
function onScroll() {
if (view.scrollTop > 0) {
console.log("up");
}
if (view.scrollTop < 0) {
console.log("down");
}
}
var view = document.getElementById('container');
view.addEventListener("wheel", onScroll);
EDIT: "scroll" instead "wheel" isn't working for me... I must have the "wheel". When I make:
if (view.scrolltop <=0) {
console.log("down");
}
that I get in my console "down" but it appears when I scrolling up too! I have my page in 100% of screen and I have no scrollbars (and I don't want to have).
EDIT2: Here is the code that solved my problem!
window.addEventListener('wheel', function (e) {
if (e.deltaY < 0) {
console.log("scrolling up");
}
if (e.deltaY > 0) {
console.log("scrolling down");
}
});
you can use the
window.onscroll
to get the scrolling event, then just use
.scrollTop
to determine your offset from the top of page or an element.
window.onscroll = function() { scrollFunction() };
scrollFunction() {
//code to check if it is scrolling up or down
}
Hopefully this was a helpful start.
I did this with the jquery method
var last = 0;
$(window).scroll(function(event){
var Pos = $(this).scrollTop();
if (Pos > last ){
// down
} else {
// up
}
last = Pos;
});
Supporting #Belmin Bedak's comment.
Use .scroll instead of .wheel:
var up = document.getElementById('up');
var down = document.getElementById('down');
function onScroll() {
if (view.scrollTop > 0) {
alert("up");
}
if (view.scrollTop <= 0) {
alert("down");
}
}
var view = document.getElementById('container');
view.addEventListener("scroll", onScroll);
div {
border: 1px solid black;
width: 200px;
height: 100px;
overflow: scroll;
}
<div id='container'>a<br>
b<br>
c<br>
d<br>
e<br>
f<br>
g<br>
h<br>
i<br>
k<br>
l<br>
</div>

Jquery functions not changing on window resize

I have the following jquery code that is aimed at running one function when the window is large (>=1024) and another when it is resized and small.
The console.logs appear as expected on resize, but the functions do not change. Meaning, if the browser was loaded in large size, when resized, the large function is still used.
(Resize code used from https://stackoverflow.com/a/4541963/1310375 and https://stackoverflow.com/a/9828919/1310375)
var waitForFinalEvent = (function () {
var timers = {};
return function (callback, ms, uniqueId) {
if (!uniqueId) {
uniqueId = "Don't call this twice without a uniqueId";
}
if (timers[uniqueId]) {
clearTimeout (timers[uniqueId]);
}
timers[uniqueId] = setTimeout(callback, ms);
};
})();
$(window).on('resize', function(){
var win = $(this); //this = window
waitForFinalEvent(function(){
console.log('Resize...');
if (win.width() >= 1024) {
console.log('large');
$('.header-navigation-menu > div > ul > li').on({
mouseenter: function() {
console.log('waitEnterExit');
waitEnterExit(this, true);
$(this).children('.nav-menu-div').addClass('open');
},
mouseleave: function() {
waitEnterExit(this, false);
},
});
function waitEnterExit(el, inside) {
var button = $(el);
setTimeout(function() {
var hovered = button.is(':hover');
if (hovered && inside)
button.children('.nav-menu-div').addClass('open');
else if (!hovered && !inside)
button.children('.nav-menu-div').removeClass('open');
}, 500);
}
}
if (win.width() <= 1023) {
console.log('small');
$('.menu-link-button').on({
click: function() {
$(this).parent().children('.nav-menu-div').slideToggle();
}
});
}
}, 500);
});
You are doing it in a wrong way, try the below steps and code,
First separate all functions and event bindings from window resize event.
Then check window's width and toggle the elements which are to be hide(if visible)
function waitEnterExit(el, inside) {
var button = $(el);
setTimeout(function() {
var hovered = button.is(':hover');
if (hovered && inside)
button.children('.nav-menu-div').addClass('open');
else if (!hovered && !inside)
button.children('.nav-menu-div').removeClass('open');
}, 500);
}
$('.header-navigation-menu > div > ul > li').on({
mouseenter: function() {
console.log('waitEnterExit');
var win = $(window);
if (win.width() >= 1024) {
console.log('large');
waitEnterExit(this, true);
$(this).children('.nav-menu-div').addClass('open');
}
},
mouseleave: function() {
if (win.width() >= 1024) {
console.log('large');
waitEnterExit(this, false);
}
},
});
$('.menu-link-button').on({
click: function() {
var win = $(window);
if (win.width() <= 1023) {
console.log('small');
$(this).parent().children('.nav-menu-div').slideToggle();
}
}
});
$(window).on('resize', function() {
var win = $(this); //this = window
waitForFinalEvent(function() {
if (win.width() >= 1024) {
console.log('large');
$('.menu-link-button').parent().children('.nav-menu-div').slideUp(); // hide it any way on large screen
} else {
$('.header-navigation-menu > div > ul > li .nav-menu-div').removeClass('open'); // hide it in small screens
}
console.log('Resize...');
}, 500);
});
If window>= 1024 and $('.menu-link-button') is sliding up again and again then check a condition for its visibility like
if (win.width() >= 1024) {
console.log('large');
$('.menu-link-button').parent().children('.nav-menu-div').is(':visible') // if visible then slideup
&&
$('.menu-link-button').parent().children('.nav-menu-div').slideUp(function(){ // hide it any way on large screen
$(this).hide();/*make it hide after slide up*/
});
} else {
$('.header-navigation-menu > div > ul > li .nav-menu-div').removeClass('open'); // hide it in small screens
}

Use function everywhere without writing it more than once

Trying to get my code cleaner I don't want to write the same code many times but don't know how to accomplish it. You can see in the code below is the if/else written twice but doing the same. How can I return data and call that function again with writing it only once?
Help and advices are much appreciated.
Code is like this:
(function($){
var scroll = $(this).scrollTop();
var header = $('header');
var headerSmall = header.children('.small');
var headerBigWrap = header.children('.big');
var headerBigWrapHeight = headerBigWrap.height();
var showNav = function() {
header.css('position','fixed');
headerBigWrap.css('display','none');
headerSmall.css('display','block');
}
var hideNav = function() {
header.css('position','static');
headerSmall.css('display','none');
headerBigWrap.css('display','block');
}
// don't want to write this more than once
// but need to call here on document ready
if( scroll >= headerBigWrapHeight ) {
showNav();
} else {
hideNav();
}
$(window).scroll(function(event){
scroll = $(this).scrollTop();
// here I need it again
// scroll is changing on scroll
// but "function" does exactly the same like above
if( scroll >= headerBigWrapHeight ) {
showNav();
} else {
hideNav();
}
});
})(jQuery);
if you need html and css working example: fiddle http://jsfiddle.net/cejs3jhs/ and rest of code:
<header>
<div class="big">
<h1>Page Title</h1>
</div>
<div class="small">
<span class="icon nav-icon">Nav Icon</span>
</div>
</header>
<div class="page"></div>
<style type="text/css">
header {
width:100%;
background-color:red;
opacity:0.5;
}
header.toggle-nav {
height:100%;
}
header.toggle-nav ul {
display:block;
}
header > div {
position:relative;
width:976px;
margin:0 auto;
}
header > div.big {
padding:30px 0;
}
.page {
height:5000px;
background-color:orange;
opacity:0.5;
}
</style>
So just make separate function for that:
function showHideNav(scroll, headerBigWrapHeight, element) {
var scroll = element.scrollTop(),
header = $('header'),
headerSmall = header.children('.small'),
headerBigWrap = header.children('.big')
headerBigWrapHeight = headerBigWrap.height();
if( scroll >= headerBigWrapHeight ) {
header.css('position','fixed');
} else {
header.css('position','static');
}
headerBigWrap.toggle();
headerSmall.toggle();
}
(function($){
showHideNav(scroll);
$(window).scroll(function(event){
scroll = $(this).scrollTop();
showHideNav(scroll);
});
})(jQuery);
The answer to your question is simply what Justinas said, make another function. But you can improve a bit with some more aggressive editing, which is what I've done.
(function ($) {
var header = $('header');
var headerSmall = header.children('.small');
var headerBigWrap = header.children('.big');
var headerBigWrapHeight = headerBigWrap.height();
function setNavStyle() {
var scroll = $(this).scrollTop();
if( scroll >= headerBigWrapHeight ) {
header.css('position', 'fixed');
headerSmall.css('display', 'block');
headerBigWrap.css('display', 'none');
} else {
header.css('position', 'static');
headerSmall.css('display', 'none');
headerBigWrap.css('display', 'block');
}
}
$(window).scroll(setNavStyle);
setNavStyle();
})(jQuery);
That's one way, but it would be better (more maintainable, simpler, faster) to do the bulk of
the work with CSS, like so:
CSS:
header {
position: static;
}
header>.small {
display: none;
}
header>.big {
display: block;
}
.stickyNav header {
position: fixed;
}
.stickyNav header>.small {
display: block;
}
.stickyNav header>.big {
display: none;
}
JavaScript:
(function ($) {
var bigNavHeight = $('header>.big').height();
function setNavStyle() {
var bigIsOffscreen = $(this).scrollTop() >= bigNavHeight;
$(document.body).toggleClass('stickyNav', bigIsOffscreen);
}
$(window).scroll(setNavStyle);
setNavStyle();
})(jQuery);
You can define a new function just as you did with the showNav & hideNav functions
(function($){
var scroll = $(this).scrollTop();
var header = $('header');
var headerSmall = header.children('.small');
var headerBigWrap = header.children('.big');
var headerBigWrapHeight = headerBigWrap.height();
var showNav = function() {
header.css('position','fixed');
headerBigWrap.css('display','none');
headerSmall.css('display','block');
}
var hideNav = function() {
header.css('position','static');
headerSmall.css('display','none');
headerBigWrap.css('display','block');
}
var checkScroll = function (scroll,headerBigWrapHeight){
if( scroll >= headerBigWrapHeight ) {
showNav();
} else {
hideNav();
}
checkScroll(scroll,headerBigWrapHeight);
$(window).scroll(function(event){
scroll = $(this).scrollTop();
checkScroll(scroll,headerBigWrapHeight);
});
})(jQuery);
Please find below updated JS code:
(function($){
var scroll = $(this).scrollTop();
var header = $('header');
var headerSmall = header.children('.small');
var headerBigWrap = header.children('.big');
var headerBigWrapHeight = headerBigWrap.height();
var showNav = function() {
header.css('position','fixed');
headerBigWrap.css('display','none');
headerSmall.css('display','block');
}
var hideNav = function() {
header.css('position','static');
headerSmall.css('display','none');
headerBigWrap.css('display','block');
}
var callFun = function(scroll) {
if( scroll >= headerBigWrapHeight ) {
showNav();
} else {
hideNav();
}
}
callFun(scroll);
$(window).scroll(function(event){
scroll = $(this).scrollTop();
callFun(scroll);
});
})(jQuery);
Do it exactly like you have done with functions showNav and hideNav: define a function with if/else inside somewhere and you can call it by name wherever needed. There are also some variables which can be omitted then, so I show all code here:
(function($){
// var scroll is moved into function scrollFunc
var header = $('header');
var headerSmall = header.children('.small');
var headerBigWrap = header.children('.big');
// var headerBigWrap is moved into function scrollFunc
var showNav = function() {
/* your code */
}
var hideNav = function() {
/* your code */
}
var scrollFunc = function () {
if($(this).scroll() >= headerBigWrap.height() ) {
showNav();
} else {
hideNav();
}
}
$(window).scroll(function(event){
scrollFunc();
});
scrollFunc(); // call it first time to initialize
});

Fix Popup to lift up smoothly

I create a pop-up dialog box which lift up on left bottom while user scroll page.
You can see it live here- http://uposonghar.com/jobs/odesk/daniel/new/
My problem is it does not smoothly lift up first time, then it is ok. Anyone please suggest any idea to fix it. Need to make smoothly lift up.
My code
<div id="scrolltriggered" style="width: 310px; left: 10px; bottom: 10px;">
<div id="inscroll">
x<a href="http://www.google.com" target="_blank"><img src="images/buyersguide.png" alt="Free Resources" height="235" width="310">
</a>
</div>
</div>
<script type="text/javascript">
var stb = {
hascolsed: false,
cookieLife: 7,
triggerHeight: 30,
stbElement: ""
};
</script>
Javascript Code-
if (typeof stb === "undefined")
var stb = {};
jQuery(document).ready(function () {
jQuery("#closebox").click(function () {
jQuery('#scrolltriggered').stop(true, true).animate({ 'bottom':'-210px' }, 700, function () {
jQuery('#scrolltriggered').hide();
stb.hascolsed = true;
jQuery.cookie('nopopup', 'true', { expires: stb.cookieLife, path: '/' });
});
return false;
});
stb.windowheight = jQuery(window).height();
stb.totalheight = jQuery(document).height();
stb.boxOffset = '';
if (stb.stbElement != '') {
stb.boxOffset = jQuery(stb.stbElement).offset().top;
}
jQuery(window).resize(function () {
stb.windowheight = jQuery(window).height();
stb.totalheight = jQuery(document).height();
});
jQuery(window).scroll(function () {
stb.y = jQuery(window).scrollTop();
stb.boxHeight = jQuery('#scrolltriggered').outerHeight();
stb.scrolled = parseInt((stb.y + stb.windowheight) / stb.totalheight * 100);
if (stb.showBox(stb.scrolled, stb.triggerHeight, stb.y) && jQuery('#scrolltriggered').is(":hidden") && stb.hascolsed != true) {
jQuery('#scrolltriggered').show();
jQuery('#scrolltriggered').stop(true, true).animate({ 'bottom':'10px' }, 700, function () {
});
}
else if (!stb.showBox(stb.scrolled, stb.triggerHeight, stb.y) && jQuery('#scrolltriggered').is(":visible") && jQuery('#scrolltriggered:animated').length < 1) {
jQuery('#scrolltriggered').stop(true, true).animate({ 'bottom':-stb.boxHeight }, 700, function () {
jQuery('#scrolltriggered').hide();
});
}
});
jQuery('#stbContactForm').submit(function (e) {
e.preventDefault();
stb.data = jQuery('#stbContactForm').serialize();
jQuery.ajax({
url:stbAjax.ajaxurl,
data:{
action:'stb_form_process',
stbNonce:stbAjax.stbNonce,
data:stb.data
},
dataType:'html',
type:'post'
}).done(function (data) {
jQuery('#stbMsgArea').html(data).show('fast');
});
return false;
});
});
(function(stb_helpers) {
stb_helpers.showBox = function(scrolled, triggerHeight, y) {
if (stb.isMobile()) return false;
if (stb.stbElement == '') {
if (scrolled >= triggerHeight) {
return true;
}
}
else {
if (stb.boxOffset < (stb.windowheight + y)) {
return true;
}
}
return false;
};
stb_helpers.isMobile = function(){
if (navigator.userAgent.match(/Android/i)
|| navigator.userAgent.match(/webOS/i)
|| navigator.userAgent.match(/iPhone/i)
|| navigator.userAgent.match(/iPod/i)
|| navigator.userAgent.match(/BlackBerry/i)
) {
return true;
}
else return false;
}
})(stb);
i think you need css changes, copy paste the following in your aspx
<div style="width: 310px; left: 10px; bottom: -225px; display: none;" id="scrolltriggered">
Hope it Helps
All you need to do is add the following line to your document ready as the First line
$("#scrolltriggered").css({bottom: -235});
This will make sure that the popup is scrolled to the bottom by 235px. If you need it to scroll variably add the Elements height by using jquery selector.
See the Fiddle Here

Hide div when clicking outside the table

I am quite new to Javascript (intermediate in HTML & CSS), though I am pretty good at working things out on my own by looking up other's examples. Unfortunately, I am having significant trouble with this one.
I have a table displaying 3 links to the viewer. Each link when clicked, slides a hidden div open to the right. When one of the other links are clicked, the opened div slides back to being hidden, and then the other one slides open.
What I am looking for, is to hide the divs again when the mouse is clicked on the link again, and also when the mouse is clicked outside the div (or anywhere on the page, really).
I have tried using "e.stopPropagation" but it doesn't seem to be working for me.
Any help is greatly appreciated - thank you.
I have a jsFiddle that I created for practice:
http://jsfiddle.net/AuU6D/3/
This is my jQuery code:
jQuery(function ($) {
$('a.panel').click(function () {
var $target = $($(this).attr('href')),
$other = $target.siblings('.active'),
animIn = function () {
$target.addClass('active').show().css({
left: -($target.width())
}).animate({
left: 0
}, 500);
};
if (!$target.hasClass('active') && $other.length > 0) {
$other.each(function (index, self) {
var $this = $(this);
$this.removeClass('active').animate({
left: -$this.width()
}, 500, animIn);
});
} else if (!$target.hasClass('active')) {
animIn();
}
});
});
Try
jQuery(function ($) {
$('a.panel').click(function () {
var $target = $($(this).attr('href')),
$other = $target.siblings('.active'),
animIn = function () {
$target.addClass('active').show().css({
left: -($target.width())
}).finish().animate({
left: 0
}, 500);
};
if (!$target.hasClass('active') && $other.length > 0) {
$other.each(function (index, self) {
var $this = $(this);
$this.removeClass('active').animate({
left: -$this.width()
}, 500, animIn);
});
} else if (!$target.hasClass('active')) {
animIn();
} else if ($target.hasClass('active')) {
$target.removeClass('active').finish().animate({
left: -$target.width()
}, 500);
}
});
$(document).click(function(e){
var $target = $(e.target), $active = $('div.panel.active');
if($active.length && $target.closest('a.panel').length == 0 && $target.closest($active).length == 0){
$active.removeClass('active').finish().animate({
left: -$active.width()
}, 500);
}
})
});
Demo: Fiddle
DEMO
$(document).click(function (e) {
if (!$(e.target).hasClass('panel')) {
$('div.panel').removeClass('active').removeAttr('style').css('background', ' #e4e4e4');
}
});
or
DEMO
$(document).click(function (e) {
console.log($(e.target).hasClass('panel'));
if (!$(e.target).hasClass('panel')) {
$('div.panel.active').removeClass('active').finish().animate({
left: -$('#right').width()
}, 500);
}
});

Categories