JSFiddle - React, Tailwind, and code Playground

by Felipe Alfaro

HTML

<div class="example" data-id="myDataId" data-color="green">
</div>

CSS

body, html{
  margin: 0;
}
div{
  width: 50px; height: 50px; background: red;
}
ul.contextOptions{
  position: absolute;
  list-style: none;
  z-index: 102200;
  position: absolute;
  overflow: hidden;
  border: 1px solid #CCC;
  white-space: nowrap;
  font-family: sans-serif;
  background: #FFF;
  border-radius: 2px;
  padding: 12px 0;
  margin: 0;
  display: none;
}
ul.contextOptions > li > a{
  color: #333;
  display: block;
  padding: 12px 25px;
  cursor: pointer;
  text-decoration: none;
  pointer: cursor;
  -webkit-transition: 100ms;
  transition: 100ms;
  font-size: 12px;
}
ul.contextOptions > li > a:hover{
  background: rgb(77, 129, 35);
  color: white;
}
li.contextOptionsSeparator{
  background: gainsboro;
  height: 1px;
  margin: 7px 0;
}

JavaScript

$(document).on("contextmenu",function(){
  return false;
});

$.fn.contextOptions = function(prop) {
	var object = $(this);
  $(object).mousedown(function(e){
  	e.preventDefault();
    $('.contextOptions').each(function(i){
      $(this).remove();
    });
    var left = e.pageX,
    		top = e.pageY;
    if( e.button == 2 ) {
    	var name, addClass, url, id, result='';
    	for(var key in prop){
      	var join = '',
        		inheritances = '';
      	if(prop[key]=='separator'){
          result += '<li class="contextOptionsSeparator"></li>';
        }else{
          if(prop[key]['name'] != undefined){
            name = prop[key]['name'];
          }else{
            name = 'Unnamed option'
          }
					if(prop[key]['class'] != undefined){
            addClass = ' class="'+prop[key]['class']+'"';
          }else{
            addClass = ''
          }
          if(prop[key]['id'] != undefined){
            id = ' id="'+prop[key]['id']+'"';
          }else{
            id = ''
          }
          if(prop[key]['inherit'] != undefined){
            for	(i = 0; i < prop[key]['inherit'].length; i++) {
                var attrName = prop[key]['inherit'][i],
                    value = object.attr(attrName);
                inheritances += ' '+attrName+'="'+value+'"';
            }
          }else{
            inheritances = ''
          }
          if(prop[key]['url'] != undefined){
            url = ' href="'+prop[key]['url']+'"';
          }else{
            url = ''
          }
          result += '<li><a'+inheritances+addClass+url+id+'>'+name+'</a></li>';
        }
      }
			$('body')
      	.append('<ul class="contextOptions" style="left:'+left+'px;top:'+top+'px;">'+result+'</ul>')
        .find('ul.contextOptions')
        .toggle(200);
    }
  });
  return this;
};
$(document).bind('click', function(){
    $('.contextOptions').remove();
});
$('.contextOptions').click(function(event){
    event.stopPropagation();
});



$('div.example').contextOptions({
...