jQuery scrollTop if URL has hash - javascript

I have wrote this simple plugin which smooth scrolls the browser window and adds the hash link to the URL.
$.fn.extend({
scrollWindow: function(options) {
var defaults = { duration: "slow", easing : "swing" }
var options = $.extend(defaults, options);
return this.each(function() {
$(this).click(function(e) {
var target = $(this).attr('href');
$('html,body').animate({scrollTop: $(target).offset().top}, options.duration, options.easing, function() {
location.hash = target;
});
e.preventDefault();
});
});
}
});
How do I extend this plugin so that it auto scrolls down to the section of the page if it has a hash in the URL that exists in the DOM?
I half understand how this will work by using the window.location.hash, although I am unclear where is the best to add this inside of the plugin.

Store the function in a separate variable, and call the function if the hash is existent. I have implemented your request such that the current location.hash is used each time $().scrollWindow is invoked. Other implementations follow the same principle.
$.fn.extend({
scrollWindow: function(options) {
var defaults = { duration: "slow", easing : "swing" }
var options = $.extend(defaults, options);
var goToHash = function(target){
$('html,body').animate({scrollTop: $(target).offset().top}, options.duration, options.easing, function() {
location.hash = target;
});
};
if(location.hash.length > 1) goToHash(location.hash);
return this.each(function() {
$(this).click(function(e) {
//Remove junk before the hash if the hash exists:
var target = $(this).attr('href').replace('^([^#]+)#','#');
goToHash(target);
e.preventDefault();
});
});
}
});

Related

Item soft rejected due to Proper Event Binding issue

An item I've submitted to themeforest.net got soft rejected with the following message:
PROPER EVENT BINDING: Consider using the preferred .on() method rather than .click(), .bind(), .hover(), etc. For best performance and concise code use event delegation whenever possible
I have no idea what to do actually and would appreciate some help.
This is my code (it’s quite long sorry):
jQuery(document).ready(function($) {
"use strict";
// PRELOADER
$(window).load(function() {
$('#preloader').fadeOut('slow', function() {
$(this).remove();
});
});
// NAV BR RESIZING
$(document).on("scroll", function() {
if ($(document).scrollTop() > 50) {
$("header").removeClass("large").addClass("small");
} else {
$("header").removeClass("small").addClass("large");
}
});
// MOBILE MENU TRIGGER
$('.menu-item').addClass('menu-trigger');
$('.menu-trigger').click(function() {
$('#menu-trigger').toggleClass('clicked');
$('.container').toggleClass('push');
$('.pushmenu').toggleClass('open');
});
// SEARCH
$('.search').click(function(e) {
$(".search-overlay").addClass("visible");
e.preventDefault();
});
$('.close-search').click(function(e) {
$(".search-overlay").removeClass("visible");
e.preventDefault();
});
// FOUNDATION INITIALIZER
$(document).foundation();
// LIGHTCASE
$('a[data-rel^=lightcase]').lightcase({
showSequenceInfo: false,
});
// CONTDOWN
$('[data-countdown]').each(function() {
var $this = $(this),
finalDate = $(this).data('countdown');
$this.countdown(finalDate, function(event) {
$this.html(event.strftime('' +
'<span class="time">%D <span>days</span></span> ' +
'<span class="time">%H <span>hr</span></span> ' +
'<span class="time">%M <span>min</span></span> ' +
'<span class="time">%S <span>sec</span></span>'));
});
});
// SCROLLDOWN BUTTON
$(".show-scrolldown-btn").append("<div class='scrolldown-btn reveal-from-bottom'></div>")
$('.scrolldown-btn').on('click', function() {
var ele = $(this).closest("div");
// this will search within the section
$("html, body").animate({
scrollTop: $(ele).offset().top + 70
}, 500);
return false;
});
// ISOTOPE MASONRY
$(window).load(function() {
var $container = $('.grid');
$container.isotope({
itemSelector: '.grid-item',
columnWidth: '.grid-sizer',
});
var $optionSets = $('.filter'),
$optionLinks = $optionSets.find('a');
$optionLinks.click(function() {
var $this = $(this);
if ($this.hasClass('active')) {
return false;
}
var $optionSet = $this.parents('.filter');
$optionSet.find('.active').removeClass('active');
$this.addClass('active');
// make option object dynamically, i.e. { filter: '.my-filter-class' }
var options = {},
key = $optionSet.attr('data-option-key'),
value = $this.attr('data-option-value');
value = value === 'false' ? false : value;
options[key] = value;
if (key === 'layoutMode' && typeof changeLayoutMode === 'function') {
changeLayoutMode($this, options);
} else {
$container.isotope(options);
}
return false;
});
});
//BACK TO TOP
var offset = 300,
offset_opacity = 1200,
scroll_top_duration = 700,
$back_to_top = $('.backtotop');
$(window).scroll(function() {
($(this).scrollTop() > offset) ? $back_to_top.addClass('is-visible'): $back_to_top.removeClass('is-visible fade-out');
if ($(this).scrollTop() > offset_opacity) {
$back_to_top.addClass('fade-out');
}
});
$back_to_top.on('click', function(event) {
event.preventDefault();
$('body,html').animate({
scrollTop: 0,
}, scroll_top_duration);
});
});
So you would change event listener assignments like the following:
$('.search').click(function(e) {
$(".search-overlay").addClass("visible");
e.preventDefault();
});
...to use the corresponding on method instead, passing the event name as an argument:
$('.search').on("click", function(e) {
$(".search-overlay").addClass("visible");
e.preventDefault();
});
Event delegation is avoiding adding several event listeners to specific nodes and instead adding a single event listener to a common parent element, which then looks to see which child element was clicked on.
There's a good article here:
https://www.google.co.uk/amp/s/davidwalsh.name/event-delegate/amp

$(...).anchorAnimate is not a function (Javascript)

I have two problems on my website.
There is a menu, and if you click on a link then the browser scrolls to the point (id) of the link. A few days ago everything worked fine, but not now. I didn't work on the webpage, so I don't know where the problem is.
Here is my Code:
jQuery.fn.anchorAnimate = function(settings) {
settings = jQuery.extend({
speed : 1000
}, settings);
return this.each(function(){
var caller = this
$(caller).click(function (event) {
event.preventDefault()
var locationHref = window.location.href
var elementClick = $(caller).attr("href")
var destination = $(elementClick).offset().top - 135;
$("html:not(:animated),body:not(:animated)").animate({ scrollTop: destination}, settings.speed, function() {
//window.location.hash = elementClick
});
return false;
})
})
};
$(document).ready(function() {
$("li.anchorLink a").anchorAnimate();
});
Can you help me?
Make sure you load JQuery library first and then your jquery plugin. Basically it doesn't recognize your current file, because Jquery wasn't loaded / wasn't found.

Call the same instance of jQuery plugin

I have written a jQuery plugin below and would like to be able to call it again for the same instance on an element.
The plugin goes...
(function($) {
$.fn.myPlugin = function(options){
var settings = {
color: null
};
if (options) {
$.extend(settings, options);
}
return this.each(function(){
var self = this;
var pics = $('li', self);
function refresh() {
pics = $('li', self);
};
$('a', self).click(function(){
pics.filter(':last').remove();
alert(settings.color);
refresh();
return false;
});
});
}
})(jQuery);
In the page this is called...
$('#test').myPlugin({ color: 'blue' });
Now I want to call the same plugin for the same instance but pass the string refresh as the option whilst all the other variables are the same (so color would still be blue) e.g...
$('#test').myPlugin('refresh');
This would then execute the refresh() function.
How could I achieve that with the above?
Edit: To make it clearer I am thinking of how jQuery UI does their plugins. In the sortable plugin you can do $("#sortable").sortable(); and then $("#sortable").sortable('refresh'); on the same element. This is what I am trying to achieve.
You can store your instance with .data() and check for it when creating an instance.
Something like:
$.fn.doStuff = function () {
var ob = $(this);
var data = ob.data();
if (data.doStuff !== undefined) {
return data.doStuff;
}
doStuff;
});
(function($) {
$.fn.myPlugin = function(options){
var init = function($self, ops){
$self.find("a").click(function(){
pics.filter(':last').remove();
alert(settings.color);
refresh();
return false;
});
};
this.refresh = function(){
//your code here
};
return this.each(function(){
var self = this;
var pics = $('li', self);
var settings = {
color: null
};
var ops = $.extend(true, settings, options);
init($(this), ops);
});
}
})(jQuery);
try something like this. and you can call refresh() like $().myPlugin().refresh();

Click Function on jQuery plugin only allows for single click

I've created this simple plugin to add multiple animations on click but the problem is that once the object is clicked it can not repeat the animation by clicking again, i can't figure out why the added class is not removing itself after the click function is complete to allow it to be clicked again and repeat.. any suggestions?
(function($) {
$.fn.vivify = function(options) {
var defaults = {
animation: 'bounce',
};
var options = $.extend(defaults, options);
return this.each(function() {
var o = options;
var obj = $(this);
var animation = o.animation;
obj.bind("click", function() {
obj.addClass(o.animation);
obj.addClass('vivify');
}, function() {
obj.removeClass(o.animation);
});
})
}
})(jQuery);​
Here's a working example (I guess, because I don't know exactly what's the intended effect of your plugin):
http://jsfiddle.net/gabrieleromanato/Fmr9g/
obj.bind("click", function() {
obj.addClass(o.animation);
obj.addClass('vivify');
},
// this callback is not valid
function() {
obj.removeClass(o.animation);
});
because .bind() accept parameters like following:
.bind(eventName, [eventData], [callback])
Read about .bind()
To remove class you can do:
obj.bind("click", function() {
obj.addClass(o.animation);
obj.addClass('vivify');
// you can removeClass here
obj.removeClass(o.animation);
// but you need some delay
setTimeou(function() {
obj.removeClass(o.animation);
}, 5000);
});
To increase the timeout you can do following:
return this.each(function(index, val) {
var o = options;
var obj = $(this);
var animation = o.animation;
obj.bind("click", function() {
obj.addClass(o.animation);
obj.addClass('vivify');
}, index * 2000);
});

Building simple jQuery plugin, need assistance

I'm building my first ever jQuery plugin (it's just a simple experiment). Here's what I have so far:
(function($){
$.fn.extend({
auchieFader: function(options) {
var defaults = {
mask: '',
topImg : '',
}
var options = $.extend(defaults, options);
return this.each(function() {
var o = options;
var obj = $(this);
var masker = $(o.mask, obj);
masker.hover(function () {
$(o.topImg).stop().animate({
"opacity": "0"
}, "slow");
}, function () {
$(o.topImg).stop().animate({
"opacity": "1"
}, "slow");
});
});
}
});
})(jQuery);
I'm then calling the plugin using:
$('.fader').auchieFader({mask: ".mask", topImg: ".top"});
If I then add another request say:
$('.fader2').auchieFader({mask: ".mask", topImg: ".top"});
Then no matter what instance of my 2 faders I hover both of them will trigger. I know this is because my mask mask and topImg options have the same class - but how can I modify the plugin to allow for these items to have the same class? I know it's probably something really simple, but I'm still finding my way with jQuery and Javascript in general. Any other tips on improving my code would also be greatly appreciated!
Cheers,
Chris
You seem to already have the answer to your question in the code. For the masker you wrote this:
var masker = $(o.mask, obj);
Which scopes the class in o.mask inside of the dom element obj
I think you just need to do the same thing for o.topImg.
Try changing
masker.hover(function () {
$(o.topImg)
into
masker.hover(function () {
$(o.topImg, obj)
try this:
(function($){
$.fn.extend({
auchieFader: function(options) {
var
// defaults options
defaults = {
mask: null,
topImg: null
},
// extend options in defaults
o = $.extend(defaults, options);
if (!o.mask || !o.topImg) return this;
return this.each(function() {
var
masker = $(o.mask, this),
topImg = $(o.topImg, this);
if (masker.length == 0 || topImg.length == 0) return;
masker.hover(
function () { topImg.stop().animate({ "opacity": "0" }, "slow"); },
function () { topImg.stop().animate({ "opacity": "1" }, "slow"); }
);
});
};
});
})(jQuery);

Categories

Resources