JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
vanilla ckeditor-3.2
[ckeditor.git] / _source / plugins / menu / plugin.js
index 93ac77f..ac45279 100644 (file)
@@ -8,57 +8,65 @@ CKEDITOR.plugins.add( 'menu',
        beforeInit : function( editor )\r
        {\r
                var groups = editor.config.menu_groups.split( ',' ),\r
-                       groupsOrder = {};\r
+                       groupsOrder = editor._.menuGroups = {},\r
+                       menuItems = editor._.menuItems = {};\r
 \r
                for ( var i = 0 ; i < groups.length ; i++ )\r
                        groupsOrder[ groups[ i ] ] = i + 1;\r
 \r
-               editor._.menuGroups = groupsOrder;\r
-               editor._.menuItems = {};\r
-       },\r
-\r
-       requires : [ 'floatpanel' ]\r
-});\r
+               editor.addMenuGroup = function( name, order )\r
+                       {\r
+                               groupsOrder[ name ] = order || 100;\r
+                       };\r
 \r
-CKEDITOR.tools.extend( CKEDITOR.editor.prototype,\r
-{\r
-       addMenuGroup : function( name, order )\r
-       {\r
-               this._.menuGroups[ name ] = order || 100;\r
-       },\r
+               editor.addMenuItem = function( name, definition )\r
+                       {\r
+                               if ( groupsOrder[ definition.group ] )\r
+                                       menuItems[ name ] = new CKEDITOR.menuItem( this, name, definition );\r
+                       };\r
 \r
-       addMenuItem : function( name, definition )\r
-       {\r
-               if ( this._.menuGroups[ definition.group ] )\r
-                       this._.menuItems[ name ] = new CKEDITOR.menuItem( this, name, definition );\r
-       },\r
+               editor.addMenuItems = function( definitions )\r
+                       {\r
+                               for ( var itemName in definitions )\r
+                               {\r
+                                       this.addMenuItem( itemName, definitions[ itemName ] );\r
+                               }\r
+                       };\r
 \r
-       addMenuItems : function( definitions )\r
-       {\r
-               for ( var itemName in definitions )\r
-               {\r
-                       this.addMenuItem( itemName, definitions[ itemName ] );\r
-               }\r
+               editor.getMenuItem = function( name )\r
+                       {\r
+                               return menuItems[ name ];\r
+                       };\r
        },\r
 \r
-       getMenuItem : function( name )\r
-       {\r
-               return this._.menuItems[ name ];\r
-       }\r
+       requires : [ 'floatpanel' ]\r
 });\r
 \r
 (function()\r
 {\r
        CKEDITOR.menu = CKEDITOR.tools.createClass(\r
        {\r
-               $ : function( editor, level )\r
+               $ : function( editor, definition )\r
                {\r
+                       definition = this._.definition = definition || {};\r
                        this.id = 'cke_' + CKEDITOR.tools.getNextNumber();\r
 \r
                        this.editor = editor;\r
                        this.items = [];\r
 \r
-                       this._.level = level || 1;\r
+                       this._.level = definition.level || 1;\r
+\r
+                       var panelDefinition = CKEDITOR.tools.extend( {}, definition.panel,\r
+                       {\r
+                               css : editor.skin.editor.css,\r
+                               level : this._.level - 1,\r
+                               block : {}\r
+                       } );\r
+\r
+                       var attrs = panelDefinition.block.attributes = ( panelDefinition.attributes || {} );\r
+                       // Provide default role of 'menu'.\r
+                       !attrs.role && ( attrs.role = 'menu' );\r
+                       this._.panelDefinition = panelDefinition;\r
                },\r
 \r
                _ :\r
@@ -77,15 +85,22 @@ CKEDITOR.tools.extend( CKEDITOR.editor.prototype,
                                        return;\r
                                }\r
 \r
+                               // Record parent menu focused item first (#3389).\r
+                               var block = this._.panel.getBlock( this.id );\r
+                               block._.focusIndex = index;\r
+\r
                                // Create the submenu, if not available, or clean the existing\r
                                // one.\r
                                if ( menu )\r
                                        menu.removeAll();\r
                                else\r
                                {\r
-                                       menu = this._.subMenu = new CKEDITOR.menu( this.editor, this._.level + 1 );\r
+                                       menu = this._.subMenu = new CKEDITOR.menu( this.editor,\r
+                                                                  CKEDITOR.tools.extend( {}, this._.definition, { level : this._.level + 1 }, true ) );\r
                                        menu.parent = this;\r
                                        menu.onClick = CKEDITOR.tools.bind( this.onClick, this );\r
+                                       // Sub menu use their own scope for binding onEscape.\r
+                                       menu.onEscape = this.onEscape;\r
                                }\r
 \r
                                // Add all submenu items to the menu.\r
@@ -135,18 +150,15 @@ CKEDITOR.tools.extend( CKEDITOR.editor.prototype,
                                // Create the floating panel for this menu.\r
                                if ( !panel )\r
                                {\r
-                                       panel = this._.panel = new CKEDITOR.ui.floatPanel( this.editor, CKEDITOR.document.getBody(),\r
-                                               {\r
-                                                       css : editor.skin.editor.css,\r
-                                                       level : this._.level - 1,\r
-                                                       className : editor.skinClass + ' cke_contextmenu'\r
-                                               },\r
-                                               this._.level);\r
+                                       panel = this._.panel = new CKEDITOR.ui.floatPanel( this.editor,\r
+                                               CKEDITOR.document.getBody(),\r
+                                               this._.panelDefinition,\r
+                                               this._.level );\r
 \r
-                                       panel.onEscape = CKEDITOR.tools.bind( function()\r
+                                       panel.onEscape = CKEDITOR.tools.bind( function( keystroke )\r
                                        {\r
-                                               this.onEscape && this.onEscape();\r
-                                               this.hide();\r
+                                               if ( this.onEscape && this.onEscape( keystroke ) === false )\r
+                                                       return false;\r
                                        },\r
                                        this );\r
 \r
@@ -157,7 +169,7 @@ CKEDITOR.tools.extend( CKEDITOR.editor.prototype,
                                        this );\r
 \r
                                        // Create an autosize block inside the panel.\r
-                                       var block = panel.addBlock( this.id );\r
+                                       var block = panel.addBlock( this.id, this._.panelDefinition.block );\r
                                        block.autoSize = true;\r
 \r
                                        var keys = block.keys;\r
@@ -166,7 +178,7 @@ CKEDITOR.tools.extend( CKEDITOR.editor.prototype,
                                        keys[ 38 ]      = 'prev';                                       // ARROW-UP\r
                                        keys[ CKEDITOR.SHIFT + 9 ]      = 'prev';       // SHIFT + TAB\r
                                        keys[ 32 ]      = 'click';                                      // SPACE\r
-                                       keys[ 39 ]      = 'click';                                      // ARROW-RIGHT\r
+                                       keys[ ( editor.lang.dir == 'rtl' ? 37 : 39 ) ]  = 'click';  // ARROW-RIGHT/ARROW-LEFT(rtl)\r
 \r
                                        element = this._.element = block.element;\r
                                        element.addClass( editor.skinClass );\r
@@ -210,7 +222,7 @@ CKEDITOR.tools.extend( CKEDITOR.editor.prototype,
                                sortItems( items );\r
 \r
                                // Build the HTML that composes the menu and its items.\r
-                               var output = [ '<div class="cke_menu">' ];\r
+                               var output = [ '<div class="cke_menu" role="presentation">' ];\r
 \r
                                var length = items.length,\r
                                        lastGroup = length && items[ 0 ].group;\r
@@ -220,7 +232,7 @@ CKEDITOR.tools.extend( CKEDITOR.editor.prototype,
                                        var item = items[ i ];\r
                                        if ( lastGroup != item.group )\r
                                        {\r
-                                               output.push( '<div class="cke_menuseparator"></div>' );\r
+                                               output.push( '<div class="cke_menuseparator" role="separator"></div>' );\r
                                                lastGroup = item.group;\r
                                        }\r
 \r
@@ -295,12 +307,12 @@ CKEDITOR.menuItem = CKEDITOR.tools.createClass(
                                'off' );\r
 \r
                        var htmlLabel = this.label;\r
-                       if ( state == CKEDITOR.TRISTATE_DISABLED )\r
-                               htmlLabel = this.editor.lang.common.unavailable.replace( '%1', htmlLabel );\r
 \r
                        if ( this.className )\r
                                classes += ' ' + this.className;\r
 \r
+                       var hasSubMenu = this.getItems;\r
+\r
                        output.push(\r
                                '<span class="cke_menuitem">' +\r
                                '<a id="', id, '"' +\r
@@ -308,7 +320,11 @@ CKEDITOR.menuItem = CKEDITOR.tools.createClass(
                                        ' title="', this.label, '"' +\r
                                        ' tabindex="-1"' +\r
                                        '_cke_focus=1' +\r
-                                       ' hidefocus="true"' );\r
+                                       ' hidefocus="true"' +\r
+                                       ' role="menuitem"' +\r
+                                       ( hasSubMenu ? 'aria-haspopup="true"' : '' ) +\r
+                                       ( state == CKEDITOR.TRISTATE_DISABLED ? 'aria-disabled="true"' : '' ) +\r
+                                       ( state == CKEDITOR.TRISTATE_ON ? 'aria-pressed="true"' : '' ) );\r
 \r
                        // Some browsers don't cancel key events in the keydown but in the\r
                        // keypress.\r
@@ -340,10 +356,16 @@ CKEDITOR.menuItem = CKEDITOR.tools.createClass(
                                                        '></span></span>' +\r
                                                '<span class="cke_label">' );\r
 \r
-                       if ( this.getItems )\r
+                       if ( hasSubMenu )\r
                        {\r
                                output.push(\r
-                                                       '<span class="cke_menuarrow"></span>' );\r
+                                                       '<span class="cke_menuarrow">',\r
+                                                               '<span>&#',\r
+                                                                       ( this.editor.lang.dir == 'rtl' ?\r
+                                                                               '9668' :        // BLACK LEFT-POINTING POINTER\r
+                                                                               '9658' ),       // BLACK RIGHT-POINTING POINTER\r
+                                                               ';</span>',\r
+                                                       '</span>' );\r
                        }\r
 \r
                        output.push(\r