2 * Superfish v1.4.8 - jQuery menu widget
3 * Copyright (c) 2008 Joel Birch
5 * Dual licensed under the MIT and GPL licenses:
6 * http://www.opensource.org/licenses/mit-license.php
7 * http://www.gnu.org/licenses/gpl.html
9 * CHANGELOG: http://users.tpg.com.au/j_birch/plugins/superfish/changelog.txt
13 $.fn.superfish = function(op) {
15 var sf = $.fn.superfish,
18 $arrow = $(['<span class="', c.arrowClass, '"> »</span>'].join('')),
19 click = function(evt) {
20 $(".subnav.ddopen").hide();
24 if (o.firstOnClick && !menuActive && $$.parent()[0] == menu)
27 clearTimeout(menu.sfTimer);
29 $$.showSuperfishUl().siblings().hideSuperfishUl();
30 // prevent redirect to anchor target href
38 //Bug#52225: Activate submenu while hs-activated
39 if($$.parent().hasClass("hs-active")) {
42 $$.removeClass("iefix");
45 if (!o.firstOnClick || menuActive || $$.parent()[0] != menu)
47 clearTimeout(menu.sfTimer);
48 $$.showSuperfishUl().siblings().hideSuperfishUl();
49 if($$.parent().hasClass('megamenuSiblings')) {
50 $$.parent().siblings().children('li').hideSuperfishUl();
60 if($$.parent().hasClass("hs-active")) {
62 setTimeout(function() {
63 if($menu.hasClass(sf.defaults['retainClass']) === false)
67 $$.removeClass("iefix");
70 clearTimeout(menu.sfTimer);
71 menu.sfTimer = $menu.hasClass(sf.defaults['retainClass']) ? null : setTimeout(function() {
72 if($menu.hasClass(sf.defaults['retainClass']) === false) {
73 o.retainPath = ($.inArray($$[0], o.$path) > -1);
75 if (o.$path.length && $$.parents(['li.', o.hoverClass].join('')).length < 1)
88 getMenu = function($menu) {
89 var menu = $menu.hasClass(sf.menuClass) ? $menu[0] : $menu.parents(['ul.', c.menuClass, ':first'].join(''))[0];
92 sf.op = sf.o[menu.serial];
95 addArrow = function($a) {
96 $a.addClass(c.anchorClass).append($arrow.clone());
99 return this.each(function() {
100 var s = this.serial = sf.o.length;
104 $('li.' + o.pathClass, this).slice(0, o.pathLevels).each
107 $(this).addClass([o.hoverClass, c.bcClass].join(' '))
109 .filter('li:has(ul)').removeClass(o.pathClass);
114 $('li:has(ul)', this).not('li:has( > .' + sf.ignoreClass + ')')['click'](click);
116 $('li:has(ul)', this).not('li:has( > .' + sf.ignoreClass + ')')[($.fn.hoverIntent && !o.disableHI) ? 'hoverIntent' : 'hover'](over, out);
119 $('li:has(ul)', this)
122 if (o.autoArrows) addArrow(
123 $('>a:first-child', this));
125 .not('.' + c.bcClass)
128 var $a = $('a', this);
129 $a.each(function(i) {
130 var $li = $a.eq(i).parents('li');
132 $a.eq(i).attr("tabindex",-1).focus(function() {
141 $a.eq(i).click(function(event)
143 event.preventDefault();
144 if ( !$a.eq(i).hasClass("sf-with-ul") || $li.children('ul').size() == 0) {
145 SUGAR.ajaxUI.loadContent(this.href);
150 $a.eq(i).dblclick(function(event)
152 SUGAR.ajaxUI.loadContent(this.href);
160 var menuClasses = [c.menuClass];
161 if (sf.op.dropShadows && !($.browser.msie &&
163 7)) menuClasses.push(c.shadowClass);
164 $(this).addClass(menuClasses.join(' '));
168 var sf = $.fn.superfish;
172 sf.IE7fix = function() {
174 if ($.browser.msie && $.browser.version > 6 && o.dropShadows &&
175 o.animation.opacity != undefined)
176 this.toggleClass(sf.c.shadowClass + '-off');
179 sf.positionMenu = function($ul) {
181 if(this.offset() && this.parent().parent().hasClass('sf-menu') != true) {
182 var viewPortHeight = $(window).height(),
183 submenuHeight = this.outerHeight(),
184 submenuTop = this.offset().top - $(document).scrollTop();
186 if(submenuTop + submenuHeight > viewPortHeight) {
187 this.css('top','auto');
188 this.css('bottom','0px');
193 * Return css property variale which contains numerical data.
194 * i.e. width, border, padding-left, etc.
195 * @param this - element that is trying to retrive
196 * @param $css - css properity which contains numerical data
197 * @return int - value of the size
199 sf.cssValue = function($css) {
202 var _val = parseInt(this.css($css).replace("px", ""));
203 return (_val) ? _val : 0;
206 * To support IE fixed size rendering,
207 * parse out dom elements out of the fixed element
210 * <div style=position:fixed>
212 * <li jquery-attached>
213 * <ul style=position:absoulte>
220 * <div style=position:fixed>
221 * <li ul-child-id='auto-evaluted-id'>
226 * <ul id='auto-evaluted-id' style=position:fix;left/right/top-positioning:auto-calculated>
229 * @param this - element container which is inside the fixed box model
230 * @param $ul - dropdown box model which needs to render out of the fixed box range
231 * if $ul is not given, it will restore back to the original structure
233 sf.IEfix = function($ul) {
234 if ( ($.browser.msie && $.browser.version > 6) || $(this).hasClass("iefix") ) {
236 //Take out the element out of the fixed box model,
237 //and then append it into the end of body container
238 this.each(function(){
241 _id = $$.attr("ul-child-id") ? $$.attr("ul-child-id") : ($ul.attr('id')) ? $ul.attr('id') : o.megamenuID ? o.megamenuID + ++sf.counter : 'megamenu' + ++sf.counter,
242 _top = $$.position().top + $$.parent().offset().top - $(document).scrollTop(),
243 _left = $$.offset().left - sf.cssValue.call($ul, "border-left-width"),
244 $menu = $('ul.' + sf.c.menuClass + ':visible');
245 //handling sub-sliding menu
246 if($$.css('position') == 'static' || $$.parent().hasClass('megamenuSiblings')) {
247 _left += $$.outerWidth() + sf.cssValue.call($ul, "border-right-width");
248 $ul.addClass('sf-sub-modulelist').on('mouseover', function(){
249 $$.addClass(sf.defaults['retainClass']);
250 }).on('mouseout', function(){
251 $$.removeClass(sf.defaults['retainClass']);
252 $('ul.' + sf.c.menuClass + ':visible').removeClass(sf.defaults['retainClass'])[0].sfTimer = setTimeout(function(){
253 $$.hideSuperfishUl();
254 $('ul.' + sf.c.menuClass + ':visible > li').hideSuperfishUl();
258 _top += $$.outerHeight();
261 //append the item into the body element, and then save the id to restore back later
262 $('body').append($ul.attr("id", _id).css({
266 }).on('mouseover',function(){
267 //maintaining the dropdown container
268 var menu = sf.getMenu($menu),
270 clearTimeout(menu.sfTimer);
271 if( $(menu).hasClass(sf.defaults['retainClass']) === false )
272 $(menu).addClass(sf.defaults['retainClass']);
273 }).on('mouseout', function(){
274 //clear out the dropdown menu
275 var menu = sf.getMenu($menu),
277 clearTimeout(menu.sfTimer);
279 menu.sfTimer = setTimeout(function() {
280 $$.hideSuperfishUl();
281 $(menu).removeClass(sf.defaults['retainClass']);
282 $(menu).hideSuperfishUl();
286 $$.attr("ul-child-id", _id);
290 //restore back the element to the original structure
291 this.each(function(){
292 var _id = $(this).attr("ul-child-id");
293 $(this).append($("body>#"+_id).off('mouseover mouseout'));
299 bcClass: 'sf-breadcrumb',
300 menuClass: 'sf-js-enabled',
301 anchorClass: 'sf-with-ul',
302 arrowClass: 'sf-sub-indicator',
303 shadowClass: 'sf-shadow'
306 hoverClass: 'sfHover',
307 retainClass: 'retainThisItem',
309 pathClass: 'overideThisToUse',
319 // true disables hoverIntent detection
320 onInit: function() {},
321 // callback functions
322 onBeforeShow: function() {},
323 onShow: function() {},
324 onHide: function() {},
326 // true - open first level on click (like classic application menu)
330 hideSuperfishUl: function() {
332 not = (o.retainPath === true) ? o.$path: '';
333 o.retainPath = false;
335 var $ul = $(['li.', o.hoverClass].join(''), this).add(this).not
336 (not).removeClass(o.hoverClass).find('>ul').hide().css('visibility', 'hidden');
340 showSuperfishUl: function() {
342 sh = sf.c.shadowClass + '-off',
343 $ul = this.addClass(o.hoverClass).find('>ul:hidden').show().css('visibility', 'visible');
345 sf.positionMenu.call($ul);
346 o.onBeforeShow.call($ul);
347 sf.IEfix.call(this, $ul);
348 $ul.animate(o.animation, o.speed,