/**\r
- * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.\r
+ * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.\r
* For licensing, see LICENSE.md or http://ckeditor.com/license\r
*/\r
\r
};\r
\r
/**\r
- * Adds one or more items from the specified definition array to the editor context menu.\r
+ * Adds one or more items from the specified definition object to the editor context menu.\r
*\r
* @method\r
- * @param {Array} definitions List of definitions for each menu item as if {@link #addMenuItem} is called.\r
+ * @param {Object} definitions Object where keys are used as itemName and corresponding values as definition for a {@link #addMenuItem} call.\r
* @member CKEDITOR.editor\r
*/\r
editor.addMenuItems = function( definitions ) {\r
' class="cke_menubutton cke_menubutton__{name} cke_menubutton_{state} {cls}" href="{href}"' +\r
' title="{title}"' +\r
' tabindex="-1"' +\r
- '_cke_focus=1' +\r
+ ' _cke_focus=1' +\r
' hidefocus="true"' +\r
' role="{role}"' +\r
+ ' aria-label="{label}"' +\r
+ ' aria-describedby="{id}_description"' +\r
' aria-haspopup="{hasPopup}"' +\r
' aria-disabled="{disabled}"' +\r
- ' {ariaChecked}';\r
+ ' {ariaChecked}' +\r
+ ' draggable="false"';\r
\r
// Some browsers don't cancel key events in the keydown but in the\r
// keypress.\r
menuItemSource += ' onkeypress="return false;"';\r
\r
// With Firefox, we need to force the button to redraw, otherwise it\r
- // will remain in the focus state.\r
- if ( CKEDITOR.env.gecko )\r
- menuItemSource += ' onblur="this.style.cssText = this.style.cssText;"';\r
+ // will remain in the focus state. Also we some extra help to prevent dragging (http://dev.ckeditor.com/ticket/10373).\r
+ if ( CKEDITOR.env.gecko ) {\r
+ menuItemSource += ( ' onblur="this.style.cssText = this.style.cssText;"' +\r
+ ' ondragstart="return false;"' );\r
+ }\r
\r
- // #188\r
+ // http://dev.ckeditor.com/ticket/188\r
menuItemSource += ' onmouseover="CKEDITOR.tools.callFunction({hoverFn},{index});"' +\r
' onmouseout="CKEDITOR.tools.callFunction({moveOutFn},{index});" ' +\r
( CKEDITOR.env.ie ? 'onclick="return false;" onmouseup' : 'onclick' ) +\r
'>';\r
\r
menuItemSource +=\r
+ //'' +\r
'<span class="cke_menubutton_inner">' +\r
'<span class="cke_menubutton_icon">' +\r
'<span class="cke_button_icon cke_button__{iconName}_icon" style="{iconStyle}"></span>' +\r
'<span class="cke_menubutton_label">' +\r
'{label}' +\r
'</span>' +\r
+ '{shortcutHtml}' +\r
'{arrowHtml}' +\r
'</span>' +\r
- '</a></span>';\r
+ '</a><span id="{id}_description" class="cke_voice_label" aria-hidden="false">{ariaShortcut}</span></span>';\r
\r
var menuArrowSource = '<span class="cke_menuarrow">' +\r
'<span>{label}</span>' +\r
'</span>';\r
\r
+ var menuShortcutSource = '<span class="cke_menubutton_label cke_menubutton_shortcut">' +\r
+ '{shortcut}' +\r
+ '</span>';\r
+\r
var menuItemTpl = CKEDITOR.addTemplate( 'menuItem', menuItemSource ),\r
- menuArrowTpl = CKEDITOR.addTemplate( 'menuArrow', menuArrowSource );\r
+ menuArrowTpl = CKEDITOR.addTemplate( 'menuArrow', menuArrowSource ),\r
+ menuShortcutTpl = CKEDITOR.addTemplate( 'menuShortcut', menuShortcutSource );\r
\r
/**\r
* @class\r
\r
// Show the submenu.\r
// This timeout is needed to give time for the sub-menu get\r
- // focus when JAWS is running. (#9844)\r
+ // focus when JAWS is running. (http://dev.ckeditor.com/ticket/9844)\r
setTimeout( function() {\r
menu.show( element, 2 );\r
}, 0 );\r
add: function( item ) {\r
// Later we may sort the items, but Array#sort is not stable in\r
// some browsers, here we're forcing the original sequence with\r
- // 'order' attribute if it hasn't been assigned. (#3868)\r
+ // 'order' attribute if it hasn't been assigned. (http://dev.ckeditor.com/ticket/3868)\r
if ( !item.order )\r
item.order = this.items.length;\r
\r
keys[ CKEDITOR.SHIFT + 9 ] = 'prev'; // SHIFT + TAB\r
keys[ ( editor.lang.dir == 'rtl' ? 37 : 39 ) ] = CKEDITOR.env.ie ? 'mouseup' : 'click'; // ARROW-RIGHT/ARROW-LEFT(rtl)\r
keys[ 32 ] = CKEDITOR.env.ie ? 'mouseup' : 'click'; // SPACE\r
- CKEDITOR.env.ie && ( keys[ 13 ] = 'mouseup' ); // Manage ENTER, since onclick is blocked in IE (#8041).\r
+ CKEDITOR.env.ie && ( keys[ 13 ] = 'mouseup' ); // Manage ENTER, since onclick is blocked in IE (http://dev.ckeditor.com/ticket/8041).\r
\r
element = this._.element = block.element;\r
\r
render: function( menu, index, output ) {\r
var id = menu.id + String( index ),\r
state = ( typeof this.state == 'undefined' ) ? CKEDITOR.TRISTATE_OFF : this.state,\r
- ariaChecked = '';\r
+ ariaChecked = '',\r
+ editor = this.editor,\r
+ keystroke,\r
+ command,\r
+ shortcut;\r
\r
var stateName = state == CKEDITOR.TRISTATE_ON ? 'on' : state == CKEDITOR.TRISTATE_DISABLED ? 'disabled' : 'off';\r
\r
if ( this.icon && !( /\./ ).test( this.icon ) )\r
iconName = this.icon;\r
\r
+ if ( this.command ) {\r
+ command = editor.getCommand( this.command );\r
+ keystroke = editor.getCommandKeystroke( command );\r
+\r
+ if ( keystroke ) {\r
+ shortcut = CKEDITOR.tools.keystrokeToString( editor.lang.common.keyboard, keystroke );\r
+ }\r
+ }\r
+\r
var params = {\r
id: id,\r
name: this.name,\r
state: stateName,\r
hasPopup: hasSubMenu ? 'true' : 'false',\r
disabled: state == CKEDITOR.TRISTATE_DISABLED,\r
- title: this.label,\r
+ title: this.label + ( shortcut ? ' (' + shortcut.display + ')' : '' ),\r
+ ariaShortcut: shortcut ? editor.lang.common.keyboardShortcut + ' ' + shortcut.aria : '',\r
href: 'javascript:void(\'' + ( this.label || '' ).replace( "'" + '' ) + '\')', // jshint ignore:line\r
hoverFn: menu._.itemOverFn,\r
moveOutFn: menu._.itemOutFn,\r
clickFn: menu._.itemClickFn,\r
index: index,\r
iconStyle: CKEDITOR.skin.getIconStyle( iconName, ( this.editor.lang.dir == 'rtl' ), iconName == this.icon ? null : this.icon, this.iconOffset ),\r
+ shortcutHtml: shortcut ? menuShortcutTpl.output( { shortcut: shortcut.display } ) : '',\r
arrowHtml: hasSubMenu ? menuArrowTpl.output( { label: arrowLabel } ) : '',\r
role: this.role ? this.role : 'menuitem',\r
ariaChecked: ariaChecked\r