JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
vanilla ckeditor-3.6.1
[ckeditor.git] / _source / plugins / panel / plugin.js
index ec682a6..cb0a615 100644 (file)
@@ -1,5 +1,5 @@
 /*\r
-Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved.\r
+Copyright (c) 2003-2011, CKSource - Frederico Knabben. All rights reserved.\r
 For licensing, see LICENSE.html or http://ckeditor.com/license\r
 */\r
 \r
@@ -16,7 +16,7 @@ CKEDITOR.plugins.add( 'panel',
  * @constant\r
  * @example\r
  */\r
-CKEDITOR.UI_PANEL = 2;\r
+CKEDITOR.UI_PANEL = 'panel';\r
 \r
 CKEDITOR.ui.panel = function( document, definition )\r
 {\r
@@ -31,7 +31,7 @@ CKEDITOR.ui.panel = function( document, definition )
                        css : []\r
                });\r
 \r
-       this.id = CKEDITOR.tools.getNextNumber();\r
+       this.id = CKEDITOR.tools.getNextId();\r
        this.document = document;\r
 \r
        this._ =\r
@@ -73,16 +73,18 @@ CKEDITOR.ui.panel.prototype =
         */\r
        render : function( editor, output )\r
        {\r
-               var id = 'cke_' + this.id;\r
+               var id = this.id;\r
 \r
                output.push(\r
                        '<div class="', editor.skinClass ,'"' +\r
                                ' lang="', editor.langCode, '"' +\r
+                               ' role="presentation"' +\r
                                // iframe loading need sometime, keep the panel hidden(#4186).\r
                                ' style="display:none;z-index:' + ( editor.config.baseFloatZIndex + 1 ) + '">' +\r
                                '<div' +\r
                                        ' id=', id,\r
                                        ' dir=', editor.lang.dir,\r
+                                       ' role="presentation"' +\r
                                        ' class="cke_panel cke_', editor.lang.dir );\r
 \r
                if ( this.className )\r
@@ -96,7 +98,7 @@ CKEDITOR.ui.panel.prototype =
                        output.push(\r
                                                '<iframe id="', id, '_frame"' +\r
                                                        ' frameborder="0"' +\r
-                                                       ' src="javascript:void(' );\r
+                                                       ' role="application" src="javascript:void(' );\r
 \r
                        output.push(\r
                                                        // Support for custom document.domain in IE.\r
@@ -128,18 +130,12 @@ CKEDITOR.ui.panel.prototype =
                {\r
                        if ( this.forceIFrame || this.css.length )\r
                        {\r
-                               var iframe = this.document.getById( 'cke_' + this.id + '_frame' ),\r
+                               var iframe = this.document.getById( this.id + '_frame' ),\r
                                        parentDiv = iframe.getParent(),\r
                                        dir = parentDiv.getAttribute( 'dir' ),\r
                                        className = parentDiv.getParent().getAttribute( 'class' ),\r
                                        langCode = parentDiv.getParent().getAttribute( 'lang' ),\r
                                        doc = iframe.getFrameDocument();\r
-                               // Initialize the IFRAME document body.\r
-                               doc.$.open();\r
-\r
-                               // Support for custom document.domain in IE.\r
-                               if ( CKEDITOR.env.isCustomDomain() )\r
-                                       doc.$.domain = document.domain;\r
 \r
                                var onLoad = CKEDITOR.tools.addFunction( CKEDITOR.tools.bind( function( ev )\r
                                        {\r
@@ -148,30 +144,32 @@ CKEDITOR.ui.panel.prototype =
                                                        this.onLoad();\r
                                        }, this ) );\r
 \r
-                               doc.$.write(\r
+                               var data =\r
                                        '<!DOCTYPE html>' +\r
                                        '<html dir="' + dir + '" class="' + className + '_container" lang="' + langCode + '">' +\r
                                                '<head>' +\r
                                                        '<style>.' + className + '_container{visibility:hidden}</style>' +\r
                                                '</head>' +\r
                                                '<body class="cke_' + dir + ' cke_panel_frame ' + CKEDITOR.env.cssClass + '" style="margin:0;padding:0"' +\r
-                                               ' onload="( window.CKEDITOR || window.parent.CKEDITOR ).tools.callFunction(' + onLoad + ');">' +\r
-                                               '</body>' +\r
+                                               ' onload="( window.CKEDITOR || window.parent.CKEDITOR ).tools.callFunction(' + onLoad + ');"></body>' +\r
                                                // It looks strange, but for FF2, the styles must go\r
                                                // after <body>, so it (body) becames immediatelly\r
                                                // available. (#3031)\r
-                                               '<link type="text/css" rel=stylesheet href="' + this.css.join( '"><link type="text/css" rel="stylesheet" href="' ) + '">' +\r
-                                       '<\/html>' );\r
-                               doc.$.close();\r
+                                               CKEDITOR.tools.buildStyleHtml( this.css ) +\r
+                                       '<\/html>';\r
+\r
+                               doc.write( data );\r
 \r
                                var win = doc.getWindow();\r
 \r
                                // Register the CKEDITOR global.\r
                                win.$.CKEDITOR = CKEDITOR;\r
 \r
-                               doc.on( 'keydown', function( evt )\r
+                               // Arrow keys for scrolling is only preventable with 'keypress' event in Opera (#4534).\r
+                               doc.on( 'key' + ( CKEDITOR.env.opera? 'press':'down' ), function( evt )\r
                                        {\r
-                                               var keystroke = evt.data.getKeystroke();\r
+                                               var keystroke = evt.data.getKeystroke(),\r
+                                                       dir = this.document.getById( this.id ).getAttribute( 'dir' );\r
 \r
                                                // Delegate key processing to block.\r
                                                if ( this._.onKeyDown && this._.onKeyDown( keystroke ) === false )\r
@@ -180,15 +178,21 @@ CKEDITOR.ui.panel.prototype =
                                                        return;\r
                                                }\r
 \r
-                                               if ( keystroke == 27 )          // ESC\r
-                                                       this.onEscape && this.onEscape();\r
+                                               // ESC/ARROW-LEFT(ltr) OR ARROW-RIGHT(rtl)\r
+                                               if ( keystroke == 27 || keystroke == ( dir == 'rtl' ? 39 : 37 ) )\r
+                                               {\r
+                                                       if ( this.onEscape && this.onEscape( keystroke ) === false )\r
+                                                               evt.data.preventDefault();\r
+                                               }\r
                                        },\r
                                        this );\r
 \r
                                holder = doc.getBody();\r
+                               holder.unselectable();\r
+                               CKEDITOR.env.air && CKEDITOR.tools.callFunction( onLoad );\r
                        }\r
                        else\r
-                               holder = this.document.getById( 'cke_' + this.id );\r
+                               holder = this.document.getById( this.id );\r
 \r
                        this._.holder = holder;\r
                }\r
@@ -198,7 +202,8 @@ CKEDITOR.ui.panel.prototype =
 \r
        addBlock : function( name, block )\r
        {\r
-               block = this._.blocks[ name ] = block || new CKEDITOR.ui.panel.block( this.getHolderElement() );\r
+               block = this._.blocks[ name ] = block instanceof CKEDITOR.ui.panel.block ?  block\r
+                               : new CKEDITOR.ui.panel.block( this.getHolderElement(), block );\r
 \r
                if ( !this._.currentBlock )\r
                        this.showBlock( name );\r
@@ -215,34 +220,64 @@ CKEDITOR.ui.panel.prototype =
        {\r
                var blocks = this._.blocks,\r
                        block = blocks[ name ],\r
-                       current = this._.currentBlock;\r
+                       current = this._.currentBlock,\r
+                       holder = this.forceIFrame ?\r
+                               this.document.getById( this.id + '_frame' )\r
+                               : this._.holder;\r
+\r
+               // Disable context menu for block panel.\r
+               holder.getParent().getParent().disableContextMenu();\r
 \r
                if ( current )\r
+               {\r
+                       // Clean up the current block's effects on holder.\r
+                       holder.removeAttributes( current.attributes );\r
                        current.hide();\r
+               }\r
 \r
                this._.currentBlock = block;\r
 \r
+               holder.setAttributes( block.attributes );\r
+               CKEDITOR.fire( 'ariaWidget', holder );\r
+\r
                // Reset the focus index, so it will always go into the first one.\r
                block._.focusIndex = -1;\r
 \r
                this._.onKeyDown = block.onKeyDown && CKEDITOR.tools.bind( block.onKeyDown, block );\r
 \r
+               block.onMark = function( item )\r
+               {\r
+                       holder.setAttribute( 'aria-activedescendant', item.getId() + '_option' );\r
+               };\r
+\r
+               block.onUnmark = function()\r
+               {\r
+                       holder.removeAttribute( 'aria-activedescendant' );\r
+               };\r
+\r
                block.show();\r
 \r
                return block;\r
+       },\r
+\r
+       destroy : function()\r
+       {\r
+               this.element && this.element.remove();\r
        }\r
 };\r
 \r
 CKEDITOR.ui.panel.block = CKEDITOR.tools.createClass(\r
 {\r
-       $ : function( blockHolder )\r
+       $ : function( blockHolder, blockDefinition )\r
        {\r
                this.element = blockHolder.append(\r
                        blockHolder.getDocument().createElement( 'div',\r
                                {\r
                                        attributes :\r
                                        {\r
-                                               'class' : 'cke_panel_block'\r
+                                               'tabIndex' : -1,\r
+                                               'class' : 'cke_panel_block',\r
+                                               'role' : 'presentation'\r
                                        },\r
                                        styles :\r
                                        {\r
@@ -250,6 +285,13 @@ CKEDITOR.ui.panel.block = CKEDITOR.tools.createClass(
                                        }\r
                                }) );\r
 \r
+               // Copy all definition properties to this object.\r
+               if ( blockDefinition )\r
+                       CKEDITOR.tools.extend( this, blockDefinition );\r
+\r
+               if ( !this.attributes.title )\r
+                       this.attributes.title = this.attributes[ 'aria-label' ];\r
+\r
                this.keys = {};\r
 \r
                this._.focusIndex = -1;\r
@@ -258,7 +300,27 @@ CKEDITOR.ui.panel.block = CKEDITOR.tools.createClass(
                this.element.disableContextMenu();\r
        },\r
 \r
-       _ : {},\r
+       _ : {\r
+\r
+               /**\r
+                * Mark the item specified by the index as current activated.\r
+                */\r
+               markItem: function( index )\r
+               {\r
+                       if ( index == -1 )\r
+                               return;\r
+                       var links = this.element.getElementsByTag( 'a' );\r
+                       var item = links.getItem( this._.focusIndex = index );\r
+\r
+                       // Safari need focus on the iframe window first(#3389), but we need\r
+                       // lock the blur to avoid hiding the panel.\r
+                       if ( CKEDITOR.env.webkit || CKEDITOR.env.opera )\r
+                               item.getDocument().getWindow().focus();\r
+                       item.focus();\r
+\r
+                       this.onMark && this.onMark( item );\r
+               }\r
+       },\r
 \r
        proto :\r
        {\r
@@ -318,11 +380,12 @@ CKEDITOR.ui.panel.block = CKEDITOR.tools.createClass(
                                        return false;\r
 \r
                                case 'click' :\r
+                               case 'mouseup' :\r
                                        index = this._.focusIndex;\r
                                        link = index >= 0 && this.element.getElementsByTag( 'a' ).getItem( index );\r
 \r
                                        if ( link )\r
-                                               link.$.click ? link.$.click() : link.$.onclick();\r
+                                               link.$[ keyAction ] ? link.$[ keyAction ]() : link.$[ 'on' + keyAction ]();\r
 \r
                                        return false;\r
                        }\r
@@ -331,3 +394,10 @@ CKEDITOR.ui.panel.block = CKEDITOR.tools.createClass(
                }\r
        }\r
 });\r
+\r
+/**\r
+ * Fired when a panel is added to the document\r
+ * @name CKEDITOR#ariaWidget\r
+ * @event\r
+ * @param {Object} holder The element wrapping the panel\r
+ */\r