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),
                     ...