Prevent window on scroll function occurring on mobile - javascript

I have a function that runs on window scroll, I only want it to work however on screensizes of 768 and above. This is working fine if i loaded it on mobile size, but if the initial page load is on a widescreen of 768px + and then i shrink the viewport down it doesn't prevent the function?
(function($) {
var s,
clippy = {
settings: {
heading: $('.js-clippy'),
},
init: function() {
s = this.settings;
this.bindEvents();
},
bindEvents: function(){
if ($(window).width() > 768) {
$(window).on("load resize scroll", $.proxy(this.getClippy, this));
}
},
getClippy: function(){
s.heading.each(function() {
var layerOffset = $(this).closest('a').offset(),
containerOffset = layerOffset.top - $(window).scrollTop(),
clippy = containerOffset - $(this).css("top").replace(/[^-\d\.]/g, '') - $(this).css("margin-top").replace(/[^-\d\.]/g, '');
$(this).css('clip', 'rect('+ clippy +'px, auto, auto, auto)');
});
},
};
clippy.init();
})(jQuery);
I've tried adding a conditional statement to my binded event with no luck...
bindEvents: function(){
if ($(window).width() > 768) {
$(window).on("load resize scroll", $.proxy(this.getClippy, this));
}
});
to the event only it doesn't seem to work?

You should consider checking the width inside the getClippy function. That will work if you load the page with a large viewport and shrink it and vice versa.
(function($) {
var s,
clippy = {
settings: {
heading: $('.js-clippy'),
},
init: function() {
s = this.settings;
this.bindEvents();
},
bindEvents: function(){
$(window).on("load resize scroll", $.proxy(this.getClippy, this));
},
getClippy: function(){
if ($(window).width() > 768) {
s.heading.each(function() {
var layerOffset = $(this).closest('a').offset(),
containerOffset = layerOffset.top - $(window).scrollTop(),
clippy = containerOffset - $(this).css("top").replace(/[^-\d\.]/g, '') - $(this).css("margin-top").replace(/[^-\d\.]/g, '');
$(this).css('clip', 'rect('+ clippy +'px, auto, auto, auto)');
});
}
},
};
clippy.init();
})(jQuery);

Related

Unable to access variable and apply certain CSS using object literal module pattern

I'm unable to access my DOM selectors even though I cached "this" before the window event.
If I were to change it to just $('.banner') it works.
Before in my code, I had scrolltop on the window event set the variable scrolled which I was able to use in my scrollEvent() method using module.scrolled.
Also, the opacity rule in the CSS is not working.
The top and relative position is though.
var parallax = {
init: function() {
this.cacheDom();
this.scrollEvent();
},
cacheDom: function() {
var $window = $(window),
banner = $('.banner'),
callout = $('.callout'),
bannerHeight = Math.round(banner.outerHeight()),
hideElem = false,
hasScrolled = false,
scrolled;
},
scrollEvent: function() {
var module = this;
$(window).on('scroll', function() {
var scrollTop = $(this).scrollTop();
module.banner.css("background-position", '50%' + (scrollTop / 1.75) + "px");
module.callout.css({'position': 'relative', 'top' : scrollTop * 0.75, 'opacity' : 1 - (scrollTop / module.bannerHeight * 2)});
});
}
};
parallax.init();
The cacheDom() function is setting local variables, not object properties. Change it to:
cacheDom: function() {
this.$window = $(window);
this.banner = $('.banner');
this.callout = $('.callout'),
this.bannerHeight = Math.round(this.banner.outerHeight());
this.hideElem = false;
this.hasScrolled = false;
this.scrolled = null;
},

Call same function in window ready and window resize

I have 2 different functions to call based on the size of the screen. I call them in ready function like this:
$(document).ready(function() {
var $window = $(window);
var $window_width = $(window).width();
if ($window_width < 768) {
faq_mobile();
} else {
faq();
}
});
But again I want call them on window resize event since the functions are not called then. So I wrote this:
$(window).bind('resize', function(e) {
window.resizeEvt;
$(window).resize(function() {
clearTimeout(window.resizeEvt);
window.resizeEvt = setTimeout(function() {
if ($(window).width() < 768) {
faq_mobile();
} else {
faq();
}
}, 250);
});
});
But this does not work properly since the functions faq and faq_mobile have been called multiple times when I resize the window. What is the best solution for on this case?
function handler() { // separate the code and wrap it in a function
var $window_width = $(window).width();
if ($window_width < 768) {
faq_mobile();
} else {
faq();
}
}
$(handler); // on load of the document
$(window).resize(handler); // on resize of the window
If you want to keep the delay of the resize event, then change the last line above to this:
$(window).resize(function() {
window.clearTimeout(window.resizeEvt); // remove previous delay if any
window.resizeEvt = setTimeout(function() { // create a new delay
handler();
window.resizeEvt = 0;
}, 250);
});
Well.. thanks everyone for help. I googled it a bit and found a fix for it. I had to unbind the events which were added inside faq and faq_mobile functions after a resize is done. Then call those functions again. Here is the modified code: (Thanks #disstruct for your advice).
$(document).ready(function() {
var width = $(window).width();
handleView(width);
});
$(window).bind('resize', function(e) {
window.resizeEvt;
$(window).resize(function() {
clearTimeout(window.resizeEvt);
window.resizeEvt = setTimeout(function() {
// here i am unbinding the click events which were previously added inside faq and faq_mobile functions.
$('.faq-expand, .answer-close').off('click');
var width = $(window).width();
handleView(width);
}, 250);
});
});
function handleView(width) {
if (width < 768) {
faq_mobile();
} else {
faq();
}
}
Your code looks a little strange. Consider this example
var isMobileView = false;
var isDesktopView = false;
function handleView(width) {
if (width < 768 && isDesktopView) {
faq_mobile();
isMobileView = true;
isDesktopView = false;
} else if (width >= 768 && isMobileView) {
faq();
isMobileView = false;
isDesktopView = true;
}
}
$(document).ready(function() {
var width = $(window).width();
handleView(width)
});
$(window).resize(function() {
var width = $(window).width();
handleView(width)
})

On mouseenter on toggled class

I use a little jquery to change the class of my menu when I resize my browser. That works but when I want to use mouseenter on the new class it doesnt work.
This is my code for resizing:
$( window ).resize(function() {
windowWidth = $(window).width();
windowWidth = windowWidth + 17;
if(windowWidth < 780) {
$('.menu_bar').parent().addClass('mobile-header');
$('.nav_top').removeClass('nav_top').addClass('nav-left');
$('.primary-content').addClass('responsive');
} else {
$('.menu_bar').parent().removeClass('mobile-header');
$('.nav-left').removeClass('nav-left').addClass('nav_top');
$('.primary-content').removeClass('responsive');
}
});
This is the code for the mouseenter:
$(".nav-left ul").on({
mouseenter: function () {
$('ul', this).stop(true, true).slideDown(100);
},
mouseleave: function () {
$('ul', this).stop(true, true).slideUp(100);
}
}, "li");
If I change nav-top to nav-left in my markup (when the menu has the class nav-left on document ready) the mouseenter works fine.
try this :
$( window ).resize(function() {
windowWidth = $(window).width();
windowWidth = windowWidth + 17;
if(windowWidth < 780) {
$('.menu_bar').parent().addClass('mobile-header');
$('.nav_top').removeClass('nav_top').addClass('nav-left');
$('.primary-content').addClass('responsive');
} else {
$('.menu_bar').parent().removeClass('mobile-header');
$('.nav-left').removeClass('nav-left').addClass('nav_top');
$('.primary-content').removeClass('responsive');
}
$(".nav-left ul").on({
mouseenter: function () {
$('ul', this).stop(true, true).slideDown(100);
},
mouseleave: function () {
$('ul', this).stop(true, true).slideUp(100);
}
}, "li");
});

JavaScript is being triggered before its time, *only on Chrome & IE

I have a gallery of three Grids with images. The grid sizes changes depending on the screen size, and I have achieved that using Media-Query - ie, on desktop the grid's width will be 33% to make three columns view next to each other, and on tablet it will be 50% to make two columns view, and on phone it will be a 100% for each grid making one column view.
The reason I did this is to create a tiled gallery with images of different heights - and if I did it the normal way it will generate White-empty-spaces when floating.
So to fix this problem, and with the help of few members on this website, we have created a JavaScrip function that will MOVE all of the images that are inside Grid3 equally to Grid1 & Grid2 when screen size is tablet, so we get rid of the third grid making a view of fine two columns. Everything is working great!
Now, the problem is - on Chrome & IE - The function is being fired before its time for some reason that I need your help to help me find it! Please try it your self here: [http://90.195.175.51:93/portfolio.html][2]
Slowly on Chrome or IE - (try it on Firefox as well) - try to re-size the window from large to small, you will notice that BEFORE the top header changes to be a responsive Header (which indicate that you are on a small screen) the images have been sent to Grid1 and Grid 2! but a few px before the time. As on the function it says to fire it on <770.
Hope my question is clear enough for you to help me solve this issue which is stopping me from launching my website. Thanks.
Here is the JavaScrip:
//Gallery Grid System//
var testimonial = $(".testimonial, .galleryItem", "#grid3");
(function () {
$(document).ready(GalleryGrid);
$(window).resize(GalleryGrid);
})(jQuery);
function GalleryGrid() {
var grid3 = $('#grid3');
var width = $(window).width();
if (width < 1030 && width > 770) {
var grid1 = $('#grid1');
var grid2 = $('#grid2');
for (var i = 0; i < testimonial.length; i++) {
if (i < testimonial.length / 2) {
grid1.append(testimonial[i]);
} else {
grid2.append(testimonial[i]);
}
}
} else {
grid3.append(testimonial);
}
}
Note: The following is the whole page with all the functions:
$(document).ready(function () {
//Prevent clicking on .active links
$('.active').click(function (a) {
a.preventDefault();
});
//Allow :active on touch screens
document.addEventListener("touchstart", function () {}, true);
//Hide toolbar by default
window.addEventListener('load', function () {
setTimeout(scrollTo, 0, 0, 0);
}, false);
//Scroll-up button
$(window).scroll(function () {
if ($(this).scrollTop() > 100) {
$('.scrollup').fadeIn();
} else {
$('.scrollup').fadeOut();
}
});
$('.scrollup').click(function () {
$("html, body").animate({
scrollTop: 0
}, 600);
return false;
});
//StickyBox
$(function () {
$.fn.scrollBottom = function () {
return $(document).height() - this.scrollTop() - this.height();
};
var $StickyBox = $('.detailsBox');
var $window = $(window);
$window.bind("scroll resize", function () {
var gap = $window.height() - $StickyBox.height() - 10;
var footer = 288 - $window.scrollBottom();
var scrollTop = $window.scrollTop();
$StickyBox.css({
top: 'auto',
bottom: 'auto'
});
if ($window.width() <= 770) {
return;
$StickyBox.css({
top: '0',
bottom: 'auto'
});
}
if (scrollTop < 50) {
$StickyBox.css({
bottom: "auto"
});
} else if (footer > gap - 100) {
$StickyBox.css({
top: "auto",
bottom: footer + "px"
});
} else {
$StickyBox.css({
top: 80,
bottom: "auto"
});
}
});
});
//Change items location depending on the width of the screen//
$(function () { //Load Ready
function myFunction() {
var insert = $(window).width() <= 770 ? 'insertBefore' : 'insertAfter';
$('#home-sectionB img')[insert]($('#home-sectionB div'));
$('#home-sectionD img')[insert]($('#home-sectionD div'));
}
myFunction(); //For When Load
$(window).resize(myFunction); //For When Resize
});
//Contact Form//
$(".input").addClass('notSelected');
$(".input").focus(function () {
$(this).addClass('selected');
});
$(".input").focusout(function () {
$(this).removeClass('selected');
});
$(document).ready(function () {
GalleryGrid();
$(window).resize(GalleryGrid);
});
//Gallery Grid System//
var testimonial = $(".testimonial, .galleryItem", "#grid3");
(function () {
$(document).ready(GalleryGrid);
$(window).resize(GalleryGrid);
})(jQuery);
function GalleryGrid() {
var grid3 = $('#grid3');
var width = $(window).width();
if (width < 1030 && width > 770) {
var grid1 = $('#grid1');
var grid2 = $('#grid2');
for (var i = 0; i < testimonial.length; i++) {
if (i < testimonial.length / 2) {
grid1.append(testimonial[i]);
} else {
grid2.append(testimonial[i]);
}
}
} else {
grid3.append(testimonial);
}
}
//Testimonials Animation//
$(".testimonial").hover(function () {
$(".testimonial").addClass('testimonialNotActive');
$(this).removeClass('testimonialNotActive').addClass('testimonialActive');
},
function () {
$(".testimonial").removeClass('testimonialNotActive');
$(this).removeClass('testimonialActive');
});
//Portfolio Gallery Filter//
(function () {
var $portfolioGallerySection = $('#portfolio-sectionB'),
$filterbuttons = $('#portfolio-sectionA a');
$filterbuttons.on('click', function () {
var filter = $(this).data('filter');
$filterbuttons.removeClass('portfolio-sectionAClicked');
$(this).addClass('portfolio-sectionAClicked');
$portfolioGallerySection.attr('class', filter);
$('.galleryItem').removeClass('selectedFilter');
$('.galleryItem.' + filter).addClass('selectedFilter');
});
}());
});
Your problem is that CSS media queries and jQuery's $(window).width() do not always align.
function getCSSWidth() {
var e = window, a = 'inner';
if (!('innerWidth' in window )) {
a = 'client';
e = document.documentElement || document.body;
}
return e[ a+'Width' ];
}
Use this instead of $(window).width()
modified from http://andylangton.co.uk/articles/javascript/get-viewport-size-javascript/
I think this could solve your problem (but I'm not quite sure)
//Put that before the document ready event
(function($,sr){
// debouncing function from John Hann
// http://unscriptable.com/index.php/2009/03/20/debouncing-javascript-methods/
var debounce = function (func, threshold, execAsap) {
var timeout;
return function debounced () {
var obj = this, args = arguments;
function delayed () {
if (!execAsap)
func.apply(obj, args);
timeout = null;
};
if (timeout)
clearTimeout(timeout);
else if (execAsap)
func.apply(obj, args);
timeout = setTimeout(delayed, threshold || 100);
};
}
// smartresize
jQuery.fn[sr] = function(fn){ return fn ? this.bind('resize', debounce(fn)) : this.trigger(sr); };
})(jQuery,'smartresize');
// Here you call GalleryGrid (replace $(window).resize(GalleryGrid) with that):
$(window).smartresize(GalleryGrid);
http://www.paulirish.com/2009/throttled-smartresize-jquery-event-handler/
The reason is your vertical scrollbar. Your content is fixed at width=1030, but when the window size is 1030, the size of the viewport is actually: window size (1030) - vertical scroll bar
Try setting
<body style="overflow:hidden">
You will see that it works correctly when the scrollbar is removed. Or try setting:
<link href="assets/css/tablets-landscape.css" rel="stylesheet" type="text/css" media="screen and (max-width : 1045px)"/>
Set max-width:1045px to make up for scrollbar, you will see that it works correctly.
Your javascript should be like this:
var width = $(window).width() + verticalscrollbarWidth;

Javascript Scroll up and Down buttons

Im trying to make 2 buttons, one called "up" and one called "down".
Those should when I hold down my mouse on one of them, it should scroll up or down the whole page.
I tried with this code, but it didn't worked well.
Up
down​
<script>
$(document).ready(function() {
$("#down").hover(function () {
scroll_page("down");
}, function() { $('.content').stop(); });
$("#up").hover(function () {
scroll_page("up");
}, function() { $('.content').stop(); });
});
function scroll_page(direction) {
var scrolled = $(window).scrollTop();
if (direction == 'up') {
var scroll = scrolled + 100;
}else{
var scroll = scrolled - 100;
}
$("html, body").animate({ scrollTop: scroll }, "fast");
}
​
</script>
Does anyone have any ideas what to do?

Categories

Resources