Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Updated version of Supposition. This version is compatible with Superfish 1.6+. See this ancient page for description, example and caveats: http://users.tpg.com.au/j_birch/plugins/superfish/supposition-test/
/*
* Supposition v0.3a - an optional enhancer for Superfish jQuery menu widget
*
* Copyright (c) 2013 Joel Birch - based on work by Jesse Klaasse - credit goes largely to him.
* Special thanks to Karl Swedberg for valuable input.
*
* Dual licensed under the MIT and GPL licenses:
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html
*/
;(function($){
$.fn.supposition = function(){
var $w = $(window), /*do this once instead of every onBeforeShow call*/
_offset = function(dir) {
return window[dir == 'y' ? 'pageYOffset' : 'pageXOffset']
|| document.documentElement && document.documentElement[dir=='y' ? 'scrollTop' : 'scrollLeft']
|| document.body[dir=='y' ? 'scrollTop' : 'scrollLeft'];
},
onInit = function(){
/* I haven't touched this bit - needs work as there are still z-index issues */
$topNav = $('li',this);
var cZ=parseInt($topNav.css('z-index')) + $topNav.length;
$topNav.each(function() {
$(this).css({zIndex:--cZ});
});
},
onHide = function(){
this.css({marginTop:'',marginLeft:''});
},
onBeforeShow = function(){
this.each(function(){
var $u = $(this);
$u.css('display','block');
var menuWidth = $u.width(),
parentWidth = $u.parents('ul').width(),
totalRight = $w.width() + _offset('x'),
menuRight = $u.offset().left + menuWidth;
if (menuRight > totalRight) {
$u.css('margin-left', ($u.parents('ul').length == 1 ? totalRight - menuRight : -(menuWidth + parentWidth)) + 'px');
}
var windowHeight = $w.height(),
offsetTop = $u.offset().top,
menuHeight = $u.height(),
baseline = windowHeight + _offset('y');
var expandUp = (offsetTop + menuHeight > baseline);
if (expandUp) {
$u.css('margin-top',baseline - (menuHeight + offsetTop));
}
$u.css('display','none');
});
};
return this.each(function() {
var $this = $(this),
o = $this.data('sf-options'); /* get this menu's options */
/* if callbacks already set, store them */
var _onInit = o.onInit,
_onBeforeShow = o.onBeforeShow,
_onHide = o.onHide;
$.extend($this.data('sf-options'),{
onInit: function() {
onInit.call(this); /* fire our Supposition callback */
_onInit.call(this); /* fire stored callbacks */
},
onBeforeShow: function() {
onBeforeShow.call(this); /* fire our Supposition callback */
_onBeforeShow.call(this); /* fire stored callbacks */
},
onHide: function() {
onHide.call(this); /* fire our Supposition callback */
_onHide.call(this); /* fire stored callbacks */
}
});
});
};
})(jQuery);
@matrym

This comment has been minimized.

Copy link

@matrym matrym commented Jun 5, 2013

The current version with the most recent superfish.js can create a flash when used with hoverintent. This issue doesn't exist on the demo site, which uses older versions of each. I believe the issue may be with the latest hoverintent.

@mcpmbstu

This comment has been minimized.

Copy link

@mcpmbstu mcpmbstu commented Dec 29, 2014

Hello Matrym, i faced the same issue, then i got the solution. here is the code with latest script i used.

jQuery('ul.sf-menu').superfish({
animation : { opacity:'show' }, /also works with 'height' etc./
onInit : jQuery.fn.supposition.onInit,
onBeforeShow : jQuery.fn.supposition.onBeforeShow,
onHide : jQuery.fn.supposition.onHide
});

hope this will help you. important to use "fn"

thanks

@joefaron

This comment has been minimized.

Copy link

@joefaron joefaron commented Apr 21, 2015

solid addition.

@Matticus289

This comment has been minimized.

Copy link

@Matticus289 Matticus289 commented Jul 13, 2015

I have found that IE10+ has a problem maintaining the position of the re-positioned nav items when used with superfish (happening up to version 1.7.5 of superfish). For example, if the child nav item would normally appear outside the browser window when its parent is hovered over and is given a negative margin left of -200px by suppostion() to correct it, it will suddenly lose the -200px margin the moment a link inside the element is clicked and not navigate to the clicked link. It moves back to it's normal position. Surprisingly, IE9 doesn't seem to have this problem.

A Live example:
http://www.wileyrein.com - try clicking on a menu item under "diversity" when you make your browser window small enough that the dropdown menu has to be re-positioned and you will see what I mean.

https://www.taylorenglish.com/ Same thing on the "careers" drop down.

@cemelmaci

This comment has been minimized.

Copy link

@cemelmaci cemelmaci commented Sep 27, 2015

i think solition for flashing problem
52 $u.css('display','none'); to //$u.css('display','none');

thanks

@carasmo

This comment has been minimized.

Copy link

@carasmo carasmo commented Nov 25, 2015

This works in the sense that it moves the menu, but the hovered menus that have children have to be hovered twice since it doesn't open the link on the first click.

@carasmo

This comment has been minimized.

Copy link

@carasmo carasmo commented Nov 25, 2015

Never mind. It was a wordpress issue. Works great!

@imfaisalkh

This comment has been minimized.

Copy link

@imfaisalkh imfaisalkh commented Oct 13, 2016

@cemelmaci Commenting out this line $u.css('display','none'); solves the flickering issue, but it also disables any animaion on the menu.

@moorthidaniel

This comment has been minimized.

Copy link

@moorthidaniel moorthidaniel commented Nov 14, 2017

this plugin helped me to display sub menu items in the left side, if there is not enough screen space on the right
check out this post https://stackoverflow.com/a/47286812/202503

@namkazt

This comment has been minimized.

Copy link

@namkazt namkazt commented Jan 16, 2020

for anyone that have issue with flashing and animation, replace onBeforeShow this only check for sub-menu and no need to set display to block to check.

onBeforeShow = function () {
                this.each(function () {
                    var $u = $(this);
                    var menuWidth = $u.width(),
                        parentWidth = $u.parents('ul').width(),
                        totalRight = $w.width() + _offset('x'),
                        menuRight = $u.offset().left + menuWidth;
                    if ($u.parents('li').hasClass('menu-has-children')) {
                        menuRight = $u.parents('ul').offset().left + menuWidth + $u.parents('ul').width()
                    }
                    if (menuRight > totalRight) {
                        $u.css('margin-left', ($u.parents('ul').length == 1 ? totalRight - menuRight : -(menuWidth + parentWidth)) + 'px');
                    }

                    var windowHeight = $w.height(),
                        offsetTop = $u.offset().top,
                        menuHeight = $u.height(),
                        baseline = windowHeight + _offset('y');
                    var expandUp = (offsetTop + menuHeight > baseline);
                    if (expandUp) {
                        $u.css('margin-top', baseline - (menuHeight + offsetTop));
                    }
                });
            };
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment