Changeset 3222


Ignore:
Timestamp:
03/17/09 10:15:34 (6 years ago)
Author:
fredck
Message:

#3104 : Tab system review, including better support on the editor focus handling.

Location:
CKEditor/trunk/_source
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • CKEditor/trunk/_source/core/config.js

    r3210 r3222  
    155155
    156156        /**
     157         * The editor tabindex value.
     158         * @type Number
     159         * @default 0 (zero)
     160         * @example
     161         * config.tabIndex = 1;
     162         */
     163        tabIndex : 0,
     164
     165        /**
    157166         * The theme to be used to build the UI.
    158167         * @type String
  • CKEditor/trunk/_source/core/dom/element.js

    r3194 r3222  
    733733
    734734                /**
     735                 * Checks if this element is visible. May not work if the element is
     736                 * child of an element with visibility set to "hidden", but works well
     737                 * on the great majority of cases.
     738                 * @return {Boolean} True if the element is visible.
     739                 */
     740                isVisible : function()
     741                {
     742                        return this.$.offsetWidth && ( this.$.style.visibility != 'hidden' );
     743                },
     744
     745                /**
    735746                 * Indicates that the element has defined attributes.
    736747                 * @returns {Boolean} True if the element has attributes.
     
    884895                                        if ( name == 'class' )
    885896                                                this.$.className = value;
    886                                         if ( name == 'style' )
     897                                        else if ( name == 'style' )
    887898                                                this.$.style.cssText = value;
     899                                        else if ( name == 'tabindex' )  // Case sensitive.
     900                                                this.$.tabIndex = value;
    888901                                        else
    889902                                                standard.apply( this, arguments );
  • CKEditor/trunk/_source/core/dom/node.js

    r3194 r3222  
    309309                getPreviousSourceNode : function( startFromSibling, nodeType )
    310310                {
    311                         var $ = startFromSibling ? this.$.previousSibling : this.$,
    312                                 node = null;
    313 
    314                         if ( !$ )
    315                                 return null;
    316 
    317                         if ( ( node = $.previousSibling ) )
    318                         {
    319                                 while ( node.lastChild )
    320                                         node = node.lastChild;
    321                         }
    322                         else
    323                                 node = $.parentNode;
     311                        var $ = this.$;
     312
     313                        var node = ( !startFromSibling && $.lastChild ) ?
     314                                $.lastChild :
     315                                $.previousSibling;
     316
     317                        var parent;
     318
     319                        while ( !node && ( parent = ( parent || $ ).parentNode ) )
     320                                node = parent.previousSibling;
    324321
    325322                        if ( !node )
     
    327324
    328325                        if ( nodeType && node.nodeType != nodeType )
    329                                 return arguments.callee.apply( { $ : node }, false, nodeType );
     326                                return arguments.callee.call( { $ : node }, false, nodeType );
    330327
    331328                        return new CKEDITOR.dom.node( node );
  • CKEditor/trunk/_source/plugins/editingblock/plugin.js

    r3174 r3222  
    9999                                        event.removeListener();
    100100
     101                                        // Grab editor focus if the editor container is focused. (#3104)
     102                                        editor.container.on( 'focus', function()
     103                                                {
     104                                                        editor.focus();
     105                                                });
     106
    101107                                        // Fire instanceReady for both the editor and CKEDITOR.
    102108                                        editor.fireOnce( 'instanceReady' );
  • CKEditor/trunk/_source/plugins/sourcearea/plugin.js

    r3187 r3222  
    2727                                                        // Create the source area <textarea>.
    2828                                                        textarea = new CKEDITOR.dom.element( 'textarea' );
    29                                                         textarea.setAttribute( 'dir', 'ltr' );
     29                                                        textarea.setAttributes(
     30                                                                {
     31                                                                        dir : 'ltr',
     32                                                                        tabIndex : -1
     33                                                                });
    3034                                                        textarea.addClass( 'cke_source' );
    3135                                                        textarea.setStyles({
     
    3539                                                                outline : 'none',
    3640                                                                'text-align' : 'left' });
    37 
    38                                                         // Add the tab index for #3098.
    39                                                         var tabIndex = editor.element && editor.element.getAttribute( 'tabIndex' );
    40                                                         if ( tabIndex )
    41                                                                 textarea.setAttribute( 'tabIndex', tabIndex );
    4241
    4342                                                        // The textarea height/width='100%' doesn't
     
    7473                                                        // Set the <textarea> value.
    7574                                                        this.loadData( data );
     75
     76                                                        var keystrokeHandler = editor.keystrokeHandler;
     77                                                        if ( keystrokeHandler )
     78                                                                keystrokeHandler.attach( textarea );
    7679
    7780                                                        editor.mode = 'source';
  • CKEditor/trunk/_source/plugins/tab/plugin.js

    r3174 r3222  
    66(function()
    77{
    8         var blurInternal = function( editor, previous )
    9         {
    10                 var hasContainer = editor.container;
    11 
    12                 if ( hasContainer )
    13                 {
    14                         // We need an empty element after the container, so the focus don't go to a container child.
    15                         var tempSpan = new CKEDITOR.dom.element( 'span' );
    16                         tempSpan.setAttribute( 'tabindex', editor.container.getTabIndex() );
    17                         tempSpan.hide();
    18 
    19                         // Insert the temp element and set the focus.
    20                         if ( previous )
    21                         {
    22                                 tempSpan.insertBefore( editor.container );
    23                                 tempSpan.focusPrevious();
    24                         }
    25                         else
    26                         {
    27                                 tempSpan.insertAfter( editor.container );
    28                                 tempSpan.focusNext();
    29                         }
    30 
    31                         // Remove the temporary node.
    32                         tempSpan.remove();
    33                 }
    34 
    35                 return hasContainer;
    36         };
    37 
    388        var blurCommand =
    399                {
    4010                        exec : function( editor )
    4111                        {
    42                                 return blurInternal( editor );
     12                                editor.container.focusNext( true );
    4313                        }
    4414                };
     
    4818                        exec : function( editor )
    4919                        {
    50                                 return blurInternal( editor, true );
     20                                editor.container.focusPrevious( true );
    5121                        }
    5222                };
     
    12393 * element.focusNext();
    12494 */
    125 CKEDITOR.dom.element.prototype.focusNext = function()
     95CKEDITOR.dom.element.prototype.focusNext = function( ignoreChildren )
    12696{
    12797        var $ = this.$,
    12898                curTabIndex = this.getTabIndex(),
    129                 passedCurrent = false,
    130                 elected,
    131                 electedTabIndex;
    132 
    133         var all = document.body.all || document.body.getElementsByTagName( '*' );
     99                passedCurrent, enteredCurrent,
     100                elected, electedTabIndex,
     101                element, elementTabIndex;
    134102
    135103        if ( curTabIndex <= 0 )
    136104        {
    137                 for ( var i = 0, element ; element = all[ i ] ; i++ )
    138                 {
    139                         if ( !passedCurrent )
    140                         {
    141                                 if ( element == $ )
    142                                         passedCurrent = true;
    143                                 continue;
    144                         }
    145 
    146                         element = new CKEDITOR.dom.element( element );
    147 
    148                         if ( element.getComputedStyle( 'display' ) == 'none' || element.getComputedStyle( 'visibility' ) == 'hidden' )
    149                                 continue;
    150 
    151                         if ( element.getTabIndex() === 0 )
    152                         {
    153                                 elected = element;
    154                                 break;
    155                         }
     105                // If this element has tabindex <= 0 then we must simply look for any
     106                // element following it containing tabindex=0.
     107
     108                var element = this.getNextSourceNode( ignoreChildren, CKEDITOR.NODE_ELEMENT );
     109
     110                while( element )
     111                {
     112                        if ( element.isVisible() && element.getTabIndex() === 0 )
     113                        {
     114                                elected = element;
     115                                break;
     116                        }
     117
     118                        element = element.getNextSourceNode( false, CKEDITOR.NODE_ELEMENT );
    156119                }
    157120        }
    158121        else
    159122        {
    160                 for ( i = 0, element ; element = all[ i ] ; i++ )
    161                 {
    162                         if ( !passedCurrent && element == $ )
    163                         {
    164                                 passedCurrent = true;
     123                // If this element has tabindex > 0 then we must look for:
     124                //              1. An element following this element with the same tabindex.
     125                //              2. The first element in source other with the lowest tabindex
     126                //                 that is higher than this element tabindex.
     127                //              3. The first element with tabindex=0.
     128
     129                var element = this.getDocument().getBody().getFirst();
     130
     131                while( ( element = element.getNextSourceNode( false, CKEDITOR.NODE_ELEMENT ) ) )
     132                {
     133                        if ( !passedCurrent )
     134                        {
     135                                if ( !enteredCurrent && element.equals( this ) )
     136                                {
     137                                        enteredCurrent = true;
     138
     139                                        // Ignore this element, if required.
     140                                        if ( ignoreChildren )
     141                                        {
     142                                                if ( !( element = element.getNextSourceNode( true, CKEDITOR.NODE_ELEMENT ) ) )
     143                                                        break;
     144                                                passedCurrent = 1;
     145                                        }
     146                                }
     147                                else if ( enteredCurrent && !this.contains( element ) )
     148                                        passedCurrent = 1;
     149                        }
     150
     151                        if ( !element.isVisible() || ( elementTabIndex = element.getTabIndex() ) < 0 )
    165152                                continue;
    166                         }
    167 
    168                         element = new CKEDITOR.dom.element( element );
    169 
    170                         if ( element.getComputedStyle( 'display' ) == 'none' || element.getComputedStyle( 'visibility' ) == 'hidden' )
    171                                 continue;
    172 
    173                         var elementTabIndex = element.getTabIndex();
    174153
    175154                        if ( passedCurrent && elementTabIndex == curTabIndex )
     
    178157                                break;
    179158                        }
    180                         else if ( elementTabIndex > curTabIndex && ( !elected || electedTabIndex > elementTabIndex || electedTabIndex === 0 ) )
     159
     160                        if ( elementTabIndex > curTabIndex && ( !elected || !electedTabIndex || elementTabIndex < electedTabIndex ) )
    181161                        {
    182162                                elected = element;
     
    201181 * element.focusPrevious();
    202182 */
    203 CKEDITOR.dom.element.prototype.focusPrevious = function()
     183CKEDITOR.dom.element.prototype.focusPrevious = function( ignoreChildren )
    204184{
    205185        var $ = this.$,
    206186                curTabIndex = this.getTabIndex(),
    207                 passedCurrent = false,
     187                passedCurrent, enteredCurrent,
    208188                elected,
    209                 electedTabIndex;
    210 
    211         var all = document.body.all || document.body.getElementsByTagName( '*' );
    212 
    213         if ( curTabIndex <= 0 )
    214         {
    215                 for ( var i = 0, element ; element = all[ i ] ; i++ )
    216                 {
    217                         if ( !passedCurrent && element == $ )
    218                         {
    219                                 if ( elected && electedTabIndex === 0 )
    220                                         break;
    221 
    222                                 passedCurrent = true;
    223                                 continue;
    224                         }
    225 
    226                         element = new CKEDITOR.dom.element( element );
    227 
    228                         if ( element.getComputedStyle( 'display' ) == 'none' || element.getComputedStyle( 'visibility' ) == 'hidden' )
    229                                 continue;
    230 
    231                         var elementTabIndex = element.getTabIndex();
    232 
    233                         if ( ( !passedCurrent && elementTabIndex === 0 )
    234                                 || ( elementTabIndex > 0 && ( !elected || ( electedTabIndex > 0 && electedTabIndex <= elementTabIndex ) ) ) )
    235                         {
    236                                 elected = element;
    237                                 electedTabIndex = elementTabIndex;
    238                         }
    239                 }
    240         }
    241         else
    242         {
    243                 for ( i = 0, element ; element = all[ i ] ; i++ )
    244                 {
    245                         if ( !passedCurrent && element == $ )
    246                         {
    247                                 if ( elected && electedTabIndex == curTabIndex )
    248                                         break;
    249 
    250                                 passedCurrent = true;
    251                                 continue;
    252                         }
    253 
    254                         element = new CKEDITOR.dom.element( element );
    255 
    256                         elementTabIndex = element.getTabIndex();
    257 
    258                         if ( elementTabIndex > 0 )
    259                         {
    260                                 if ( ( !passedCurrent && elementTabIndex == curTabIndex )
    261                                         || ( elementTabIndex < curTabIndex && ( !elected || electedTabIndex <= elementTabIndex ) ) )
    262                                 {
    263                                         elected = element;
    264                                         electedTabIndex = elementTabIndex;
     189                electedTabIndex = 0,
     190                elementTabIndex;
     191
     192        var element = this.getDocument().getBody().getLast();
     193
     194        while( ( element = element.getPreviousSourceNode( false, CKEDITOR.NODE_ELEMENT ) ) )
     195        {
     196                if ( !passedCurrent )
     197                {
     198                        if ( !enteredCurrent && element.equals( this ) )
     199                        {
     200                                enteredCurrent = true;
     201
     202                                // Ignore this element, if required.
     203                                if ( ignoreChildren )
     204                                {
     205                                        if ( !( element = element.getPreviousSourceNode( true, CKEDITOR.NODE_ELEMENT ) ) )
     206                                                break;
     207                                        passedCurrent = 1;
    265208                                }
     209                        }
     210                        else if ( enteredCurrent && !this.contains( element ) )
     211                                passedCurrent = 1;
     212                }
     213
     214                if ( !element.isVisible() || ( elementTabIndex = element.getTabIndex() ) < 0 )
     215                        continue;
     216
     217                if ( curTabIndex <= 0 )
     218                {
     219                        // If this element has tabindex <= 0 then we must look for:
     220                        //              1. An element before this one containing tabindex=0.
     221                        //              2. The last element with the highest tabindex.
     222
     223                        if ( passedCurrent && elementTabIndex === 0 )
     224                        {
     225                                elected = element;
     226                                break;
     227                        }
     228
     229                        if ( elementTabIndex > electedTabIndex )
     230                        {
     231                                elected = element;
     232                                electedTabIndex = elementTabIndex;
     233                        }
     234                }
     235                else
     236                {
     237                        // If this element has tabindex > 0 we must look for:
     238                        //              1. An element preceeding this one, with the same tabindex.
     239                        //              2. The last element in source other with the highest tabindex
     240                        //                 that is lower than this element tabindex.
     241
     242                        if ( passedCurrent && elementTabIndex == curTabIndex )
     243                        {
     244                                elected = element;
     245                                break;
     246                        }
     247
     248                        if ( elementTabIndex < curTabIndex && ( !elected || elementTabIndex > electedTabIndex ) )
     249                        {
     250                                elected = element;
     251                                electedTabIndex = elementTabIndex;
    266252                        }
    267253                }
  • CKEditor/trunk/_source/plugins/wysiwygarea/plugin.js

    r3195 r3222  
    117117                                                        .setAttributes({
    118118                                                                frameBorder : 0,
     119                                                                tabIndex : -1,
    119120                                                                allowTransparency : true })
    120121                                                        .setStyles({
    121122                                                                width : '100%',
    122123                                                                height : '100%' });
    123 
    124                                                 var tabIndex = editor.element && editor.element.getAttribute( 'tabIndex' );
    125                                                 if ( tabIndex )
    126                                                         iframe.setAttribute( 'tabIndex', tabIndex );
    127124
    128125                                                if ( CKEDITOR.env.ie )
  • CKEditor/trunk/_source/themes/default/theme.js

    r3208 r3222  
    4747                        var width       = editor.config.width;
    4848
     49                        var tabIndex = editor.config.tabIndex || editor.element.getAttribute( 'tabindex' ) || 0;
     50
    4951                        // The editor height is considered only if the contents space got filled.
    5052                        if ( !contentsHtml )
     
    6668                        // differently by the browsers ("semi-inline").
    6769                        var container = CKEDITOR.dom.element.createFromHtml( [
    68                                 '<span id="cke_', name, '" onmousedown="return false;" class="', editor.skinClass,
    69                                         '" dir="', editor.lang.dir, '" title="', ( CKEDITOR.env.gecko ? ' ' : '' ), '">' +
     70                                '<span' +
     71                                        ' id="cke_', name, '"' +
     72                                        ' onmousedown="return false;"' +
     73                                        ' class="', editor.skinClass, '"' +
     74                                        ' dir="', editor.lang.dir, '"' +
     75                                        ' title="', ( CKEDITOR.env.gecko ? ' ' : '' ), '"' +
     76                                        ' tabindex="' + tabIndex + '">' +
    7077                                '<span class="' , browserCssClass, ' cke_', editor.lang.dir, '">' +
    7178                                        '<table class="cke_editor" border="0" cellspacing="0" cellpadding="0" style="width:', width, ';height:', height, '"><tbody>' +
Note: See TracChangeset for help on using the changeset viewer.
© 2003 – 2015 CKSource – Frederico Knabben. All rights reserved. | Terms of use | Privacy policy