js animate function scrolls to bottom of div instead of top - javascript

js windows animate scrolltop to div class is scrolling right to to the bottom of the div
js
$(document).ready(function () {
$('html, body').animate({
scrollTop: $('.tariff').offset().top
}, 'slow');
});
it is scrolling right to the bottom of div class 'tariff'. I want it to scroll and stop at the top of the div.
Did a lot of googling. Don't know where I am going wrong.
EDIT
I think it may have something to do with my external js.js file. Something here is probably effecting the animate scrolling height. Because if I omit this file,
it scrolls properly to the top of the div.
But I don't know what is interfering here.
js.js
$('document').ready(function(){
$('#smshare').click(function() {
$('#smp').slideToggle('fast');
$('#smp').load('social-media-share.php');
});
$('#offer,#orderlink').click(function()
{
$('#order').fadeIn('fast');
$('html, body').animate({
scrollTop: $("#order").offset().top
}, 2000);
$('.scrolltop').fadeIn('fast');
$('.aboutus,.tariff,.services,.contactus,.logged_order,.pers_dets,.clothes_submitted,.locations_list').fadeOut('fast');
});
$('.scrolltop').click(function(){
$('#order').fadeOut('fast');
$('html, body').animate({
scrollTop: $(".header").offset().top
}, 2000);
$('.scrolltop').fadeOut('fast');
});
$('#svl').click(function()
{
$('html, body').animate({
scrollTop: $(".service_locations").offset().top
}, 2000);
});
$('.more1').click(function() {
$('.more_dry_cleaning').slideToggle('fast');
$('.more1').fadeOut('fast');
});
$('.less1').click(function() {
$('.more_dry_cleaning').fadeOut('fast');
$('.more1').fadeIn('fast');
});
var valid=0;
$('form[name=orderform]').submit(function(e) {
// alert('Got you!');
$('.clothesqty').each(function(){
// alert('Got you!');
if($(this).val() != 0) {valid+=1;}
});
if(valid!=0){
// e.preventDefault();
// alert(valid + " inputs have been filled");
return true;
}
else {
e.preventDefault();
//alert('Houston we have contact!');
alert("error: you must fill in at least one field");
return false;
}
});
var oblen=Object.keys(item).length;
var zero=0;
var cloth = "";
var i;
var it=1;
var totitems=0;
var tot=0;
var totcost=0;
var itemid="";
var itemclass="";
var totval=0;
for (var key in item) {
if (!item.hasOwnProperty(key)) {
//The current property is not a direct property of p
continue;
}
var k=key;
var v=item[key];
// alert(v);
cloth = k.replace(/ |-|&|\//g, '').toLowerCase();
itemid="#" + cloth;
itemclass="#" + cloth + "cost";
// alert(v+"/"+itemid);
$(itemid).keyup((function (id, cls,itm,val) {
return function () {
var x = $(id).val();
if(x!=0){
itemtot=x * val;
// alert(itm+"->"+itemtot + "=" + x + "x" + val);
$(cls).css("background-color", "#446666").css("padding","3px").css("color","white").css("width","60px").html("Rs." + itemtot);
}else{
$(cls).css("background-color", "#446666").css("padding","3px").css("color","white").css("width","60px").html("Rs." + zero);
}
}
} (itemid, itemclass,cloth,v)));
}
$("input").each(function() {
$(this).keyup(function(){
// calculateCost();
calculateSum();
});
});
});
//Totals
function calculateSum() {
var sum = 0;
var totcost=0;
//iterate through each textboxes and add the values
$("input").each(function() {
//add only if the value is number
if(!isNaN(this.value) && this.value.length!=0 && this.value.length<=3) {
sum += eval(parseInt(this.value));
}
});
$("div.ittot").each(function() {
var tots=0;
var str=$(this).text();
var thenum = str.replace( /^\D+/g, '');
var tots = parseInt(thenum,10);
//add only if the value is number
//if(!isNaN(tots) && tots.length!=0) {
totcost += tots;
//}
});
// alert(totcost);
$("#totalcost").css("background-color", "green").html("<div style='float:left;margin-left:5px'><span style='font-weight:700'>Total Cost : </span>Rs."+ totcost + "</div><div style='float:right;margin-right:5px'><span style='font-weight:700'>Total Items : </span>" + sum + "</div><div style='clear:both'></div>");
}
//slider2
var myPicIndex = 0;
picCarousel();
function picCarousel() {
var i;
var x = getElementsByClassName("myPicSlides");
for (i = 0; i < x.length; i++) {
x[i].style.display = "none";
}
myPicIndex++;
if (myPicIndex > x.length) {myPicIndex = 1}
x[myPicIndex-1].style.display = "block";
setTimeout(picCarousel, 3000); // Change image every 2 seconds
}
function getElementsByClassName(className) {
var found = [];
var elements = document.getElementsByTagName("*");
for (var i = 0; i < elements.length; i++) {
var names = elements[i].className.split(' ');
for (var j = 0; j < names.length; j++) {
if (names[j] == className) found.push(elements[i]);
}
}
return found;
}
//slider1
var myIndex = 0;
carousel();
function carousel() {
var i;
var x = getElementsByClassName("mySlides");
for (i = 0; i < x.length; i++) {
x[i].style.display = "none";
}
myIndex++;
if (myIndex > x.length) {myIndex = 1}
x[myIndex-1].style.display = "block";
setTimeout(carousel, 3000); // Change image every 2 seconds
}
function getElementsByClassName(className) {
var found = [];
var elements = document.getElementsByTagName("*");
for (var i = 0; i < elements.length; i++) {
var names = elements[i].className.split(' ');
for (var j = 0; j < names.length; j++) {
if (names[j] == className) found.push(elements[i]);
}
}
return found;
}
EDIT 2
I have further narrowed down the problem to the slider2 JS functions which seem to be a problem. Because if I remove the slider html which i have put in a slider2.php file and am including into the tariff.php file, then the scroll behaves properly.
slider2.php
<div style="width:100%;margin:0 auto">
<img class="myPicSlides" src="images/header/clothes-drying-on-line-iv.jpg" alt="Laundry Clothes Drying">
<img class="myPicSlides" src="images/header/new/shirts-on-line-iv.jpg" alt="Laundry Foam">
<img class="myPicSlides" src="images/header/iron-and-clothes-iv.jpg" alt="Iron Clothes">
<img class="myPicSlides" src="images/header/woollens-iv.jpg" alt="Woollens Laundry">
<img class="myPicSlides" src="images/header/shirts-on-hanger-iv.jpg" alt="Laundry Shirts mylaundrywala">
</div>
EDIT 3
I believe the animate function is taking into consideration the heights of the images in the slider and adding them up ! How to resolve that ?

If you want to reach to the top of window, please use this:
$("html, body").animate({
scrollTop: 0
}, 500);
$('.tariff').offset().top gives position distance between top of body and top of div with class "tariff".
As a result, it covers that much distance when scrolled.
Please try like this.

Use this code.
$(document).ready(function () {
$('html, body').animate({
scrollTop: $('.tariff').offset().top + $('.tariff').height()
}, 'slow');
});

Check the fiddle its is working for me there. Let me know if this helps.
$("#scroll").click(function(e) {
$('html, body').animate({
scrollTop: $('.tariff').offset().top
}, 'slow');
});
Fiddle

Since I realized that it was the heights of the images in the slider which was being laid out one below the other by html rather than fading in and out one by one when javascript is called (which has a fractional delay), the animate function registers the page height including all the heights of the images ! And scrolls keeping those heights in consideration. That is why it was scrolling right down to the bottom. Instead of top of the div.
Though I was not able to find a js solution to the real problem, I managed to find a work around.
Finally, what I did was to delay the slider images loading by using 'load' function. And placed one static image there till slider loaded and then faded the static image out after slider images loaded.
During this period, the animate function picks up only the height of that one static image which is actually the height that div should have after all images have loaded.
Now the animate scroll function is scrolling to the top of the relevant div.
Thanks all for your efforts to help

Vanilla way
var el = document.getElementById('myelement');
el.scrollTop = el.scrollHeight;

Related

How to scroll from section to section on one mwheeldown

I have been making a navigation menu for a small project I'm making but because of my lack of knowledge in codeing, I got stuck.
I have attached a link to the navigation code and I can't seem to make it scroll from section to section on one mwheeldown.
In simple words: I want to skip to the next section each time I scroll down.
https://codepen.io/tonyexe/pen/NVrjJp
$(".navigation-container-versia a[href^='#']").on('click', function(event) {
if (this.hash !== "") {
event.preventDefault();
var hash = this.hash;
$('html, body').animate({scrollTop: $(hash).offset().top}, 500);
}
});
function getTargetTop(elem){
var id = elem.attr("href");
var offset = 60;
return $(id).offset().top - offset;
}
$(window).on("load scroll", function(e){
isSelected($(window).scrollTop())
});
var sections = $(".navigation-container-versia a[href^='#']");
function isSelected(scrolledTo){
var threshold = 100;
var i;
for (i = 0; i < sections.length; i++) {
var section = $(sections[i]);
var target = getTargetTop(section);
if (scrolledTo > target - threshold && scrolledTo < target + threshold) {
sections.removeClass("active");
section.addClass("active");
}
};

How to do line preloader with jquery

I tried this code for a line preloader but it didn't work and i don't know where is the problem.
var $preload = $("<div class='preloader'><div class='percent'></div><div class='line-parent'><div class='line'></div></div></div>");
$("body").prepend($preload);
var $imgs = $("img");
var imgsLoaded = 0;
var ratio = 0;
$imgs.each(function(){
$this = $(this);
$this.load(function(){
imgsLoaded++;
ratio = imgsLoaded / $imgs.length;
$(".percent").html(ratio / 0.01 + "%");
$(".line").animate({
width : ratio / 0.01 + "%"
});
}, function(){
if(ratio === 1){
$(".preloader").fadeOut();
}
});
});
I belive you want to show 100% wenn all images are loaded and do some action. First load event will not work if is atteched after image is already loaded.
I sugest to check for each img comlete and naturalWidth property every 100ms (with setInterval).
Loader = (function() {
var list, img_length, loaded, interval;
function _check_one(i) { o = list[i]; if (o.complete == true && o.naturalWidth > 0) { loaded++; delete list[i]; } };
function _procent(l, a) { console.log((100*loaded/img_length) + '%'); }
function _check_list() { for(var i in list) {_check_one(i)};_procent();_kill(); };
function _kill() { if(img_length <= loaded) clearInterval(interval); }
function _start() { loaded = 0; list = $('img'); img_length = list.length;
if(img_length != loaded) interval = setInterval(_check_list, 100); }
return { start: _start }
})();
Now at end of the body or in $(document).ready(..) you need to call Loader.start();
Or put all images source (src) in data-src attribite, attach load events and copy data-scr to src attribite. In body all relevant images looks like this:
<img data-src="some url">...
In Script Tag:
$('img').on('load', function() {
// Your action.
}).each(function() { var img = $(this); img.attr('src', img.attr('data-src')); });

Pass arrays in function

I created a function but then realised I had to call it three times with two different parameters so I decided to create two different arrays and modify the function so it is called once. After modifiying the function it doesn't work so I am not sure what is happening. Here it is:
function scrll(selector,speed){
for (var i = 0; i < selector.length; i++){
var findIt = '.find("a")';
var selected = selector[i];
selected += findIt;
selected.click(function(e) {
e.preventDefault();
var section = $(this).attr("href");
$("html, body").animate({
scrollTop: $(section).offset().top - 54
},speed[i]);
});
};
};
var selector = ['$(".navbar")','$(".click")','$("#foot")'];
var speed = [2000,1000,2000];
scrll(selector,speed);
Here is a jsfiddle example: http://jsfiddle.net/theMugician/31fws6kd/16/
You seem to be under the impression that you can combine some strings together and the result will be what you would have gotten by executing the contents of that string.
JavaScript doesn't work like that.
This is how you can use selectors like you were trying to do.
function scrll(selectors, speed) {
for (var i = 0; i < selectors.length; i++) {
var selected = $(selectors[i]);
var link = selected.find("a");
link.click(function(e) {
e.preventDefault();
var section = $(this).attr("href");
$("html, body").animate({
scrollTop: $(section).offset().top - 54
}, speed[i]);
});
}
}
var selectors = [".navbar", ".click", "#foot"];
var speed = [2000, 1000, 2000];
scrll(selectors, speed);
There's still a bug here, because i is a closure variable and by the time the events run, it will have the value 3 and everything will be broken. An easy way to fix this is to use forEach():
function scrll(selectors, speed) {
selectors.forEach(function (selector, i) {
var selected = $(selector);
var link = selected.find("a");
link.click(function(e) {
e.preventDefault();
var section = $(this).attr("href");
$("html, body").animate({
scrollTop: $(section).offset().top - 54
}, speed[i]);
});
});
}

get interval ID from else statement when set in IF

I am attempting to create a responsive slider, that will change to a simple set of dot points when in mobile mode (< 940).
The issue I am facing is in my else statement I am unable to clearintervals that were made in the if statement, because t comes up as undefined. I have resorted to using
for (var i = 1; i < 99999; i++) window.clearInterval(i); to clear the interval which works, but I don't like it because it's ugly and cumbersome, is there another way of accomplishing this?
$(document).ready(function() {
function rePosition() {
//get responsive width
var container_width = $('.container').width();
//Slider for desktops only
if(container_width >= 940) {
//get variables
var slide_width = $('.slider_container').width();
var number_of_slides = $('.slider_container .slide').length;
var slider_width = slide_width*number_of_slides;
//set element dimensions
$('.slide').width(slide_width);
$('.slider').width(slider_width);
var n = 1;
var t = 0;
$('.slider_container').hover(function() {
clearInterval(t);
}, function() {
t = setInterval(sliderLoop,6000);
});
var marginSize = i = 1;
//Called in Doc Load
function sliderLoop(trans_speed) {
if (trans_speed) {
var trans_speed = trans_speed;
}
else
{
var trans_speed = 3000;
}
if (i < number_of_slides) {
marginSize = -(slide_width * i++);
}
else
{
marginSize = i = 1;
}
$('.slider').animate({ marginLeft: marginSize }, trans_speed);
}
t = setInterval(sliderLoop,6000);
$('.items li').hover(function() {
$('.slider').stop();
clearInterval(t);
var item_numb = $(this).index();
i = item_numb;
sliderLoop(500);
}, function() {
t = setInterval(sliderLoop,6000);
});
}
else
{
for (var i = 1; i < 99999; i++)
window.clearInterval(i);
$('.slider').stop(true, true);
$('.slider').css('margin-left', '0px');
//rearrange content
if($('.slider .slide .slide_title').length < 1) {
$('.items ul li').each(function() {
var item_numb = $(this).index();
var content = $(this).text();
$('.slider .slide:eq(' + item_numb + ')').prepend('<div class="title slide_title">' + content + '</div>')
});
}
}
}
rePosition();
$(window).resize(function() {
rePosition();
});
});
Teemu's comment is correct. I'll expand on it. Make an array available to all of the relevant code (just remember that globals are bad).
$(document).ready(function() {
var myIntervalArray = [];
Now, whenever you create an interval you will need to reference later, do this:
var t = setInterval();//etc
myIntervalArray.push(t); //or just put the interval directly in.
Then to clear them, just loop the array and clear each interval.
for (var i=0; i<myIntervalArray.length; i++)
clearInterval(myIntervalArray[i]);
}
Umm, wouldn't t only be defined when the if part ran... as far as I can tell, this is going to run and be done... the scope will be destroyed. If you need to maintain the scope across calls, you'll need to move your var statements outside of reposition(), like so:
$(document).ready(function() {
var t = 0;
...
function rePosition() { ... }
});

Stop .animate() on last image

I'm trying to make a gallery of images to scroll using up/down buttons. So far I go the animation but now I need to make it stop on the first and last image.
This is what I got so far, jsfiddle.net/sJDMq/47 (don't mind the buttons, I still need to work on them but they are there, top and bottom red boxes)
Thanks!
$(document).ready(function() {
$(".down_button").click(function () {
$(".scroll-products").animate({marginTop: '-=700px'}, 300);
});
$(".up_button").click(function () {
$(".scroll-products").animate({ marginTop: '+=700px' }, 300);
});
});
I wouldn't have done it this way but just going with what you started with I would just let this JS do the trick:
$(document).ready(function(){
var curIndex = 0;
var height = 700;
var maxHeight = 0;
var allImages = document.getElementsByClassName("sidebar_images");
for(var i=0; i<allImages.length; i++) {
maxHeight += allImages[i].offsetHeight;
}
var maxIndex = Math.ceil(maxHeight/height);
$(".down_button").click(function () {
if(curIndex < maxIndex) {
$(".scroll-products").animate({marginTop: '-='+height+'px'}, 300);
curIndex++;
}
});
$(".up_button").click(function () {
if(curIndex > 0){
$(".scroll-products").animate({ marginTop: '+='+height+'px' }, 300);
curIndex--;
}
});
});
I just updated your fiddle here.

Categories

Resources