2 * jQuery plugin to update the tooltip to show the correct access key
4 * @class jQuery.plugin.accessKeyLabel
8 // Cached access key modifiers for used browser
9 var cachedAccessKeyModifiers
,
11 // Whether to use 'test-' instead of correct prefix (used for testing)
12 useTestPrefix
= false,
14 // tag names which can have a label tag
15 // https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Content_categories#Form-associated_content
16 labelable
= 'button, input, textarea, keygen, meter, output, progress, select';
19 * Find the modifier keys that need to be pressed together with the accesskey to trigger the input.
21 * The result is dependant on the ua paramater or the current platform.
22 * For browsers that support accessKeyLabel, #getAccessKeyLabel never calls here.
23 * Valid key values that are returned can be: ctrl, alt, option, shift, esc
26 * @param {Object} [ua] An object with a 'userAgent' and 'platform' property.
27 * @return {Array} Array with 1 or more of the string values, in this order: ctrl, option, alt, shift, esc
29 function getAccessKeyModifiers( ua
) {
30 var profile
, accessKeyModifiers
;
32 // use cached prefix if possible
33 if ( !ua
&& cachedAccessKeyModifiers
) {
34 return cachedAccessKeyModifiers
;
37 profile
= $.client
.profile( ua
);
39 switch ( profile
.name
) {
42 if ( profile
.name
=== 'opera' && profile
.versionNumber
< 15 ) {
43 accessKeyModifiers
= [ 'shift', 'esc' ];
44 } else if ( profile
.platform
=== 'mac' ) {
45 accessKeyModifiers
= [ 'ctrl', 'option' ];
47 // Chrome/Opera on Windows or Linux
48 // (both alt- and alt-shift work, but alt with E, D, F etc does not
49 // work since they are browser shortcuts)
50 accessKeyModifiers
= [ 'alt', 'shift' ];
55 if ( profile
.versionBase
< 2 ) {
56 // Before v2, Firefox used alt, though it was rebindable in about:config
57 accessKeyModifiers
= [ 'alt' ];
59 if ( profile
.platform
=== 'mac' ) {
60 if ( profile
.versionNumber
< 14 ) {
61 accessKeyModifiers
= [ 'ctrl' ];
63 accessKeyModifiers
= [ 'ctrl', 'option' ];
66 accessKeyModifiers
= [ 'alt', 'shift' ];
72 if ( profile
.platform
=== 'win' ) {
73 accessKeyModifiers
= [ 'alt' ];
75 if ( profile
.layoutVersion
> 526 ) {
76 // Non-Windows Safari with webkit_version > 526
77 accessKeyModifiers
= [ 'ctrl', profile
.platform
=== 'mac' ? 'option' : 'alt' ];
79 accessKeyModifiers
= [ 'ctrl' ];
85 accessKeyModifiers
= [ 'alt' ];
88 accessKeyModifiers
= profile
.platform
=== 'mac' ? [ 'ctrl' ] : [ 'alt' ];
94 cachedAccessKeyModifiers
= accessKeyModifiers
;
96 return accessKeyModifiers
;
100 * Get the access key label for an element.
102 * Will use native accessKeyLabel if available (currently only in Firefox 8+),
103 * falls back to #getAccessKeyModifiers.
106 * @param {HTMLElement} element Element to get the label for
107 * @return {string} Access key label
109 function getAccessKeyLabel( element
) {
110 // abort early if no access key
111 if ( !element
.accessKey
) {
114 // use accessKeyLabel if possible
115 // https://html.spec.whatwg.org/multipage/interaction.html#dom-accesskeylabel
116 if ( !useTestPrefix
&& element
.accessKeyLabel
) {
117 return element
.accessKeyLabel
;
119 return ( useTestPrefix
? 'test' : getAccessKeyModifiers().join( '-' ) ) + '-' + element
.accessKey
;
123 * Update the title for an element (on the element with the access key or it's label) to show
124 * the correct access key label.
127 * @param {HTMLElement} element Element with the accesskey
128 * @param {HTMLElement} titleElement Element with the title to update (may be the same as `element`)
130 function updateTooltipOnElement( element
, titleElement
) {
131 var oldTitle
, parts
, regexp
, newTitle
, accessKeyLabel
;
133 oldTitle
= titleElement
.title
;
135 // don't add a title if the element didn't have one before
139 parts
= ( mw
.msg( 'word-separator' ) + mw
.msg( 'brackets' ) ).split( '$1' );
140 regexp
= new RegExp( $.map( parts
, mw
.RegExp
.escape
).join( '.*?' ) + '$' );
141 newTitle
= oldTitle
.replace( regexp
, '' );
142 accessKeyLabel
= getAccessKeyLabel( element
);
144 if ( accessKeyLabel
) {
145 // Should be build the same as in Linker::titleAttrib
146 newTitle
+= mw
.msg( 'word-separator' ) + mw
.msg( 'brackets', accessKeyLabel
);
148 if ( oldTitle
!== newTitle
) {
149 titleElement
.title
= newTitle
;
154 * Update the title for an element to show the correct access key label.
157 * @param {HTMLElement} element Element with the accesskey
159 function updateTooltip( element
) {
160 var id
, $element
, $label
, $labelParent
;
161 updateTooltipOnElement( element
, element
);
163 // update associated label if there is one
164 $element
= $( element
);
165 if ( $element
.is( labelable
) ) {
166 // Search it using 'for' attribute
167 id
= element
.id
.replace( /"/g, '\\"' );
169 $label = $( 'label
[for="' + id + '"]' );
170 if ( $label.length === 1 ) {
171 updateTooltipOnElement( element, $label[ 0 ] );
175 // Search it as parent, because the form control can also be inside the label element itself
176 $labelParent = $element.parents( 'label
' );
177 if ( $labelParent.length === 1 ) {
178 updateTooltipOnElement( element, $labelParent[ 0 ] );
184 * Update the titles for all elements in a jQuery selection.
189 $.fn.updateTooltipAccessKeys = function () {
190 return this.each( function () {
191 updateTooltip( this );
196 * getAccessKeyModifiers
198 * @method updateTooltipAccessKeys_getAccessKeyModifiers
199 * @inheritdoc #getAccessKeyModifiers
201 $.fn.updateTooltipAccessKeys.getAccessKeyModifiers = getAccessKeyModifiers;
206 * @method updateTooltipAccessKeys_getAccessKeyLabel
207 * @inheritdoc #getAccessKeyLabel
209 $.fn.updateTooltipAccessKeys.getAccessKeyLabel = getAccessKeyLabel;
214 * @method updateTooltipAccessKeys_getAccessKeyPrefix
215 * @deprecated since 1.27 Use #getAccessKeyModifiers
216 * @param {Object} [ua] An object with a 'userAgent
' and 'platform
' property.
219 $.fn.updateTooltipAccessKeys.getAccessKeyPrefix = function ( ua ) {
220 return getAccessKeyModifiers( ua ).join( '-' ) + '-';
224 * Switch test mode on and off.
226 * @method updateTooltipAccessKeys_setTestMode
227 * @param {boolean} mode New mode
229 $.fn.updateTooltipAccessKeys.setTestMode = function ( mode ) {
230 useTestPrefix = mode;
235 * @mixins jQuery.plugin.accessKeyLabel
238 }( jQuery, mediaWiki ) );