javascript - evento - click derecho jquery
Haciendo menús personalizados con el botón derecho del mouse para mi aplicación web (7)
Tengo algunos sitios web como google-docs y map-quest que tienen menús desplegables personalizados cuando haces clic derecho. De alguna manera, anulan el comportamiento del navegador del menú desplegable, y ahora estoy seguro de cómo lo hacen. Encontré un plugin jQuery que hace esto, pero aún tengo curiosidad por algunas cosas:
- ¿Como funciona esto? ¿Se está anulando el menú desplegable del navegador o se simuló el efecto? ¿Si es así, cómo?
- ¿Qué abstrae el complemento? ¿Qué está pasando detrás de escena?
- ¿Es esta la única forma de lograr este efecto?
Como dijo Adrian, los complementos funcionarán de la misma manera. Hay tres partes básicas que vas a necesitar:
1: Manejador de eventos para ''contextmenu''
evento ''contextmenu''
:
$(document).bind("contextmenu", function(event) {
event.preventDefault();
$("<div class=''custom-menu''>Custom menu</div>")
.appendTo("body")
.css({top: event.pageY + "px", left: event.pageX + "px"});
});
Aquí, puede vincular el controlador de eventos a cualquier selector para el que desee mostrar un menú. Elegí el documento completo.
2: controlador de eventos para ''click''
evento ''click''
(para cerrar el menú personalizado):
$(document).bind("click", function(event) {
$("div.custom-menu").hide();
});
3: CSS para controlar la posición del menú:
.custom-menu {
z-index:1000;
position: absolute;
background-color:#C0C0C0;
border: 1px solid black;
padding: 2px;
}
Lo importante con CSS es incluir el z-index
y la position: absolute
No sería demasiado difícil envolver todo esto en un hábil plugin jQuery.
Puede ver una demostración simple aquí: http://jsfiddle.net/andrewwhitaker/fELma/
El menú de contexto del navegador está siendo anulado. No hay forma de aumentar el menú contextual nativo en ningún navegador importante.
Como el complemento está creando su propio menú, la única parte que realmente se está abstrayendo es el evento del menú contextual del navegador. El complemento crea un menú html basado en su configuración, luego coloca ese contenido en la ubicación de su clic.
Sí, esta es la única forma de crear un menú contextual personalizado. Obviamente, los diferentes complementos hacen las cosas un poco diferentes, pero todos anularán el evento del navegador y colocarán su propio menú basado en html en el lugar correcto.
Puede ver este tutorial: http://www.youtube.com/watch?v=iDyEfKWCzhg Asegúrese de que el menú contextual esté oculto al principio y tenga una posición de absoluta. Esto asegurará que no habrá un menú contextual múltiple y una creación inútil del menú contextual. El enlace a la página se coloca en la descripción del video de YouTube.
$(document).bind("contextmenu", function(event){
$("#contextmenu").css({"top": event.pageY + "px", "left": event.pageX + "px"}).show();
});
$(document).bind("click", function(){
$("#contextmenu").hide();
});
Sé que esta pregunta es muy antigua, pero me ocurrió el mismo problema y lo resolví yo mismo, así que estoy respondiendo por si alguien encuentra esto en Google como lo hice yo. Basé mi solución en la de @ Andrew, pero básicamente modifiqué todo después.
EDITAR : viendo lo popular que ha sido últimamente, decidí actualizar también los estilos para que se vea más como 2014 y menos como Windows 95. Solucioné los errores @Quantico y @Trengot detectados, por lo que ahora es una respuesta más sólida.
EDIT 2 : Lo configuré con StackSnippets ya que son una nueva característica realmente genial. Dejo la buena jsfiddle aquí como referencia (haga clic en el 4º panel para ver cómo funcionan).
Nuevo fragmento de pila:
// JAVASCRIPT (jQuery)
// Trigger action when the contexmenu is about to be shown
$(document).bind("contextmenu", function (event) {
// Avoid the real one
event.preventDefault();
// Show contextmenu
$(".custom-menu").finish().toggle(100).
// In the right position (the mouse)
css({
top: event.pageY + "px",
left: event.pageX + "px"
});
});
// If the document is clicked somewhere
$(document).bind("mousedown", function (e) {
// If the clicked element is not the menu
if (!$(e.target).parents(".custom-menu").length > 0) {
// Hide it
$(".custom-menu").hide(100);
}
});
// If the menu element is clicked
$(".custom-menu li").click(function(){
// This is the triggered action name
switch($(this).attr("data-action")) {
// A case for each action. Your actions here
case "first": alert("first"); break;
case "second": alert("second"); break;
case "third": alert("third"); break;
}
// Hide it AFTER the action was triggered
$(".custom-menu").hide(100);
});
/* CSS3 */
/* The whole thing */
.custom-menu {
display: none;
z-index: 1000;
position: absolute;
overflow: hidden;
border: 1px solid #CCC;
white-space: nowrap;
font-family: sans-serif;
background: #FFF;
color: #333;
border-radius: 5px;
padding: 0;
}
/* Each of the items in the list */
.custom-menu li {
padding: 8px 12px;
cursor: pointer;
list-style-type: none;
transition: all .3s ease;
user-select: none;
}
.custom-menu li:hover {
background-color: #DEF;
}
<!-- HTML -->
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.js"></script>
<ul class=''custom-menu''>
<li data-action="first">First thing</li>
<li data-action="second">Second thing</li>
<li data-action="third">Third thing</li>
</ul>
<!-- Not needed, only for making it clickable on -->
Right click me
Nota: es posible que vea algunos pequeños errores (menú desplegable lejos del cursor, etc.), asegúrese de que funciona en jsfiddle , ya que es más similar a su página web que StackSnippets.
Sé que esto también es bastante viejo. Hace poco tuve la necesidad de crear un menú contextual que inserte en otros sitios que tienen diferentes propiedades en función del elemento al que se hace clic.
Es bastante duro, y hay formas probables de lograr esto. Utiliza el menú de contexto de jQuery Biblioteca ubicada aquí
Disfruté crearlo y aunque ustedes podrían sacarle provecho.
Aquí está el fiddle . Espero que pueda ayudar a alguien allá afuera.
$(function() {
function createSomeMenu() {
var all_array = ''{'';
var x = event.clientX,
y = event.clientY,
elementMouseIsOver = document.elementFromPoint(x, y);
if (elementMouseIsOver.closest(''a'')) {
all_array += ''"Link-Fold": {"name": "Link", "icon": "fa-external-link", "items": {"fold2-key1": {"name": "Open Site in New Tab"}, "fold2-key2": {"name": "Open Site in Split Tab"}, "fold2-key3": {"name": "Copy URL"}}},'';
}
if (elementMouseIsOver.closest(''img'')) {
all_array += ''"Image-Fold": {"name": "Image","icon": "fa-picture-o","items": {"fold1-key1": {"name":"Download Image"},"fold1-key2": {"name": "Copy Image Location"},"fold1-key3": {"name": "Go To Image"}}},'';
}
all_array += ''"copy": {"name": "Copy","icon": "copy"},"paste": {"name": "Paste","icon": "paste"},"edit": {"name": "Edit HTML","icon": "fa-code"}}'';
return JSON.parse(all_array);
}
// setup context menu
$.contextMenu({
selector: ''body'',
build: function($trigger, e) {
return {
callback: function(key, options) {
var m = "clicked: " + key;
console.log(m);
},
items: createSomeMenu()
};
}
});
});
aquí hay un ejemplo de menú contextual con el botón derecho en javascript: Menú contextual con el botón derecho
Se utilizó el código javasScript sin formato para la funcionalidad del menú contextual. ¿Puedes verificar esto? Espero que esto te ayude.
Código en vivo:
(function() {
"use strict";
/*********************************************** Context Menu Function Only ********************************/
function clickInsideElement( e, className ) {
var el = e.srcElement || e.target;
if ( el.classList.contains(className) ) {
return el;
} else {
while ( el = el.parentNode ) {
if ( el.classList && el.classList.contains(className) ) {
return el;
}
}
}
return false;
}
function getPosition(e) {
var posx = 0, posy = 0;
if (!e) var e = window.event;
if (e.pageX || e.pageY) {
posx = e.pageX;
posy = e.pageY;
} else if (e.clientX || e.clientY) {
posx = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
posy = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
}
return {
x: posx,
y: posy
}
}
// Your Menu Class Name
var taskItemClassName = "thumb";
var contextMenuClassName = "context-menu",contextMenuItemClassName = "context-menu__item",contextMenuLinkClassName = "context-menu__link", contextMenuActive = "context-menu--active";
var taskItemInContext, clickCoords, clickCoordsX, clickCoordsY, menu = document.querySelector("#context-menu"), menuItems = menu.querySelectorAll(".context-menu__item");
var menuState = 0, menuWidth, menuHeight, menuPosition, menuPositionX, menuPositionY, windowWidth, windowHeight;
function initMenuFunction() {
contextListener();
clickListener();
keyupListener();
resizeListener();
}
/**
* Listens for contextmenu events.
*/
function contextListener() {
document.addEventListener( "contextmenu", function(e) {
taskItemInContext = clickInsideElement( e, taskItemClassName );
if ( taskItemInContext ) {
e.preventDefault();
toggleMenuOn();
positionMenu(e);
} else {
taskItemInContext = null;
toggleMenuOff();
}
});
}
/**
* Listens for click events.
*/
function clickListener() {
document.addEventListener( "click", function(e) {
var clickeElIsLink = clickInsideElement( e, contextMenuLinkClassName );
if ( clickeElIsLink ) {
e.preventDefault();
menuItemListener( clickeElIsLink );
} else {
var button = e.which || e.button;
if ( button === 1 ) {
toggleMenuOff();
}
}
});
}
/**
* Listens for keyup events.
*/
function keyupListener() {
window.onkeyup = function(e) {
if ( e.keyCode === 27 ) {
toggleMenuOff();
}
}
}
/**
* Window resize event listener
*/
function resizeListener() {
window.onresize = function(e) {
toggleMenuOff();
};
}
/**
* Turns the custom context menu on.
*/
function toggleMenuOn() {
if ( menuState !== 1 ) {
menuState = 1;
menu.classList.add( contextMenuActive );
}
}
/**
* Turns the custom context menu off.
*/
function toggleMenuOff() {
if ( menuState !== 0 ) {
menuState = 0;
menu.classList.remove( contextMenuActive );
}
}
function positionMenu(e) {
clickCoords = getPosition(e);
clickCoordsX = clickCoords.x;
clickCoordsY = clickCoords.y;
menuWidth = menu.offsetWidth + 4;
menuHeight = menu.offsetHeight + 4;
windowWidth = window.innerWidth;
windowHeight = window.innerHeight;
if ( (windowWidth - clickCoordsX) < menuWidth ) {
menu.style.left = (windowWidth - menuWidth)-0 + "px";
} else {
menu.style.left = clickCoordsX-0 + "px";
}
// menu.style.top = clickCoordsY + "px";
if ( Math.abs(windowHeight - clickCoordsY) < menuHeight ) {
menu.style.top = (windowHeight - menuHeight)-0 + "px";
} else {
menu.style.top = clickCoordsY-0 + "px";
}
}
function menuItemListener( link ) {
var menuSelectedPhotoId = taskItemInContext.getAttribute("data-id");
console.log(''Your Selected Photo: ''+menuSelectedPhotoId)
var moveToAlbumSelectedId = link.getAttribute("data-action");
if(moveToAlbumSelectedId == ''remove''){
console.log(''You Clicked the remove button'')
}else if(moveToAlbumSelectedId && moveToAlbumSelectedId.length > 7){
console.log(''Clicked Album Name: ''+moveToAlbumSelectedId);
}
toggleMenuOff();
}
initMenuFunction();
})();
/* For Body Padding and content */
body { padding-top: 70px; }
li a { text-decoration: none !important; }
/* Thumbnail only */
.thumb {
margin-bottom: 30px;
}
.thumb:hover a, .thumb:active a, .thumb:focus a {
border: 1px solid purple;
}
/************** For Context menu ***********/
/* context menu */
.context-menu { display: none; position: absolute; z-index: 9999; padding: 12px 0; width: 200px; background-color: #fff; border: solid 1px #dfdfdf; box-shadow: 1px 1px 2px #cfcfcf; }
.context-menu--active { display: block; }
.context-menu__items { list-style: none; margin: 0; padding: 0; }
.context-menu__item { display: block; margin-bottom: 4px; }
.context-menu__item:last-child { margin-bottom: 0; }
.context-menu__link { display: block; padding: 4px 12px; color: #0066aa; text-decoration: none; }
.context-menu__link:hover { color: #fff; background-color: #0066aa; }
.context-menu__items ul { position: absolute; white-space: nowrap; z-index: 1; left: -99999em;}
.context-menu__items > li:hover > ul { left: auto; padding-top: 5px ; min-width: 100%; }
.context-menu__items > li li ul { border-left:1px solid #fff;}
.context-menu__items > li li:hover > ul { left: 100%; top: -1px; }
.context-menu__item ul { background-color: #ffffff; padding: 7px 11px; list-style-type: none; text-decoration: none; margin-left: 40px; }
.page-media .context-menu__items ul li { display: block; }
/************** For Context menu ***********/
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet"/>
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<body>
<!-- Page Content -->
<div class="container">
<div class="row">
<div class="col-lg-12">
<h1 class="page-header">Thumbnail Gallery <small>(Right click to see the context menu)</small></h1>
</div>
<div class="col-lg-3 col-md-4 col-xs-6 thumb">
<a class="thumbnail" href="#">
<img class="img-responsive" src="http://placehold.it/400x300" alt="">
</a>
</div>
<div class="col-lg-3 col-md-4 col-xs-6 thumb">
<a class="thumbnail" href="#">
<img class="img-responsive" src="http://placehold.it/400x300" alt="">
</a>
</div>
<div class="col-lg-3 col-md-4 col-xs-6 thumb">
<a class="thumbnail" href="#">
<img class="img-responsive" src="http://placehold.it/400x300" alt="">
</a>
</div>
<div class="col-lg-3 col-md-4 col-xs-6 thumb">
<a class="thumbnail" href="#">
<img class="img-responsive" src="http://placehold.it/400x300" alt="">
</a>
</div>
<div class="col-lg-3 col-md-4 col-xs-6 thumb">
<a class="thumbnail" href="#">
<img class="img-responsive" src="http://placehold.it/400x300" alt="">
</a>
</div>
<div class="col-lg-3 col-md-4 col-xs-6 thumb">
<a class="thumbnail" href="#">
<img class="img-responsive" src="http://placehold.it/400x300" alt="">
</a>
</div>
<div class="col-lg-3 col-md-4 col-xs-6 thumb">
<a class="thumbnail" href="#">
<img class="img-responsive" src="http://placehold.it/400x300" alt="">
</a>
</div>
<div class="col-lg-3 col-md-4 col-xs-6 thumb">
<a class="thumbnail" href="#">
<img class="img-responsive" src="http://placehold.it/400x300" alt="">
</a>
</div>
</div>
<hr>
</div>
<!-- /.container -->
<!-- / The Context Menu -->
<nav id="context-menu" class="context-menu">
<ul class="context-menu__items">
<li class="context-menu__item">
<a href="#" class="context-menu__link" data-action="Delete This Photo"><i class="fa fa-empire"></i> Delete This Photo</a>
</li>
<li class="context-menu__item">
<a href="#" class="context-menu__link" data-action="Photo Option 2"><i class="fa fa-envira"></i> Photo Option 2</a>
</li>
<li class="context-menu__item">
<a href="#" class="context-menu__link" data-action="Photo Option 3"><i class="fa fa-first-order"></i> Photo Option 3</a>
</li>
<li class="context-menu__item">
<a href="#" class="context-menu__link" data-action="Photo Option 4"><i class="fa fa-gitlab"></i> Photo Option 4</a>
</li>
<li class="context-menu__item">
<a href="#" class="context-menu__link" data-action="Photo Option 5"><i class="fa fa-ioxhost"></i> Photo Option 5</a>
</li>
<li class="context-menu__item">
<a href="#" class="context-menu__link"><i class="fa fa-arrow-right"></i> Add Photo to</a>
<ul>
<li><a href="#!" class="context-menu__link" data-action="album-one"><i class="fa fa-camera-retro"></i> Album One</a></li>
<li><a href="#!" class="context-menu__link" data-action="album-two"><i class="fa fa-camera-retro"></i> Album Two</a></li>
<li><a href="#!" class="context-menu__link" data-action="album-three"><i class="fa fa-camera-retro"></i> Album Three</a></li>
<li><a href="#!" class="context-menu__link" data-action="album-four"><i class="fa fa-camera-retro"></i> Album Four</a></li>
</ul>
</li>
</ul>
</nav>
<!-- End # Context Menu -->
</body>
<!DOCTYPE html>
<html>
<head>
<title>Right Click</title>
<link href="https://swisnl.github.io/jQuery-contextMenu/dist/jquery.contextMenu.css" rel="stylesheet" type="text/css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="https://swisnl.github.io/jQuery-contextMenu/dist/jquery.contextMenu.js" type="text/javascript"></script>
<script src="https://swisnl.github.io/jQuery-contextMenu/dist/jquery.ui.position.min.js" type="text/javascript"></script>
</head>
<body>
<span class="context-menu-one" style="border:solid 1px black; padding:5px;">Right Click Me</span>
<script type="text/javascript">
$(function() {
$.contextMenu({
selector: ''.context-menu-one'',
callback: function(key, options) {
var m = "clicked: " + key;
window.console && console.log(m) || alert(m);
},
items: {
"edit": {name: "Edit", icon: "edit"},
"cut": {name: "Cut", icon: "cut"},
copy: {name: "Copy", icon: "copy"},
"paste": {name: "Paste", icon: "paste"},
"delete": {name: "Delete", icon: "delete"},
"sep1": "---------",
"quit": {name: "Quit", icon: function(){
return ''context-menu-icon context-menu-icon-quit'';
}}
}
});
$(''.context-menu-one'').on(''click'', function(e){
console.log(''clicked'', this);
})
});
</script>
</body>
</html>