HTML using onclick input to run javascript code - javascript

I am currently trying to implement a menu with many clickable buttons - appetizers, soups, etc. By using parameters, I can send the type of food to my JavaScript.
These are the buttons.
http://puu.sh/kugEs/5048221343.jpg
This is the code when I click on appetizers.
function scroll(type) {
var test = "('#" + type + "')";
alert(test); //('#appetizers')
$("html, body").animate({ scrollTop: $test.offset().top-150 }, 600); //this doesnt work
$("html, body").animate({ scrollTop: $('#appetizers').offset().top-150 }, 600); //this works
}
Of course I want to make it so that I don't have to manually use the working line. I want to use the one that doesn't work that it can be applied to all buttons running the same function with only different parameters.
How can I use the var test in order to run the line that doesn't work?

You should use $ and take care about your quotes::
var $test = $('#' + type); // Now it's a jQuery Object
In your example:
function scroll(type) {
var $test = $('#' + type);
$("html, body").animate({ scrollTop: $test.offset().top-150 }, 600);
}

You should define $test as an object, instead of a string.
function scroll(type) {
var test = $('#' + type);
alert($test.attr("id")); // appetizers
$("html, body").animate({ scrollTop: $test.offset().top-150 }, 600);
}

Try it with this code. It should work.
function scroll(type) {
var test = "('#" + type + "')";
alert(test); //('#appetizers')
$("html, body").animate({ scrollTop: $('#'+type).offset().top-150 }, 600);
}

Related

JQuery to vanilla JavaScript translation not working

I have the following code in jQuery:
$('body').on('click', '#gtco-offcanvas ul a:not([class="external"]), .main-nav a:not([class="external"])', function (event) {
var section = $(this).data('nav-section');
if ($('[data-section="' + section + '"]').length) {
$('html, body').animate({
scrollTop: $('[data-section="' + section + '"]').offset().top - 55
}, 500, 'easeInOutExpo');
}
and I need to rewrite it in pure vanilla JS. I have tried to do this, but I just got a lot of errors and don't know how to correct them...
This is my version of the code:
document.body.addEventListener('click', function (e) {
if (e.target.closest('body #gtco-offcanvas ul a:not([class="external"]), .main-nav a:not([class="external"])')) {
var section = document.querySelector('data').dataset('nav-section');
if (document.querySelectorAll('[data-section="' + section + '"]').length) {
document.querySelectorAll('html, body').animate({
scrollTop: document.querySelectorAll('[data-section="' + section + '"]').offset().top - 55
}, 500, 'easeInOutExpo');
}
};
And the output is:
Uncaught TypeError: Cannot read property 'dataset' of null
If I try to let this line in jQuery to test that the rest part of the code is working, I get no errors, but it doesn't do anything also...
Assuming your html element has the data attribute data-nav-section="" what you are looking for would be:
var section = e.target.dataset.navSection;
e.target would be the equivilant of $(this) and dataset is not a function but a property having to use a camelcase naming convention when using dashes in the attribute name
You can use the matches method without the closest to test if the receiving element is the one delegated:
if (e.target.matches('#gtco-offcanvas ul a:not([class="external"]), .main-nav a:not([class="external"])')) {
var section = e.target.dataset['navSection'];
// ...
}

Javascript array click

I'm trying to avoid having the same lines of Javascript for the same purpose.
I have 3 sections:
<div class="specs"></div>
<div class="description"></div>
<div class="comments"></div>
And these 3 links:
Produkt beskrivelse
Produkt specs
</i>Kommentarer
And this javascript which, on click scrolls to the section
$(".facebook").on('click', function () {
$('html, body').animate({
scrollTop: $(".comments").offset().top - 200
}, 1000);
});
$(".readMore.desc").on('click', function () {
$('html, body').animate({
scrollTop: $(".description").offset().top - 200
}, 1000);
});
$(".readMore.spec").on('click', function () {
$('html, body').animate({
scrollTop: $(".specs").offset().top - 200
}, 1000);
});
These 3 pieces of javascript code is annoying because it does the exact same thing.
A live example can be seen here a live example. You'll see the 3 buttons on the right of the product image.
I don't know if a solution could be to add an array of some sort?
One way of handling this is giving each link a data- property that describes where the link should scroll to. You can use .data() to access these properties.
$(".readMore").on('click', function() {
// Get the selector of where to scroll to
var selector = $(this).data('selector');
$('html, body').animate({
scrollTop: $(selector).offset().top - 200
}, 1000);
});
html, body {
height: 100%;
}
div {
height: 100%;
margin-top: 20px;
border: solid 1px #000;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Produkt beskrivelse
Produkt specs
Kommentarer
<div class="specs">
Specs
</div>
<div class="description">
Description
</div>
<div class="comments">
Comments
</div>
Common classes (which you have) and data attributes will save you here.
Produkt beskrivelse
Produkt specs
</i>Kommentarer
And now, one handler to rule them all:
$(".readMore").on('click', function () {
var dest = $(this).data("dest");
$('html, body').animate({
scrollTop: $(dest).offset().top - 200
}, 1000);
});
//extraced the common parts
function scrollToTop ( elementSelector ) {
$('html, body').animate({
scrollTop: $(elementSelector).offset().top - 200
}, 1000);
}
$(".facebook").on('click', function () {
scrollToTop('.comments');
});
$(".readMore.desc").on('click', function () {
scrollToTop('.description');
});
$(".readMore.spec").on('click', function () {
scrollToTop('.specs');
});
Use a helper function instead of copy-pasting your code
function foo(target, element) {
target.on('click', function () {
$('html, body').animate({
scrollTop: element.offset().top - 200
}, 1000);
});
}
foo($(".facebook"), $(".comments"));
foo($(".readMore.desc"), $(".description"));
foo($(".readMore.spec"), $(".specs"));
Probably better you just read the class on the object, split it to get the value you want. As such:
$('.readMore').on('click', function() {
var classes = $(this).attr('class');
var cursor = class.split(' ')[1];
if(cursor == 'facebook') {
...
}else if(cursor == 'desc') {
...
} else if(cursor == 'spec') {
...
}
});
First you'll need to map which dom is effecting which. you could have solved this by using some kind of class name convention. I'll assume you can't decide on the class names. So let's create a map/object/hash
var map = {
spec: "specs",
desc: "description",
facebook: "comments,
}
Now let's just iterate the map and add the functionality
Object.keys(map).forEach(function(key) {
var value = map[key];
$(".readMore." + key).on('click', function () {
$('html, body').animate({
scrollTop: $("." + value).offset().top - 200
}, 1000);
});
})
And now you are a happy coder.
If you've learned closures, I prefer those to make re-usable events more readable...
I have a jsFiddle for this here
// use a closure to make your event's callback,
// with the target as a parameter
function makeClickFn(target) {
return function() {
$('html, body').animate({
scrollTop: $(target).offset().top - 200
}, 1000);
};
}
var clickFn;
// facebook comments
clickFn = makeClickFn('.comments');
$(".facebook").on('click', clickFn);
// readmore description
clickFn = makeClickFn('.description');
$(".readMore.desc").on('click', clickFn);
// readmore specs
clickFn = makeClickFn('.specs');
$(".readMore.spec").on('click', clickFn);

How to turn these 3 scripts into 1?

I have a script that does similar things for different id's and i'm pretty much certain this can be done in 1 script rather than 3, any suggestions are welcome.
$("#size-btn-one").click(function() {
$('html,body').animate({
scrollTop: $(".scroll-one").offset().top -100}, 2000);
});
});
$("#size-btn-two").click(function() {
$('html,body').animate({
scrollTop: $(".scroll-two").offset().top -100}, 2000);
});
});
$("#size-btn-three").click(function() {
$('html,body').animate({
scrollTop: $(".scroll-three").top -100}, 2000);
});
});
Combine the selector, you can make an and select by comma separation, like you did with html, body too. And you can extract the name from the element id by different ways, e.g with a simple replace.
$("#size-btn-one, #size-btn-two, #size-btn-three").click(function() {
// getting only the last part of the elements id
var id = $(this).attr("id").replace("size-btn-", "");
$("html, body").animate({
// append the 'id' to the selector class
scrollTop: $(".scroll-" + id).offset().top -100}, 2000);
});
});
$("#size-btn-one, #size-btn-two, #size-btn-three").click(function(){
var id = $(this).attr("id");
var number = id.substring(id.lastIndexOf("-"));
$('html,body').animate({
scrollTop: $(".scroll-"+ number).offset().top -100}, 2000);
});
});
As an alternative, I'd pair up the btn and the scroll- using data- attributes and not use id= for this.
<a href='#' data-link='1'>one</a>
<a href='#' data-link='2'>one</a>
<a href='#' data-link='xyz'>one</a>
<div data-link='1'>content 1</div>
<div data-link='2'>content 2</div>
<div data-link='xyz'>content 3</div>
This also means you can use semantic definitions, rather than just numbers (though you could with IDs as well ofc).
Then:
$("a[data-link]").click(function() {
var link = $(this).data("link");
var div = $("div[data-link=" + link + "]");
$('html,body').animate({
scrollTop: div.offset().top - 100}, 2000);
});
});
Normally, you'd also add a class, but left off to show the concept of pairing via data attributes.
$("#size-btn-one, #size-btn-two, #size-btn-three").on("click",function(){
var idLastPart = $(this).attr('id');
idLastPart = idLastPart.match(/one|two|three/)[0];
$('.scroll-'+idLastPart).animate({
//your animation
},300);
});

Use jQuery attr to scroll to data?

I was wondering how I would use this method:
$('[data-jump-spy]').each(function(){
var dataObj = .data('jump-spy');
$(this).onclick ({
scrollTop: $("#" + dataObj ).offset().top();
});
});
to attach it to a link like so:
Who we are
....
....
....
....
<div class="box radius box-grey --animate" id="divContentThatsFarDownPage">
....
</div>
Final Solution can be found below
This function will allow you to code your website more easily. Simply type <div class="whatever iconArrow-to-Content LinkText-to-Content Img-to-Content" data-jump-spy="page-content"
$('[data-jump-spy]').each(function(){
var dataObj = $(this).data('jump-spy');
$(this).click(function() {
$("html, body").animate({
scrollTop: $("#" + dataObj ).offset().top
}, 1000);
});
});
A couple of changes
$('[data-jump-spy]').each(function(){
var dataObj = $(this).data('jump-spy'); // needs $(this) at beginning since .data needs to run on some object
$(this).click(function(){ // used click instead of onclick and you need to pass a function as an argument
$('html,body').animate({scrollTop: $("#" + dataObj ).offset().top}); // use .top instead of .top() as it is a property and not a method
});
});

waypoint js click to next div

Working on a function with waypoint.js that takes the current div in the viewport and finds the next div when clicking a button.
Currently I’m getting a undefined value for the ‘next’. Not sure what could be wrong I guess the value can’t move from the waypoint function to the click function. Any help would be lovely.
$('.wrap').waypoint(function() {
var next = $(this).next();
$(".button").click(function() {
$("html, body").animate({ scrollTop: next.offset().top }, 1000);
});
});
i suggest you to chain it instead of doing this in the callback:
$('.wrap').waypoint().addBack(this).find(".button").click(function() {
var next = $(this).closest('.wrap').next();
$("html, body").animate({ scrollTop: next.offset().top }, 1000);
});
or could be something like this:
$('.wrap').waypoint().done(function(){
$(this).find(".button").click(function() {
var next = $(this).closest('.wrap').next();
$("html, body").animate({ scrollTop: next.offset().top }, 1000);
});
});

Categories

Resources