2
YUI 3.10.3 (build 2fb5187)
3
Copyright 2013 Yahoo! Inc. All rights reserved.
4
Licensed under the BSD License.
5
http://yuilibrary.com/license/
8
YUI.add('event-contextmenu', function (Y, NAME) {
11
* Provides extended keyboard support for the "contextmenu" event such that:
13
* <li>The browser's default context menu is suppressed regardless of how the event is triggered.</li>
14
* <li>On Windows the "contextmenu" event is fired consistently regardless of whether the user
15
* pressed the Menu key or Shift + F10.</li>
16
* <li>When the "contextmenu" event is fired via the keyboard, the pageX, pageY, clientX and clientY
17
* properties reference the center of the event target. This makes it easy for "contextmenu" event listeners
18
* to position an overlay in response to the event by not having to worry about special handling of the x
19
* and y coordinates based on the device that fired the event.</li>
20
* <li>For Webkit and Gecko on the Mac it enables the use of the Shift + Control + Option + M keyboard
21
* shortcut to fire the "contextmenu" event, which (by default) is only available when VoiceOver
22
* (the screen reader on the Mac) is enabled.</li>
23
* <li>For Opera on the Mac it ensures the "contextmenu" event is fired when the user presses
24
* Shift + Command + M (Opera's context menu keyboard shortcut).</li>
26
* @module event-contextmenu
40
isWin = (OS === "windows"),
41
isMac = (OS === "macintosh"),
47
on: function (node, subscription, notifier, filter) {
51
handles.push(Event._attach(["contextmenu", function (e) {
53
// Any developer listening for the "contextmenu" event is likely
54
// going to call preventDefault() to prevent the display of
55
// the browser's context menu. So, you know, save them a step.
58
var id = Y.stamp(node),
62
e.clientX = data.clientX;
63
e.clientY = data.clientY;
74
handles.push(node[filter ? "delegate" : "on"]("keydown", function (e) {
76
var target = this.getDOMNode(),
77
shiftKey = e.shiftKey,
79
shiftF10 = (shiftKey && keyCode == 121),
80
menuKey = (isWin && keyCode == 93),
82
mKey = (keyCode === 77),
83
macWebkitAndGeckoShortcut = (isMac && (webkit || gecko) && ctrlKey && shiftKey && e.altKey && mKey),
85
// Note: The context menu keyboard shortcut for Opera on the Mac is Shift + Cmd (metaKey) + M,
86
// but e.metaKey is false for Opera, and Opera sets e.ctrlKey to true instead.
87
macOperaShortcut = (isMac && opera && ctrlKey && shiftKey && mKey),
100
if ((isWin && (shiftF10 || menuKey)) ||
101
(macWebkitAndGeckoShortcut || macOperaShortcut)) {
103
// Need to call preventDefault() here b/c:
104
// 1) To prevent IE's menubar from gaining focus when the
105
// user presses Shift + F10
106
// 2) In Firefox and Opera for Win, Shift + F10 will display a
107
// context menu, but won't fire the "contextmenu" event. So, need
108
// to call preventDefault() to prevent the display of the
109
// browser's context menu
110
// 3) For Opera on the Mac the context menu keyboard shortcut
111
// (Shift + Cmd + M) will display a context menu, but like Firefox
112
// and Opera on windows, Opera doesn't fire a "contextmenu" event,
113
// so preventDefault() is just used to supress Opera's
114
// default context menu.
115
if (((ie || (isWin && (gecko || opera))) && shiftF10) || macOperaShortcut) {
119
xy = DOM.getXY(target);
122
scrollX = DOM.docScrollX();
123
scrollY = DOM.docScrollY();
125
// Protect against instances where xy and might not be returned,
126
// for example if the target is the document.
127
if (!Y.Lang.isUndefined(x)) {
128
clientX = (x + (target.offsetWidth/2)) - scrollX;
129
clientY = (y + (target.offsetHeight/2)) - scrollY;
132
pageX = clientX + scrollX;
133
pageY = clientY + scrollY;
135
// When the "contextmenu" event is fired from the keyboard
136
// clientX, clientY, pageX or pageY aren't set to useful
137
// values. So, we follow Safari's model here of setting
138
// the x & x coords to the center of the event target.
140
if (menuKey || (isWin && webkit && shiftF10)) {
141
eventData[Y.stamp(node)] = {
149
// Don't need to call notifier.fire(e) when the Menu key
150
// is pressed as it fires the "contextmenu" event by default.
152
// In IE the call to preventDefault() for Shift + F10
153
// prevents the "contextmenu" event from firing, so we need
154
// to call notifier.fire(e)
156
// Need to also call notifier.fire(e) for Gecko and Opera since
157
// neither Shift + F10 or Shift + Cmd + M fire the "contextmenu" event.
159
// Lastly, also need to call notifier.fire(e) for all Mac browsers
160
// since neither Shift + Ctrl + Option + M (Webkit and Gecko) or
161
// Shift + Command + M (Opera) fire the "contextmenu" event.
163
if (((ie || (isWin && (gecko || opera))) && shiftF10) || isMac) {
177
subscription._handles = handles;
181
detach: function (node, subscription, notifier) {
183
Y.each(subscription._handles, function (handle) {
192
conf.delegate = conf.on;
193
conf.detachDelegate = conf.detach;
196
Event.define("contextmenu", conf, true);
199
}, '3.10.3', {"requires": ["event-synthetic", "dom-screen"]});