I am trying to late-bind context menus to elements, using the ContextMenu plugin. So on the first right-click on those elements, I would like to :
intercept the right-click through a live event on a certain "uncontextmenued" class,
determine if the data('events').contextmenu exists,
if not, attach the context-menu (and change the class to avoid re-throwing this live process),
re-throw the right-click event to show the right-click.
I'm having trouble with the last item. jQuery allows to .click() or to .trigger('click'), which simulate a left-click, but there seems not to be a way to fire a right-click event through trigger.
Or is there?
You can trigger it by
$('#element').trigger({
type: 'mousedown',
which: 3
});
http://api.jquery.com/trigger/#example-5
There is a newer way to do this:
$('#element').triggerHandler('contextmenu');
Documentation can be found here.
Similar to this, but I'm not sure if you may be referring to jQuery UI data, but.
$('#element').mousedown(function(event)
{
if(event.which == 3)
{
if(typeof($(this).data('events')) === 'undefined')
{
$(this).data('events', { somedata: 'hello' });
}
else
{
// "re-throw" right click context menu
}
}
});
Related
I have a special scenario where I need to capture key events on a higher level, and redirect them to a lower level. I'm trying to write code like this, but actually it seems like jQuery is dumbly using the exact same event object, so target is not changed, so Maximum callstack size exceeded...
$("#outer").on("keydown", function(evt) {
if (evt.target !== $("#inner")[0] && !$.contains($("#inner")[0], evt.target)) {
$("#inner").trigger(evt);
}
});
With a sample markup
<div id="#outer">
<div id="#inner">
</div>
</div>
What is the proper way to redirect an event to another element? I could of course manually "hack" the target, but is it safe?
I'm working on a plugin which dynamically shows a menu as a popup or as a modal based on screen size. If I have a modal, I need this key redirection. The consumer should not know about wether it's a popup or a modal. I'm using bootstrap's modal plugin, which captures key events because of a "focus-lock thing", so the only way I can make it transparent is that I redirect these events to my real menu.
You could attach the event handler onto the outer and specify a selector to use to match the event:
$('#outer').on('keydown', '#inner', event => {
/* this is executed when #inner is clicked */
});
If you really want to use trigger, you could put it in a setTimeout:
$('#outer').on('keydown', event => {
if (yourCondition) {
setTimeout(() => $('#inner').trigger(event), 0);
}
});
The event will bubble up and you're right, it's the same event. This isn't a jQuery thing but actually just how javascript works. You may want to set a listener on the child element, and use preventDefault();
$("#outer").on("keydown", doSomeThing);
$("#inner").on("keydown", doSomeThingElse);
function doSomeThing(e) {
}
function doSomeThingElse(e) {
e.preventDefault();
}
this will allow you to separate your listeners into distinct functions.
Thank you all for the answers and comments. A few of you suggested preventing propagation of the event at the #inner div. I need to avoid this, I need a way where any external consumer will see this event just as it was triggered by the #inner element for real.
In the meantime I digged into jQuery source and found this line in trigger.
if ( !event.target ) {
event.target = elem;
}
So when jQuery initializes the event to trigger, it only assignes the element to the target if the target is not yet specified. sure they have some good reasons for this behavior, which I cannot see at this moment.
So the best thing I could come up with is a function like this.
function redirectEvent(currentTarget, evt, newTarget) {
if (currentTarget !== newTarget && !$.contains(currentTarget, newTarget)) {
evt = $.Event(evt.type, evt);
delete evt.target;
$(newTarget).trigger(evt);
}
}
As far as first tests go, I can't see any side-effect or drawback.
In the code below, the right-click is not getting trapped. left-click works fine. This code was given in the dojo documentation. Can someone tell me why isRight is not working? Essentially, when I right-click the element, I just get the browser's right-click menu, no console message is generated.
https://dojotoolkit.org/reference-guide/1.10/dojo/mouse.html
on(myNode,'click',function(e) {
if (mouse.isLeft(e)){
console.log("left click", e);
} else if (mouse.isRight(e)){
console.log("right click",e);
}
});
The browser right click context menu consumes the click event. It will work if you use 'mousedown' instead of 'click'. There are also many questions about right click detection in javascript that you can look into for alternate methods. For example: Failing to identify right click event in Mozilla Firefox.
The dojo/mouse module is mostly a utility wrapper over the usual event handling, so the information in these questions still applies.
You cannot detect mouse.isRight when using event click. Instead you could use mousedown as in the following example:
https://jsfiddle.net/xgekrp5e/
require(["dojo/mouse", "dojo/on"], function(mouse, on) {
on(document, "mousedown", function(evt) {
if (mouse.isLeft(event)) {
// handle mouse left click
alert('MOUSE LEFT');
} else if (mouse.isRight(event)) {
// handle mouse right click
alert('MOUSE RIGHT');
}
});
});
In this Meteor template code, when the canvas is clicked, it prints out the canvas element to the console but it is expected not to fire the event.
How can it be made so that it fires if the element which is clicked is not a canvas?
Template.myTemp.events({
'click *:not(canvas)': function(e) {
e.stopPropagation();
console.log(e.target);
});
Definitely an interesting problem as the :not selector is supported by Blaze, and works properly with other HTML elements. You might want to open an issue about this in the Blaze repo.
The above being said, there are a few different ways you can work around this. You could add a check in your event handler to make sure you don't do anything with canvas related events:
Template.myTemp.events({
'click *'(event, instance) {
if (event.target.nodeName.toLowerCase() !== 'canvas') {
// Handle non-canvas events ...
}
},
});
Another option involves chaining your event handlers, if you want to be able to filter out canvas events specifically. For example:
Template.myTemp.events({
'click canvas'(event, instance) {
event.stopImmediatePropagation();
// Handle canvas click events only ...
},
'click *'(event, instance) {
// Handle all click events except canvas click events, since they're
// captured and handled above ...
},
});
A websites Button isn't rendering on my browser. I know it's there, when I'm in the view source I still see the button, and the onclick function. Can I still call this function by passing the url the function? Or in the console?
Even if it's not an onclick, is it possible to call functions by either URL or Console?
You can click any DOM element by selecting it and calling the click() function.
document.getElementById("yourElementId").click();
Works with Jquery as well.
$(selector).click();
To accomplish this, you can use the following line:
document.getElementById("element_id").click()
According to MDN, this simulates a full click on the element, including all it entails:
When click is used with elements that support it (e.g. one of the types listed above), it also fires the element's click event which will bubble up to elements higher up the document tree (or event chain) and fire their click events too. However, bubbling of a click event will not cause an element to initiate navigation as if a real mouse-click had been received.
Alternatively, you can use jQuery to accomplish the same thing:
$("#trigger").click();
Here is the simplest way:
function fireClick(node){
if ( document.createEvent ) {
var evt = document.createEvent('MouseEvents');
evt.initEvent('click', true, false);
node.dispatchEvent(evt);
} else if( document.createEventObject ) {
node.fireEvent('onclick') ;
} else if (typeof node.onclick == 'function' ) {
node.onclick();
}
}
So you can trigger the click event for an element like below:
fireClick(document.getElementById('id'));
Reference from here.
I have a jquery script that attaches a click event to every link, running an action when the link is clicked. This has been working great, but I just got some betatester feedback that's foiling me.
The user was right-clicking on the link and opening it in a new tab. When she did this, jquery didn't trap the click. BAD USER. I reproduced this with cmd-click as well.
Is there a way to trap these gestures, or this an inherent limitation?
So you want to capture every click? Event the right or middle one? Shouldn't the mousedown event do just that?
Of course, she could right click a link just to "Copy Link Location"...
See if you can somehow make use of jQuery rightclick plugin:
http://abeautifulsite.net/notebook/68
Usage:
$(document).ready( function() {
// Capture right click
$("#selector").rightClick( function(e) {
// Do something
});
// Capture right mouse down
$("#selector").rightMouseDown( function(e) {
// Do something
});
// Capture right mouseup
$("#selector").rightMouseUp( function(e) {
// Do something
});
// Disable context menu on an element
$("#selector").noContext();
});
As for the cmd-clickie bit, I'm really not sure. In case it's helpful, here's the jQuery hotkeys plugin:
http://www.webappers.com/2008/07/31/bind-a-hot-key-combination-with-jquery-hotkeys/
I've seen jquery.rightclick.js code in firebug. There are modifiers with the mousedown and mouseup event like:
altKey
ctrlKey
so you can use these two modifiers:
if(evt.altKey || evt.ctrKey)
in jquery.rightclick.js