Detect resize and execute code at X resolution in JQuery - javascript

I want the following:
Detect page width on load and add/remove class if it's below/above 959px
If I resize the page I want to do the same
$(window).on("resize load", function(e) {
e = $("body").width();
if (e <= 959) {
$("#button").addClass("active")
}
if (e >= 960) {
$("#button").removeClass("active")
}
})
This code works, but it removes the active class even if I resize the window from 500px to 501px. I want that to only add the class if I go above 960px or remove it if I go below 959px. How can I do that?
EDIT
Thanks for the answers! In the meantime I figured out a solution that works and suit my needs.
$(window).one("load", function () {
r = $("body").width();
if (r >= 960) {
$("body").attr("mobile","0")
//do something
}
if (r <= 959) {
$("body").attr("mobile","1")
//do something
}
});
$(window).on("resize", function() {
r = $("body").width();
if ($("body").attr("mobile") == "0") {
if (r <= 959) {
//do something
$("body").attr("mobile","1")
}
}
if ($("body").attr("mobile") == "1") {
if (r >= 960) {
//do something
$("body").attr("mobile","0")
}
}
})
Explanation:
It's a very specific solution since I modify the tabindex values in mobile view and I don't want to change these values back to 0 on a simple resize, only in the case I switch from mobile view to desktop.

The width of the window is different than the width of the body. Using $('body').width() will account for the overflow, whereas using $(window).width() will give you the actual screen width.
$(window).on('load resize', function() {
$('#button').toggleClass('active', $(this).width() <= 959)
});
However, using media queries is much more straight forward if in fact, you are just adding CSS properties.
#button {
opacity: 0.5;
}
#media (max-width: 959px) {
#button {
opacity: 1;
}
}

You could ouse window.matchMedia for this. If you look at the perf test, matchMedia is a lot faster than resize.
var mq = window.matchMedia("(min-width:959px)");
// onload
setButton(mql);
// add listener for the query
mq.addListener(setButton);
function setButton(mq) {
if (mql.matches) {
// do something with your setButton
} else {
// no match....
}
}

Here you go with a solution https://jsfiddle.net/hLkv1xan/1/
$(window).on("resize load", function(e) {
e = $("body").width();
if (e <= 959) {
$("#button").addClass("active")
} else {
$("#button").removeClass("active")
}
});
.active{
background: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="button">
Submit
</button>
I just modified your code a bit, change in the condition.
Hope this will help you.

Related

JavaScript execute page resize and reload event simultaneously

I am trying to execute a window resize and page reload event simultaneously. When the screen size is less than 768 px, I am adding an attribute to an element. I also need that attribute added when the page is reload and a specific size as well, not just when its resized. The code I have below works, except when my screen size hs < 769 px, it takes a few seconds for the attribute to be added which affects how it looks. Any tips on how I can fix this?
window.onload = function(event) {
var element = document.querySelector('.filter-select');
if (window.innerWidth < 768) {
element.classList.add('testing');
element.removeAttribute("size", "4")
element.removeAttribute("multiple", "yes")
} else {
element.classList.remove('testing');
}
}
document.addEventListener("DOMContentLoaded", function(event) {
var element = document.querySelector('.filter-select');
function resize() {
if (window.innerWidth < 768) {
element.classList.add('testing');
element.removeAttribute("size", "4")
element.removeAttribute("multiple", "yes")
} else {
element.classList.remove('testing');
}
}
window.onresize = resize;
});
My only guess is that you doubled up the same process under different events and these events happen at different times thus the NOTICABLE lag.. if this doesn't solve.. this is an amazing question I already upvoted..
function resize() {
var element = document.querySelector('.filter-select')
if (window.innerWidth < 768) {
element.classList.add('testing')
element.removeAttribute("size", "4")
element.removeAttribute("multiple", "yes")
}
else {
element.classList.remove('testing');
}
}
window.onload=resize

Why my fix menu in not working smoothly on scrolling.

$(window).scroll(function() {
var windscroll = $(window).scrollTop();
if (windscroll >= 5) {
$('#page-header').addClass('fixed');
} else {
$('#page-header').removeClass('fixed');
}
}).scroll();
Why my fix menu in not working smoothly on scrolling. i am using in my moodle theme frontpage.php or i have to add some thing for smoothness.
You're modifying the DOM too frequently, as $(window).scroll fires multiple times in a single scroll. Consider checking the existence of the class before add or remove it.
$(window).scroll(function() {
var windscroll = $(window).scrollTop();
if (windscroll >= 5) {
if(!$('#page-header').hasClass('fixed')) {
$('#page-header').addClass('fixed');
}
} else {
if(!$('#page-header').hasClass('fixed')) {
$('#page-header').removeClass('fixed');
}
}
});
also, I removed an extra .scroll() call at the end of the script.
Alternatively, you can make use of a jQuery On Screen plugin which will add a pseudo class :onscreen with the div visible in the browser. Codes are as follow:
$(document).scroll(function() {
if($("#page-header").is(':onScreen')) {
console.log("Element appeared on Screen");
if(!$('#page-header').hasClass('fixed')) {
$('#page-header').addClass('fixed');
}
} else {
console.log("Element not on Screen");
if(!$('#page-header').hasClass('fixed')) {
$('#page-header').removeClass('fixed');
}
}
});
See if the plugin fits your needs.

jQuery Undelegate does not work

I'm creating a responsive template and I want to remove the listeners on an element when screen is being resized or is smaller than the specified width.
Imagine an menu which when you hover on it's items, it shows you the sub-menus in normal displays but the same menu in mobile devices will show the sub-menus only by tapping or clicking on the items.
I can't make the undelegate work. In resized screen I still have the mouseover and mouseout event-listeners. I'm not getting any errors in console and I've tried both:
.off('mouseover', 'li')
.off('mouseover')
.undelegate('li', 'mouseover')
.undelegate('li')
and none of them works.
var $window = $(window);
function handleSidenav() {
$(".nav-list").delegate('li', 'mouseover', function(e) {
$(this).find("a").addClass('active');
$(this).find("div.sub-items").toggle();
}).delegate('li', 'mouseout', function(e) {
$(this).find('a').removeClass('active');
$(this).find("div.sub-items").toggle();
});
}
function checkWidth() {
var windowsize = $window.width();
if (windowsize < 767) {
smallScreenDelegation();
} else {
SmallScreenUndelegation();
}
}
checkWidth();
handleSidenav();
$window.resize(checkWidth());
function smallScreenDelegation() {
$(".nav-list").undelegate('li'); //It's not working
$(".nav-list").undelegate('li'); //It's not working
$(".nav-list").delegate('li a:first', 'click', function(event) {
if ($(this).next().is(':hidden')) {
$(this).addClass('active');
$(this).next().slideDown('slow');
} else {
$(this).removeClass('active').next().slideUp('slow');
}
event.preventDefault();
});
}
You need to wrap window in the jQuery object. I'm not sure if you set $window = $(window), but it seems here that $window.width() and $window.resize(checkWidth) are missing parenthesis. I was able to get it working fine once I changed those to $(window). You have to define which event you want to undelegate. I used:
$('.nav-list').undelegate('li', 'mouseover');
Open up console and you can see that it works: http://jsbin.com/efonut/6/edit
Also, it's really best to use .on() and off() vs .delegate() and .undelegate(), but at least this works...
I still don't know what was wrong with undelegate which I couldn't make it work, but I managed to fix my code by using on and off.
As adeneo said I was delegating and undelegating on each window resize which was quiet a bug and I think I fixed that but holding the last state on device variable.
var $window = $(window);
var device;
function desktopSidenav() {
$(".nav-list > li").off('click');
$(".nav-list > li").on('mouseover', function(e) {
$(this).find("a").addClass('active');
$(this).find("div.sub-items").toggle();
}).on('mouseout', function(e) {
$(this).find('a').removeClass('active');
$(this).find("div.sub-items").toggle();
});
}
function handheldSidenav() {
$(".nav-list > li").off('mouseover').off('mouseout');
$(".nav-list > li").on('click', function(e) {
if ($(this).find("div.sub-items").is(':hidden')) {
$(this).find("a:first").addClass('active').next().slideDown('slow');
} else {
$(this).find("a:first").removeClass('active').next().slideUp('slow');
}
e.preventDefault();
});
}
Now I check the window size before doing anything else an I'll hold the device type in device variable. If window is resized, I'm gonna check the device state and do the things based on device type.
if ($window.width() > 767) {
device = 'desktop';
desktopSidenav();
} else {
device = 'handheld';
handheldSidenav();
}
$window.resize(function() {
if ($window.width() > 767) {
if (device == 'handheld') {
device = 'desktop';
desktopSidenav();
}
} else {
if (device == 'desktop') {
device = 'handheld';
handheldSidenav();
}
}
});
If I use delegate and undelegate instead of on and off, the code won't work and I still don't know why, so this cannot be count as a real answer, but I wanted to tell everyone who has a similar problem to use jQuery's on and off instead on delegate.

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.

Trigger event using Jquery on CSS change?

I'm curious is there an event listener or perhaps a way to construct a method that will trigger when a CSS change happens?
My stylesheet uses media queries and I want to know if there's a way to attach a listener to see when those media queries kick in and out. For example I have a media query that hides a button at certain screen widths
#media screen and (max-width: 480px) {
#search-button {
display: none;
}
}
What event listener would I use to detect when that display changes? I'm currently doing this:
$(window).resize(function() {
if($('#search-button').css("display") == "none") {
//do something
} else {
//do something else
}
});
Which works fine, but it calls the listener every time the user changes the screen and I'd rather just have it fire only when the css of the button changes. I hope that makes sense.
for example this is what I'd like
$('#search-button').cssEventListenerOfSomeKind(function() {
alert('the display changed');
});
Binding to the window.resize is your best option (I believe). There isn't any event fired when you change an element's CSS. You can however optimize a bit by caching the selector used:
var $searcButton = $('#search-button');
$(window).resize(function() {
if($searcButton.css("display") == "none") {
//do something
} else {
//do something else
}
});
Or you can use $(window).width() to check the width of the viewport:
var $window = $(window);
$window.resize(function() {
if($window.width() <= 480) {
//do something
} else {
//do something else
}
});
UPDATE
You can always throttle your own event handler:
var $window = $(window),
resize_ok = true,
timer;
timer = setInterval(function () {
resize_ok = true;
}, 250);
$window.resize(function() {
if (resize_ok === true) {
resize_ok = false;
if($window.width() <= 480) {
//do something
} else {
//do something else
}
}
});
This will prevent the code in your resize event handler from running more than once every quarter second.
If it is only a one time event you could try to unbind the event.
http://api.jquery.com/unbind/
I know this is old but I managed to solve it with this logic
// set width and height of element that is controlled by the media query
var page_width = $page.width();
var page_height = $page.height();
$window = $(window).resize(function(){
if( $page.width() != page_width ) {
// update page_width and height so it only executes your
// function when a change occurs
page_width = $page.width();
page_height = $page.height();
// do something
// ...
}
});

Categories