I've made a single page website, with with each div taking up 100% of the page.
At the moment I have some code that takes the user down the page, one div at a time.
$(".box1").click(function(e){
$('html, body').animate({scrollTop:$('.box2').offset().top }, 'slow');
});
$(".box2").click(function(e){
$('html, body').animate({scrollTop:$('.box3').offset().top}, 'slow');
});
$(".box3").click(function(e){
$('html, body').animate({scrollTop:$('.box4').offset().top}, 'slow');
});
$(".box4").click(function(e){
$('html, body').animate({scrollTop:$('.box5').offset().top}, 'slow');
});
Rather than having the user click different divs (box1, box2, etc) each time, can I let the user click the same div (.arrow) every time?
I have attempted this, with the user clicking .arrow to go through the loop:
var boxes = ["box1", "box2", "box3", "box4"];
for (i = 1; i > boxes.length; i++) {
$(".arrow")click(function(e){
$('html, body').animate({scrollTop:$(boxes[i]).offset().top}, 'slow');
});
}
This however is unresponsive, and won't scroll at all. Does anyone know what is wrong with this loop?
Only have one listener on .arrow which has some logic to decide where to go
(function enableArrow() {
var i = 1; // initial box
$(".arrow").click(function (e) {
i = i % 5 + 1; // (0 to 4) + 1 => 1 to 5
$('html, body').animate(
{scrollTop: $('.box'+i).offset().top},
'slow'
);
});
}());
Paul S. is right. What you attempted to do was assigning multiple click handlers to one .arrow element.
Paul S. suggests to define an i variable which will be visible to function (e) closure and will be modified each time you call the closure.
Try Changing like this.Hope this works.
var boxes = [".box1", ".box2", ".box3", ".box4"];
for (i = 0; i < boxes.length; i++) {
$(".arrow")click(function(e){
$('html, body').animate({scrollTop:$(boxes[i]).offset().top}, 'slow');
});
}
Rather than having a click handler per div, why not use event delegation?
$(document).on('click', '.box', function(event) {
$('html, body').animate({
scrollTop: $(event.target).offset().top
}, 'slow');
});
This way you'll only have a single event handler and the event will carry the div that you clicked on the target.
Related
I'm writing a quiz web ap with an opening heading and then 10 questions that follow it. The div of the opening and the div of each question are all siblings, so I traverse the page by passing current.nextSibling and current.previousSibling to whatever functions I'm using.
Right now I'm trying to create a smooth scroll with jQuery through its 'animate' and 'scrollTop' methods, but it's not working. Does anyone have any thoughts on this? Code attached here, link to fiddle here: https://jsfiddle.net/fjydnc9m/1/
var main = function () {
var root = $('html, body');
var current = document.getElementById("opening");
$('.upButton').click(function () {
$('html, body').animate({ scrollTop:$(current.previousSibling).offset().top}, 2000);
current = current.previousSibling;
});
$('.downButton').click(function() {
$('html, body').animate({ scrollTop: $(current.nextSibling).offset().top}, 2000);
current = current.nextSibling;
});
}
$(document).ready(main);
You've been trying to use jQuery .offset() on a regular HTML DOM element.
See this updated version of the fiddle:
https://jsfiddle.net/fjydnc9m/12/
What I did is to get the prev and next sibling via jQuery and use .offset() on that.
Note that you'll also have to account for the cases where current is the first or last wrapper, or some strange scrolling will take place. You can do this by checking if the length of prevSibling or nextSibling is > 0 before scrolling.
If you log the current variable, you find out that there is a #text sibling that is assigned to the current variable.
Check out this fiddle:
https://jsfiddle.net/fjydnc9m/13/
You can see that I assigned the current variable twice PRIOR to using it in the scrollTop function:
var main = function() {
var root = $('html, body');
var current = document.getElementById("opening");
$('.upButton').click(function() {
current = current.previousSibling;
current = current.previousSibling;
$('html, body').animate({
scrollTop: $(current).offset().top
}, 2000);
console.log(current);
});
$('.downButton').click(function() {
current = current.nextSibling;
current = current.nextSibling;
$('html, body').animate({
scrollTop: $(current).offset().top
}, 2000);
console.log(current);
});
}
$(document).ready(main);
Note that I'm logging the current variable. Remove one of the current assignments and see what the log shows (you will see what's going on).
When You click on button, page should scroll down, to div with id="myTarget".
here is my HTML:
<button class="go"> GO </button>
<div id="myTarget">
<p>
la lalal lalala lalala
</p>
</div>
and jquery:
$(function() {
$(".go").on('click', function(event) {
event.stopPropagation();
$('html, body').animate({
scrollTop: $("#myTarget").offset().top }, 3000);
});
});
My problem is that when you click a few times on button, page scroll down. After that you can't scroll up. Is any way to stop click event while page moving?
JsFiddle
And if you stop the animation when user mousewheel?
$(function() {
$(".go").on('click', function(event) {
event.stopPropagation();
$('html, body').animate({
scrollTop: $("#myTarget").offset().top }, 3000);
});
});
var page = $("html, body");
page.on("scroll mousedown wheel DOMMouseScroll mousewheel keyup touchmove", function(){
page.stop();
});
Demo
What about disabling the button while it is running and enabling it again once animation is done?
$(function() {
$(".go").on('click', function(event) {
var $but = jQuery(this);
event.stopPropagation();
$but.attr("disabled", true);
$('html, body').animate({
scrollTop: $("#myTarget").offset().top }, 3000, "linear", function(){
$but.removeAttr("disabled");
});
});
});
I assume you mean that if you rapidly click the button a couple of times it'll scroll down and not let you scroll back up, and not that it doesn't work when you "Click Button, Scroll Down, wait, Scroll Up".
If it's the first case, you can fix it like this.
$(function() { $(".go").on('click', function(event) {
event.stopPropagation();
$(".go").attr("disabled", true).delay(3000).attr("disabled", false); $('html, body').animate({
scrollTop: $("#myTarget").offset().top
},
3000);
});
});
This means that when you click on the button, it will be disabled for 3000 milliseconds (the time of your animation. This should stop a user from being able to click on it and trigger the animation more than once while it's animating.
The issue is that your animation is getting appended onto the previous animation for the html and body tags. Thus, you have to wait for all of the animations that have been started to die before you can scroll back up.
Things that you can do about this problem
Make the duration of the animation smaller
Call stop() on the elements you are animating before creating the new animation
Call stop() if the window is scrolled. This solution could be problematic if you ever have the body tag doing other animations. The first two solutions should be enough, anyway.
The first should be self explanatory and the second is very easy:
$(".go").on('click', function(event) {
event.stopPropagation();
$('body').stop().animate({
scrollTop: $("#myTarget").offset().top }, 500);
});
You also only need to animate the body element (not the html element).
JSFiddle Example
Use a scrolling state, like so :
$(function() {
//global var
isScrolling = false;
$(".go").on('click', function(event) {
event.stopPropagation();
if(!isScrolling) {
isScrolling = true;
$('html, body').animate({
scrollTop: $("#myTarget").offset().top }, 3000,
//Only when it's completed (callback)
function() {
isScrolling = false;
}
);
}
});
});
Your problem is that it keeps trying to scroll down even though you are already down.
In Demo 01 You can see the Div is Scrolling top of the page with increase height. And I need the same animation with click Buttons, like in Demo 02.
$('.work-showcase').click(function(){
$('.work-showcase').animate({height:'135px'}, 500);
$(this).animate({height:'400px'}, 500,function() {
$("html, body").animate({ scrollTop: $(this).offset().top });
});
});
Not sure if I understand what you want, but see if this Javascript works for you:
var map = {
"slice1": "#post1",
"slice2": "#post2",
"slice3": "#post3",
}
$('.clickable').click(function(){
var postId = map[$(this).attr('id')];
$('.post').animate({height:'50px'}, 500);
$(postId).animate({height:'400px'}, 500,function() {
$("html, body").animate({ scrollTop: $(postId).offset().top });
});
});
See demo at http://jsfiddle.net/xCKPW/1/.
What I think you want to do is have the animation and size change that you currently have get triggered when a button is clicked.
I also suspect you want the action to occur when the image is clicked.
In this case, move the animations into a separate function, and call that function onclick.
Here's your jsfiddle updated with buttons.
http://jsfiddle.net/Jq4Vw/132/
$('.work-showcase, button').click(function(){
moveAndResize($(this).index());
});
function moveAndResize(index){
var item = $('.work-showcase:eq('+index+')');
$('.work-showcase').animate({height:'135px'}, 500);
$(item).animate({height:'400px'}, 500,function() {
$("html, body").animate({ scrollTop: $(item).offset().top });
});
}
This works as long as the indexes are the same. If you want the index of the buttons to be different, add an id tag or something else that you can then pass to the moveAndResize which maps to the index of the item you want to change.
I'm trying to get the window to scroll through a sequence of divs. Here is my code, but it is quite targeted, and won't work for more than one div.
$('.down_arrow').click(function(e){
$('html, body')
.animate({scrollTop:$('.two')
.offset()
.top }, 'slow');
});
JSFIDDLE
Is there a way I can then go through each $('.container') on each $('.arrow_down') click?
$('.down_arrow').click(function(e){
$('html, body')
.animate(
{
scrollTop:$(this).closest('.container').next().offset().top
}, 'slow');
});
jsFiddle
$('.down_arrow').click(function(e) {
var next_container = $(this).parents(".container").next(".container");
$('html, body')
.animate({ scrollTop:next_container.offset().top }, 'slow');
});
JSFiddle
You should save the last scrolled container, and scroll to the next one.
Something like this:
var currentContainerIndex = 0;
$('.down_arrow').click(function(e){
var currentContainer = $($('.container')[currentContainerIndex]);
if (!currentContainer.size()) {
currentContainerIndex = 0;
currentContainer = $($('.container')[currentContainerIndex]);
}
$('html, body').animate({scrollTop:currentContainer.offset().top }, 'slow');
currentContainerIndex++;
});
I've the following function:
$('.link1').click(function(){
$("#div2").slideUp(function(){$("#div1").slideToggle();});
$('html, body').animate({scrollTop: '600px'}, 800);
});
It toggles a div and scroll the page down. The problem is that everytime the user toggles the page scroll down again...how could I run this animate function only at first click?
Use a flag or set a data attribute to make sure the scrolling animation only occurs on the first click.
var flag=true;
$('.link1').click(function(){
$("#div2").slideUp(function(){$("#div1").slideToggle();});
if (flag) {
$('html, body').animate({scrollTop: '600px'}, 800);
flag = false;
}
});
I'm guessing #div2 should still toggle, but that it just should'nt scroll on every click?
jQuery .one() http://api.jquery.com/one/
$('.link1').one( 'click', function(){
$("#div2").slideUp(function(){$("#div1").slideToggle();});
$('html, body').animate({scrollTop: '600px'}, 800);
});
use the .one function to bind an event that fires only once.
$('.link1').one('click', function(){
$("#div2").slideUp(function(){$("#div1").slideToggle();});
$('html, body').animate({scrollTop: '600px'}, 800);
});
The following works with JQuery.
The CSS used:
.cpos {
position: relative;
top: -1.65em;
left: 1.8em;
}
The JQuery used:
var p=null; /* Initialize variable p. */
p=$("b").detach(); /* Detach every possible <b>b</b>-tags. */
var p=$("<b>Console loaded!</b>").addClass("cpos"); /* Do anything, like adding class. */
p.appendTo("#container"); /* Append new data to the anchor container. */
Maybe you could use this for reference when animating. ;)
You could unbind that click handler at the end of the handler so that it never triggers again:
$('.link1').off('click');
Use a flag
var noRun = 0
$('.link1').click(function(){
if(noRun==1) {
return
}
noRun = 1
$("#div2").slideUp(function(){$("#div1").slideToggle();});
$('html, body').animate({scrollTop: '600px'}, 800);
});
You can save a simple "token" to check if is the first time that click is fired in this way:
$('.link1').click(function(){
if(!$(this).data('isFirstTime')) {
$("#div2").slideUp(function(){$("#div1").slideToggle();});
$('html, body').animate({scrollTop: '600px'}, 800);
$(this).data('isFirstTime', true);
}
});
This should prevent further click
This should do it
(function(){
var first=true;
$('.link1').click(function(){
if (first){
first=false;
$("#div2").slideUp(function(){$("#div1").slideToggle();});
$('html, body').animate({scrollTop: '600px'}, 800);
}
});
})();