Jquery functions not changing on window resize - javascript

I have the following jquery code that is aimed at running one function when the window is large (>=1024) and another when it is resized and small.
The console.logs appear as expected on resize, but the functions do not change. Meaning, if the browser was loaded in large size, when resized, the large function is still used.
(Resize code used from https://stackoverflow.com/a/4541963/1310375 and https://stackoverflow.com/a/9828919/1310375)
var waitForFinalEvent = (function () {
var timers = {};
return function (callback, ms, uniqueId) {
if (!uniqueId) {
uniqueId = "Don't call this twice without a uniqueId";
}
if (timers[uniqueId]) {
clearTimeout (timers[uniqueId]);
}
timers[uniqueId] = setTimeout(callback, ms);
};
})();
$(window).on('resize', function(){
var win = $(this); //this = window
waitForFinalEvent(function(){
console.log('Resize...');
if (win.width() >= 1024) {
console.log('large');
$('.header-navigation-menu > div > ul > li').on({
mouseenter: function() {
console.log('waitEnterExit');
waitEnterExit(this, true);
$(this).children('.nav-menu-div').addClass('open');
},
mouseleave: function() {
waitEnterExit(this, false);
},
});
function waitEnterExit(el, inside) {
var button = $(el);
setTimeout(function() {
var hovered = button.is(':hover');
if (hovered && inside)
button.children('.nav-menu-div').addClass('open');
else if (!hovered && !inside)
button.children('.nav-menu-div').removeClass('open');
}, 500);
}
}
if (win.width() <= 1023) {
console.log('small');
$('.menu-link-button').on({
click: function() {
$(this).parent().children('.nav-menu-div').slideToggle();
}
});
}
}, 500);
});

You are doing it in a wrong way, try the below steps and code,
First separate all functions and event bindings from window resize event.
Then check window's width and toggle the elements which are to be hide(if visible)
function waitEnterExit(el, inside) {
var button = $(el);
setTimeout(function() {
var hovered = button.is(':hover');
if (hovered && inside)
button.children('.nav-menu-div').addClass('open');
else if (!hovered && !inside)
button.children('.nav-menu-div').removeClass('open');
}, 500);
}
$('.header-navigation-menu > div > ul > li').on({
mouseenter: function() {
console.log('waitEnterExit');
var win = $(window);
if (win.width() >= 1024) {
console.log('large');
waitEnterExit(this, true);
$(this).children('.nav-menu-div').addClass('open');
}
},
mouseleave: function() {
if (win.width() >= 1024) {
console.log('large');
waitEnterExit(this, false);
}
},
});
$('.menu-link-button').on({
click: function() {
var win = $(window);
if (win.width() <= 1023) {
console.log('small');
$(this).parent().children('.nav-menu-div').slideToggle();
}
}
});
$(window).on('resize', function() {
var win = $(this); //this = window
waitForFinalEvent(function() {
if (win.width() >= 1024) {
console.log('large');
$('.menu-link-button').parent().children('.nav-menu-div').slideUp(); // hide it any way on large screen
} else {
$('.header-navigation-menu > div > ul > li .nav-menu-div').removeClass('open'); // hide it in small screens
}
console.log('Resize...');
}, 500);
});
If window>= 1024 and $('.menu-link-button') is sliding up again and again then check a condition for its visibility like
if (win.width() >= 1024) {
console.log('large');
$('.menu-link-button').parent().children('.nav-menu-div').is(':visible') // if visible then slideup
&&
$('.menu-link-button').parent().children('.nav-menu-div').slideUp(function(){ // hide it any way on large screen
$(this).hide();/*make it hide after slide up*/
});
} else {
$('.header-navigation-menu > div > ul > li .nav-menu-div').removeClass('open'); // hide it in small screens
}

Related

Accordion options will open but not collapse

I'm creating product variant accordions for my Shopify store and so far I've been able to make it so that the accordions will open but they won't collapse when you click on them again. If anyone can provide some guidance on what I'm doing wrong I'd appreciate it!
function swatchNamePlacement() {
$('.swatches .swatch-view .swatch-img-text').each(function () {
var elm = $(this);
var parent = elm.closest('.swatch-view-item');
parent.append(elm);
});
}
function isSwatchKingLoaded() {
var watch = setInterval(myTimer, 200);
function stopTimer() {
clearInterval(watch);
}
function myTimer() {
if(typeof VariantSwatchKing !== "undefined" && VariantSwatchKing !== '') {
if($('.swatches').length > 0){
$('.swatches > div').eq().addClass('open');
stopTimer();
swatchNamePlacement();
}
}
}
}
$('.product__info-wrapper').on('click','.swatches > div', function(e){
e.preventDefault();
var element = $(this);
var parent = element.parent();
// parent.toggleClass('open');
if(parent.hasClass('open')) {
element.removeClass('open')
} else {
parent.find('.swatches > div').removeClass('open');
element.addClass('open')
}
});

How to combine .with() and .resize() in one script

Can you help me with the following?
I have this working javascript code.
This code makes the bootstrap columns in a row all an equal height for screens with a bigger width than 640px.
if($(window).width() >= 640){
$(document).ready(function () {
$(".row").each(function () {
var highestBox = 0;
$(".col", this).each(function () {
if ($(this).height() > highestBox) highestBox = $(this).height();
});
$(".col", this).height(highestBox);
});
});
}
Problem
The problem is that if I resize the window from less than 640px to more than 640px, I have to refresh the page in order to see the changes. I'd like a script that automatically checks the window size. I think the .resize() function can help me with this but I can't figure out how to implement it.
You could implement it as follows. Put your code inside a function, let's call it resizeMe() .Then:
var rtime,
timeout = false,
waitingTime = 200,
resizeFinished = function () {
if (new Date() - rtime < waitingTime) {
window.setTimeout(resizeFinished, waitingTime);
} else {
timeout = false;
if ($(window).width() >= 640) {
resizeMe();
}
}
};
$(window).resize(function () {
rtime = new Date();
if (timeout === false) {
timeout = true;
window.setTimeout(resizeFinished, waitingTime);
}
}).resize();
With this function, your function resizeMe() is fired only when the resizing process has finished. That way it is assured that resizeMe()isn't fired at every mouse move but only if waitingTime is reached (200ms). This is quite important for performance. (Thanks to urban pointing at)
You could use following snippet, using window.matchMedia() (support & polyfill) method and binding handler in load/resize window events:
$(window).on('load resize', function() {
clearTimeout(this.resizeTimeout);
this.resizeTimeout = setTimeout(function() {
if (window.matchMedia("(min-width: 640px)").matches) {
$(".row").each(function() {
var highestBox = Math.max.apply(null, $(this).find('.box').map(function() {
return this.clientHeight; // or $(this).height()
}));
$(this).find('.box').height(highestBox);
});
}
}, 50);
});
EDIT Adding debouncing regarding good point done in #Daenu's answer
just make a function and pass it to window
function resizeMe(){
if($(window).width() >= 640){
$(document).ready(function () {
$(".row").each(function () {
var highestBox = 0;
$(".col", this).each(function () {
if ($(this).height() > highestBox) highestBox = $(this).height();
});
$(".col", this).height(highestBox);
});
});
}
}
then attach an event to window and pass your function
window.addEventListener("resize", resizeMe);
you need to put the
$(document).ready(function () on the top before the if($(window).width() >= 640)
you can use
$( window ).resize(function() function
Based on #Daenu's answer. A compressed/simplified version that is reusing the same timeout:
$(function(){
timeout = null
waitingTime = 200
$(window).resize(function(){
// Clear old timeout
if (timeout)
clearTimeout(timeout)
// Set new
timeout = setTimeout(resizeMe, waitingTime);
})
})
function resizeMe(){
$(".row").each(function () {
var highestBox = 0;
$(".col", this).each(function () {
if ($(this).height() > highestBox) highestBox = $(this).height();
});
$(".col", this).height(highestBox);
});
}
The idea is that if resize is fired while there is an active timeout, we cancel the old and re-schedule a new one
Fiddle: https://jsfiddle.net/hq1jd47v/2/

jQuery toggle not working on resize

When I resize the window, the toggle part is not working, I had to refresh the page again(keeping the window in the resized state) and it works fine.
bodyClass() part is working fine, just not the menu() part.
Please help :)
jQuery(document).ready(function() {
function menu(){
var memberAreaWidth = jQuery(window).width();
if( memberAreaWidth <= 900 ){
jQuery('.memebers-menu').css('display', 'none');
jQuery('.memebers-header-logo span').click(function(){
jQuery('.memebers-menu').toggle();
});
}
}
function bodyClass(){
var memberAreaWidth = jQuery(window).width();
if( memberAreaWidth > 900 ){
jQuery('body').addClass('fullwidth');
}else{
jQuery('body').removeClass('fullwidth');
}
}
jQuery(window).on("load resize",function(){
menu();
bodyClass();
});
});
Move the click event delegation so it only happens once. The rest of the code looks fine.
var smallWidth = false;
jQuery('.memebers-header-logo span').click(function(){
if (smallWidth){
jQuery('.memebers-menu').toggle();
}
});
function menu(){
var memberAreaWidth = jQuery(window).width();
if( memberAreaWidth <= 900 ){
jQuery('.memebers-menu').css('display', 'none');
smallWidth = true;
} else {
smallWidth = false;
}
}
Simplify your code a bit, put the event handlers outside the functions so they do not re-bind each time the function is called (which would end up with multiple event handlers firing); pass a parameter so you only have to calculate it once.
jQuery(document).ready(function() {
jQuery('.memebers-header-logo span').on('click', function() {
jQuery('.memebers-menu').toggle();
});
jQuery(window).on("load resize", function() {
var memberAreaWidth = jQuery(window).width();
menu(memberAreaWidth);
bodyClass(memberAreaWidth);
});
function menu(memberAreaWidth) {
if (memberAreaWidth <= 900) {
jQuery('.memebers-menu').hide();
}
}
function bodyClass(memberAreaWidth) {
if (memberAreaWidth > 900) {
jQuery('body').addClass('fullwidth');
} else {
jQuery('body').removeClass('fullwidth');
}
}
});

Understanding Jquery function - $(document).ready(callback);

Hi am trying to run a function on window resize and document ready. As resize is triggered by mobile scroll it is necessary to check the height hasn't changed. This code works for resize but not on load. Is anyone able to explain whey the function isn't executed on document ready? Thanks in advance.
//CLOSE EXPANDED ELEMENTS FOR MOBILE
var $window = $(window);
var width = $(window).width();
var callback = function () {
if($(window).width() != width){
if ($window.width() < 756) {
$(".content_lower.collapse").removeClass('in');
}
else {
$(".content_lower.collapse").addClass('in');
}
}
};
$(document).ready(callback);
$(window).resize(callback);
console.log(callback.toString());
Actually on document ready the document is just loaded and the $(window).width() is equal to width variable.
So the function callback will be called while width = $(window).width() so it will not enter the if condition and nothing will happen inside the function.
If you try to log somtheing to the console or alert a message in the beginning of your function you will see that it's executed:
var callback = function() {
console.log("Callback entered !!!");
if ($(window).width() != width) {
if ($window.width() < 756) {
$(".content_lower.collapse").removeClass('in');
} else {
$(".content_lower.collapse").addClass('in');
}
}
};
EDIT:
If you still want to execute it in document load you can add a boolean flag initialized to false and set it to true if the window is once resized then test with it:
var $window = $(window);
var width = $(window).width();
var called = false;
var callback = function() {
console.log("callback entered !!!");
if ($(window).width() != width || !called) {
if ($window.width() < 756) {
$(".content_lower.collapse").removeClass('in');
} else {
$(".content_lower.collapse").addClass('in');
}
}
called = true;
};
$(document).ready(callback);
$(window).resize(callback);
console.log(callback.toString());
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="content_lower.collapse">the div</div>
EDIT 2:
A better approach is to use the boolean flag as a parameter of the callback function, and call it with false on document load and true on window resize:
var $window = $(window);
var width = $(window).width();
var callback = function(resized) {
if ($(window).width() != width || !resized) {
if ($window.width() < 756) {
$(".content_lower.collapse").removeClass('in');
} else {
$(".content_lower.collapse").addClass('in');
}
}
};
$(document).ready(callback(false));
$(window).resize(callback(true));
This gave the desired effect. Tanks for the help guys.
var $window = $(window);
var width = $(window).width();
var callback = function () {
if ($window.width() < 756) {
$(".content_lower.collapse").removeClass('in');
}
else {
$(".content_lower.collapse").addClass('in');
}
};
$(document).ready(callback);
$( window ).resize(function() {
if($(window).width() != width){
callback();
}
});
When the document is loaded the width variable will be set to your window-width (let's say 500px). Then it checks if the current window-width (so 500px) is equal to the width var (500 !== 500). This returns false, so you code won't be executed. You can do this instead:
var callback = function() {
if ($(window).width() < 756) {
$('body').text($(window).width() + " - if");
} else {
$('body').text($(window).width() + " - else");
}
};
$(document).ready(callback);
$(window).resize(callback);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Prevent scrolling jquery script from running twice

I'm new to jquery and have put together the following code to make a DIV appear after a set scroll-down amount. If scrolling back up, the DIV disappears. Optionally, once the DIV has appeared, there is a link to close it. This all works as intended, apart from that I only want the script to run once. At the moment if I scroll back up, the yellow box appears again. How can I ensure the box stays closed? As another option, could I integrate cookies or localStorage?
Many thanks! Russ.
Javascript:
$(function () {
var target = $(".box");
if ($(window).scrollTop() > 30) {
target.hide();
}
$(window).scroll(function () {
var pos = $(window).scrollTop();
if (pos > 30) {
target.stop(true, true).fadeIn('slow');
} else {
target.stop(true, true).fadeOut('slow');
}
});
$('a.close').click(function () {
$($(this).attr('href')).slideUp();
return false;
});
});
Here is the jsfiddle link to my code: jsfiddle link
You can remove the class to ensure the box stays enclosed with removeClass(). Or directly $(".box").remove() after your animation.
You can store this choice with cookie but if the client deletes his cookies, it's lost.
You can remove event scroll from window and for localStorage do something like that:
$(function () {
var target = $(".box");
if ($(window).scrollTop() > 30) {
target.hide();
}
$(window).scroll(function () {
var pos = $(window).scrollTop();
if (pos > 30) {
target.stop(true, true).fadeIn('slow');
} else {
target.stop(true, true).fadeOut('slow');
}
if(localStorage['noNotification'] == 'true'){
$(window).off('scroll');
}
});
$('a.close').click(function () {
$($(this).attr('href')).slideUp();
$(window).off('scroll');
localStorage['noNotification'] = 'true';
return false;
});
});
try this http://jsfiddle.net/AbwXu/4/
var notdisplayed=true;
$(function(){
var target = $(".box");
if($(window).scrollTop() > 30){
target.hide();
}
$(window).scroll(function(){
var pos = $(window).scrollTop();
if(pos > 30 && notdisplayed){
target.stop(true, true).fadeIn('slow');
} else {
target.stop(true, true).fadeOut('slow');
notdisplayed=false;
}
});
$('a.close').click(function() {
$($(this).attr('href')).slideUp();
notdisplayed=false;
return false;
});

Categories