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 – 2012 CKSource – Frederico Knabben. All rights reserved. | Terms of use | Privacy policy