Creating a jQuery vertical scroll loop - javascript

I'm trying to write a jQuery script that will continually scroll these <p> tags within their <div> parent. I got the idea from this site.
function shuffle(){
$('#wrapper > p').each(function(){
h = ($(this).offset().top + 130);
if( h > 500 ){
console.log(h);
$(this).css ('top', 0 );
return;
}
if( h == 270 ){
$(this).addClass('current' );
}
if( h == 360 ){
$(this).removeClass('current' );
}
$(this).animate({
top: h,
easing: 'easeIn'
}, 500, '');
if( h > 1350 ){
$(this).css ('top', 0 );
}
});
window.setTimeout(shuffle, 2500);
}
var i = 0;
$('#wrapper > p').each(function(){
starter = $(this).css('top', ((i * 90) ) + 'px' );
starterWhite = ($(this).offset().top + 130);
if((i*90) == 270)
$(this).addClass('current');
$(this).css('top', starter );
i++;
});
window.setTimeout(shuffle, 2000);
#wrapper {
height: 500px;
overflow: hidden;
position: relative;
}
p {
position: absolute;
margin: 0;
padding: 0;
}
.current {
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="wrapper">
<p>1</p>
<p>2</p>
<p>3</p>
<p>4</p>
<p>5</p>
<p>6</p>
<p>7</p>
</div>
Problem is when I try to make it scroll the <p> tags overlap, and the highlighted tag doesn't change. Any idea how to make it work? Here's a JSFiddle of what I got so far.

Check this out:
// Constants, you can play with it
var STEP = 90;
var CURRENT_INDEX = 3;
// Variables for calculating
var currentTop = STEP * CURRENT_INDEX;
var nextForCurrentTop = STEP * (CURRENT_INDEX + 1);
var $numbers = $('#wrapper > p');
// In this case = 7
var count = $numbers.length;
var secondToLastTop = STEP * (count - 1);
$numbers.each(function(i) {
var $this = $(this);
$this.css('top', i * STEP + 'px');
if (i === CURRENT_INDEX) {
$this.addClass('current');
}
});
window.setTimeout(shuffle, 2000);
function shuffle() {
$numbers.each(function() {
$this = $(this);
// Calculating the new position of the element
h = parseInt($this.css('top')) + STEP;
// In this case = 540
if (h > secondToLastTop) {
$this.css('top', 0);
return;
}
// In this case visually = 3rd element
if (h === currentTop) {
$this.addClass('current');
}
// In this case visually = 4th element
if (h === nextForCurrentTop) {
$this.removeClass('current');
}
$this.animate({
top: h,
easing: 'easeIn'
}, 500, '');
});
window.setTimeout(shuffle, 2500);
}
#wrapper {
height: 500px;
overflow: hidden;
position: relative;
}
p {
position: absolute;
margin: 0;
padding: 0;
}
.current {
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="wrapper">
<p>1</p>
<p>2</p>
<p>3</p>
<p>4</p>
<p>5</p>
<p>6</p>
<p>7</p>
</div>
I improved and commented code from your example, removed magic numbers. You can play with constants.

Related

Javascript scroll listener not working in chrome or firefox

I have created a simple slider that on scroll scrolls down 100vh. It works perfectly in Safari but it doesn't seem to fire at all in both Chrome or Firefox.
Really appreciate it if anyone could point out to me where i may have gone wrong. I'm sure it's something simple but I just can't figure it out.
I have uploaded the files to my test web server so you can see the issue.
test.liamcrane.co.uk
var slider = document.querySelector('.section__wrapper__inner');
var sections = document.querySelectorAll('.section');
var currentTransform = 0;
var activeSection = 0;
function slideDown() {
if (!(activeSection === sections.length - 1)) {
sectionReset();
currentTransform -= 100;
slider.style.transform = "translate3d(0," + currentTransform + "vh, 0)";
activeSection++;
sections[activeSection].classList.add('active');
}
setTimeout(function() {
ready = true;
}, 2000);
}
function slideUp() {
if (!(activeSection === 0)) {
sectionReset();
currentTransform += 100;
slider.style.transform = "translate3d(0," + currentTransform + "vh, 0)";
activeSection--;
sections[activeSection].classList.add('active');
}
setTimeout(function() {
ready = true;
}, 2000);
}
function sectionReset() {
sections[activeSection].classList.remove('active');
}
var ready = true;
document.addEventListener('scroll', function() {
if (ready && window.pageYOffset > 0) {
ready = false;
slideDown();
} else if (ready && window.pageYOffset <= 0) {
ready = false;
slideUp();
}
});
.section__wrapper {
height: 100vh;
overflow: hidden;
}
.section__wrapper__inner {
height: 100%;
transform: translate3d(0, 0, 0);
transition: transform 1s;
}
.section {
position: relative;
height: 100vh;
color: black;
text-align: center;
}
.section span {
line-height: 100vh;
display:block;
}
<div class="section__wrapper">
<div class="section__wrapper__inner">
<section class="section"><span>1</span></section>
<section class="section"><span>2</span></section>
<section class="section"><span>3</span></section>
<section class="section"><span>4</span></section>
<section class="section"><span>5</span></section>
</div>
</div>
I think is that what you want
I have made a little workarround to force scroll ... maybe a little bit ugly but work see fakeScroll() function bellow.
That force the scrollbar to does not reach the beggining and the end. Because in your example above if the scroll bar reach the end ... scroll event can't be triggered (same if reach the begining).
I have also changed the conditions and the timming from setTimeout (ready = true) to 500. You can change it as you want
Sory for my English.
var slider = document.querySelector('.section__wrapper__inner');
var sections = document.querySelectorAll('.section');
var currentTransform = 0;
var activeSection = 0;
var lastOffset = window.pageYOffset;
var actualOffset = lastOffset;
function fakeScroll(){
if(lastOffset > 1){
window.scrollTo(0,lastOffset - 1);
}else{
window.scrollTo(0,1);
}
}
function slideDown() {
if (!(activeSection === sections.length - 1)) {
sectionReset();
currentTransform -= 100;
slider.style.transform = "translate3d(0," + currentTransform + "vh, 0)";
activeSection++;
sections[activeSection].classList.add('active');
}
fakeScroll();
setTimeout(function() {
ready = true;
}, 500);
}
function slideUp() {
if (!(activeSection === 0)) {
sectionReset();
currentTransform += 100;
slider.style.transform = "translate3d(0," + currentTransform + "vh, 0)";
activeSection--;
sections[activeSection].classList.add('active');
}
fakeScroll();
setTimeout(function() {
ready = true;
}, 500);
}
function sectionReset() {
sections[activeSection].classList.remove('active');
}
var ready = true;
window.addEventListener('scroll', function() {
actualOffset = window.pageYOffset;
if (actualOffset > lastOffset) {
if(ready){
ready = false;
slideDown();
}else{
fakeScroll();
}
} else if (window.pageYOffset <= lastOffset) {
if(ready){
ready = false;
slideUp();
}else{
fakeScroll();
}
}
lastOffset = window.pageYOffset;
});
.section__wrapper {
height: 100vh;
position:relative;
overflow: hidden;
}
.section__wrapper__inner {
height: 100%;
position:relative;
transform: translate3d(0, 0, 0);
transition: transform 1s;
}
.section {
position: relative;
height: 100vh;
color: black;
text-align: center;
}
.section span {
line-height: 100vh;
display:block;
}
<div class="section__wrapper">
<div class="section__wrapper__inner">
<section class="section"><span>1</span></section>
<section class="section"><span>2</span></section>
<section class="section"><span>3</span></section>
<section class="section"><span>4</span></section>
<section class="section"><span>5</span></section>
</div>
</div>
window.addEventListener('scroll', function() {
if (ready && window.pageYOffset > 0) {
ready = false;
slideDown();
} else if (ready && window.pageYOffset <= 0) {
ready = false;
slideUp();
}
});

How to scrollLock body when a modal/lightbox is open

I am using the lightbox jquery plugin to open a lightbox when a user clicks on a product. Often the lightbox content stretches below the fold, and at the moment the right scrollbar moves the entire page when you scroll down.
I'd like it to work like the pinterest lightbox, whereby the right scrollbar only scrolls the lightbox, and the rest of the page stays fixed. I've seen a few posts on this, but nothing seems to work for me.
Problem is I want the lightbox to scroll if the content is bigger than the viewport of the browser but not the background.
CSS:
#lightbox{ position: absolute; left: 0; width: 100%; z-index: 100; text-align: center; line-height: 0;}
#lightbox img{ width: auto; height: auto;}
#lightbox a img{ border: none; }
#outerImageContainer{ position: relative; background-color: #fff; width: 250px; height: 250px; margin: 0 auto; }
#imageContainer{ padding: 10px; }
#loading{ position: absolute; top: 40%; left: 0%; height: 25%; width: 100%; text-align: center; line-height: 0; }
#hoverNav{ position: absolute; top: 0; left: 0; height: 100%; width: 100%; z-index: 10; }
#imageContainer>#hoverNav{ left: 0;}
#hoverNav a{ outline: none;}
#prevLink, #nextLink{ width: 49%; height: 100%; background-image: url(data:image2/gif;base64,AAAA); /* Trick IE into showing hover */ display: block; }
#prevLink { left: 0; float: left;}
#nextLink { right: 0; float: right;}
#prevLink:hover, #prevLink:visited:hover { background: url(../images2/prevlabel.gif) left 15% no-repeat; }
#nextLink:hover, #nextLink:visited:hover { background: url(../images2/nextlabel.gif) right 15% no-repeat; }
#imageDataContainer{ font: 10px Verdana, Helvetica, sans-serif; background-color: #fff; margin: 0 auto; line-height: 1.4em; overflow: auto; width: 100% ; }
#imageData{ padding:0 10px; color: #666; }
#imageData #imageDetails{ width: 70%; float: left; text-align: left; }
#imageData #caption{ font-weight: bold; }
#imageData #numberDisplay{ display: block; clear: left; padding-bottom: 1.0em; }
#imageData #bottomNavClose{ width: 66px; float: right; padding-bottom: 0.7em; outline: none;}
#overlay{ position: absolute; top: 0; left: 0; z-index: 90; width: 100%; height: 500px; background-color: #000; }
JS:
// -----------------------------------------------------------------------------------
//
// Lightbox v2.04
// by Lokesh Dhakar - http://www.lokeshdhakar.com
// Last Modification: 2/9/08
//
// For more information, visit:
// http://lokeshdhakar.com/projects/lightbox2/
//
// Licensed under the Creative Commons Attribution 2.5 License - http://creativecommons.org/licenses/by/2.5/
// - Free for use in both personal and commercial projects
// - Attribution requires leaving author name, author link, and the license info intact.
//
// Thanks: Scott Upton(uptonic.com), Peter-Paul Koch(quirksmode.com), and Thomas Fuchs(mir.aculo.us) for ideas, libs, and snippets.
// Artemy Tregubenko (arty.name) for cleanup and help in updating to latest ver of proto-aculous.
//
// -----------------------------------------------------------------------------------
/*
Table of Contents
-----------------
Configuration
Lightbox Class Declaration
- initialize()
- updateImageList()
- start()
- changeImage()
- resizeImageContainer()
- showImage()
- updateDetails()
- updateNav()
- enableKeyboardNav()
- disableKeyboardNav()
- keyboardAction()
- preloadNeighborImages()
- end()
Function Calls
- document.observe()
*/
// -----------------------------------------------------------------------------------
//
// Configurationl
//
LightboxOptions = Object.extend({
fileLoadingImage: 'images2/loading.gif',
fileBottomNavCloseImage: 'images2/closelabel.gif',
overlayOpacity: 0.8, // controls transparency of shadow overlay
animate: true, // toggles resizing animations
resizeSpeed: 7, // controls the speed of the image resizing animations (1=slowest and 10=fastest)
borderSize: 10, //if you adjust the padding in the CSS, you will need to update this variable
// When grouping images this is used to write: Image # of #.
// Change it for non-english localization
labelImage: "Image",
labelOf: "of"
}, window.LightboxOptions || {});
// -----------------------------------------------------------------------------------
var Lightbox = Class.create();
Lightbox.prototype = {
imageArray: [],
activeImage: undefined,
// initialize()
// Constructor runs on completion of the DOM loading. Calls updateImageList and then
// the function inserts html at the bottom of the page which is used to display the shadow
// overlay and the image container.
//
initialize: function() {
this.updateImageList();
this.keyboardAction = this.keyboardAction.bindAsEventListener(this);
if (LightboxOptions.resizeSpeed > 10) LightboxOptions.resizeSpeed = 10;
if (LightboxOptions.resizeSpeed < 1) LightboxOptions.resizeSpeed = 1;
this.resizeDuration = LightboxOptions.animate ? ((11 - LightboxOptions.resizeSpeed) * 0.15) : 0;
this.overlayDuration = LightboxOptions.animate ? 0.2 : 0; // shadow fade in/out duration
// When Lightbox starts it will resize itself from 250 by 250 to the current image dimension.
// If animations are turned off, it will be hidden as to prevent a flicker of a
// white 250 by 250 box.
var size = (LightboxOptions.animate ? 250 : 1) + 'px';
// Code inserts html at the bottom of the page that looks similar to this:
//
// <div id="overlay"></div>
// <div id="lightbox">
// <div id="outerImageContainer">
// <div id="imageContainer">
// <img id="lightboxImage">
// <div style="" id="hoverNav">
//
//
// </div>
// <div id="loading">
// <a href="#" id="loadingLink">
// <img src="images/loading.gif">
// </a>
// </div>
// </div>
// </div>
// <div id="imageDataContainer">
// <div id="imageData">
// <div id="imageDetails">
// <span id="caption"></span>
// <span id="numberDisplay"></span>
// </div>
// <div id="bottomNav">
// <a href="#" id="bottomNavClose">
// <img src="images/close.gif">
// </a>
// </div>
// </div>
// </div>
// </div>
var objBody = $$('body')[0];
objBody.appendChild(Builder.node('div',{id:'overlay'}));
objBody.appendChild(Builder.node('div',{id:'lightbox'}, [
Builder.node('div',{id:'outerImageContainer'},
Builder.node('div',{id:'imageContainer'}, [
Builder.node('img',{id:'lightboxImage'}),
Builder.node('div',{id:'hoverNav'}, [
Builder.node('a',{id:'prevLink', href: '#' }),
Builder.node('a',{id:'nextLink', href: '#' })
]),
Builder.node('div',{id:'loading'},
Builder.node('a',{id:'loadingLink', href: '#' },
Builder.node('img', {src: LightboxOptions.fileLoadingImage})
)
)
])
),
Builder.node('div', {id:'imageDataContainer'},
Builder.node('div',{id:'imageData'}, [
Builder.node('div',{id:'imageDetails'}, [
Builder.node('span',{id:'caption'}),
Builder.node('span',{id:'numberDisplay'})
]),
Builder.node('div',{id:'bottomNav'},
Builder.node('a',{id:'bottomNavClose', href: '#' },
Builder.node('img', { src: LightboxOptions.fileBottomNavCloseImage })
)
)
])
)
]));
$('overlay').hide().observe('click', (function() { this.end(); }).bind(this));
$('lightbox').hide().observe('click', (function(event) { if (event.element().id == 'lightbox') this.end(); }).bind(this));
$('outerImageContainer').setStyle({ width: size, height: size });
$('prevLink').observe('click', (function(event) { event.stop(); this.changeImage(this.activeImage - 1); }).bindAsEventListener(this));
$('nextLink').observe('click', (function(event) { event.stop(); this.changeImage(this.activeImage + 1); }).bindAsEventListener(this));
$('loadingLink').observe('click', (function(event) { event.stop(); this.end(); }).bind(this));
$('bottomNavClose').observe('click', (function(event) { event.stop(); this.end(); }).bind(this));
var th = this;
(function(){
var ids =
'overlay lightbox outerImageContainer imageContainer lightboxImage hoverNav prevLink nextLink loading loadingLink ' +
'imageDataContainer imageData imageDetails caption numberDisplay bottomNav bottomNavClose';
$w(ids).each(function(id){ th[id] = $(id); });
}).defer();
},
//
// updateImageList()
// Loops through anchor tags looking for 'lightbox' references and applies onclick
// events to appropriate links. You can rerun after dynamically adding images w/ajax.
//
updateImageList: function() {
this.updateImageList = Prototype.emptyFunction;
document.observe('click', (function(event){
var target = event.findElement('a[rel^=lightbox]') || event.findElement('area[rel^=lightbox]');
if (target) {
event.stop();
this.start(target);
}
}).bind(this));
},
//
// start()
// Display overlay and lightbox. If image is part of a set, add siblings to imageArray.
//
start: function(imageLink) {
$$('select', 'object', 'embed').each(function(node){ node.style.visibility = 'hidden' });
// stretch overlay to fill page and fade in
var arrayPageSize = this.getPageSize();
$('overlay').setStyle({ width: arrayPageSize[0] + 'px', height: arrayPageSize[1] + 'px' });
new Effect.Appear(this.overlay, { duration: this.overlayDuration, from: 0.0, to: LightboxOptions.overlayOpacity });
this.imageArray = [];
var imageNum = 0;
if ((imageLink.rel == 'lightbox')){
// if image is NOT part of a set, add single image to imageArray
this.imageArray.push([imageLink.href, imageLink.title]);
} else {
// if image is part of a set..
this.imageArray =
$$(imageLink.tagName + '[href][rel="' + imageLink.rel + '"]').
collect(function(anchor){ return [anchor.href, anchor.title]; }).
uniq();
while (this.imageArray[imageNum][0] != imageLink.href) { imageNum++; }
}
// calculate top and left offset for the lightbox
var arrayPageScroll = document.viewport.getScrollOffsets();
var lightboxTop = arrayPageScroll[1] + (document.viewport.getHeight() / 10);
var lightboxLeft = arrayPageScroll[0];
this.lightbox.setStyle({ top: lightboxTop + 'px', left: lightboxLeft + 'px' }).show();
this.changeImage(imageNum);
},
//
// changeImage()
// Hide most elements and preload image in preparation for resizing image container.
//
changeImage: function(imageNum) {
this.activeImage = imageNum; // update global var
// hide elements during transition
if (LightboxOptions.animate) this.loading.show();
this.lightboxImage.hide();
this.hoverNav.hide();
this.prevLink.hide();
this.nextLink.hide();
// HACK: Opera9 does not currently support scriptaculous opacity and appear fx
this.imageDataContainer.setStyle({opacity: .0001});
this.numberDisplay.hide();
var imgPreloader = new Image();
// once image is preloaded, resize image container
imgPreloader.onload = (function(){
this.lightboxImage.src = this.imageArray[this.activeImage][0];
this.resizeImageContainer(imgPreloader.width, imgPreloader.height);
}).bind(this);
imgPreloader.src = this.imageArray[this.activeImage][0];
},
//
// resizeImageContainer()
//
resizeImageContainer: function(imgWidth, imgHeight) {
// get current width and height
var widthCurrent = this.outerImageContainer.getWidth();
var heightCurrent = this.outerImageContainer.getHeight();
// get new width and height
var widthNew = (imgWidth + LightboxOptions.borderSize * 2);
var heightNew = (imgHeight + LightboxOptions.borderSize * 2);
// scalars based on change from old to new
var xScale = (widthNew / widthCurrent) * 100;
var yScale = (heightNew / heightCurrent) * 100;
// calculate size difference between new and old image, and resize if necessary
var wDiff = widthCurrent - widthNew;
var hDiff = heightCurrent - heightNew;
if (hDiff != 0) new Effect.Scale(this.outerImageContainer, yScale, {scaleX: false, duration: this.resizeDuration, queue: 'front'});
if (wDiff != 0) new Effect.Scale(this.outerImageContainer, xScale, {scaleY: false, duration: this.resizeDuration, delay: this.resizeDuration});
// if new and old image are same size and no scaling transition is necessary,
// do a quick pause to prevent image flicker.
var timeout = 0;
if ((hDiff == 0) && (wDiff == 0)){
timeout = 100;
if (Prototype.Browser.IE) timeout = 250;
}
(function(){
this.prevLink.setStyle({ height: imgHeight + 'px' });
this.nextLink.setStyle({ height: imgHeight + 'px' });
this.imageDataContainer.setStyle({ width: widthNew + 'px' });
this.showImage();
}).bind(this).delay(timeout / 1000);
},
//
// showImage()
// Display image and begin preloading neighbors.
//
showImage: function(){
this.loading.hide();
new Effect.Appear(this.lightboxImage, {
duration: this.resizeDuration,
queue: 'end',
afterFinish: (function(){ this.updateDetails(); }).bind(this)
});
this.preloadNeighborImages();
},
//
// updateDetails()
// Display caption, image number, and bottom nav.
//
updateDetails: function() {
// if caption is not null
if (this.imageArray[this.activeImage][1] != ""){
this.caption.update(this.imageArray[this.activeImage][1]).show();
}
// if image is part of set display 'Image x of x'
if (this.imageArray.length > 1){
this.numberDisplay.update( LightboxOptions.labelImage + ' ' + (this.activeImage + 1) + ' ' + LightboxOptions.labelOf + ' ' + this.imageArray.length).show();
}
new Effect.Parallel(
[
new Effect.SlideDown(this.imageDataContainer, { sync: true, duration: this.resizeDuration, from: 0.0, to: 1.0 }),
new Effect.Appear(this.imageDataContainer, { sync: true, duration: this.resizeDuration })
],
{
duration: this.resizeDuration,
afterFinish: (function() {
// update overlay size and update nav
var arrayPageSize = this.getPageSize();
this.overlay.setStyle({ height: arrayPageSize[1] + 'px' });
this.updateNav();
}).bind(this)
}
);
},
//
// updateNav()
// Display appropriate previous and next hover navigation.
//
updateNav: function() {
this.hoverNav.show();
// if not first image in set, display prev image button
if (this.activeImage > 0) this.prevLink.show();
// if not last image in set, display next image button
if (this.activeImage < (this.imageArray.length - 1)) this.nextLink.show();
this.enableKeyboardNav();
},
//
// enableKeyboardNav()
//
enableKeyboardNav: function() {
document.observe('keydown', this.keyboardAction);
},
//
// disableKeyboardNav()
//
disableKeyboardNav: function() {
document.stopObserving('keydown', this.keyboardAction);
},
//
// keyboardAction()
//
keyboardAction: function(event) {
var keycode = event.keyCode;
var escapeKey;
if (event.DOM_VK_ESCAPE) { // mozilla
escapeKey = event.DOM_VK_ESCAPE;
} else { // ie
escapeKey = 27;
}
var key = String.fromCharCode(keycode).toLowerCase();
if (key.match(/x|o|c/) || (keycode == escapeKey)){ // close lightbox
this.end();
} else if ((key == 'p') || (keycode == 37)){ // display previous image
if (this.activeImage != 0){
this.disableKeyboardNav();
this.changeImage(this.activeImage - 1);
}
} else if ((key == 'n') || (keycode == 39)){ // display next image
if (this.activeImage != (this.imageArray.length - 1)){
this.disableKeyboardNav();
this.changeImage(this.activeImage + 1);
}
}
},
//
// preloadNeighborImages()
// Preload previous and next images.
//
preloadNeighborImages: function(){
var preloadNextImage, preloadPrevImage;
if (this.imageArray.length > this.activeImage + 1){
preloadNextImage = new Image();
preloadNextImage.src = this.imageArray[this.activeImage + 1][0];
}
if (this.activeImage > 0){
preloadPrevImage = new Image();
preloadPrevImage.src = this.imageArray[this.activeImage - 1][0];
}
},
//
// end()
//
end: function() {
this.disableKeyboardNav();
this.lightbox.hide();
new Effect.Fade(this.overlay, { duration: this.overlayDuration });
$$('select', 'object', 'embed').each(function(node){ node.style.visibility = 'visible' });
},
//
// getPageSize()
//
getPageSize: function() {
var xScroll, yScroll;
if (window.innerHeight && window.scrollMaxY) {
xScroll = window.innerWidth + window.scrollMaxX;
yScroll = window.innerHeight + window.scrollMaxY;
} else if (document.body.scrollHeight > document.body.offsetHeight){ // all but Explorer Mac
xScroll = document.body.scrollWidth;
yScroll = document.body.scrollHeight;
} else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari
xScroll = document.body.offsetWidth;
yScroll = document.body.offsetHeight;
}
var windowWidth, windowHeight;
if (self.innerHeight) { // all except Explorer
if(document.documentElement.clientWidth){
windowWidth = document.documentElement.clientWidth;
} else {
windowWidth = self.innerWidth;
}
windowHeight = self.innerHeight;
} else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode
windowWidth = document.documentElement.clientWidth;
windowHeight = document.documentElement.clientHeight;
} else if (document.body) { // other Explorers
windowWidth = document.body.clientWidth;
windowHeight = document.body.clientHeight;
}
// for small pages with total height less then height of the viewport
if(yScroll < windowHeight){
pageHeight = windowHeight;
} else {
pageHeight = yScroll;
}
// for small pages with total width less then width of the viewport
if(xScroll < windowWidth){
pageWidth = xScroll;
} else {
pageWidth = windowWidth;
}
return [pageWidth,pageHeight];
}
}
document.observe('dom:loaded', function () { new Lightbox(); });
Here's a class that'll allow you to do just that:
class ScrollLock {
constructor () {
this.pageBody = document.querySelector('body');
this.scrollY = 0;
}
saveScrollY = (num) => {
this.scrollY = num;
}
setScrollY = (num) => {
window.scroll(0, num);
}
setScrollOffset = (vOffset) => {
this.pageBody.style.top = `-${vOffset}px`;
}
freezeBodyScroll = () => {
this.saveScrollY(window.scrollY);
this.setScrollOffset(this.scrollY);
this.pageBody.classList.add('is-fixed');
}
unfreezeBodyScroll = () => {
this.pageBody.classList.remove('is-fixed');
// Don't reset scroll position if lock hasn't occurred
if (this.scrollY === 0) return;
this.setScrollOffset(0);
this.setScrollY(this.scrollY);
this.saveScrollY(0);
}
}
Include the following style declaration:
// In your CSS
body.is-fixed {
position: fixed;
max-width: 100%;
}
Use:
const { freezeBodyScroll, unfreezeBodyScroll } = new ScrollLock();
// Call when you open your modal
freezeBodyScroll();
// Call when you close your modal
unfreezeBodyScroll();

simple animation in java script

I'm trying to learn Java Script Animations and I found really good examples on this site: http://javascript.info/tutorial/animation#maths-the-function-of-progress-delta
But the problem is, as a beginner, I don't understand how the functions and objects work with each other.
Question 01
I copied the example "Let’s create a movement animation on it’s base:" But my version does not work.
<!DOCTYPE HTML>
<html>
<head>
<style>
.example_path{
position: relative;
width: 600px;
height: 100px;
border-style: solid;
border-width: 5px;
}
.example_block{
position: absolute;
width: 100px;
height: 100px;
background-color: yellow;
}
</style>
</head>
<body>
<div onclick="move(this.children[0])" class="example_path">
<div class="example_block"></div>
</div>
<script>
function move(element, delta, duration) {
var to = 500
animate({
delay: 10,
duration: duration || 1000, // 1 sec by default
delta: delta,
step: function(delta) {
element.style.left = to*delta + "px"
}
})
}
</script>
</body>
</html>
output console: ReferenceError: animate is not defined
Does anyone know what the problem is?
Question 02
My second wish is, to integrate the easeInOut function
function makeEaseInOut(delta) {
return function(progress) {
if (progress < .5)
return delta(2*progress) / 2
else
return (2 - delta(2*(1-progress))) / 2
}
}
bounceEaseInOut = makeEaseInOut(bounce)
How can I link both code snippets? The code is also from this page: http://javascript.info/tutorial/animation#maths-the-function-of-progress-delta
Add animate and makeEaseInOut into your script tag then you can use them. You may want to include the functions in a separate JavaScript file eventually.
<script>
function animate(opts) {
var start = new Date
var id = setInterval(function() {
var timePassed = new Date - start
var progress = timePassed / opts.duration
if (progress > 1) progress = 1
var delta = opts.delta(progress)
opts.step(delta)
if (progress == 1) {
clearInterval(id)
}
}, opts.delay || 10)
}
function makeEaseInOut(delta) {
return function(progress) {
if (progress < .5)
return delta(2*progress) / 2
else
return (2 - delta(2*(1-progress))) / 2
}
}
bounceEaseInOut = makeEaseInOut(bounce)
</script>
that's what I tried.
I still have problems.
output console: delta is not a function. bounce is not a function.
I know I have to learn more about creating functions. But right now I'm not that good to solve the problem.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>
.example_path{
position: relative;
width: 600px;
height: 100px;
border-style: solid;
border-width: 5px;
}
.example_block{
position: absolute;
width: 100px;
height: 100px;
background-color: yellow;
}
</style>
<script>
function move(element, delta, duration) {
var to = 500;
animate({
delay: 10,
duration: duration || 1000, // 1 sec by default
delta: delta,
step: function(delta) {
element.style.left = to*delta + "px"
}
});
}
function animate(opts) {
var start = new Date;
var id = setInterval(function() {
var timePassed = new Date - start;
var progress = timePassed / opts.duration;
if (progress > 1) progress = 1
var delta = opts.delta(progress);
opts.step(delta);
if (progress == 1) {
clearInterval(id);
}
}, opts.delay || 10);
}
function makeEaseInOut(delta) {
return function(progress) {
if (progress < .5)
return delta(2*progress)/2;
else
return (2 - delta(2*(1-progress)))/2;
};
}
varbounceEaseInOut = makeEaseInOut(bounce);
</script>
</head>
<body>
<div onclick="move(this.children[0], makeEaseInOut(bounce), 3000)" class="example_path">
<div class="example_block"></div>
</div>
</body>
</html>
I've made a very simple animation using javascript, hope it helps, try to "Run code snippet" for better understanding.
/*JavaScript*/
function myMove() {
var elem = document.getElementById("animate");
var pos = 0;
var id = setInterval(frame, 5);
function frame() {
if (pos == 350) {
clearInterval(id);
} else {
pos++;
elem.style.top = pos + 'px';
elem.style.left = pos + 'px';
}
}
}
function Back() {
var elem1 = document.getElementById("animate");
var id1 = setInterval(frame2, 5);
var pos1 = 350;
function frame2() {
if (pos1 == 0) {
clearInterval(id1);
} else {
pos1--;
elem1.style.top = pos1 + 'px';
elem1.style.left = pos1 + 'px';
}
}
}
/*CSS*/
#container {
width: 400px;
height: 400px;
position: relative;
background: yellow;
}
#animate {
width: 50px;
height: 50px;
position: absolute;
background-color: red;
}
/*HTML*/
<button onclick="myMove()">Click Me</button>
<button onclick="Back()"> roll back</button>
<div id ="container">
<div id ="animate"></div>
</div>

jQuery autoScroll to the nearest section

If the user is place in the top half of current section it automatically scroll top of that section.
Then if the user is in the bottom half of the current section it automatically scroll to the top next section.
function autoScroll(aid){
var aTag = $("#"+ aid);
body.animate({scrollTop: aTag.offset().top},1500);
}
$(window).scroll(function() {
var windowScroll = $(window).scrollTop();
if(windowScroll < ($("#Section2").offset().top/2) && !(windowScroll > ($("#Section2").offset().top/2))){
section_id = 'Section1';
}
$(document).off('scroll');
console.log(section_id);
autoScroll(section_id);
});
http://jsfiddle.net/x6xzh69v/2/
I created a working example in CODEPEN.
$(document).ready(function() {
var origHeight = [];
var curScroll = 0;
var cumSumHeight = 0;
var animHeight = 0;
var i = 0;
var timeoutVar;
$(".section").each(function(index) {
origHeight.push($(this).height());
});
$(window).scroll(function() {
curScroll = $("body").scrollTop();
cumSumHeight = 0;
while ((cumSumHeight + origHeight[i]) < curScroll) {
cumSumHeight += origHeight[i];
i++;
}
if (i == 0) {
if (curScroll < (origHeight[i] / 2)) {
animHeight = 0;
} else {
animHeight = origHeight[i];
}
} else {
if ((curScroll - cumSumHeight) < (origHeight[i] / 2)) {
animHeight = cumSumHeight;
} else {
animHeight = origHeight[i] + cumSumHeight;
}
}
clearTimeout(timeoutVar);
timeoutVar = setTimeout(function() {
$("body").stop(true,true).animate({
scrollTop: animHeight
}, 200);
}, 300);
});
});
.section {
width: 100%;
position: relative;
height: 300px;
}
#Section1 {
background: red;
}
#Section2 {
background: blue;
}
#Section3 {
background: orange;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<section id="Section1" class="section"></section>
<section id="Section2" class="section"></section>
<section id="Section3" class="section"></section>

Multiple sliders sliding at the same time when only the active one should be sliding

I have multiple sliders, each in its own section->article. My problem is this: When I hit the next or previous button on one of the sliders all sliders start sliding at the same time.
html:
<section id="section01">
<article class="article01">
<div class="wrapper">
<ul class="slider">
<li class="slide"></li>
<li class="slide"></li>
<li class="slide"></li>
</ul>
</div>
<img class="previous" src="images/arrow-transparent.png">
<img class="next" src="images/arrow-transparent.png">
</article>
</section>
css
.wrapper{
height: 342px;
margin: 0 auto;
overflow: hidden;
width: 918px;
}
.slider{
height: 342px;
position: relative;
width: 5000px;
}
.slide{
float: left;
height: 342px;
position: relative;
width: 306px;
}
js
/* slider */
$(function(){
var i = 0;
$('.previous').click(function(){
var currentSlides = $(this).parent().find('.slide'),
parent = $(this).parent().find('.wrapper ul li');
i = --i -2 % currentSlides.length;
if(i - 3 >= -3) {
$('.slider').animate({'left' : -(parent.eq(i).position().left)}, 600);
} else {
i = 0;
}
});
$('.next').click(function(){
var currentSlides = $(this).parent().find('.slide'),
parent = $(this).parent().find('.wrapper ul li'),
current = i;
i = ++i + 2 % currentSlides.length;
if(i + 3 < currentSlides.length) {
$('.slider').animate({'left' : -(parent.eq(i).position().left)}, 600);
} else {
i = current;
}
});
});
How do I fix this?
This is because you are selecting all slider class elements so this will animate them all.
What if you select slide instead?
$(function(){
var i = 0;
$('.previous').click(function(){
var currentSlides = $(this).parent().find('.slide'),
parent = $(this).parent().find('.wrapper ul li');
i = --i -2 % currentSlides.length;
if(i - 3 >= -3) {
$('.slide').animate({'left' : -(parent.eq(i).position().left)}, 600);
} else {
i = 0;
}
});
I decided to completely ditch the javascript code from my original post and ended up using this instead:
$(function() {
$('article .wrapper').each(function(){
var slider = $(this).find('.slider'),
parent = $(this),
step =855,
left = parseInt(slider.css('left'), 10),
max = parent.width() - slider.width(),
min = 0;
parent.find(".previous").click(function() {
if (left < 0) {
var newLeft = left + step;
left = (newLeft<min) ? newLeft : min;
slider.animate({
"left": left + 'px'
}, "slow");
}
});
parent.find(".next").click(function() {
if (left > max) {
var newLeft = left - step;
left = (newLeft>max) ? newLeft : max;
slider.animate({
"left": left + 'px'
}, "slow");
}
});
});
});
I also slightly modified widths of several elements in css and now it all works like a charm.

Categories

Resources