JSFiddle - React, Tailwind, and code Playground
by snoopydaniels
HTML
<body>
<ul class="menubar">
<li>Home</li>
<li>Contact Us</li>
<li id="submenu">
Submenu
</li>
</ul>
</body>
CSS
.menubar > li {
display: inline-block;
padding: 5px;
height: 1em;
position: relative;
}
div.dropDownMenu {
position: absolute;
min-width: 100px;
background-color: white;
}
div.dropDownMenu li {
position: relative;
padding: 5px;
font-size: .8em;
}
.dropDownMenu ul {
list-style-type: none;
padding-left: 0px;
}
.dropDownMenu-hidden {
display: none;
}
JavaScript
function Namespace() {
return {};
}
var Widgets = Namespace();
Widgets.DropDownMenu = (function($){
var defaultConfig = {
hideDelay: 300
};
var menuClass = 'dropDownMenu';
function DropDownMenu($container, model, config) {
this.$container = $container;
this.model = model;
this.config = $.extend(defaultConfig, config);
this.$markup = this.render(this.model);
this.hideTimeout = null;
$container.append(this.$markup);
this.bindHoverEvents();
}
DropDownMenu.prototype.render = function(menuItems) {
var $menu = $('<div class="' + menuClass + '"><ul></ul></div>');
var $ul = $menu.children();
$menu.hide();
for (var i = 0; i < menuItems.length; i++) {
var menuItem = menuItems[i];
var $li = $('<li></li>');
$ul.append($li);
$li.text(menuItem.text);
if (menuItem.action) {
$li.click(this.createAction(menuItem.action, menuItem));
}
if (menuItem.submenu) {
var submenu = new DropDownMenu($li, menuItem.submenu, this.config);
$li.data('dropDownMenu', submenu);
}
}
return $menu;
}
DropDownMenu.prototype.createAction = function(action, menuItem) {
var self = this;
if (action instanceof Function) {
return function() {
action.call(self, menuItem);
};
} else if (this.router) {
return function() {
self.router.route(action);
};
} else {
return function() {
location.href = action;
};
}
}
function mouseEnter() {
this.show();
if (this.hideTimeout) {
clearTimeout(this.hideTimeout);
this.hideTimeout = null;
}
}
function mouseLeave() {
var self = this;
if (!this.$container.is(':hover') && !this.$markup.is(':hover'))
this.hideTimeout = setTimeout(function() {
self.hide();
self.hideTimeout = null;
}, this.config.hideDelay);
}
...