Skip to content

Commit e0ed809

Browse files
committed
fixing issue swisnl#51 - delay elementFromPoint test because Firefox 12 would trigger the contextmenu event on the newly uncovered element instead of the layer
1 parent 13ae5b7 commit e0ed809

File tree

1 file changed

+68
-42
lines changed

1 file changed

+68
-42
lines changed

src/jquery.contextMenu.js

Lines changed: 68 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,8 @@ var // currently active contextMenu trigger
310310
layerClick: function(e) {
311311
var $this = $(this),
312312
root = $this.data('contextMenuRoot'),
313+
mouseup = false,
314+
button = e.button,
313315
x = e.pageX,
314316
y = e.pageY,
315317
target,
@@ -319,59 +321,83 @@ var // currently active contextMenu trigger
319321
e.preventDefault();
320322
e.stopImmediatePropagation();
321323

322-
if ((root.trigger == 'left' && e.button == 0) || (root.trigger == 'right' && e.button == 2)) {
323-
if (document.elementFromPoint) {
324-
root.$layer.hide();
325-
target = document.elementFromPoint(x, y);
326-
root.$layer.show();
324+
// This hack looks about as ugly as it is
325+
// Firefox 12 (at least) fires the contextmenu event directly "after" mousedown
326+
// for some reason `root.$layer.hide(); document.elementFromPoint()` causes this
327+
// contextmenu event to be triggered on the uncovered element instead of on the
328+
// layer (where every other sane browser, including Firefox nightly at the time)
329+
// triggers the event. This workaround might be obsolete by September 2012.
330+
$this.on('mouseup', function() {
331+
mouseup = true;
332+
});
333+
setTimeout(function() {
334+
var $window, hideshow;
335+
336+
// test if we need to reposition the menu
337+
if ((root.trigger == 'left' && button == 0) || (root.trigger == 'right' && button == 2)) {
338+
if (document.elementFromPoint) {
339+
root.$layer.hide();
340+
target = document.elementFromPoint(x, y);
341+
root.$layer.show();
327342

328-
selectors = [];
329-
for (var s in namespaces) {
330-
selectors.push(s);
331-
}
343+
selectors = [];
344+
for (var s in namespaces) {
345+
selectors.push(s);
346+
}
332347

333-
target = $(target).closest(selectors.join(', '));
348+
target = $(target).closest(selectors.join(', '));
334349

335-
if (target.length) {
336-
if (target.is(root.$trigger[0])) {
337-
root.position.call(root.$trigger, root, x, y);
338-
return;
350+
if (target.length) {
351+
if (target.is(root.$trigger[0])) {
352+
root.position.call(root.$trigger, root, x, y);
353+
return;
354+
}
339355
}
340-
}
341-
} else {
342-
offset = root.$trigger.offset();
343-
344-
// while this looks kinda awful, it's the best way to avoid
345-
// unnecessarily calculating any positions
346-
offset.top += $(window).scrollTop();
347-
if (offset.top <= e.pageY) {
348-
offset.left += $(window).scrollLeft();
349-
if (offset.left <= e.pageX) {
350-
offset.bottom = offset.top + root.$trigger.outerHeight();
351-
if (offset.bottom >= e.pageY) {
352-
offset.right = offset.left + root.$trigger.outerWidth();
353-
if (offset.right >= e.pageX) {
354-
// reposition
355-
root.position.call(root.$trigger, root, x, y);
356-
return;
356+
} else {
357+
offset = root.$trigger.offset();
358+
$window = $(window);
359+
// while this looks kinda awful, it's the best way to avoid
360+
// unnecessarily calculating any positions
361+
offset.top += $window.scrollTop();
362+
if (offset.top <= e.pageY) {
363+
offset.left += $window.scrollLeft();
364+
if (offset.left <= e.pageX) {
365+
offset.bottom = offset.top + root.$trigger.outerHeight();
366+
if (offset.bottom >= e.pageY) {
367+
offset.right = offset.left + root.$trigger.outerWidth();
368+
if (offset.right >= e.pageX) {
369+
// reposition
370+
root.position.call(root.$trigger, root, x, y);
371+
return;
372+
}
357373
}
358374
}
359375
}
360376
}
361377
}
362-
}
378+
379+
hideshow = function(e) {
380+
if (e) {
381+
e.preventDefault();
382+
e.stopImmediatePropagation();
383+
}
384+
385+
root.$menu.trigger('contextmenu:hide');
386+
if (target && target.length) {
387+
setTimeout(function() {
388+
target.contextMenu({x: x, y: y});
389+
}, 50);
390+
}
391+
};
363392

364-
// remove only after mouseup has completed
365-
$this.on('mouseup', function(e) {
366-
e.preventDefault();
367-
e.stopImmediatePropagation();
368-
root.$menu.trigger('contextmenu:hide');
369-
if (target && target.length) {
370-
setTimeout(function() {
371-
target.contextMenu({x: x, y: y});
372-
}, 50);
393+
if (mouseup) {
394+
// mouseup has already happened
395+
hideshow();
396+
} else {
397+
// remove only after mouseup has completed
398+
$this.on('mouseup', hideshow);
373399
}
374-
});
400+
}, 50);
375401
},
376402
// key handled :hover
377403
keyStop: function(e, opt) {

0 commit comments

Comments
 (0)