Last active
April 8, 2016 08:25
-
-
Save SimonHooker/c797a95d965cec891e4df72028b1da2b to your computer and use it in GitHub Desktop.
Dropdown menu example for http://www.edugeek.net/newreply.php?do=postreply&t=168504
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<script src="http://code.jquery.com/jquery-1.12.3.min.js"></script> | |
<style type="text/css"> | |
#nav ul { list-style: none; margin: 0; padding: 0; } | |
#nav ul li { display: inline-block; margin: 0 1em 0 1em; padding: 0.35em 0.75em 0.35em 0.75em; border-radius: 0.5em; } | |
#nav ul li.active { background: #999; } | |
#nav ul li.active a { color: #fff; text-decoration: none; } | |
.dropotron { background: #444; border-radius: 0.5em; list-style: none; margin: 0; min-width: 10em; padding: 0.75em 1em 0.75em 1em; } | |
.dropotron > li { border-top: solid 1px #555; margin: 0; padding: 0; } | |
.dropotron > li:first-child { border-top: 0; } | |
.dropotron > li > a { color: #ccc; display: block; padding: 0.5em 0 0.5em 0; text-decoration: none; } | |
.dropotron > li.active > a, .dropotron > li:hover > a { color: #fff; } | |
.dropotron.level-0 { margin-top: 1.25em; } | |
.dropotron.level-0:before { content: ''; position: absolute; border-bottom: solid 0.5em #444; border-left: solid 0.5em transparent; border-right: solid 0.5em transparent; top: -0.5em; } | |
</style> | |
<nav id="nav"> | |
<ul> | |
<li> | |
<a href="#">Curriculum</a> | |
<ul> | |
<li><a tabindex="1" href="URLTOPAGE">Art</a></li> | |
<li><a tabindex="1" href="URLTOPAGE">GCSE Media Studies</a></li> | |
<li><a tabindex="1" href="URLTOPAGE">Humanities & Social Sciences</a></li> | |
</ul> | |
</li> | |
<li> | |
<a href="URLTOPAGE">Information</a> | |
<ul> | |
<li><a tabindex="1" href="URLTOPAGE">Information Home</a></li> | |
<li><a tabindex="1" href="URLTOPAGE">Admissions</a></li> | |
<li><a tabindex="1" href="URLTOPAGE">Behaviour For Learning</a></li> | |
</ul> | |
</li> | |
</ul> | |
</nav> | |
<script type="text/javascript"> | |
$( function() { | |
/* jquery.dropotron.js v1.4.3 | (c) n33 | n33.co | MIT licensed */ | |
(function($) { | |
// Disables selection. | |
$.fn.disableSelection_dropotron = function() { return $(this).css('user-select', 'none').css('-khtml-user-select', 'none').css('-moz-user-select', 'none').css('-o-user-select', 'none').css('-webkit-user-select', 'none'); } | |
// Dropotron prototype method. | |
$.fn.dropotron = function(options) { | |
if (this.length == 0) | |
return $(this); | |
if (this.length > 1) | |
for (var i=0; i < this.length; i++) | |
$(this[i]).dropotron(options); | |
return $.dropotron($.extend({ selectorParent: $(this) }, options)); | |
} | |
// Dropotron method. | |
$.dropotron = function(options) { | |
// Settings. | |
var settings = $.extend({ | |
// Parent jQuery object. | |
selectorParent: null, | |
// Base Z-Index. | |
baseZIndex: 1000, | |
// Menu class (assigned to every <ul>). | |
menuClass: 'dropotron', | |
// Expansion mode ("hover" or "click"). | |
expandMode: 'hover', | |
// Hover delay (in ms). | |
hoverDelay: 150, | |
// Hide delay (in ms; 0 disables). | |
hideDelay: 250, | |
// Opener class. | |
openerClass: 'opener', | |
// Active opener class. | |
openerActiveClass: 'active', | |
// Submenu class prefix. | |
submenuClassPrefix: 'level-', | |
// Menu mode ("instant", "fade", "slide", "zoom"). | |
mode: 'fade', | |
// Menu speed ("fast", "slow", or ms). | |
speed: 'fast', | |
// Easing mode ("swing", "linear"). | |
easing: 'swing', | |
// Alignment ("left", "center", "right"). | |
alignment: 'left', | |
// Submenu offset X. | |
offsetX: 0, | |
// Submenu offset Y. | |
offsetY: 0, | |
// Global offset Y. | |
globalOffsetY: 0, | |
// IE Offset X. | |
IEOffsetX: 0, | |
// IE Offset Y. | |
IEOffsetY: 0, | |
// If true and mode = "fade", prevents top-level opener fade. | |
noOpenerFade: true, | |
// Detach second level menus (prevents parent style bleed). | |
detach: true, | |
// If true and detach = true, leave original menu intact. | |
cloneOnDetach: true | |
}, options); | |
// Vars. | |
var $top = settings.selectorParent, | |
$menus = $top.find('ul'), | |
$body = $('body'), | |
$bodyhtml = $('body,html'), | |
$window = $(window); | |
var isLocked = false, | |
hoverTimeoutId = null, | |
hideTimeoutId = null; | |
// Main. | |
// Top. | |
$top | |
.on('doCollapseAll', function() { | |
$menus.trigger('doCollapse'); | |
}); | |
// Top level menus. | |
$menus.each(function() { | |
var $menu = $(this), $opener = $menu.parent(); | |
// If a hideDelay is set, set up the event. | |
if (settings.hideDelay > 0) | |
$menu.add($opener) | |
.on('mouseleave', function(e) { | |
window.clearTimeout(hideTimeoutId); | |
hideTimeoutId = window.setTimeout(function() { | |
$menu.trigger('doCollapse'); | |
}, settings.hideDelay); | |
}); | |
// Menu. | |
$menu | |
.disableSelection_dropotron() | |
.hide() | |
.addClass(settings.menuClass) | |
.css('position', 'absolute') | |
.on('mouseenter', function(e) { | |
window.clearTimeout(hideTimeoutId); | |
}) | |
.on('doExpand', function() { | |
// Already visible? Bail out. | |
if ($menu.is(':visible')) | |
return false; | |
// Reset our "hide" timeout. | |
window.clearTimeout(hideTimeoutId); | |
// Collapse everything but this menu. | |
$menus.each(function() { | |
var $this = $(this); | |
if (!$.contains($this.get(0), $opener.get(0))) | |
$this.trigger('doCollapse'); | |
}); | |
// Vars. | |
var oo = $opener.offset(), | |
op = $opener.position(), | |
opp = $opener.parent().position(), | |
ow = $opener.outerWidth(), | |
mw = $menu.outerWidth(), | |
isTL = ($menu.css('z-index') == settings.baseZIndex); | |
var x, c, left, top; | |
// If this is a top level menu ... | |
if (isTL) { | |
// If detach is enabled, use .position() | |
if (!settings.detach) | |
x = op; | |
// Otherwise, use .offset() | |
else | |
x = oo; | |
top = x.top + $opener.outerHeight() + settings.globalOffsetY; | |
c = settings.alignment; | |
// Remove alignment classes. | |
$menu | |
.removeClass('left') | |
.removeClass('right') | |
.removeClass('center'); | |
// Figure out alignment and position. | |
switch (settings.alignment) { | |
case 'right': | |
left = x.left - mw + ow; | |
if (left < 0) { | |
left = x.left; | |
c = 'left'; | |
} | |
break; | |
case 'center': | |
left = x.left - Math.floor((mw - ow) / 2); | |
if (left < 0) { | |
left = x.left; | |
c = 'left'; | |
} | |
else if (left + mw > $window.width()) { | |
left = x.left - mw + ow; | |
c = 'right'; | |
} | |
break; | |
case 'left': | |
default: | |
left = x.left; | |
if (left + mw > $window.width()) { | |
left = x.left - mw + ow; | |
c = 'right'; | |
} | |
break; | |
} | |
// Add alignment class. | |
$opener.find( 'a' ).blur(); | |
$menu | |
.addClass(c) | |
.find( 'li:first-of-type a' ) | |
.focus(); | |
} | |
// Otherwise, we're dealing with a submenu. | |
else { | |
// If the opener position isn't static ... | |
if ($opener.css('position') == 'relative' | |
|| $opener.css('position') == 'absolute') { | |
top = settings.offsetY; | |
left = (-1 * op.left); | |
} | |
else { | |
top = op.top + settings.offsetY; | |
left = 0; | |
} | |
// Figure out position (based on alignment). | |
switch (settings.alignment) { | |
case 'right': | |
left += (-1 * $opener.parent().outerWidth()) + settings.offsetX; | |
break; | |
case 'center': | |
case 'left': | |
default: | |
left += $opener.parent().outerWidth() + settings.offsetX; | |
break; | |
} | |
} | |
// Legacy IE? Apply IE-specific offsets. | |
if (navigator.userAgent.match(/MSIE ([0-9]+)\./) && RegExp.$1 < 8) { | |
left += settings.IEOffsetX; | |
top += settings.IEOffsetY; | |
} | |
// Position and show the menu. | |
$menu | |
.css('left', left + 'px') | |
.css('top', top + 'px') | |
.css('opacity', '0.01') | |
.show(); | |
// Kludge! | |
var tmp = false; | |
// Non-static position fix. | |
if ($opener.css('position') == 'relative' | |
|| $opener.css('position') == 'absolute') | |
left = (-1 * op.left); | |
else | |
left = 0; | |
if ($menu.offset().left < 0) { | |
left += $opener.parent().outerWidth() - settings.offsetX; | |
tmp = true; | |
} | |
else if ($menu.offset().left + mw > $window.width()) { | |
left += (-1 * $opener.parent().outerWidth()) - settings.offsetX; | |
tmp = true; | |
} | |
if (tmp) | |
$menu | |
.css('left', left + 'px'); | |
$menu | |
.hide() | |
.css('opacity', '1'); | |
// Figure out animation mode. | |
switch (settings.mode) { | |
case 'zoom': | |
isLocked = true; | |
$opener.addClass(settings.openerActiveClass); | |
$menu.animate({ | |
width: 'toggle', | |
height: 'toggle' | |
}, settings.speed, settings.easing, function() { | |
isLocked = false; | |
}); | |
break; | |
case 'slide': | |
isLocked = true; | |
$opener.addClass(settings.openerActiveClass); | |
$menu.animate({ height: 'toggle' }, settings.speed, settings.easing, function() { | |
isLocked = false; | |
}); | |
break; | |
case 'fade': | |
isLocked = true; | |
if (isTL && !settings.noOpenerFade) { | |
var tmp; | |
if (settings.speed == 'slow') | |
tmp = 80; | |
else if (settings.speed == 'fast') | |
tmp = 40; | |
else | |
tmp = Math.floor(settings.speed / 2); | |
$opener.fadeTo(tmp, 0.01, function() { | |
$opener.addClass(settings.openerActiveClass); | |
$opener.fadeTo(settings.speed, 1); | |
$menu.fadeIn(settings.speed, function() { | |
isLocked = false; | |
}); | |
}); | |
} | |
else { | |
$opener.addClass(settings.openerActiveClass); | |
$opener.fadeTo(settings.speed, 1); | |
$menu.fadeIn(settings.speed, function() { | |
isLocked = false; | |
}); | |
} | |
break; | |
case 'instant': | |
default: | |
$opener.addClass(settings.openerActiveClass); | |
$menu.show(); | |
break; | |
} | |
return false; | |
}) | |
.on('doCollapse', function() { | |
// Not visible? Bail out. | |
if (!$menu.is(':visible')) | |
return false; | |
// Collapse the menu. | |
$menu.hide(); | |
$opener.removeClass(settings.openerActiveClass); | |
$menu.find('.' + settings.openerActiveClass).removeClass(settings.openerActiveClass); | |
$menu.find('ul').hide(); | |
return false; | |
}) | |
.on('doToggle', function(e) { | |
if ($menu.is(':visible')) | |
$menu.trigger('doCollapse'); | |
else | |
$menu.trigger('doExpand'); | |
return false; | |
}); | |
// Menu's opener. | |
$opener | |
.disableSelection_dropotron() | |
.addClass('opener') | |
.css('cursor', 'pointer') | |
.on('click touchend', function(e) { | |
// Locked? Bail. | |
if (isLocked) | |
return; | |
// Toggle menu. | |
e.preventDefault(); | |
e.stopPropagation(); | |
$menu.trigger('doToggle'); | |
}); | |
// If expandMode is "hover", set up the event. | |
if (settings.expandMode == 'hover') | |
$opener.hover(function(e) { | |
if (isLocked) | |
return; | |
hoverTimeoutId = window.setTimeout(function() { | |
$menu.trigger('doExpand'); | |
}, settings.hoverDelay); | |
}, | |
function (e) { | |
window.clearTimeout(hoverTimeoutId); | |
}); | |
}); | |
// All links. | |
$menus.find('a') | |
.css('display', 'block') | |
.on('click touchend', function(e) { | |
// Locked? Bail. | |
if (isLocked) | |
return; | |
// No href? Prevent default. | |
if ($(this).attr('href').length < 1) | |
e.preventDefault(); | |
}); | |
// All list items. | |
$top.find('li') | |
.css('white-space', 'nowrap') | |
.each(function() { | |
var $this = $(this), $a = $this.children('a'), $ul = $this.children('ul'), | |
href = $a.attr('href'); | |
// If href is blank ("") or a hash (#), prevent the link from doing anything. | |
$a.on('click touchend', function(e) { | |
if (href.length == 0 | |
|| href == '#') | |
e.preventDefault(); | |
else | |
e.stopPropagation(); | |
}); | |
// If there is a link but no unordered list ... | |
if ($a.length > 0 && $ul.length == 0) | |
$this.on('click touchend', function(e) { | |
if (isLocked) | |
return; | |
$top.trigger('doCollapseAll'); | |
e.stopPropagation(); | |
}); | |
}); | |
// Top level list items. | |
$top.children('li').each(function() { | |
var $opener = $(this), $menu = $opener.children('ul'), | |
c; | |
if ($menu.length > 0) { | |
// If we're using detach ... | |
if (settings.detach) { | |
// If we're cloning on detach ... | |
if (settings.cloneOnDetach) { | |
// Make a copy of the menu. | |
c = $menu.clone(); | |
// Leave it behind | |
c | |
.attr('class', '') | |
.hide() | |
.appendTo($menu.parent()); | |
} | |
// Detach the menu and move it to the end of the <body> element. | |
$menu | |
.detach() | |
.appendTo($body); | |
} | |
// Step through menus, assigning z-indexes and submenu class prefixes as necessary. | |
for(var z = settings.baseZIndex, i = 1, y = $menu; y.length > 0; i++) { | |
y.css('z-index', z++); | |
if (settings.submenuClassPrefix) | |
y.addClass(settings.submenuClassPrefix + (z - 1 - settings.baseZIndex)); | |
y = y.find('> li > ul'); | |
} | |
} | |
}); | |
// Window. | |
$window | |
.on('', function() { | |
$top.trigger('doCollapseAll'); | |
}) | |
.on('keypress', function(e) { | |
// Collapse all menus if the user hits escape. | |
if (!isLocked && e.keyCode == 27) { | |
e.preventDefault(); | |
$top.trigger('doCollapseAll'); | |
} | |
}); | |
// Body. | |
$bodyhtml | |
.on('click touchend', function() { | |
if (!isLocked) | |
$top.trigger('doCollapseAll'); | |
}); | |
}; | |
})(jQuery); | |
// custom code down here | |
var foo = $('#nav > ul'); | |
foo.dropotron(); | |
console.log( foo ); | |
}); | |
</script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment