JSFiddle - React, Tailwind, and code Playground
by DeanOutlaw
HTML
<ul id="nested">
<li id="folder1"><span>New Folder1</span></li>
<li id="folder2"><span>New Folder2</span></li>
<li id="folder3"><span>New Folder3</span></li>
<li id="folder4"><span>New Folder4</span></li>
<li id="folder5"><span>New Folder5</span></li>
<li id="folder6"><span>New Folder6</span></li>
</ul>
CSS
#contextmenu { border:1px solid #999; padding:0; background:#eee; width:200px; list-style-type:none; display:none; }
#contextmenu .separator { border-top:1px solid #999; }
#contextmenu li { margin:0; padding:0;height:30px }
#contextmenu li a { display:block; padding:5px 10px 5px 35px; width:155px; font-size:12px; text-decoration:none; font-family:tahoma,arial,sans-serif; color:#000; background-position:8px 8px; background-repeat:no-repeat; }
#contextmenu li a:hover { background-color:#ddd; }
#contextmenu li a.disabled { color:#ccc; font-style:italic; }
#contextmenu li a.disabled:hover { background-color:#eee; }
/*#contextmenu li a.edit { background-image:url(tree/folder_tree_edit.png); }
#contextmenu li a.new { background-image:url(tree/folder_tree_add.png); }
#contextmenu li a.copy { background-image:url(copy.png); }
#contextmenu li a.paste { background-image:url(paste.png); }
#contextmenu li a.delete { background-image:url(tree/folder_tree_delete.png); }
#contextmenu li a.quit { background-image:url(quit.png); }*/
/* begin MenuSubItem */
#contextmenu ul{border:1px solid #999;padding:0;visibility: hidden;width:200px; list-style-type:none;z-index: 10;left: 0;top: 0;background:#eee;}
#contextmenu li:hover>ul{visibility: visible;top: 100%;}
#contextmenu li ol, li ul{margin:-29px 0 0 200px;padding:0;}
#contextmenu ul ul a{margin-left: auto;}
/*#contextmenu ul li a.single-upload { background-image:url(tree/single_upload.png); }*/
JavaScript
/*
---
description: ContextMenu
authors:
- David Walsh (http://davidwalsh.name)
license:
- MIT-style license
requires:
core/1.2.1: '*'
more/1.2.1: 'Fx.*'
provides:
- ContextMenu
...
*/
var ContextMenu = new Class({
//implements
Implements: [Options,Events],
//options
options: {
actions: {},
menu: 'contextmenu',
labels: [],
stopEvent: true,
targets: 'body',
trigger: 'contextmenu',
offsets: { x:0, y:0 },
onShow: function(){},
onHide: function(){},
onClick: function(){},
fadeSpeed: 200
},
//initialization
initialize: function(options) {
//set options
this.setOptions(options);
//option diffs menu
this.menu = this.parseNodes(this.options.labels, this.options.menu).inject(document.body);
this.targets = $$(this.options.targets);
//fx
this.fx = new Fx.Tween(this.menu, { property: 'opacity', duration:this.options.fadeSpeed });
//hide and begin the listener
this.hide().startListener();
//hide the menu
this.menu.setStyles({ position:'absolute',top:'-900000px',display:'block' });
},
//get things started
startListener: function() {
/* all elemnts */
this.targets.each(function(el) {
/* show the menu */
el.addEvent(this.options.trigger,function(e) {
//enabled?
if(!this.options.disabled) {
//prevent default, if told to
if(this.options.stopEvent) { e.stop(); }
//record this as the trigger
this.options.element = document.id(el);
//position the menu
this.menu.setStyles({
top: (e.page.y + this.options.offsets.y),
left: (e.page.x + this.options.offsets.x),
...