Pass arrays in function - javascript

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]);
});
});
}

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");
}
};

js animate function scrolls to bottom of div instead of top

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;

setTimeout function is not working

The problem is that it keeps scrolling endlessly with no end i tried to terminate it using exit but it's not working, any solution ?
Learn More
<script>
var marginY = 0;
var destination= 0;
var speed = 10;
var scroller = null;
function initScroll(elementId)
{
destination= document.getElementById(elementId).offsettop;
scroller = setTimeout(function(){initScroll(elementId);},1);
marginY = marginY + speed;
if(marginY >= destination)
{
clearTimeout(scroller);
}
window.scroll(0,marginY);
}
</script>
JavaScript is CaSe SeNsItIvE! It is offsetTop and not offsettop:
destination = document.getElementById(elementId).offsetTop;
On a different note, I am not sure how that does work. If you are trying a smooth scroll, you can also use jQuery by:
$(document).ready(function(){
$('a[href^="#"]').on('click',function (e) {
e.preventDefault();
var target = this.hash;
var $target = $(target);
$('html, body').stop().animate({
'scrollTop': $target.offset().top
}, 900, 'swing', function () {
window.location.hash = target;
});
});
});

jQuery animation for each element

I do not have much experience in animation on Jquery. I want to make a simple animation that will highlight my text line by line with the possibility of stopping. I know how to do something like this for one line but I have no idea how to deal with loop.
here is my code:
var lines = $('#page')[0].getClientRects();
for (var i=0, max = lines.length; i < max; i++)
{
$('#under_liner')
.queue(function() {
$(this).css('top', lines[i].bottom).dequeue();
})
.animate({
width: lines[i].right - lines[i].left
}, 1000 )
.queue(function() {
$(this).css('width', 0).dequeue();
});
}
and jsfiddle http://jsfiddle.net/mz03kfua/2
I don't know if this is exactly what you are looking for, but here's how I'd do it.
Make a function that does the underlining
Make a recursive call on animation callback
Create a global variable to keep count of the current underlined line
Add a boolean that stops the function when false
var lines = $('#page')[0].getClientRects();
var play = true;
var index = 0;
underlineLine();
$('button').click(function(){
play = !play
if(play){
underlineLine()
$(this).html("STOP")
}else{
$(this).html("CONTINUE")
}
})
function underlineLine(){
if(index >= lines.length) return
if(play){
$('#under_liner').css('top', lines[index].bottom).dequeue();
$('#under_liner').css('width','0px');
$('#under_liner').animate({
width: lines[index].right - lines[index].left
}, 1000, function(){
underlineLine(index++)
})
$('#under_liner').css('width', 0).dequeue();
}
}
HERE IS A FIDDLE WITH THE CODE.
Hope it helps.
http://jsfiddle.net/mz03kfua/4/
var lines = $('#page')[0].getClientRects();
var current = 0;
var element;
function animateLine() {
if(typeof lines[current] !== "object") {
return;
}
var line = lines[current];
element = jQuery("<div />", {"class": "under_liner"}).prependTo("#page");
element.css({top: line.bottom}).animate({width: line.width}, 1000, function() {
current++;
animateLine();
});
}
function stopLine(e) {
e.preventDefault();
element.stop(true);
}
jQuery(".stop").click(stopLine);
animateLine();

$.each animation running separately

I'm trying to run each animation function one after the other instead of all at once.
This is what I've got so far:
$(document).ready(function(){
var bars = $('.bar');
bars.each(function(){
var widthpercent = $(this).attr("data-percent");
$(this).fadeIn();
$(this).animate({width:widthpercent},500);
});
});
I've tried using .delay() and setTimeout() in various combinations to no avail.
Could anyone point me in the right direction? Thank you!
It sounds to me like you're looking for animate's complete function. You can write a recursive function to keep calling the function in the complete function until all the items have been animated. To simplify: every time one element is animated, a callback is fired that animates the next element. That is the purpose of the complete parameter, so I'm certain that is what you're looking for.
Here's an example you can adapt to your specific needs.
Live demo here (click).
var $divs = $('div');
function animate(element) {
$(element).animate({height: '30px'}, {
complete: function() {
if (current < $divs.length-1) {
++current;
animate($divs[current]);
}
}
});
}
var current = 0;
animate($divs[current]);
Further, this same logic can be applied to your fadeIn. Just wrap fadeIn's callback around that logic, like this:
Live demo here (click).
var $divs = $('div');
function animate(element) {
$(element).fadeIn(function() { //now the animation is a callback to the fadeIn
$(element).animate({height: '70px'}, {
complete: function() {
if (current < $divs.length-1) {
++current;
animate($divs[current]);
}
}
});
});
}
var current = 0;
animate($divs[current]);
And here's your code: live demo here (click).
$(document).ready(function(){
var $divs = $('.bar');
function animate(element) {
$(element).fadeIn(function() { //you could unwrap this depending on what you're looking for
var widthpercent = $(element).attr("data-percent");
$(element).animate({
width:widthpercent,
duration: '500ms'
}, {
complete: function() {
if (current < $divs.length-1) {
++current;
animate($divs[current]);
}
}
});
}); //end fadeIn callback
}
var current = 0;
animate($divs[current]);
});
Try this:
var animate = function (el) {
return function () {
var widthpercent = el.data('percent');
el.fadeIn();
el.animate({
width: widthpercent
}, 500);
}
}
var bars = $('.bar');
bars.each(function (index) {
var $this = $(this);
setTimeout(animate($this), index * 500);
});
Fiddle
$(document).ready(function(){
var bars = $('.bar');
bars.each(function(i){
var widthpercent = $(this).attr("data-percent");
$(this).delay(i*800).animate({width:widthpercent,opacity:1,},500);
});
});
This will animate after delaying 800 * i milliseconds.
See this JSFiddle example.

Categories

Resources