How to simplify jQuery code.
If I have 1 page with several different blocks.
I need to duplicate this code multiple times to use different elements?
How to write 1 code for multiple blocks ?
$('.go_to').click( function(){
var scroll_el = $(this).attr('href');
if ($(scroll_el).length != 0) {
$('html, body').animate({ scrollTop: $(scroll_el).offset().top }, 500);
}
return false;
});
<a class="go_to" href="#elm">button</a> или <a class="go_to" href=".elm">block-scroll</a>
$('.go_to-1').click( function(){
var scroll_el = $(this).attr('href');
if ($(scroll_el).length != 0) {
$('html, body').animate({ scrollTop: $(scroll_el).offset().top }, 500);
}
return false;
});
<a class="go_to-1" href="#elm">button</a> или <a class="go_to-1" href=".elm">block-scroll</a>
$('.go_to-2').click( function(){
var scroll_el = $(this).attr('href');
if ($(scroll_el).length != 0) {
$('html, body').animate({ scrollTop: $(scroll_el).offset().top }, 500);
}
return false;
});
<a class="go_to-2" href="#elm">button</a> или <a class="go_to-2" href=".elm">block-scroll</a>
Given your example, the simplest way is to select multiple elements with jquery using a comma separated list, and define the click handler all of them at once:
$('.go_to, .go_to-1, .go_to-2').click( function(){
//on click code
});
I am assuming you need different classes for the anchors, but if not, you could just give them all the same class (for example class="go_to") and use
$('.go_to').click( function(){
//on click code
});
Related
I have an application with a landing page that has many sections, and use Scrollspy for the smooth scrolling effect in the page. At the end of my navigation items I have a call to action button that takes the user to another page. However, because it's in my navigation items, when the page loads, Scrollspy is throwing an error on the link to another page.
Uncaught Error: Syntax error, unrecognized expression: https://example.com/page2
Is there anything I can do to tell scrollspy to ignore that link or is there some other way to get rid of that error? Thanks!
Here is the code I am using to initialize scrollspy:
(function ($) {
'use strict';
// SmoothLink
function initSmoothLink() {
$('.nav-item a').on('click', function(event) {
var $anchor = $(this);
$('html, body').stop().animate({
scrollTop: $($anchor.attr('href')).offset().top - 0
}, 1500, 'easeInOutExpo');
event.preventDefault();
});
}
// StickyMenu
function initStickyMenu() {
$(window).on('scroll',function() {
var scroll = $(window).scrollTop();
if (scroll >= 50) {
$(".sticky").addClass("stickyadd");
} else {
$(".sticky").removeClass("stickyadd");
}
});
}
// Scrollspy
function initScrollspy() {
$("#navbarCollapse").scrollspy({
offset: 70
});
}
//MFPVideo
function initMFPVideo() {
$('.video_play').magnificPopup({
disableOn: 700,
type: 'iframe',
mainClass: 'mfp-fade',
removalDelay: 160,
preloader: false,
fixedContentPos: false
});
}
// Back To Top
function initBackToTop() {
$(window).on('scroll',function(){
if ($(this).scrollTop() > 100) {
$('.back_top').fadeIn();
} else {
$('.back_top').fadeOut();
}
});
$('.back_top, .footer_logo_link').on('click',function(){
$("html, body").animate({ scrollTop: 0 }, 1000);
return false;
});
}
function init() {
initSmoothLink();
initStickyMenu();
initScrollspy();
initMFPVideo();
initBackToTop();
}
$(document).on('turbolinks:load', function(){
init();
});
})(jQuery);
You can add in if statement to check if the href has a hash. If it doesn't have one, then it will just proceed as normal.
function initSmoothLink() {
$('.nav-item a').on('click', function(event) {
var $anchor = $(this);
if (this.hash !== "") {
$('html, body').stop().animate({
scrollTop: $($anchor.attr('href')).offset().top - 0
}, 1500, 'easeInOutExpo');
event.preventDefault();
}
});
}
Scrollspy looks for all a tags in given container, takes href attribute and uses it's value as jQuery selector. Here is the possible solution using JS:
Page 2
Setting href and id is required in your case if you don't want to add additional checks in initSmoothLink() function.
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);
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);
});
I have the following jquery function which shows / hides content depending on the div that is selected...
jQuery(document).ready(function() {
jQuery('.showSingle').on('click', function () {
jQuery(this).addClass('selected').siblings().removeClass('selected');
jQuery('.targetDiv').hide();
var selector = '#div' + jQuery(this).data('target');
jQuery(selector).show();
location.hash = selector;
});
});
http://jsfiddle.net/W4Km8/7944/
I also have the following script taken from http://1stwebmagazine.com/jquery-scroll-to-anchor-point
$(document).ready(function(){
$('a[href^="#"]').bind('click.smoothscroll',function (e) {
e.preventDefault();
var target = this.hash,
$target = $(target);
$('html, body').stop().animate({
'scrollTop': $target.offset().top-40
}, 900, 'swing', function () {
window.location.hash = target;
});
});
});
I am trying to combine the 2 so that instead of jumping to the anchor it scrolls to it. Do I need to combine them or can they be made to work separate?
Looks like you can combine them easily enough, I've made it work with this jsfiddle: http://jsfiddle.net/9soxbhpj/
var target = jQuery(selector);
target.show()
$('html, body').stop().animate({
'scrollTop': target.offset().top-40
}, 900, 'swing', function () {
window.location.hash = selector;
});
You can add the scroll action in the same click call.
See the js:
jQuery(document).ready(function() {
jQuery('.showSingle').on('click', function () {
var _el = jQuery(this),
_target = jQuery('#div' + _el.data('target')),
_targetDiv = jQuery('.targetDiv');
_el.addClass('selected').siblings().removeClass('selected');
_targetDiv.hide();
_target.show();
// Scroll to object
$('html, body').animate({
scrollTop: _target.offset().top
}, 800);
});
});
Here is a working example.
$(function () {
$('#button').click(function () {
$('html, body').animate({
scrollTop: $(document).height()
},
400);
return false;
});
$('#top').click(function () {
$('html, body').animate({
scrollTop: '0px'
},
400);
return false;
});
});
I'm using that code to scroll to the bottom/top of the page. I'm wondering if there is a better way to write that? I'm new to jquery so I'm not sure but I've heard using event.preventDefault() may be better instead of return false? If so, where would I insert that?
How about just using a ternary to select the scroll? eg
$(function () {
$('#button').add('#top').click(function () {
$('html, body').animate({
scrollTop : ((this.id=='button') ? $(document).height() : '0px')
},
400);
return false;
});
});
JSFiddle for this code here
You could make this better by adding a class eg 'navButton' to each of these buttons and then using that as the selection ie $('.navButton') - This will eliminate the .add() call.
Also I'd recommend giving the bottom button the id bottom rather than button :) eg
$(function () {
$('.navButton').click(function () {
$('html, body').animate({
scrollTop : ((this.id=='bottom') ? $(document).height() : '0px')
},
400);
});
});
Sure:
$(function() {
var map = {'#button': $(document).height, '#top': '0px'};
jQuery.each(map, function(k, v) {
$(k).click(function() {
$(document.body).animate({
scrollTop:(typeof v === 'function') ? v() : v
},
400);
});
});
});
According to jQuery manual return false and preventDefault does different things:
Example: Cancel a default action and prevent it from bubbling up, return false:
$("a").live("click", function() { return false; })
Example: To cancel only the default action by using the preventDefault method.
$("a").live("click", function(event){
event.preventDefault();
});
So preventDefault is more limited.
Using a specialized plugin jquery.scrollTo.
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery-scrollTo/1.4.11/jquery.scrollTo.min.js"></script>
Makes code nice and easy
$(function() {
$('#button').click(function() {
$.scrollTo('max', 400);
return false;
});
$('#top').click(function() {
$.scrollTo(0, 400);
return false;
});
});
Demo: http://jsfiddle.net/disfated/mkZp3/
Also if you want a more flexible code, you could do something like
$(function() {
$(document).on('click', '[data-scroll]', function(e) {
e.preventDefault();
$.scrollTo($(this).data('scroll'), jQuery.fx.speeds._default);
});
});
Then, define scroll behaviour directly in html, example
<button data-scroll="max">scroll to page bottom</button>
<button data-scroll="0">scroll to page top</button>
<button data-scroll="#my_selector">scroll to #my_selector element</button>
Demo: http://jsfiddle.net/disfated/Sj8m7/