onresize can be used for knowing window has been resized. Is there any similar notification/event before window resizes.
I want to set will-change on some elements before window resize starts and subsequently remove that after window has resized.
It seems there are no direct solutions but you can achieve both start|end events with some workaround using window.addEventListener("resize",yourFunction); and some global variables (it is a workaround, it is not perfect).
//Accesible variables
var atStart = true;
var timer;
function yourFunction(){
return ()=>{
if(atStart){
console.log("START");
//Some code to be executed once at start
atStart = false;
}
console.log("WHILE");
//Some code to be executed while resizing
if (timer) clearTimeout(timer);
timer= setTimeout(atEnd, 500);
}
}
function atEnd(){
//Some code to be executed at the end of resizing
//..well some 500ms after the end of resizing
console.log("END")
atStart = true;
}
window.addEventListener("resize",yourFunction());
Hope it helps someone.
There are no events that fire before resize. Only during resize. Most solutions to do something on rezise use setTimeout to check when a certain amount of time passed since the last resize event. So I guess you're out of luck.
Related
I have a responsive design with multiple breakpoints. Some of the block dimensions in the content are calculated with jQuery. When the viewport changes these dimensions change thus the calculation should be run. How can I fire these events when the dimension of the reference element changes? The reference element changes when a breakpoint is crossed.
I've looked at the "orientationchange" event but it's not having the results I need.
You provide very little specifics and no code so all we can do is answer very generally.
Usually, you install a .resize() event handler and on every resize of the containing window, you check to see if the resulting dimensions have changed such that you need to recalculate and modify the layout.
$(window).resize(function(e) {
// check dimensions here to decide if layout needs to be adjusted
});
jQuery mobile supports the orientationchange event like this which also gives you e.orientation as "portrait" or "landscape":
$(window).on( "orientationchange", function(e) {
// check dimensions here to decide if layout needs to be adjusted
});
There are no DOM events for watching a size change on a specific element in the page other than a window object. Instead, you have to watch whatever other events might cause a given element to get resized which might be a resize of the window, an orientation change or some other action in the page that modifies the page (a button press or click on something, for example). Then, when those other events fire and get processed, you can then check the size of your target element and see if it changed.
Here's a jQuery plugin that debounces the resize event so it only tells you about a resize when the size has stopped changing:
(function($) {
var uniqueCntr = 0;
$.fn.resized = function (waitTime, fn) {
if (typeof waitTime === "function") {
fn = waitTime;
waitTime = 250;
}
var tag = "resizeTimer" + uniqueCntr++;
this.resize(function () {
var self = $(this);
var timer = self.data(tag);
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(function () {
self.removeData(tag);
fn.call(self[0]);
}, waitTime);
self.data(tag, timer);
});
}
})(jQuery);
Working demo: https://jsfiddle.net/jfriend00/k415qunp/
Sample usage:
$(window).resized(function() {
// put code here to act when window stopped getting resized
});
This page might help you. They talk about JS execution based on breakpoints and doing it with cross-browser support. Basically you'll be using a hidden pseudo element using the "content" property of .myClass:after.
I'm trying to make this site show a tab-box on large screens, but just a normal layout on smaller screens. Here's what I have:
function adapt() {
if(document.documentElement.clientWidth > 800) {
$(document).ready(function() {
$(".box").hide();
$(".box:first").show();
$("ul.tabs li").click(function() {
$("ul.tabs li").removeClass("active");
$(this).addClass("active");
$(".box").hide();
var activeTab = $(this).attr("rel");
$("#"+activeTab).show();
});
});
}else{
$(document).ready(function () {
$('.box').show();
});
};}
window.onload = adapt();
window.onresize = adapt();
The onload event handler works, so the tab-box jquery function only works if the page is loaded on a larger screen, and it shows all the content when loaded on a smaller screen. I added the onresize event so it would also change when the browser window is shrunk down, but it doesn't work. If I load on a large screen and then shrink it, all that shows is the content that was in the first tab, and if I load on a small screen, and then make the window bigger, all the content is displayed and the tab buttons don't work. Am I just misinterpreting how window.resize is supposed to work?
I'm guessing that maybe the event only fires once the first time the resize occurs, and if the difference isn't enough that time for my other conditional to take over, it doesn't happen. If this is the case, is there a way to make it continually check for screen size, like with CSS media queries?
don't forget, that if some other code in your project also uses window.onresize or window.onload - your code will be overwritten
it's a better practice to use addEventListener function
window.addEventListener('resize', adapt);
You need to call the reference, not execute the function
window.onload = adapt;
window.onresize = adapt;
Because when you do
window.onload = adapt();
window.onresize = adapt();
You execute adapt() and since it return nothing, you have nothing done on these events
You can try with jquery:
$(document).ready(function() {
adapt(); // onload
$(window).resize(adapt()); // resize
});
I'm using scrollTo() for page scrolling. One problem I found is, when I resize browser, page don't scroll again to element I specified, but it stays somewhere in middle, so I have to click 'scroll' button again to align the page. Is there any way to align page when user resize browser.
I tried using this:
window.onresize = function() {
scrollToPosition(section[position]);
}
// position is variable which I declared above this event
But this makes scrolling crazy, the page start to move right/left really fast which is not normal. I believe it binds onresize event every time I resize browser.
Is there any solution for my problem
EDIT:
This is jsFiddle, but it seems I don't know how to use jsFiddle since nothing works here: http://jsfiddle.net/52eRj/1/
You can avoid reruning function everytime the resize event is executed by writing code as below. scrollToPosition function will be executed every 1 second when scrolling.
var last = new Date().getTime();
var interval = 1000; // Set your own time.
window.addEventListener('resize', function() {
var curr = new Date().getTime();
if (curr - last > interval) {
last = curr;
scrollToPosition(section[position]);
}
});
The problem might be that you are calling your scrollToPosition function on every resize event, which can be fired 100 times in a normal manual resize.
To avoid this you can use clearTimeout like this:
$(window).resize(function () {
clearTimeout(resizeId);
resizeId = setTimeout(doneResizing, 500);
});
function doneResizing() {
scrollToPosition(section[position]);
}
This way the doneResizing function would only be called after 500 miliseconds since the window has stopped resizing, avoiding therefore, those tens or hundreds of unnecessary calls.
People!
This is the first time I come here to ask something, so far, always when I had a problem, I could find a good answer here. So, in first place, thanks for this amazing community!
Now let's go to the problem:
I'm doing a responsive menu that check the window.resize event and, when it fits the minimum browser width, a click function for a button is allowed. If the browser width is greater, then the click function is unbound. I need to do this because the same element that is the button on the mobile version, is a visual element on the desktop version.
The problem is that, with the code that I have now, when the page is loaded, the click function works fine. But, if I resize the browser and click on the element again, it triggers more than once the state, sometimes leaving the impression that the function isn't triggered. And, if I resize the browser again, it triggers the click function more than the last time I clicked. Really annoying.
To help understand what is happening, I've made a simple example. Here's is the simple code (just to check the click function issue):
HTML:
<ul>
<li><span class="sub-toggle">Testing 01</span></li>
<li><span class="sub-toggle">Testing 02</span></li>
<li><span class="sub-toggle">Testing 03</span></li>
</ul>
CSS:
.sub-toggle{
display:block;
padding: 20px;
}
.sub-toggle.active{
background-color: #ffcc00;
color: #fff;
}
Javascript (jQuery):
jQuery(function($){
var i = 1;
// check if browser size is compatible with click event
onResize = function() {
// if browser size is ok, do the click function
if($(window).width() <= 480){
// click function
$('.sub-toggle').click(function(){
alert('click');
if($(this).hasClass('active')){
alert('active');
$(this).removeClass('active');
} else {
$(this).addClass('active');
}
});
} else{
// if browser size is greater than expected, unbind the click function
$('.sub-toggle').removeClass('active').unbind('click');
}
// just checking how many times the resize function is triggered
console.log('resize: '+ i);
i++;
}
$(document).ready(onResize);
var timer;
$(window).bind('resize', function(){
timer && clearTimeout(timer);
timer = setTimeout(onResize, 500);
});
});
(Edited to remove some unnecessary code)
If you want to see it in action, I've made a Fiddle (try resize the output frame to see it working): http://jsfiddle.net/C7ppv/1/
Maybe I've missing something really stupid, since I don't have a huge knowledge in JavaScript. But what I want to do is just trigger the click event once, even if multiple resizes.
I hope I could explain well my problem. I've searched and didn't found a solution for this issue (or maybe I just didn't know really well what to look for).
Any help would be appreciated!
Your code currently binds a new click events every time the method onResize is called and the window width is less than or equal to 480px.
Simply unbind any existing click events on the .sub-toggle element before binding a new one.
$('.sub-toggle').unbind('click').click(function() {
...
});
DEMO
The resize event is triggered multiple times during resizing, and each time you're binding a new click handler. My suggestion: bind only once, from outside the resize handler, and set a flag while resizing to let the click handler know if it should do something or not.
Then you won't even need to defer the handling of resize with setTimeout as you're doing.
DEMO
jQuery(function($){
var i = 1;
// flag to allow clicking
var clickAllowed = true;
// click function
$('.sub-toggle').click(function(){
if(clickAllowed) {
alert('click');
if($(this).hasClass('active')){
alert('active');
$(this).removeClass('active');
} else {
$(this).addClass('active');
}
}
});
// check if browser size is compatible with click event
onResize = function() {
//if browser size is ok, do the click function
if($(window).width() <= 480){
clickAllowed = true;
}
else{
// if browser size is greater than expected, disallow clicking
clickAllowed = false;
}
// just checking how many times the resize function is triggered
console.log('resize: '+ i);
i++;
}
$(document).ready(onResize);
var timer;
$(window).bind('resize', onResize);
});
Move $('.sub-toggle').click(function(){...} outside the onResize event handler and move if($(window).width() <= 480){...} into the click handler.
I'm trying to figure out a way to do this. I have a list of boxes, each about 150px high. I am using javascript (and jquery) and want that, after a user scrolls down a page, the page will auto scroll so that the boxes line up with the rest of the page (that is to say, if the user scrolls and the y position of the page is not divisible by 150, it will scroll to that nearest point).
Now, I at the moment, I know I can activate an event using the .scroll() jquery event, and I can make it move to a certain point using .scrollTop(). But every pixel the user moves the scroll bar activates the whole function. So is there a way to delay the function from firing until the user hasn't scrolled, and if they should begin to scroll again, the function will halt?
As you are already using jQuery, have a look at Ben Alman's doTimeout plugin which already handles the debouncing of methods (which is what you are after).
Example shamelessly stolen from his website:
$(window).scroll(function(){
$.doTimeout( 'scroll', 250, function(){
// do something computationally expensive
});
});
This is basically the same as Šime Vidas' answer, but less complex:
var scrollTimeout = null;
$(window).scroll(function(){
if (scrollTimeout) clearTimeout(scrollTimeout);
scrollTimeout = setTimeout(function(){yourFunctionGoesHere()},500);
});
500 is the delay. Should be ok for mouse scroll.
Sure, in the event handler for the scroll event, fire off a setTimeout for 100 or 200 milliseconds later. Have that setTimeout function you set inside of the scroll event handler do the positioning logic you mention above. Also have the scroll event handler clear any timeouts set by itself. This way, the last time the scroll event fires, the setTimeout function will get to complete as the scroll event has not cleared it.
The code:
var scrollTimeout = null;
var scrollendDelay = 500; // ms
$(window).scroll(function() {
if ( scrollTimeout === null ) {
scrollbeginHandler();
} else {
clearTimeout( scrollTimeout );
}
scrollTimeout = setTimeout( scrollendHandler, scrollendDelay );
});
function scrollbeginHandler() {
// this code executes on "scrollbegin"
document.body.style.backgroundColor = "yellow";
}
function scrollendHandler() {
// this code executes on "scrollend"
document.body.style.backgroundColor = "gray";
scrollTimeout = null;
}
This would be a scenario, where vanilla JavaScript would be useful.
var yourFunction = function(){
// do something computationally expensive
}
$(window).scroll(function(){
yfTime=setTimeout("yourFunction()",250);
});