window onresize perform actions on breakpoints in Jquery - javascript

What I would like to do is create window breakpoints, like 300, 400, 500
and perform a certain action when the window reaches a certain breakpoint, ideally could be something like:
300: function(){...}
400: function(){...}
500: function(){...}
and the following code is how I tried to fire only 1 time a certain function associated to a certain breakpoint, but actually I'm stuck because I don't know how to pass them dynamically inside a single little function, and because all breakpoints in my code look pretty the same and they are useless repeated...
breakpoints = [300, 400, 500];
function screenBreakpoints(){
var regex = / ?breakpoint[0-9] ?/;
if( $(window).width() < breakpoints[0] ){
if( !$('html').hasClass('breakpoint0') ){
$('html')[0].className = $('html')[0].className.replace(regex, '');
$('html').addClass('breakpoint0');
console.log('breakpoint0');
$('li.MOVING').insertBefore('ul li.one'); // breakpoint function (fires only one time)
}
}
else if( $(window).width() > breakpoints[0] && $(window).width() < breakpoints[1] ){
if( !$('html').hasClass('breakpoint1') ){
$('html')[0].className = $('html')[0].className.replace(regex, '');
$('html').addClass('breakpoint1');
console.log('breakpoint1');
$('li.MOVING').insertBefore('ul li.two'); // breakpoint function (fires only one time)
}
}
else if( $(window).width() > breakpoints[1] && $(window).width() < breakpoints[2] ){
if( !$('html').hasClass('breakpoint2') ){
$('html')[0].className = $('html')[0].className.replace(regex, '');
$('html').addClass('breakpoint2');
console.log('breakpoint2');
$('li.MOVING').insertBefore('ul li.three'); // breakpoint function (fires only one time)
}
}
else if( $(window).width() > breakpoints[1] ){
if( !$('html').hasClass('breakpoint3') ){
$('html')[0].className = $('html')[0].className.replace(regex, '');
$('html').addClass('breakpoint3');
console.log('breakpoint3');
$('li.MOVING').insertBefore('ul li.four'); // breakpoint function (fires only one time)
}
}
}
$(window).resize(function(){
screenBreakpoints();
});
FIDDLE

First you get the window width using jquery's width() function.
Then declare three variables accordingly for the three sizes and write your functions inside that variable according to the condition
Keep the other two variables empty based on the width size and call the screenBreakpoints
NOTE: As #flowtron said in the comments, you can use <= or >= in the if condition based on your requirements
$(window).resize(function(){
var viewportWidth = $(window).width();
if(viewportWidth == 300){ // Use <= or >= based on ur requirements
var function300= function300(){};
var function400 ='';
var function500='';
screenBreakpoints(function300,function400,function500);
}
else if(viewportWidth == 400){ // Use <= or >= based on ur requirements
var function400= function400(){};
var function300 ='';
var function500='';
screenBreakpoints(function300,function400,function500);
}
else if(viewportWidth == 500){ // Use <= or >= based on ur requirements
var function500= function500(){
var function300 ='';
var function400='';
};
screenBreakpoints(function300,function400,function500);
}
});
Then in your screenBreakpoints function check which parameter is empty
For Ex:
function screenBreakpoints(function300,function400,function500){
if( $(window).width() < breakpoints[0] ){
if(function300 != null && function300 != undefined){
if( !$('html').hasClass('breakpoint0') ){
$('html')[0].className = $('html')[0].className.replace(regex, '');
$('html').addClass('breakpoint0');
console.log('breakpoint0');
$('li.MOVING').insertBefore('ul li.one'); // breakpoint function (fires only one time)
}
}
}
}

In my work I've come to use a set of DIVs (usually invisible, not via display: none though!) that have an ID of "ThisIsMediaQuery_Alpha", .. Beta, Gamma .. however you name them and as many as you need - then each breakpoint you're interested in just has to modify one of these from the default settings all got initially - I usually use a background-color (legacy from when they were created to FIX a MediaQuery-usage and were visible), but anything you like can work really. Then just call whichMediaQueryIsThis() on $(window).resize(), which iterates over the DIVs and finds out which one has the "marker value" (e.g. cur.style.backgroundColor=="red"). Then just use a case to switch out the appropriate values when calling your manageMediaQuerySwitch(arg0,arg1,arg2) function. HTH
The upside of this is, it also works with MediaQueries that aren't pixel-oriented! ;-)

Here is a complete edit that is done to the js file from the jsfiddle
the you provided. Just copy paste this over there or, just run this jsfiddle. I found it working. What I'm doing is, I'm just making a single function and calling it with different parameters.
Here is your modified js
breakpoints = [300, 400, 500];
function screenBreakpoints(breakpoint,listName){
var regex = / ?breakpoint[0-9] ?/;
if( !$('html').hasClass(breakpoint) ){
$('html')[0].className = $('html')[0].className.replace(regex, '');
$('html').addClass(breakpoint);
console.log(breakpoint);
$('li.MOVING').insertBefore(listName); // breakpoint function (fires only one time)
}
}
$(window).resize(function(){
if( $(window).width() < breakpoints[0] ){
screenBreakpoints("breakpoint0","ul li.one");
}
else if( $(window).width() < breakpoints[1] ){
screenBreakpoints("breakpoint1","ul li.two");
}
else if( $(window).width() < breakpoints[2] ){
screenBreakpoints("breakpoint2","ul li.three");
}
else{
screenBreakpoints("breakpoint3","ul li.four");
}
});

Related

Do something once in $(window).scroll function during multiple conditional statements

This is throwing me for a loop..
The basic idea is we're using $(window).scroll() and as you scroll down the page, when an element is in view by using offset() with scrollTop "do something" then when you hit the next element down the page "do something more".
However, because the scroll event (probably the wrong term) fires every single time in the conditional statement because technically the statement is true every scroll, I need it to only fire once, but then be able to 're-fire again' one time when the next conditional happens.
$(window).scroll(function(){
let windowTop = $(window).scrollTop()
if( windowTop > $('.element').offset().top && windowTop < $('.element2').offset().top ) {
doSomething(); // want this to only fire once
} else if( windowTop > $('.element2').offset().top ) {
doSomething(); // want this to only fire once
}
});
I had a theory about possibly setting a variable to true so it only fire's doSomething() once, but then when it's inside the 2nd conditional statement I can't wrap my head around undoing / resetting it.
let fired = false;
$(window).scroll(function(){
let windowTop = $(window).scrollTop()
if( windowTop > $('.element').offset().top && windowTop < $('.element2').offset().top ) {
if(!fired){
doSomething();
fired = true;
}
} else if( windowTop > $('.element2').offset().top ) {
// need to somehow set fired to false again so it triggers once then sets back to true
if(!fired){
doSomething();
fired = true;
}
}
});
Hope I somehow made sense!
Consider the following.
var fire = {
"element1": true,
"element2": true
};
$(window).scroll(function(event){
var windowTop = $(window).scrollTop();
console.log("Window Scroll Top: " + windowTop);
if( fire.element1 && (windowTop > $('.element').offset().top && windowTop < $('.element2').offset().top) ) {
console.log("Do Something!", $('.element').offset().top);
fire.element1 = false;
doSomething();
} else if( fire.element2 && (windowTop > $('.element2').offset().top) ) {
console.log("Do Something!", $('.element2').offset().top);
fire.element2 = false;
doSomething();
}
});
The logic here is we check if we should fire the event for each element. In this way we have a more complex IF condition. Fire for that element must be true and the Scroll position must have gone down far enough.
If the Top of the element is 100, this condition should only be true at one time and one time only, when windowTop is a value of 101 or higher. Now if you want it to trigger when the element is fully in view, you need the Top plus the Height. If it's 40px tall, then it would be 140 (Top + Height).

Nav Shrink on Scroll or Resize

I'm trying to apply a series of classes to a nav that cause it to shrink if the window is either resized or scrolled passed a certain point. However, I believe my conditions are cancelling each other out, and I'm not sure how to structure the if-statements or if it is better to just pass a variable.
Here's what I am trying to accomplish:
If the window is resized between a certain set of media queries, shrink the nav
If the window is outside of those break-points, and the user scrolls passed 1 (I used one just for example purposes in my code so I could see it right away) the nav will shrink and if they scroll up again, it will become it's full size
My code is here:
$(document).ready(function() {
var logo = $('.logo');
var topLevelListItems = $('.mainNav li');
var navShrink = false;
var mQ = window.matchMedia( '(min-width: 100px) and (max-width: 770px)' );
$(window).resize(function() {
if ( mQ.matches ) {
$('nav').addClass('shrink');
$('.nav-fixedWidth').addClass('shrink');
logo.addClass('shrink');
topLevelListItems.addClass('shrink');
navShrink = true;
}
else{
$('nav').removeClass('shrink');
$('.nav-fixedWidth').removeClass('shrink');
logo.removeClass('shrink');
topLevelListItems.removeClass('shrink');
navShrink = false;
}
});//end of resize function
$(window).onscroll(function(){
if( !(mQ.match) && $(this).scrollTop >= 1 ) {
$('nav').addClass('shrink');
$('.nav-fixedWidth').addClass('shrink');
logo.addClass('shrink');
topLevelListItems.addClass('shrink');
navShrink = true;
} else {
$('nav').removeClass('shrink');
$('.nav-fixedWidth').removeClass('shrink');
logo.removeClass('shrink');
topLevelListItems.removeClass('shrink');
navShrink = false;
}
});//end of scroll function
});//end of doc
Could it simply be a typo in your onscroll function?
i.e you have:
if( !(mQ.match) && $(this).scrollTop >= 1 ) { ...
should it not be:
if( !(mQ.matches) && $(this).scrollTop >= 1 ) { ...

How to check if the method modernizer.mq is supported?

I created a navigation with hover effect with the Modernizer.mq method:
$('ul#mainNav > li').hover(function() {
if(Modernizr.mq('(min-width: 701px)'))
{
Since I want a hover effect for the navigation when width is larger then 700px and a click-mobile like navigation when the width is less then 700px.
I used the above code instead of
$('ul#mainNav > li').hover(function() {
if($( window ).width()> 701)
{
because $( window ).width() is different from my media-queries.
For IE < 8 I use respond.js to get my mediq-queries working. However, I noticed that my hover does not work anymore because the method Modernizr.mq is not working. Is there a way to find out if the method Modernizr.mq is supported?
Something like:
var mqWorks = checkIfMqWorks();
$('ul#mainNav > li').hover(function() {
if(mqWorks){
if(Modernizr.mq('(min-width: 701px)'))
{...}
} else {
if($( window ).width()> 701)
{...}
}
You can use the typeof contruct in an if then statement.
Live Example http://codepen.io/larryjoelane/pen/NxZKWr
JavaScript:
//test conditions
var modernizrLoaded = typeof Modernizr === "object";
var modernizrMQLoaded = typeof Modernizr.mq === "function";
var modernizrMinWidth = Modernizr.mq('(min-width: 10px)');
//debugging tests
console.log(modernizrLoaded);
console.log(modernizrMQLoaded);
console.log(modernizrMinWidth);
//if Modernizr is object that is loaded. It contains an mq function and the test function call for mq returns true
if (modernizrLoaded && modernizrMQLoaded && modernizrMinWidth) {
console.log("Modernizr is a function and the mq function call returns true.");
} else {
console.log("false")
}
You could then create a function to call or just place your code in the if block to run if the conditions are met and place your code for when the conditions are not met in the else block.

Jquery window scroll. call just one time

Hi I have one question about jquery window scroll function. I have code somthing like this.
$(window).scroll(function(){
if($(window).scrollTop() > $(".pages").offset().top) {
$('.top-slider').slick('slickPause');
}else {
$('.top-slider').slick('slickPlay');
}
});
Ok every time when you scroll if first is true it call every 1px scrolled window. Is that way to call just one time if true but check on scroll if other is true call that just one time?
Thanks for your answers :)
Try with a flag, something like this:
var paused = false;
$(window).scroll(function(){
if( $(window).scrollTop() > $(".pages").offset().top ) {
if( !paused ){
$('.top-slider').slick('slickPause');
paused = true;
}
}else {
if( paused ){
$('.top-slider').slick('slickPlay');
paused = false;
}
}
});
Adding a test variable will be a solution here :
var checkDown = true;
var checkUp = false;
$(window).scroll(function(){
if($(window).scrollTop() > $(".pages").offset().top && checkDown ) {
$('.top-slider').slick('slickPause');
checkDown = false;
checkUp = true;
}else if(checkUp) {
$('.top-slider').slick('slickPlay');
checkDown = true;
checkUp = false;
}
});
I tell you another solution, is a debouncer. Debounce functions make scroll and resize events more efficient, because stop the event firing till the end of the first fired event.
You can view a debounce function with underscore.js library.
http://underscorejs.org/#debounce
The use is simple:
var debounced = _.debounce(myFunction, 1000);
$(window).scroll(debounced);

Browser Viewport detection with plain JavaScript

I am using plain JavaScript code to detect browser viewport and which is as follows:
function setLocation(url) {
if (window.location.href.indexOf(url) === -1)
window.location = url;
}
function reloadPage(width) {
if (width < 701) {
setLocation("layout700.php");
} else if (width < 900) {
setLocation("layout900.php");
} else {
setLocation("layout1200.php");
}
}
var done = false;
function ready() {
if(!done) {
done = true;
reloadPage(document.width);
}
}
if(window.addEventListener) {
window.addEventListener('DOMContentLoaded', ready, false);
window.addEventListener('load', ready, false);
} else if(window.attachEvent) {
window.attachEvent('onload', ready);
}
window.onresize = function() {
reloadPage(document.width);
};
My question is : How can I define width range in this?
What I mean is.... Is it correct if I use as
function reloadPage(width) {
if (width <= 701 && >= 480) {
setLocation("layout700.php");
} else if (width <= 900 && >= 701) {
setLocation("layout900.php");
} else {
setLocation("layout1200.php");
}
}
If this is not correct then what is the correct syntax? Kindly help.
function reloadPage(width) {
if( width >= 480 ) {
if (width <= 701 ) {
setLocation("layout700.php");
} else if ( width <= 900 ) {
setLocation("layout900.php");
} else {
setLocation("layout1200.php");
}
}
}
What is changed from your code ?
- After the logical operator " && " you did not mention the variable name, which is incorrect.
- You need not check for " width > 701 " in the second condition, because, if it was <= 701, the first condition would have been satisfied.
EDIT : Added a wrapper if() to check the page is greater than 480, since you don't have any layouts specific to that.
Start at the largest and move to the smallest. Also, because setLocation should immediate halt execution, you can optionally leave out the "else" stuff. Finally, I assume if width is less than 900, you should go to layout700, even if the width is less than 700? It seems like it would be the closest-fit for a very thin browser.
if (width>1200) {
setLocation("layout1200.php"); }
if (width>900) {
setLocation("layout900.php"); }
setLocation("layout700.php");
I'd be tempted to borrow this (http://adactio.com/journal/5429/) technique that Jeremy Keith has just blogged about and use the content attribute to store the correct page for the relevant dimensions - you could then use media queries to differentiate between the various sizes.
Something else you might want to consider... is using Device Atlas or
WUFRL to detect the end users browser and serve them out the correct layout to start - redirects are poor experience for end users and particularly slow over mobile.

Categories