Disable superfish on resize event - javascript

I'm trying to combine the Superfish jQuery plugin with Nathan Smith's adapt.js snippet, which dynamically loads in different CSS files depending on browser width. I want to disable/replace/something the Superfish menu when in mobile mode, because drop-downs don't make any sense there. I've attempted to detect the change and disable the menu, but I need it to re-enable when the window is resized wide again.
Here's what I have:
function htmlId(i, width) {
document.documentElement.id = 'pagesize_' + i;
}
var ADAPT_CONFIG = {
path: '/css/',
dynamic: true,
callback: htmlId,
range: [
'0px to 760px = mobile.css',
'760px = 960_12.css'
]
};
function sfMenu() {
$("#pagesize_1 ul.sf-menu").superfish({
delay: 800,
animation: {opacity:'show'},
speed: 'fast',
autoArrows: true,
dropShadows: true
});
}
$(document).ready(function(){
sfMenu();
});
The rationale was to change the id of the html element on resize (between pagesize_0 and pagesize_1 - which works) and to use descendent selectors in CSS to disable the menu, but that doesn't work. I tried rerunning sfMenu() on resize (code not shown above), but it doesn't seem to inspect the changed DOM, realise pagesize_1 no longer exists, then fail gracefully (which I think would achieve the effect I'm after).
Any thoughts? Ideally I'd like to destroy the superfish function on resize-to-mobile, then re-instate it when the screen is large again.

SuperFish has a 'destroy' method (certainly in latest 1.7.3 version) that you could call depending on screen size to disable it and then re-style the navigation using CSS media queries. You could also then call the 'init' method of SuperFish when you wanted to enable it again:
var sf, body;
var breakpoint = 600;
jQuery(document).ready(function($) {
body = $('body');
sf = $('ul.sf-menu');
if(body.width() >= breakpoint) {
// enable superfish when the page first loads if we're on desktop
sf.superfish();
}
$(window).resize(function() {
if(body.width() >= breakpoint && !sf.hasClass('sf-js-enabled')) {
// you only want SuperFish to be re-enabled once (sf.hasClass)
sf.superfish('init');
} else if(body.width() < breakpoint) {
// smaller screen, disable SuperFish
sf.superfish('destroy');
}
});
});
This should hopefully explain what I'm talking about :)
http://cdpn.io/jFBtw

I've been playing around with the same thing, going from horizontal nav-bar style (window wider than subnav) to vertical drop-down style (subnav wider than window) to just plain-ol-list (main nav wider than window).
Not sure how elegant it is, but in the end unbind() and removeAttr('style') disabled the dropdowns for me:
$(window).resize(function() {
if ($(this).width() < maxNavigationWidth) {
$('#neck .navigation').removeClass('sf-menu');
$('.navigation li').unbind();
$('.navigation li ul').removeAttr('style');
} else {
$('#neck .navigation').addClass('sf-menu').addClass('sf-js-enabled');
applySuperfish();
}
});

Related

How to prevent body from scrolling with push-side menu

I am trying to properly implement a push-side menu plugin (Responsive Menu) into a wordpress theme. Based on SO #Congrim answer, I've managed to achieve a way to lock the body at scroll when push-menu is open (with all the elements including the header fixed) except the interactive links class=edge-ils edge-ils-with-scroll edge-ils-light which will still go Up at push-menu open.
I've saved this sequence into congrim.js file, I've enqueued the script into the theme in functions.php file:
function lockScroll() {
if ($('body').hasClass('lock-scroll')) {
$('body').removeClass('lock-scroll');
}
else {
$('body').addClass('lock-scroll');
}
}
/* I've implemented `onclick="lockScroll();"` in button element,
* using this sequence in the same congrim.js file:
*/
$(document).ready(function() {
$('#responsive-menu-pro-button').click(function() {
lockScroll();
});
});
Removing the jQuery wrap will not give any error in browser console (tested in Chrome) may be still a bad approach to wrapp the code like this in wordpress (?)
In these conditions, unfortunately, overflow: hidden; doesn't apply, at push-side menu open, I can't use this class in CSS file/section:
.lock-scroll {
overflow: hidden;
}
The code will allow me to use only
.lock-scroll {
position: fixed;
}
The question:
Is there any possibility to force the code to implement overflow: hidden;* OR any other a workaround in order to have the interactive links class=edge-ils edge-ils-with-scroll edge-ils-light not going up at push-side menu open, to remain fixed at the position the viewer is clicked before opening the menu?
Please focus on the interactive links issue only, the rest of the scene is fine (header and the logo are in place like it should be, the background pictures are acting like it should as well).
LE: *overflow: hidden; it looks like will produce an unwanted body shifting effect at menu open/close, during the show/hide scrollbar, which is not happening in this stage.
LE2: congrim.js file has been replaced with body-lock.min.js by Outsource WordPress, please see the solution below.
Website testpage here.
Please check the solution given below.
Step 1: Add this CSS .scroll-lock{position:fixed !important;}.
Step 2: Add this JS.
$(document).ready(function() {
var windowTop = 0;
var menuOpen = 0;
var offsetContainerList = 0;
$('#responsive-menu-pro-button').click(function() {
var offsetScrollList = $('.edge-ils-item-link:first').offset().top;
if ($('html').hasClass('scroll-lock')) {
$('#responsive-menu-pro-container').one("webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend",
function(event) {
if (menuOpen==0) {
menuOpen = 1;
$('html').removeClass('scroll-lock');
$('.edge-ils-content-table').css('top', eval(offsetContainerList)-40+'px'); //change image container top position
$('html').scrollTop(windowTop); //scroll to original position
}
else {
menuOpen = 0;
}
});
}
else {
windowTop = $(window).scrollTop();
offsetContainerList = $('.edge-ils-content-table').offset().top;
$('html').addClass('scroll-lock');
$('.edge-ils-content-table').css('top', -offsetScrollList + 'px'); //change image container top position
}
});
});
That's it!
Please add the below code in your custom js file .
jQuery('#responsive-menu-pro-button').click(function(){
var menu_active = jQuery(this).hasClass('is-active');
if(menu_active){
jQuery('body').css('position','fixed');
}else{
jQuery('body').css('position','static');
}
});
I hope it helps you.
Thanks
Your scroll isn't a natural navigator-based scroll, you have a JS somewhere swapping classes to emulate a scroll (edge-appeared,edge-up,edge-down).
On the push-side menu opening, these classes are reset, overflow-hidden won't change that.
You need to find which JavaScript is swapping those classes and prevent it from doing so, I'd be glad to be of further help but you have so many JS files that it would take quite some time to go through all of these. If you succeed in making a Minimal, Complete, and Verifiable example please post it here.

jQuery media queries for toggle button - different action depending on screen width

I have a toggle button which basically shows/hides a list of filters on a Product Index page. Desktop is simple, when clicking the button the panel is shown or hidden with the following script:
$(".filter-toggle").click(function(){
$(".grid").toggleClass("hide-filters");
});
When the browser is below 1024px I use the mmenu plugin to duplicate the filters content and move it into an off-canvas panel. The code for that looks like this:
$(document).ready(function() {
$(".filters").mmenu({
// Options
navbar: {
title: "Filters"
}
}, {
// Configuration
clone: true,
offCanvas: {
pageSelector: ".page"
},
classNames: {
selected: "active"
}
});
var API = $(".filters").data("mmenu");
var $icon = $(".filter-toggle");
$icon.on("click", function() {
API.open();
});
});
Obviously (at the minute) when the toggle button is clicked it will show/hide the content on the page but also trigger the slide-out menu at the same time.
My question is how can I only run the relevant script when it's needed. Is it also possible to do this on resize on not just on pageLoad/refresh?
I tried using matchMedia. Here's a quick CodePen showing where I'm at...
https://codepen.io/moy/pen/wymvjN
It looked like it worked to begin with. Above 1024px the toggle worked. Shrinking the browser down meant the button triggered the slide-out panel - great! But when scaling back up to desktop the slide-out menu is triggered whenever the toggle is clicked. On refresh it works again ...until you shrink the browser down and back up again.
Any ideas?
You can listen for window resize events, and fire functions accordingly. For example, in jQuery:
$(window).on('resize', function(e) {
var windowWidth = $(window).width();
if (windowWidth < 1024) {
// initialize small viewport functionality
} else {
// initialized large viewport functionality
}
});
But, you'll need a way to disable that mmenu plugin when switching back to desktop, and include it in whatever script you run during that condition.
Alternatively, the mmenu "Responsive Layout" documentation provides an example for using CSS media queries to hide the cloned menu at certain breakpoints.

How to make BootstrapDialog movable on mobile

I'm using https://github.com/nakupanda/bootstrap3-dialog to make a dialog, but on mobile phones the dialog mostly larger than the screen size. On Desktop when I change the width into the same size as mobile, we can drag the dialog header using mouse, but it can't be done on mobile.
This is the screen size.
The dialog after being dragged to left.
Is there a way to make the dialog dragable on mobile?
Or is there a better solution?
EDIT
I tried to reproduce the problem using simpler setup, but it shows different css used on .modal-dialog:
the problem:
the simpler setup:
And now I know that the problem was the CSS' min-width property.
Then I hack it by replacing that property when creating BootstrapDialog
onshown: function() {
$('.modal-dialog').css('min-width', 'auto');
}
For the dialog sizes I think this is answered in comments. For dragging the dialog around [draggable : true] on mobiles you must change a little bit in the sourcecode.
bootstrap3-dialog does simply not respond to mobile events such as touchstart, touchend and touchmove {reference}.
Take a look at the code from line 1080 :
https://github.com/nakupanda/bootstrap3-dialog/blob/master/src/js/bootstrap-dialog.js#L1080
Add mobile events so bootstrap3-dialog can be draggable on mobile devices too :
...
makeModalDraggable: function() {
if (this.options.draggable) {
this.getModalHeader().addClass(this.getNamespace('draggable')).on('mousedown touchstart', {
dialog: this
}, function(event) {
var dialog = event.data.dialog;
dialog.draggableData.isMouseDown = true;
var dialogOffset = dialog.getModalDialog().offset();
dialog.draggableData.mouseOffset = {
top: event.clientY - dialogOffset.top,
left: event.clientX - dialogOffset.left
};
});
this.getModal().on('mouseup mouseleave touchend touchcancel', {
dialog: this
}, function(event) {
event.data.dialog.draggableData.isMouseDown = false;
});
$('body').on('mousemove touchmove', {
dialog: this
}, function(event) {
var dialog = event.data.dialog;
if (!dialog.draggableData.isMouseDown) {
return;
}
dialog.getModalDialog().offset({
top: event.clientY - dialog.draggableData.mouseOffset.top,
left: event.clientX - dialog.draggableData.mouseOffset.left
});
});
}
return this;
},
...
NB: Completely untested, but I am convinced that this is (the only) way to go.
NBĀ²: The refactor above is only meant as a here-and-now solution. You should raise the issue on the github project site. I am sure the authors will think it is a great idea to make bootstrap3-dialog mobile ready too.

Applying snap.js to my main content wrapper seems to break *some* of my jQuery functions

I'm using snap.js which enables you to slide your main content div over using css3 and javascript, revealing a menu underneath.
The problem I am having is that when I apply the class snap-content, which tells snap.js which div to slide, that being my main site wrapper, the elements relying on jQuery for their sizing behave unexpectedly.
Here's my situation.
I'm using jQuery to make an element fixed when scrolling past a certain point:
jQuery(document).ready(function ($) {
$(window).scroll(function () {
if ($(this).scrollTop() > 140) {
if ($("#mainMenu").css('position') !== 'fixed') {
$("#mainMenu").css("position", "fixed");
}
} else {
if ($("#mainMenu").css('position') !== 'static') {
$("#mainMenu").css("position", "static");
}
}
});
});
When using snap.js I had to change $(window).scroll to $('#wrapper').scroll because the wrapper is now the scrollable content. I believe this could have something to do with my problem.
When the menu becomes fixed I use some jQuery to keep it the same width as the container it was inside before it became fixed:
jQuery(function ($) {
$(window).resize(_.debounce(function () {
var elementWidth = $('#sidebarWrapper').width();
$('#mainMenu').css('width', elementWidth + 'px');
}, 10));
});
This all works fine before I add the class snap-content, and I can resize the browser without any problems.
When the class is added the sizing no longer works.
There are other functions to do with sizing that start to act unexpectedly too but this is just an example.
I assumed it might be something clashing with my jQuery but I'm using jQuery(function($) so that should stop that right?
snap.js
instead of adding the event to the window scroll add it to the snapcontent since you are scrolling on the snapcontent div instead of the window

How to disable swipe.js carousel

I'm trying to responsively convert a list of images into a carousel. I am using the swipe.js (swipejs.com) libary as it's performs perfectly.
I want the carousel to be initiated when the body width reaches less than 540px but reversly if the window is resized to a body width that is greater than 540px this is reverted.
$(window).resize(function() {
var bodyWidth = $('body').width();
if(bodyWidth < 540){
loadCarousel();
}else if(bodyWidth > 540) {
unLoadCarousel();
}
});
function loadCarousel() {
window.deviceSwipe = new Swipe(
document.getElementById('device-slider')
);
}
function unLoadCarousel() {
}
Now this is close to how I want it (I believe), my real question is, how do I unload(disable?) this carousel and remove the inline styles swipe.js includes?
I can use the following line to remove the styles but this seems like a bit of a bodge job.
$('#slider-container li, #slider-container ul, #device-slider').attr('style', '')
This also doesn't stop swipe.js from just re-applying the styles on window resize (even if the bodyWidth is greater than 540px for some reason).
Any help would be greatly appreciated!
You can use method called kill as deviceSwipe.kill()

Categories