Changeset 5812


Ignore:
Timestamp:
08/03/10 21:26:04 (5 years ago)
Author:
fredck
Message:

Reintegrated the 3.4.x branch.

Location:
CKEditor/trunk
Files:
113 edited
10 copied

Legend:

Unmodified
Added
Removed
  • CKEditor/trunk

  • CKEditor/trunk/CHANGES.html

    r5802 r5812  
    3535                CKEditor Changelog
    3636        </h1>
     37        <h3>
     38                        CKEditor 3.4 Beta</h3>
     39        <p>
     40                        New features:</p>
     41        <ul>
     42                <li><a href="http://dev.fckeditor.net/ticket/5909">#5909</a> : New BiDi feature, making it possible to switch the base language direction of block elements.</li>
     43                <li><a href="http://dev.fckeditor.net/ticket/5268">#5268</a> : Introducing the "tableresize" plugin, which makes it possible to resize tables columns by mouse drag. It's not enabled by default, so it must be enabled in the configurations file.</li>
     44                <li><a href="http://dev.fckeditor.net/ticket/979">#979</a> : New <a href="http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.config.html#.enableTabKeyTools">enableTabKeyTools</a> configuration to allow using the TAB key to navigate through table cells.</li>
     45                <li><a href="http://dev.fckeditor.net/ticket/4606">#4606</a> : Introduce the "autogrow" plugin, which makes the editor resize automatically, based on the contents size.</li>
     46                <li><a href="http://dev.fckeditor.net/ticket/5737">#5737</a> : Added support for the <a href="http://www.w3.org/TR/html5/editing.html#contenteditable">HTML5 contenteditable attribute</a>, making it possible to define read only regions into the editor contents.</li>
     47                <li><a href="http://dev.fckeditor.net/ticket/5418">#5418</a> : New "Advanced" tab introduced on the Table Properties dialog. It's based on the new dialogadvtab plugin.</li>
     48                <li><a href="http://dev.fckeditor.net/ticket/6082">#6082</a> : Introduced the <a href="http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.config.html#.useComputedState">useComputedState</a> setting, making it possible to control whether toolbar features, like alignment and direction, should reflect the "computed" selection states, even when the effective feature value is not applied.</li>
     49        </ul>
     50        <p>
     51                        Fixed issues:</p>
     52        <ul>
     53                <li><a href="http://dev.fckeditor.net/ticket/5911">#5911</a> : BiDi: List items should support and retain correct base language direction
     54                <li><a href="http://dev.fckeditor.net/ticket/5689">#5689</a> : Make it possible to run CKEditor inside of Firefox chrome.</li>
     55                <li><a href="http://dev.fckeditor.net/ticket/6042">#6042</a> : It wasn't possible to align a paragraph with the dir attribute to the opposite direction.</li>
     56                <li><a href="http://dev.fckeditor.net/ticket/6058">#6058</a> : Fixed a small style glitch with file upload fields in IE+Quirks.</li>
     57        </ul>
    3758        <h3>
    3859                        CKEditor 3.3.2</h3>
  • CKEditor/trunk/_dev/releaser/ckreleaser.release

    • Property svn:mergeinfo deleted
  • CKEditor/trunk/_dev/releaser/release.bat

    • Property svn:mergeinfo deleted
    r5587 r5812  
    1111:: rmdir /S /Q release
    1212
    13 java -jar ckreleaser/ckreleaser.jar ckreleaser.release ../.. release "3.3.2 SVN" ckeditor_3.3.2_svn --run-before-release=langtool.bat
     13java -jar ckreleaser/ckreleaser.jar ckreleaser.release ../.. release "3.4 Beta" ckeditor_3.4b --run-before-release=langtool.bat
  • CKEditor/trunk/_dev/releaser/release.sh

    r5587 r5812  
    1313
    1414pushd $DIR
    15 java -jar ckreleaser/ckreleaser.jar ckreleaser.release ../.. release "3.3.2 SVN" ckeditor_3.3.2_svn --run-before-release=$LANGTOOL
     15java -jar ckreleaser/ckreleaser.jar ckreleaser.release ../.. release "3.4 Beta" ckeditor_3.4b --run-before-release=$LANGTOOL
    1616popd
  • CKEditor/trunk/_samples/index.html

    r5491 r5812  
    4242                <li><a href="output_xhtml.html">Output XHTML</a></li>
    4343                <li><a href="output_html.html">Output HTML</a></li>
     44                <li><a href="autogrow.html">AutoGrow plugin</a></li>
    4445        </ul>
    4546        <div id="footer">
  • CKEditor/trunk/_source/core/config.js

    r5548 r5812  
    244244         * @example
    245245         */
    246         plugins : 'about,a11yhelp,basicstyles,blockquote,button,clipboard,colorbutton,colordialog,contextmenu,div,elementspath,enterkey,entities,filebrowser,find,flash,font,format,forms,horizontalrule,htmldataprocessor,image,indent,justify,keystrokes,link,list,liststyle,maximize,newpage,pagebreak,pastefromword,pastetext,popup,preview,print,removeformat,resize,save,scayt,smiley,showblocks,showborders,sourcearea,stylescombo,table,tabletools,specialchar,tab,templates,toolbar,undo,wysiwygarea,wsc',
     246        plugins : 'about,a11yhelp,basicstyles,bidi,blockquote,button,clipboard,colorbutton,colordialog,contextmenu,dialogadvtab,div,elementspath,enterkey,entities,filebrowser,find,flash,font,format,forms,horizontalrule,htmldataprocessor,image,indent,justify,keystrokes,link,list,liststyle,maximize,newpage,pagebreak,pastefromword,pastetext,popup,preview,print,removeformat,resize,save,scayt,smiley,showblocks,showborders,sourcearea,stylescombo,table,tabletools,specialchar,tab,templates,toolbar,undo,wysiwygarea,wsc',
    247247
    248248        /**
     
    331331};
    332332
     333/**
     334 * Indicates that some of the editor features, like alignement and text
     335 * direction, should used the "computed value" of the feature to indicate it's
     336 * on/off state, instead of using the "real value".
     337 *
     338 * If enabled, in a left to right written document, the "Left Justify"
     339 * alignment button will show as active, even if the aligment style is not
     340 * explicitly applied to the current paragraph in the editor.
     341 * @name CKEDITOR.config.useComputedState
     342 * @type Boolean
     343 * @default true
     344 * @since 3.4
     345 * @example
     346 * config.useComputedState = false;
     347 */
     348
    333349// PACKAGER_RENAME( CKEDITOR.config )
  • CKEditor/trunk/_source/core/dom/node.js

    r5189 r5812  
    658658                                }
    659659                        }
     660                },
     661
     662                isReadOnly : function()
     663                {
     664                        var current = this;
     665                        while( current )
     666                        {
     667                                if ( current.type == CKEDITOR.NODE_ELEMENT )
     668                                {
     669                                        if ( current.is( 'body' ) || current.getCustomData( '_cke_notReadOnly' ) )
     670                                                break;
     671
     672                                        if ( current.getAttribute( 'contentEditable' ) == 'false' )
     673                                                return current;
     674                                        else if ( current.getAttribute( 'contentEditable' ) == 'true' )
     675                                                break;
     676                                }
     677                                current = current.getParent();
     678                        }
     679
     680                        return false;
    660681                }
    661682        }
  • CKEditor/trunk/_source/core/dom/range.js

    r5714 r5812  
    398398                        var baseId;
    399399                        var clone;
     400                        var collapsed = this.collapsed;
    400401
    401402                        startNode = this.document.createElement( 'span' );
     
    414415
    415416                        // If collapsed, the endNode will not be created.
    416                         if ( !this.collapsed )
     417                        if ( !collapsed )
    417418                        {
    418419                                endNode = startNode.clone();
     
    443444                                startNode : serializable ? baseId + 'S' : startNode,
    444445                                endNode : serializable ? baseId + 'E' : endNode,
    445                                 serializable : serializable
     446                                serializable : serializable,
     447                                collapsed : collapsed
    446448                        };
    447449                },
     
    466468                                endOffset       = this.endOffset;
    467469
     470                        var collapsed = this.collapsed;
     471
    468472                        var child, previous;
    469473
     
    502506
    503507                                // Process the end only if not normalized.
    504                                 if ( !this.isCollapsed )
     508                                if ( !collapsed )
    505509                                {
    506510                                        // Find out if the start is pointing to a text node that
     
    533537                        return {
    534538                                start           : startContainer.getAddress( normalized ),
    535                                 end                     : this.isCollapsed ? null : endContainer.getAddress( normalized ),
     539                                end                     : collapsed ? null : endContainer.getAddress( normalized ),
    536540                                startOffset     : startOffset,
    537541                                endOffset       : endOffset,
    538542                                normalized      : normalized,
     543                                collapsed       : collapsed,
    539544                                is2                     : true          // It's a createBookmark2 bookmark.
    540545                        };
     
    16331638
    16341639                /**
    1635                  * Check whether current range is on the inner edge of the specified element.
    1636                  * @param {Number} checkType ( CKEDITOR.START | CKEDITOR.END ) The checking side.
     1640                 * Check whether a range boundary is at the inner boundary of a given
     1641                 * element.
    16371642                 * @param {CKEDITOR.dom.element} element The target element to check.
     1643                 * @param {Number} checkType The boundary to check for both the range
     1644                 *              and the element. It can be CKEDITOR.START or CKEDITOR.END.
     1645                 * @returns {Boolean} "true" if the range boundary is at the inner
     1646                 *              boundary of the element.
    16381647                 */
    16391648                checkBoundaryOfElement : function( element, checkType )
    16401649                {
     1650                        var checkStart = ( checkType == CKEDITOR.START );
     1651
     1652                        // Create a copy of this range, so we can manipulate it for our checks.
    16411653                        var walkerRange = this.clone();
     1654
     1655                        // Collapse the range at the proper size.
     1656                        walkerRange.collapse( checkStart );
     1657
    16421658                        // Expand the range to element boundary.
    1643                         walkerRange[ checkType == CKEDITOR.START ?
    1644                          'setStartAt' : 'setEndAt' ]
    1645                          ( element, checkType == CKEDITOR.START ?
    1646                            CKEDITOR.POSITION_AFTER_START
    1647                            : CKEDITOR.POSITION_BEFORE_END );
    1648 
     1659                        walkerRange[ checkStart ? 'setStartAt' : 'setEndAt' ]
     1660                         ( element, checkStart ? CKEDITOR.POSITION_AFTER_START : CKEDITOR.POSITION_BEFORE_END );
     1661
     1662                        // Create the walker, which will check if we have anything useful
     1663                        // in the range.
    16491664                        var walker = new CKEDITOR.dom.walker( walkerRange );
    16501665                        walker.evaluator = elementBoundaryEval;
    1651                         return walker[ checkType == CKEDITOR.START ?
    1652                                 'checkBackward' : 'checkForward' ]();
     1666
     1667                        return walker[ checkStart ? 'checkBackward' : 'checkForward' ]();
    16531668                },
    16541669
  • CKEditor/trunk/_source/core/env.js

    r5407 r5812  
    7676                        isCustomDomain : function()
    7777                        {
     78                                if ( !this.ie )
     79                                        return false;
     80
    7881                                var domain = document.domain,
    7982                                        hostname = window.location.hostname;
    8083
    81                                 return this.ie &&
    82                                         domain != hostname &&
     84                                return domain != hostname &&
    8385                                        domain != ( '[' + hostname + ']' );     // IPv6 IP support (#5434)
    8486                        }
  • CKEditor/trunk/_source/core/loader.js

    r5106 r5812  
    2424                var scripts =
    2525                {
    26                         'core/_bootstrap'               : [ 'core/config', 'core/ckeditor', 'core/plugins', 'core/scriptloader', 'core/tools', /* The following are entries that we want to force loading at the end to avoid dependence recursion */ 'core/dom/comment', 'core/dom/elementpath', 'core/dom/text', 'core/dom/range' ],
     26                        'core/_bootstrap'               : [ 'core/config', 'core/ckeditor', 'core/plugins', 'core/scriptloader', 'core/tools', /* The following are entries that we want to force loading at the end to avoid dependence recursion */ 'core/dom/comment', 'core/dom/elementpath', 'core/dom/text', 'core/dom/rangelist' ],
    2727                        'core/ajax'                             : [ 'core/xml' ],
    2828                        'core/ckeditor'                 : [ 'core/ckeditor_basic', 'core/dom', 'core/dtd', 'core/dom/document', 'core/dom/element', 'core/editor', 'core/event', 'core/htmlparser', 'core/htmlparser/element', 'core/htmlparser/fragment', 'core/htmlparser/filter', 'core/htmlparser/basicwriter', 'core/tools' ],
     
    4242                        'core/dom/domobject'    : [ 'core/dom/event' ],
    4343                        'core/dom/range'                : [ 'core/dom/document', 'core/dom/documentfragment', 'core/dom/element', 'core/dom/walker' ],
     44                        'core/dom/rangelist'    : [ 'core/dom/range' ],
    4445                        'core/dom/text'                 : [ 'core/dom/node', 'core/dom/domobject' ],
    4546                        'core/dom/walker'               : [ 'core/dom/node' ],
  • CKEditor/trunk/_source/core/tools.js

    r5643 r5812  
    378378
    379379                /**
     380                 * Gets a unique ID for CKEditor's interface elements. It returns a
     381                 * string with the "cke_" prefix and a progressive number.
     382                 * @function
     383                 * @returns {String} A unique ID.
     384                 * @example
     385                 * alert( CKEDITOR.tools.<b>getNextId()</b> );  // "cke_1" (e.g.)
     386                 * alert( CKEDITOR.tools.<b>getNextId()</b> );  // "cke_2"
     387                 */
     388                getNextId : function()
     389                {
     390                        return 'cke_' + this.getNextNumber();
     391                },
     392
     393                /**
    380394                 * Creates a function override.
    381395                 * @param {Function} originalFunction The function to be overridden.
  • CKEditor/trunk/_source/lang/_translationstatus.txt

    r5768 r5812  
    22For licensing, see LICENSE.html or http://ckeditor.com/license
    33
    4 af.js      Found: 287 Missing: 238
    5 ar.js      Found: 451 Missing: 74
    6 bg.js      Found: 280 Missing: 245
    7 bn.js      Found: 281 Missing: 244
    8 bs.js      Found: 187 Missing: 338
    9 ca.js      Found: 490 Missing: 35
    10 cs.js      Found: 411 Missing: 114
    11 cy.js      Found: 452 Missing: 73
    12 da.js      Found: 404 Missing: 121
    13 de.js      Found: 522 Missing: 3
    14 el.js      Found: 286 Missing: 239
    15 en-au.js   Found: 369 Missing: 156
    16 en-ca.js   Found: 369 Missing: 156
    17 en-gb.js   Found: 370 Missing: 155
    18 eo.js      Found: 259 Missing: 266
    19 es.js      Found: 524 Missing: 1
    20 et.js      Found: 301 Missing: 224
    21 eu.js      Found: 403 Missing: 122
    22 fa.js      Found: 302 Missing: 223
    23 fi.js      Found: 518 Missing: 7
    24 fo.js      Found: 420 Missing: 105
    25 fr-ca.js   Found: 301 Missing: 224
    26 fr.js      Found: 403 Missing: 122
    27 gl.js      Found: 283 Missing: 242
    28 gu.js      Found: 300 Missing: 225
    29 he.js      Found: 525 Missing: 0
    30 hi.js      Found: 302 Missing: 223
    31 hr.js      Found: 404 Missing: 121
    32 hu.js      Found: 445 Missing: 80
    33 is.js      Found: 307 Missing: 218
    34 it.js      Found: 404 Missing: 121
    35 ja.js      Found: 413 Missing: 112
    36 km.js      Found: 275 Missing: 250
    37 ko.js      Found: 293 Missing: 232
    38 lt.js      Found: 306 Missing: 219
    39 lv.js      Found: 283 Missing: 242
    40 mn.js      Found: 300 Missing: 225
    41 ms.js      Found: 265 Missing: 260
    42 nb.js      Found: 470 Missing: 55
    43 nl.js      Found: 494 Missing: 31
    44 no.js      Found: 470 Missing: 55
    45 pl.js      Found: 411 Missing: 114
    46 pt-br.js   Found: 524 Missing: 1
    47 pt.js      Found: 282 Missing: 243
    48 ro.js      Found: 301 Missing: 224
    49 ru.js      Found: 467 Missing: 58
    50 sk.js      Found: 302 Missing: 223
    51 sl.js      Found: 410 Missing: 115
    52 sr-latn.js Found: 276 Missing: 249
    53 sr.js      Found: 275 Missing: 250
    54 sv.js      Found: 299 Missing: 226
    55 th.js      Found: 287 Missing: 238
    56 tr.js      Found: 524 Missing: 1
    57 uk.js      Found: 404 Missing: 121
    58 vi.js      Found: 481 Missing: 44
    59 zh-cn.js   Found: 523 Missing: 2
    60 zh.js      Found: 404 Missing: 121
     4af.js      Found: 287 Missing: 245
     5ar.js      Found: 451 Missing: 81
     6bg.js      Found: 280 Missing: 252
     7bn.js      Found: 281 Missing: 251
     8bs.js      Found: 187 Missing: 345
     9ca.js      Found: 490 Missing: 42
     10cs.js      Found: 411 Missing: 121
     11cy.js      Found: 452 Missing: 80
     12da.js      Found: 404 Missing: 128
     13de.js      Found: 522 Missing: 10
     14el.js      Found: 286 Missing: 246
     15en-au.js   Found: 369 Missing: 163
     16en-ca.js   Found: 369 Missing: 163
     17en-gb.js   Found: 370 Missing: 162
     18eo.js      Found: 259 Missing: 273
     19es.js      Found: 524 Missing: 8
     20et.js      Found: 301 Missing: 231
     21eu.js      Found: 403 Missing: 129
     22fa.js      Found: 302 Missing: 230
     23fi.js      Found: 518 Missing: 14
     24fo.js      Found: 420 Missing: 112
     25fr-ca.js   Found: 301 Missing: 231
     26fr.js      Found: 403 Missing: 129
     27gl.js      Found: 283 Missing: 249
     28gu.js      Found: 300 Missing: 232
     29he.js      Found: 532 Missing: 0
     30hi.js      Found: 302 Missing: 230
     31hr.js      Found: 404 Missing: 128
     32hu.js      Found: 445 Missing: 87
     33is.js      Found: 307 Missing: 225
     34it.js      Found: 404 Missing: 128
     35ja.js      Found: 413 Missing: 119
     36km.js      Found: 275 Missing: 257
     37ko.js      Found: 293 Missing: 239
     38lt.js      Found: 306 Missing: 226
     39lv.js      Found: 283 Missing: 249
     40mn.js      Found: 300 Missing: 232
     41ms.js      Found: 265 Missing: 267
     42nb.js      Found: 470 Missing: 62
     43nl.js      Found: 494 Missing: 38
     44no.js      Found: 470 Missing: 62
     45pl.js      Found: 411 Missing: 121
     46pt-br.js   Found: 524 Missing: 8
     47pt.js      Found: 282 Missing: 250
     48ro.js      Found: 301 Missing: 231
     49ru.js      Found: 467 Missing: 65
     50sk.js      Found: 302 Missing: 230
     51sl.js      Found: 410 Missing: 122
     52sr-latn.js Found: 276 Missing: 256
     53sr.js      Found: 275 Missing: 257
     54sv.js      Found: 299 Missing: 233
     55th.js      Found: 287 Missing: 245
     56tr.js      Found: 524 Missing: 8
     57uk.js      Found: 404 Missing: 128
     58vi.js      Found: 481 Missing: 51
     59zh-cn.js   Found: 523 Missing: 9
     60zh.js      Found: 404 Missing: 128
  • CKEditor/trunk/_source/lang/af.js

    r5720 r5812  
    106106                targetSelf              : 'Same Window (_self)', // MISSING
    107107                targetParent    : 'Parent Window (_parent)', // MISSING
     108                advanced                : 'Advanced', // MISSING
     109                langDirLTR              : 'Left to Right (LTR)', // MISSING
     110                langDirRTL              : 'Right to Left (RTL)', // MISSING
     111                styles                  : 'Style', // MISSING
     112                cssClasses              : 'Stylesheet Classes', // MISSING
    108113
    109114                // Put the voice-only part of the label in the span.
     
    745750
    746751        toolbarCollapse : 'Collapse Toolbar', // MISSING
    747         toolbarExpand   : 'Expand Toolbar' // MISSING
     752        toolbarExpand   : 'Expand Toolbar', // MISSING
     753
     754        bidi :
     755        {
     756                ltr : 'Text direction from left to right', // MISSING
     757                rtl : 'Text direction from right to left' // MISSING
     758        }
    748759};
  • CKEditor/trunk/_source/lang/ar.js

    r5640 r5812  
    106106                targetSelf              : 'Same Window (_self)', // MISSING
    107107                targetParent    : 'Parent Window (_parent)', // MISSING
     108                advanced                : 'Advanced', // MISSING
     109                langDirLTR              : 'Left to Right (LTR)', // MISSING
     110                langDirRTL              : 'Right to Left (RTL)', // MISSING
     111                styles                  : 'Style', // MISSING
     112                cssClasses              : 'Stylesheet Classes', // MISSING
    108113
    109114                // Put the voice-only part of the label in the span.
     
    745750
    746751        toolbarCollapse : 'Collapse Toolbar', // MISSING
    747         toolbarExpand   : 'Expand Toolbar' // MISSING
     752        toolbarExpand   : 'Expand Toolbar', // MISSING
     753
     754        bidi :
     755        {
     756                ltr : 'Text direction from left to right', // MISSING
     757                rtl : 'Text direction from right to left' // MISSING
     758        }
    748759};
  • CKEditor/trunk/_source/lang/bg.js

    r5720 r5812  
    106106                targetSelf              : 'Same Window (_self)', // MISSING
    107107                targetParent    : 'Parent Window (_parent)', // MISSING
     108                advanced                : 'Advanced', // MISSING
     109                langDirLTR              : 'Left to Right (LTR)', // MISSING
     110                langDirRTL              : 'Right to Left (RTL)', // MISSING
     111                styles                  : 'Style', // MISSING
     112                cssClasses              : 'Stylesheet Classes', // MISSING
    108113
    109114                // Put the voice-only part of the label in the span.
     
    745750
    746751        toolbarCollapse : 'Collapse Toolbar', // MISSING
    747         toolbarExpand   : 'Expand Toolbar' // MISSING
     752        toolbarExpand   : 'Expand Toolbar', // MISSING
     753
     754        bidi :
     755        {
     756                ltr : 'Text direction from left to right', // MISSING
     757                rtl : 'Text direction from right to left' // MISSING
     758        }
    748759};
  • CKEditor/trunk/_source/lang/bn.js

    r5720 r5812  
    106106                targetSelf              : 'Same Window (_self)', // MISSING
    107107                targetParent    : 'Parent Window (_parent)', // MISSING
     108                advanced                : 'Advanced', // MISSING
     109                langDirLTR              : 'Left to Right (LTR)', // MISSING
     110                langDirRTL              : 'Right to Left (RTL)', // MISSING
     111                styles                  : 'Style', // MISSING
     112                cssClasses              : 'Stylesheet Classes', // MISSING
    108113
    109114                // Put the voice-only part of the label in the span.
     
    745750
    746751        toolbarCollapse : 'Collapse Toolbar', // MISSING
    747         toolbarExpand   : 'Expand Toolbar' // MISSING
     752        toolbarExpand   : 'Expand Toolbar', // MISSING
     753
     754        bidi :
     755        {
     756                ltr : 'Text direction from left to right', // MISSING
     757                rtl : 'Text direction from right to left' // MISSING
     758        }
    748759};
  • CKEditor/trunk/_source/lang/bs.js

    r5720 r5812  
    106106                targetSelf              : 'Same Window (_self)', // MISSING
    107107                targetParent    : 'Parent Window (_parent)', // MISSING
     108                advanced                : 'Advanced', // MISSING
     109                langDirLTR              : 'Left to Right (LTR)', // MISSING
     110                langDirRTL              : 'Right to Left (RTL)', // MISSING
     111                styles                  : 'Style', // MISSING
     112                cssClasses              : 'Stylesheet Classes', // MISSING
    108113
    109114                // Put the voice-only part of the label in the span.
     
    745750
    746751        toolbarCollapse : 'Collapse Toolbar', // MISSING
    747         toolbarExpand   : 'Expand Toolbar' // MISSING
     752        toolbarExpand   : 'Expand Toolbar', // MISSING
     753
     754        bidi :
     755        {
     756                ltr : 'Text direction from left to right', // MISSING
     757                rtl : 'Text direction from right to left' // MISSING
     758        }
    748759};
  • CKEditor/trunk/_source/lang/ca.js

    r5640 r5812  
    106106                targetSelf              : 'Mateixa finestra (_self)',
    107107                targetParent    : 'Finestra pare (_parent)',
     108                advanced                : 'Advanced', // MISSING
     109                langDirLTR              : 'Left to Right (LTR)', // MISSING
     110                langDirRTL              : 'Right to Left (RTL)', // MISSING
     111                styles                  : 'Style', // MISSING
     112                cssClasses              : 'Stylesheet Classes', // MISSING
    108113
    109114                // Put the voice-only part of the label in the span.
     
    745750
    746751        toolbarCollapse : 'Redueix la barra d\'eines',
    747         toolbarExpand   : 'Amplia la barra d\'eines'
     752        toolbarExpand   : 'Amplia la barra d\'eines',
     753
     754        bidi :
     755        {
     756                ltr : 'Text direction from left to right', // MISSING
     757                rtl : 'Text direction from right to left' // MISSING
     758        }
    748759};
  • CKEditor/trunk/_source/lang/cs.js

    r5720 r5812  
    106106                targetSelf              : 'Same Window (_self)', // MISSING
    107107                targetParent    : 'Parent Window (_parent)', // MISSING
     108                advanced                : 'Advanced', // MISSING
     109                langDirLTR              : 'Left to Right (LTR)', // MISSING
     110                langDirRTL              : 'Right to Left (RTL)', // MISSING
     111                styles                  : 'Style', // MISSING
     112                cssClasses              : 'Stylesheet Classes', // MISSING
    108113
    109114                // Put the voice-only part of the label in the span.
     
    745750
    746751        toolbarCollapse : 'Collapse Toolbar', // MISSING
    747         toolbarExpand   : 'Expand Toolbar' // MISSING
     752        toolbarExpand   : 'Expand Toolbar', // MISSING
     753
     754        bidi :
     755        {
     756                ltr : 'Text direction from left to right', // MISSING
     757                rtl : 'Text direction from right to left' // MISSING
     758        }
    748759};
  • CKEditor/trunk/_source/lang/cy.js

    r5640 r5812  
    106106                targetSelf              : 'Same Window (_self)', // MISSING
    107107                targetParent    : 'Parent Window (_parent)', // MISSING
     108                advanced                : 'Advanced', // MISSING
     109                langDirLTR              : 'Left to Right (LTR)', // MISSING
     110                langDirRTL              : 'Right to Left (RTL)', // MISSING
     111                styles                  : 'Style', // MISSING
     112                cssClasses              : 'Stylesheet Classes', // MISSING
    108113
    109114                // Put the voice-only part of the label in the span.
     
    745750
    746751        toolbarCollapse : 'Cyfangu\'r Bar Offer',
    747         toolbarExpand   : 'Ehangu\'r Bar Offer'
     752        toolbarExpand   : 'Ehangu\'r Bar Offer',
     753
     754        bidi :
     755        {
     756                ltr : 'Text direction from left to right', // MISSING
     757                rtl : 'Text direction from right to left' // MISSING
     758        }
    748759};
  • CKEditor/trunk/_source/lang/da.js

    r5720 r5812  
    106106                targetSelf              : 'Same Window (_self)', // MISSING
    107107                targetParent    : 'Parent Window (_parent)', // MISSING
     108                advanced                : 'Advanced', // MISSING
     109                langDirLTR              : 'Left to Right (LTR)', // MISSING
     110                langDirRTL              : 'Right to Left (RTL)', // MISSING
     111                styles                  : 'Style', // MISSING
     112                cssClasses              : 'Stylesheet Classes', // MISSING
    108113
    109114                // Put the voice-only part of the label in the span.
     
    745750
    746751        toolbarCollapse : 'Collapse Toolbar', // MISSING
    747         toolbarExpand   : 'Expand Toolbar' // MISSING
     752        toolbarExpand   : 'Expand Toolbar', // MISSING
     753
     754        bidi :
     755        {
     756                ltr : 'Text direction from left to right', // MISSING
     757                rtl : 'Text direction from right to left' // MISSING
     758        }
    748759};
  • CKEditor/trunk/_source/lang/de.js

    r5700 r5812  
    106106                targetSelf              : 'Gleiches Fenster (_self)',
    107107                targetParent    : 'Oberes Fenster (_parent)',
     108                advanced                : 'Advanced', // MISSING
     109                langDirLTR              : 'Left to Right (LTR)', // MISSING
     110                langDirRTL              : 'Right to Left (RTL)', // MISSING
     111                styles                  : 'Style', // MISSING
     112                cssClasses              : 'Stylesheet Classes', // MISSING
    108113
    109114                // Put the voice-only part of the label in the span.
     
    745750
    746751        toolbarCollapse : 'Symbolleiste einklappen',
    747         toolbarExpand   : 'Symbolleiste ausklappen'
     752        toolbarExpand   : 'Symbolleiste ausklappen',
     753
     754        bidi :
     755        {
     756                ltr : 'Text direction from left to right', // MISSING
     757                rtl : 'Text direction from right to left' // MISSING
     758        }
    748759};
  • CKEditor/trunk/_source/lang/el.js

    r5720 r5812  
    106106                targetSelf              : 'Same Window (_self)', // MISSING
    107107                targetParent    : 'Parent Window (_parent)', // MISSING
     108                advanced                : 'Advanced', // MISSING
     109                langDirLTR              : 'Left to Right (LTR)', // MISSING
     110                langDirRTL              : 'Right to Left (RTL)', // MISSING
     111                styles                  : 'Style', // MISSING
     112                cssClasses              : 'Stylesheet Classes', // MISSING
    108113
    109114                // Put the voice-only part of the label in the span.
     
    745750
    746751        toolbarCollapse : 'Collapse Toolbar', // MISSING
    747         toolbarExpand   : 'Expand Toolbar' // MISSING
     752        toolbarExpand   : 'Expand Toolbar', // MISSING
     753
     754        bidi :
     755        {
     756                ltr : 'Text direction from left to right', // MISSING
     757                rtl : 'Text direction from right to left' // MISSING
     758        }
    748759};
  • CKEditor/trunk/_source/lang/en-au.js

    r5720 r5812  
    106106                targetSelf              : 'Same Window (_self)', // MISSING
    107107                targetParent    : 'Parent Window (_parent)', // MISSING
     108                advanced                : 'Advanced', // MISSING
     109                langDirLTR              : 'Left to Right (LTR)', // MISSING
     110                langDirRTL              : 'Right to Left (RTL)', // MISSING
     111                styles                  : 'Style', // MISSING
     112                cssClasses              : 'Stylesheet Classes', // MISSING
    108113
    109114                // Put the voice-only part of the label in the span.
     
    745750
    746751        toolbarCollapse : 'Collapse Toolbar', // MISSING
    747         toolbarExpand   : 'Expand Toolbar' // MISSING
     752        toolbarExpand   : 'Expand Toolbar', // MISSING
     753
     754        bidi :
     755        {
     756                ltr : 'Text direction from left to right', // MISSING
     757                rtl : 'Text direction from right to left' // MISSING
     758        }
    748759};
  • CKEditor/trunk/_source/lang/en-ca.js

    r5720 r5812  
    106106                targetSelf              : 'Same Window (_self)', // MISSING
    107107                targetParent    : 'Parent Window (_parent)', // MISSING
     108                advanced                : 'Advanced', // MISSING
     109                langDirLTR              : 'Left to Right (LTR)', // MISSING
     110                langDirRTL              : 'Right to Left (RTL)', // MISSING
     111                styles                  : 'Style', // MISSING
     112                cssClasses              : 'Stylesheet Classes', // MISSING
    108113
    109114                // Put the voice-only part of the label in the span.
     
    745750
    746751        toolbarCollapse : 'Collapse Toolbar', // MISSING
    747         toolbarExpand   : 'Expand Toolbar' // MISSING
     752        toolbarExpand   : 'Expand Toolbar', // MISSING
     753
     754        bidi :
     755        {
     756                ltr : 'Text direction from left to right', // MISSING
     757                rtl : 'Text direction from right to left' // MISSING
     758        }
    748759};
  • CKEditor/trunk/_source/lang/en-gb.js

    r5720 r5812  
    106106                targetSelf              : 'Same Window (_self)', // MISSING
    107107                targetParent    : 'Parent Window (_parent)', // MISSING
     108                advanced                : 'Advanced', // MISSING
     109                langDirLTR              : 'Left to Right (LTR)', // MISSING
     110                langDirRTL              : 'Right to Left (RTL)', // MISSING
     111                styles                  : 'Style', // MISSING
     112                cssClasses              : 'Stylesheet Classes', // MISSING
    108113
    109114                // Put the voice-only part of the label in the span.
     
    745750
    746751        toolbarCollapse : 'Collapse Toolbar', // MISSING
    747         toolbarExpand   : 'Expand Toolbar' // MISSING
     752        toolbarExpand   : 'Expand Toolbar', // MISSING
     753
     754        bidi :
     755        {
     756                ltr : 'Text direction from left to right', // MISSING
     757                rtl : 'Text direction from right to left' // MISSING
     758        }
    748759};
  • CKEditor/trunk/_source/lang/en.js

    r5720 r5812  
    106106                targetSelf              : 'Same Window (_self)',
    107107                targetParent    : 'Parent Window (_parent)',
     108                advanced                : 'Advanced',
     109                langDirLTR              : 'Left to Right (LTR)',
     110                langDirRTL              : 'Right to Left (RTL)',
     111                styles                  : 'Style',
     112                cssClasses              : 'Stylesheet Classes',
    108113
    109114                // Put the voice-only part of the label in the span.
     
    745750
    746751        toolbarCollapse : 'Collapse Toolbar',
    747         toolbarExpand   : 'Expand Toolbar'
     752        toolbarExpand   : 'Expand Toolbar',
     753
     754        bidi :
     755        {
     756                ltr : 'Text direction from left to right',
     757                rtl : 'Text direction from right to left'
     758        }
    748759};
  • CKEditor/trunk/_source/lang/eo.js

    r5720 r5812  
    106106                targetSelf              : 'Same Window (_self)', // MISSING
    107107                targetParent    : 'Parent Window (_parent)', // MISSING
     108                advanced                : 'Advanced', // MISSING
     109                langDirLTR              : 'Left to Right (LTR)', // MISSING
     110                langDirRTL              : 'Right to Left (RTL)', // MISSING
     111                styles                  : 'Style', // MISSING
     112                cssClasses              : 'Stylesheet Classes', // MISSING
    108113
    109114                // Put the voice-only part of the label in the span.
     
    745750
    746751        toolbarCollapse : 'Collapse Toolbar', // MISSING
    747         toolbarExpand   : 'Expand Toolbar' // MISSING
     752        toolbarExpand   : 'Expand Toolbar', // MISSING
     753
     754        bidi :
     755        {
     756                ltr : 'Text direction from left to right', // MISSING
     757                rtl : 'Text direction from right to left' // MISSING
     758        }
    748759};
  • CKEditor/trunk/_source/lang/es.js

    r5641 r5812  
    106106                targetSelf              : 'Misma ventana (_self)',
    107107                targetParent    : 'Ventana padre (_parent)',
     108                advanced                : 'Advanced', // MISSING
     109                langDirLTR              : 'Left to Right (LTR)', // MISSING
     110                langDirRTL              : 'Right to Left (RTL)', // MISSING
     111                styles                  : 'Style', // MISSING
     112                cssClasses              : 'Stylesheet Classes', // MISSING
    108113
    109114                // Put the voice-only part of the label in the span.
     
    745750
    746751        toolbarCollapse : 'Contraer barra de herramientas',
    747         toolbarExpand   : 'Expandir barra de herramientas'
     752        toolbarExpand   : 'Expandir barra de herramientas',
     753
     754        bidi :
     755        {
     756                ltr : 'Text direction from left to right', // MISSING
     757                rtl : 'Text direction from right to left' // MISSING
     758        }
    748759};
  • CKEditor/trunk/_source/lang/et.js

    r5720 r5812  
    106106                targetSelf              : 'Same Window (_self)', // MISSING
    107107                targetParent    : 'Parent Window (_parent)', // MISSING
     108                advanced                : 'Advanced', // MISSING
     109                langDirLTR              : 'Left to Right (LTR)', // MISSING
     110                langDirRTL              : 'Right to Left (RTL)', // MISSING
     111                styles                  : 'Style', // MISSING
     112                cssClasses              : 'Stylesheet Classes', // MISSING
    108113
    109114                // Put the voice-only part of the label in the span.
     
    745750
    746751        toolbarCollapse : 'Collapse Toolbar', // MISSING
    747         toolbarExpand   : 'Expand Toolbar' // MISSING
     752        toolbarExpand   : 'Expand Toolbar', // MISSING
     753
     754        bidi :
     755        {
     756                ltr : 'Text direction from left to right', // MISSING
     757                rtl : 'Text direction from right to left' // MISSING
     758        }
    748759};
  • CKEditor/trunk/_source/lang/eu.js

    r5720 r5812  
    106106                targetSelf              : 'Same Window (_self)', // MISSING
    107107                targetParent    : 'Parent Window (_parent)', // MISSING
     108                advanced                : 'Advanced', // MISSING
     109                langDirLTR              : 'Left to Right (LTR)', // MISSING
     110                langDirRTL              : 'Right to Left (RTL)', // MISSING
     111                styles                  : 'Style', // MISSING
     112                cssClasses              : 'Stylesheet Classes', // MISSING
    108113
    109114                // Put the voice-only part of the label in the span.
     
    745750
    746751        toolbarCollapse : 'Collapse Toolbar', // MISSING
    747         toolbarExpand   : 'Expand Toolbar' // MISSING
     752        toolbarExpand   : 'Expand Toolbar', // MISSING
     753
     754        bidi :
     755        {
     756                ltr : 'Text direction from left to right', // MISSING
     757                rtl : 'Text direction from right to left' // MISSING
     758        }
    748759};
  • CKEditor/trunk/_source/lang/fa.js

    r5720 r5812  
    106106                targetSelf              : 'Same Window (_self)', // MISSING
    107107                targetParent    : 'Parent Window (_parent)', // MISSING
     108                advanced                : 'Advanced', // MISSING
     109                langDirLTR              : 'Left to Right (LTR)', // MISSING
     110                langDirRTL              : 'Right to Left (RTL)', // MISSING
     111                styles                  : 'Style', // MISSING
     112                cssClasses              : 'Stylesheet Classes', // MISSING
    108113
    109114                // Put the voice-only part of the label in the span.
     
    745750
    746751        toolbarCollapse : 'Collapse Toolbar', // MISSING
    747         toolbarExpand   : 'Expand Toolbar' // MISSING
     752        toolbarExpand   : 'Expand Toolbar', // MISSING
     753
     754        bidi :
     755        {
     756                ltr : 'Text direction from left to right', // MISSING
     757                rtl : 'Text direction from right to left' // MISSING
     758        }
    748759};
  • CKEditor/trunk/_source/lang/fi.js

    r5640 r5812  
    106106                targetSelf              : 'Sama ikkuna (_self)',
    107107                targetParent    : 'Ylemmän tason ikkuna (_parent)',
     108                advanced                : 'Advanced', // MISSING
     109                langDirLTR              : 'Left to Right (LTR)', // MISSING
     110                langDirRTL              : 'Right to Left (RTL)', // MISSING
     111                styles                  : 'Style', // MISSING
     112                cssClasses              : 'Stylesheet Classes', // MISSING
    108113
    109114                // Put the voice-only part of the label in the span.
     
    745750
    746751        toolbarCollapse : 'Kutista työkalupalkki',
    747         toolbarExpand   : 'Laajenna työkalupalkki'
     752        toolbarExpand   : 'Laajenna työkalupalkki',
     753
     754        bidi :
     755        {
     756                ltr : 'Text direction from left to right', // MISSING
     757                rtl : 'Text direction from right to left' // MISSING
     758        }
    748759};
  • CKEditor/trunk/_source/lang/fo.js

    r5720 r5812  
    106106                targetSelf              : 'Sama vindeyga (_self)',
    107107                targetParent    : 'Upphavligt vindeyga (_parent)',
     108                advanced                : 'Advanced', // MISSING
     109                langDirLTR              : 'Left to Right (LTR)', // MISSING
     110                langDirRTL              : 'Right to Left (RTL)', // MISSING
     111                styles                  : 'Style', // MISSING
     112                cssClasses              : 'Stylesheet Classes', // MISSING
    108113
    109114                // Put the voice-only part of the label in the span.
     
    745750
    746751        toolbarCollapse : 'Collapse Toolbar', // MISSING
    747         toolbarExpand   : 'Expand Toolbar' // MISSING
     752        toolbarExpand   : 'Expand Toolbar', // MISSING
     753
     754        bidi :
     755        {
     756                ltr : 'Text direction from left to right', // MISSING
     757                rtl : 'Text direction from right to left' // MISSING
     758        }
    748759};
  • CKEditor/trunk/_source/lang/fr-ca.js

    r5720 r5812  
    106106                targetSelf              : 'Same Window (_self)', // MISSING
    107107                targetParent    : 'Parent Window (_parent)', // MISSING
     108                advanced                : 'Advanced', // MISSING
     109                langDirLTR              : 'Left to Right (LTR)', // MISSING
     110                langDirRTL              : 'Right to Left (RTL)', // MISSING
     111                styles                  : 'Style', // MISSING
     112                cssClasses              : 'Stylesheet Classes', // MISSING
    108113
    109114                // Put the voice-only part of the label in the span.
     
    745750
    746751        toolbarCollapse : 'Collapse Toolbar', // MISSING
    747         toolbarExpand   : 'Expand Toolbar' // MISSING
     752        toolbarExpand   : 'Expand Toolbar', // MISSING
     753
     754        bidi :
     755        {
     756                ltr : 'Text direction from left to right', // MISSING
     757                rtl : 'Text direction from right to left' // MISSING
     758        }
    748759};
  • CKEditor/trunk/_source/lang/fr.js

    r5720 r5812  
    106106                targetSelf              : 'Same Window (_self)', // MISSING
    107107                targetParent    : 'Parent Window (_parent)', // MISSING
     108                advanced                : 'Advanced', // MISSING
     109                langDirLTR              : 'Left to Right (LTR)', // MISSING
     110                langDirRTL              : 'Right to Left (RTL)', // MISSING
     111                styles                  : 'Style', // MISSING
     112                cssClasses              : 'Stylesheet Classes', // MISSING
    108113
    109114                // Put the voice-only part of the label in the span.
     
    745750
    746751        toolbarCollapse : 'Collapse Toolbar', // MISSING
    747         toolbarExpand   : 'Expand Toolbar' // MISSING
     752        toolbarExpand   : 'Expand Toolbar', // MISSING
     753
     754        bidi :
     755        {
     756                ltr : 'Text direction from left to right', // MISSING
     757                rtl : 'Text direction from right to left' // MISSING
     758        }
    748759};
  • CKEditor/trunk/_source/lang/gl.js

    r5720 r5812  
    106106                targetSelf              : 'Same Window (_self)', // MISSING
    107107                targetParent    : 'Parent Window (_parent)', // MISSING
     108                advanced                : 'Advanced', // MISSING
     109                langDirLTR              : 'Left to Right (LTR)', // MISSING
     110                langDirRTL              : 'Right to Left (RTL)', // MISSING
     111                styles                  : 'Style', // MISSING
     112                cssClasses              : 'Stylesheet Classes', // MISSING
    108113
    109114                // Put the voice-only part of the label in the span.
     
    745750
    746751        toolbarCollapse : 'Collapse Toolbar', // MISSING
    747         toolbarExpand   : 'Expand Toolbar' // MISSING
     752        toolbarExpand   : 'Expand Toolbar', // MISSING
     753
     754        bidi :
     755        {
     756                ltr : 'Text direction from left to right', // MISSING
     757                rtl : 'Text direction from right to left' // MISSING
     758        }
    748759};
  • CKEditor/trunk/_source/lang/gu.js

    r5720 r5812  
    106106                targetSelf              : 'Same Window (_self)', // MISSING
    107107                targetParent    : 'Parent Window (_parent)', // MISSING
     108                advanced                : 'Advanced', // MISSING
     109                langDirLTR              : 'Left to Right (LTR)', // MISSING
     110                langDirRTL              : 'Right to Left (RTL)', // MISSING
     111                styles                  : 'Style', // MISSING
     112                cssClasses              : 'Stylesheet Classes', // MISSING
    108113
    109114                // Put the voice-only part of the label in the span.
     
    745750
    746751        toolbarCollapse : 'Collapse Toolbar', // MISSING
    747         toolbarExpand   : 'Expand Toolbar' // MISSING
     752        toolbarExpand   : 'Expand Toolbar', // MISSING
     753
     754        bidi :
     755        {
     756                ltr : 'Text direction from left to right', // MISSING
     757                rtl : 'Text direction from right to left' // MISSING
     758        }
    748759};
  • CKEditor/trunk/_source/lang/he.js

    r5703 r5812  
    106106                targetSelf              : 'אותו חלון (_self)',
    107107                targetParent    : 'חלון האב (_parent)',
     108                advanced                : 'מתקדם',
     109                langDirLTR              : 'שמאל לימין (LTR)',
     110                langDirRTL              : 'ימין לשמאל (RTL)',
     111                styles                  : 'סגנון',
     112                cssClasses              : 'מחלקות גליונות סגנון',
    108113
    109114                // Put the voice-only part of the label in the span.
     
    745750
    746751        toolbarCollapse : 'מזעור סרגל כלים',
    747         toolbarExpand   : 'הרחבת סרגל כלים'
     752        toolbarExpand   : 'הרחבת סרגל כלים',
     753
     754        bidi :
     755        {
     756                ltr : 'כיוון טקסט משמאל לימין (LTR)',
     757                rtl : 'כיוון טקסט מימין לשמאל (RTL)'
     758        }
    748759};
  • CKEditor/trunk/_source/lang/hi.js

    r5720 r5812  
    106106                targetSelf              : 'Same Window (_self)', // MISSING
    107107                targetParent    : 'Parent Window (_parent)', // MISSING
     108                advanced                : 'Advanced', // MISSING
     109                langDirLTR              : 'Left to Right (LTR)', // MISSING
     110                langDirRTL              : 'Right to Left (RTL)', // MISSING
     111                styles                  : 'Style', // MISSING
     112                cssClasses              : 'Stylesheet Classes', // MISSING
    108113
    109114                // Put the voice-only part of the label in the span.
     
    745750
    746751        toolbarCollapse : 'Collapse Toolbar', // MISSING
    747         toolbarExpand   : 'Expand Toolbar' // MISSING
     752        toolbarExpand   : 'Expand Toolbar', // MISSING
     753
     754        bidi :
     755        {
     756                ltr : 'Text direction from left to right', // MISSING
     757                rtl : 'Text direction from right to left' // MISSING
     758        }
    748759};
  • CKEditor/trunk/_source/lang/hr.js

    r5720 r5812  
    106106                targetSelf              : 'Same Window (_self)', // MISSING
    107107                targetParent    : 'Parent Window (_parent)', // MISSING
     108                advanced                : 'Advanced', // MISSING
     109                langDirLTR              : 'Left to Right (LTR)', // MISSING
     110                langDirRTL              : 'Right to Left (RTL)', // MISSING
     111                styles                  : 'Style', // MISSING
     112                cssClasses              : 'Stylesheet Classes', // MISSING
    108113
    109114                // Put the voice-only part of the label in the span.
     
    745750
    746751        toolbarCollapse : 'Collapse Toolbar', // MISSING
    747         toolbarExpand   : 'Expand Toolbar' // MISSING
     752        toolbarExpand   : 'Expand Toolbar', // MISSING
     753
     754        bidi :
     755        {
     756                ltr : 'Text direction from left to right', // MISSING
     757                rtl : 'Text direction from right to left' // MISSING
     758        }
    748759};
  • CKEditor/trunk/_source/lang/hu.js

    r5640 r5812  
    106106                targetSelf              : 'Same Window (_self)', // MISSING
    107107                targetParent    : 'Parent Window (_parent)', // MISSING
     108                advanced                : 'Advanced', // MISSING
     109                langDirLTR              : 'Left to Right (LTR)', // MISSING
     110                langDirRTL              : 'Right to Left (RTL)', // MISSING
     111                styles                  : 'Style', // MISSING
     112                cssClasses              : 'Stylesheet Classes', // MISSING
    108113
    109114                // Put the voice-only part of the label in the span.
     
    745750
    746751        toolbarCollapse : 'Collapse Toolbar', // MISSING
    747         toolbarExpand   : 'Expand Toolbar' // MISSING
     752        toolbarExpand   : 'Expand Toolbar', // MISSING
     753
     754        bidi :
     755        {
     756                ltr : 'Text direction from left to right', // MISSING
     757                rtl : 'Text direction from right to left' // MISSING
     758        }
    748759};
  • CKEditor/trunk/_source/lang/is.js

    r5720 r5812  
    106106                targetSelf              : 'Same Window (_self)', // MISSING
    107107                targetParent    : 'Parent Window (_parent)', // MISSING
     108                advanced                : 'Advanced', // MISSING
     109                langDirLTR              : 'Left to Right (LTR)', // MISSING
     110                langDirRTL              : 'Right to Left (RTL)', // MISSING
     111                styles                  : 'Style', // MISSING
     112                cssClasses              : 'Stylesheet Classes', // MISSING
    108113
    109114                // Put the voice-only part of the label in the span.
     
    745750
    746751        toolbarCollapse : 'Collapse Toolbar', // MISSING
    747         toolbarExpand   : 'Expand Toolbar' // MISSING
     752        toolbarExpand   : 'Expand Toolbar', // MISSING
     753
     754        bidi :
     755        {
     756                ltr : 'Text direction from left to right', // MISSING
     757                rtl : 'Text direction from right to left' // MISSING
     758        }
    748759};
  • CKEditor/trunk/_source/lang/it.js

    r5720 r5812  
    106106                targetSelf              : 'Same Window (_self)', // MISSING
    107107                targetParent    : 'Parent Window (_parent)', // MISSING
     108                advanced                : 'Advanced', // MISSING
     109                langDirLTR              : 'Left to Right (LTR)', // MISSING
     110                langDirRTL              : 'Right to Left (RTL)', // MISSING
     111                styles                  : 'Style', // MISSING
     112                cssClasses              : 'Stylesheet Classes', // MISSING
    108113
    109114                // Put the voice-only part of the label in the span.
     
    745750
    746751        toolbarCollapse : 'Collapse Toolbar', // MISSING
    747         toolbarExpand   : 'Expand Toolbar' // MISSING
     752        toolbarExpand   : 'Expand Toolbar', // MISSING
     753
     754        bidi :
     755        {
     756                ltr : 'Text direction from left to right', // MISSING
     757                rtl : 'Text direction from right to left' // MISSING
     758        }
    748759};
  • CKEditor/trunk/_source/lang/ja.js

    r5731 r5812  
    106106                targetSelf              : 'Same Window (_self)', // MISSING
    107107                targetParent    : 'Parent Window (_parent)', // MISSING
     108                advanced                : 'Advanced', // MISSING
     109                langDirLTR              : 'Left to Right (LTR)', // MISSING
     110                langDirRTL              : 'Right to Left (RTL)', // MISSING
     111                styles                  : 'Style', // MISSING
     112                cssClasses              : 'Stylesheet Classes', // MISSING
    108113
    109114                // Put the voice-only part of the label in the span.
     
    745750
    746751        toolbarCollapse : 'ツールバーを閉じる',
    747         toolbarExpand   : 'ツールバーを開く'
     752        toolbarExpand   : 'ツールバーを開く',
     753
     754        bidi :
     755        {
     756                ltr : 'Text direction from left to right', // MISSING
     757                rtl : 'Text direction from right to left' // MISSING
     758        }
    748759};
  • CKEditor/trunk/_source/lang/km.js

    r5720 r5812  
    106106                targetSelf              : 'Same Window (_self)', // MISSING
    107107                targetParent    : 'Parent Window (_parent)', // MISSING
     108                advanced                : 'Advanced', // MISSING
     109                langDirLTR              : 'Left to Right (LTR)', // MISSING
     110                langDirRTL              : 'Right to Left (RTL)', // MISSING
     111                styles                  : 'Style', // MISSING
     112                cssClasses              : 'Stylesheet Classes', // MISSING
    108113
    109114                // Put the voice-only part of the label in the span.
     
    745750
    746751        toolbarCollapse : 'Collapse Toolbar', // MISSING
    747         toolbarExpand   : 'Expand Toolbar' // MISSING
     752        toolbarExpand   : 'Expand Toolbar', // MISSING
     753
     754        bidi :
     755        {
     756                ltr : 'Text direction from left to right', // MISSING
     757                rtl : 'Text direction from right to left' // MISSING
     758        }
    748759};
  • CKEditor/trunk/_source/lang/ko.js

    r5720 r5812  
    106106                targetSelf              : 'Same Window (_self)', // MISSING
    107107                targetParent    : 'Parent Window (_parent)', // MISSING
     108                advanced                : 'Advanced', // MISSING
     109                langDirLTR              : 'Left to Right (LTR)', // MISSING
     110                langDirRTL              : 'Right to Left (RTL)', // MISSING
     111                styles                  : 'Style', // MISSING
     112                cssClasses              : 'Stylesheet Classes', // MISSING
    108113
    109114                // Put the voice-only part of the label in the span.
     
    745750
    746751        toolbarCollapse : 'Collapse Toolbar', // MISSING
    747         toolbarExpand   : 'Expand Toolbar' // MISSING
     752        toolbarExpand   : 'Expand Toolbar', // MISSING
     753
     754        bidi :
     755        {
     756                ltr : 'Text direction from left to right', // MISSING
     757                rtl : 'Text direction from right to left' // MISSING
     758        }
    748759};
  • CKEditor/trunk/_source/lang/lt.js

    r5720 r5812  
    106106                targetSelf              : 'Same Window (_self)', // MISSING
    107107                targetParent    : 'Parent Window (_parent)', // MISSING
     108                advanced                : 'Advanced', // MISSING
     109                langDirLTR              : 'Left to Right (LTR)', // MISSING
     110                langDirRTL              : 'Right to Left (RTL)', // MISSING
     111                styles                  : 'Style', // MISSING
     112                cssClasses              : 'Stylesheet Classes', // MISSING
    108113
    109114                // Put the voice-only part of the label in the span.
     
    745750
    746751        toolbarCollapse : 'Collapse Toolbar', // MISSING
    747         toolbarExpand   : 'Expand Toolbar' // MISSING
     752        toolbarExpand   : 'Expand Toolbar', // MISSING
     753
     754        bidi :
     755        {
     756                ltr : 'Text direction from left to right', // MISSING
     757                rtl : 'Text direction from right to left' // MISSING
     758        }
    748759};
  • CKEditor/trunk/_source/lang/lv.js

    r5720 r5812  
    106106                targetSelf              : 'Same Window (_self)', // MISSING
    107107                targetParent    : 'Parent Window (_parent)', // MISSING
     108                advanced                : 'Advanced', // MISSING
     109                langDirLTR              : 'Left to Right (LTR)', // MISSING
     110                langDirRTL              : 'Right to Left (RTL)', // MISSING
     111                styles                  : 'Style', // MISSING
     112                cssClasses              : 'Stylesheet Classes', // MISSING
    108113
    109114                // Put the voice-only part of the label in the span.
     
    745750
    746751        toolbarCollapse : 'Collapse Toolbar', // MISSING
    747         toolbarExpand   : 'Expand Toolbar' // MISSING
     752        toolbarExpand   : 'Expand Toolbar', // MISSING
     753
     754        bidi :
     755        {
     756                ltr : 'Text direction from left to right', // MISSING
     757                rtl : 'Text direction from right to left' // MISSING
     758        }
    748759};
  • CKEditor/trunk/_source/lang/mn.js

    r5720 r5812  
    106106                targetSelf              : 'Same Window (_self)', // MISSING
    107107                targetParent    : 'Parent Window (_parent)', // MISSING
     108                advanced                : 'Advanced', // MISSING
     109                langDirLTR              : 'Left to Right (LTR)', // MISSING
     110                langDirRTL              : 'Right to Left (RTL)', // MISSING
     111                styles                  : 'Style', // MISSING
     112                cssClasses              : 'Stylesheet Classes', // MISSING
    108113
    109114                // Put the voice-only part of the label in the span.
     
    745750
    746751        toolbarCollapse : 'Collapse Toolbar', // MISSING
    747         toolbarExpand   : 'Expand Toolbar' // MISSING
     752        toolbarExpand   : 'Expand Toolbar', // MISSING
     753
     754        bidi :
     755        {
     756                ltr : 'Text direction from left to right', // MISSING
     757                rtl : 'Text direction from right to left' // MISSING
     758        }
    748759};
  • CKEditor/trunk/_source/lang/ms.js

    r5720 r5812  
    106106                targetSelf              : 'Same Window (_self)', // MISSING
    107107                targetParent    : 'Parent Window (_parent)', // MISSING
     108                advanced                : 'Advanced', // MISSING
     109                langDirLTR              : 'Left to Right (LTR)', // MISSING
     110                langDirRTL              : 'Right to Left (RTL)', // MISSING
     111                styles                  : 'Style', // MISSING
     112                cssClasses              : 'Stylesheet Classes', // MISSING
    108113
    109114                // Put the voice-only part of the label in the span.
     
    745750
    746751        toolbarCollapse : 'Collapse Toolbar', // MISSING
    747         toolbarExpand   : 'Expand Toolbar' // MISSING
     752        toolbarExpand   : 'Expand Toolbar', // MISSING
     753
     754        bidi :
     755        {
     756                ltr : 'Text direction from left to right', // MISSING
     757                rtl : 'Text direction from right to left' // MISSING
     758        }
    748759};
  • CKEditor/trunk/_source/lang/nb.js

    r5640 r5812  
    106106                targetSelf              : 'Samme vindu (_self)',
    107107                targetParent    : 'Foreldrevindu (_parent)',
     108                advanced                : 'Advanced', // MISSING
     109                langDirLTR              : 'Left to Right (LTR)', // MISSING
     110                langDirRTL              : 'Right to Left (RTL)', // MISSING
     111                styles                  : 'Style', // MISSING
     112                cssClasses              : 'Stylesheet Classes', // MISSING
    108113
    109114                // Put the voice-only part of the label in the span.
     
    745750
    746751        toolbarCollapse : 'Slå sammen verktøylinje',
    747         toolbarExpand   : 'Vis verktøylinje'
     752        toolbarExpand   : 'Vis verktøylinje',
     753
     754        bidi :
     755        {
     756                ltr : 'Text direction from left to right', // MISSING
     757                rtl : 'Text direction from right to left' // MISSING
     758        }
    748759};
  • CKEditor/trunk/_source/lang/nl.js

    r5640 r5812  
    106106                targetSelf              : 'Zelfde venster (_self)',
    107107                targetParent    : 'Origineel venster (_parent)',
     108                advanced                : 'Advanced', // MISSING
     109                langDirLTR              : 'Left to Right (LTR)', // MISSING
     110                langDirRTL              : 'Right to Left (RTL)', // MISSING
     111                styles                  : 'Style', // MISSING
     112                cssClasses              : 'Stylesheet Classes', // MISSING
    108113
    109114                // Put the voice-only part of the label in the span.
     
    745750
    746751        toolbarCollapse : 'Werkbalk inklappen',
    747         toolbarExpand   : 'Werkbalk uitklappen'
     752        toolbarExpand   : 'Werkbalk uitklappen',
     753
     754        bidi :
     755        {
     756                ltr : 'Text direction from left to right', // MISSING
     757                rtl : 'Text direction from right to left' // MISSING
     758        }
    748759};
  • CKEditor/trunk/_source/lang/no.js

    r5640 r5812  
    106106                targetSelf              : 'Samme vindu (_self)',
    107107                targetParent    : 'Foreldrevindu (_parent)',
     108                advanced                : 'Advanced', // MISSING
     109                langDirLTR              : 'Left to Right (LTR)', // MISSING
     110                langDirRTL              : 'Right to Left (RTL)', // MISSING
     111                styles                  : 'Style', // MISSING
     112                cssClasses              : 'Stylesheet Classes', // MISSING
    108113
    109114                // Put the voice-only part of the label in the span.
     
    745750
    746751        toolbarCollapse : 'Slå sammen verktøylinje',
    747         toolbarExpand   : 'Vis verktøylinje'
     752        toolbarExpand   : 'Vis verktøylinje',
     753
     754        bidi :
     755        {
     756                ltr : 'Text direction from left to right', // MISSING
     757                rtl : 'Text direction from right to left' // MISSING
     758        }
    748759};
  • CKEditor/trunk/_source/lang/pl.js

    r5720 r5812  
    106106                targetSelf              : 'Same Window (_self)', // MISSING
    107107                targetParent    : 'Parent Window (_parent)', // MISSING
     108                advanced                : 'Advanced', // MISSING
     109                langDirLTR              : 'Left to Right (LTR)', // MISSING
     110                langDirRTL              : 'Right to Left (RTL)', // MISSING
     111                styles                  : 'Style', // MISSING
     112                cssClasses              : 'Stylesheet Classes', // MISSING
    108113
    109114                // Put the voice-only part of the label in the span.
     
    745750
    746751        toolbarCollapse : 'Collapse Toolbar', // MISSING
    747         toolbarExpand   : 'Expand Toolbar' // MISSING
     752        toolbarExpand   : 'Expand Toolbar', // MISSING
     753
     754        bidi :
     755        {
     756                ltr : 'Text direction from left to right', // MISSING
     757                rtl : 'Text direction from right to left' // MISSING
     758        }
    748759};
  • CKEditor/trunk/_source/lang/pt-br.js

    r5765 r5812  
    105105                targetSelf              : 'Mesma Janela (_self)',
    106106                targetParent    : 'Janela Pai (_parent)',
     107                advanced                : 'Advanced', // MISSING
     108                langDirLTR              : 'Left to Right (LTR)', // MISSING
     109                langDirRTL              : 'Right to Left (RTL)', // MISSING
     110                styles                  : 'Style', // MISSING
     111                cssClasses              : 'Stylesheet Classes', // MISSING
    107112
    108113                // Put the voice-only part of the label in the span.
     
    744749
    745750        toolbarCollapse : 'Diminuir Barra de Ferramentas',
    746         toolbarExpand   : 'Aumentar Barra de Ferramentas'
     751        toolbarExpand   : 'Aumentar Barra de Ferramentas',
     752
     753        bidi :
     754        {
     755                ltr : 'Text direction from left to right', // MISSING
     756                rtl : 'Text direction from right to left' // MISSING
     757        }
    747758};
  • CKEditor/trunk/_source/lang/pt.js

    r5720 r5812  
    106106                targetSelf              : 'Same Window (_self)', // MISSING
    107107                targetParent    : 'Parent Window (_parent)', // MISSING
     108                advanced                : 'Advanced', // MISSING
     109                langDirLTR              : 'Left to Right (LTR)', // MISSING
     110                langDirRTL              : 'Right to Left (RTL)', // MISSING
     111                styles                  : 'Style', // MISSING
     112                cssClasses              : 'Stylesheet Classes', // MISSING
    108113
    109114                // Put the voice-only part of the label in the span.
     
    745750
    746751        toolbarCollapse : 'Collapse Toolbar', // MISSING
    747         toolbarExpand   : 'Expand Toolbar' // MISSING
     752        toolbarExpand   : 'Expand Toolbar', // MISSING
     753
     754        bidi :
     755        {
     756                ltr : 'Text direction from left to right', // MISSING
     757                rtl : 'Text direction from right to left' // MISSING
     758        }
    748759};
  • CKEditor/trunk/_source/lang/ro.js

    r5720 r5812  
    106106                targetSelf              : 'Same Window (_self)', // MISSING
    107107                targetParent    : 'Parent Window (_parent)', // MISSING
     108                advanced                : 'Advanced', // MISSING
     109                langDirLTR              : 'Left to Right (LTR)', // MISSING
     110                langDirRTL              : 'Right to Left (RTL)', // MISSING
     111                styles                  : 'Style', // MISSING
     112                cssClasses              : 'Stylesheet Classes', // MISSING
    108113
    109114                // Put the voice-only part of the label in the span.
     
    745750
    746751        toolbarCollapse : 'Collapse Toolbar', // MISSING
    747         toolbarExpand   : 'Expand Toolbar' // MISSING
     752        toolbarExpand   : 'Expand Toolbar', // MISSING
     753
     754        bidi :
     755        {
     756                ltr : 'Text direction from left to right', // MISSING
     757                rtl : 'Text direction from right to left' // MISSING
     758        }
    748759};
  • CKEditor/trunk/_source/lang/ru.js

    r5640 r5812  
    106106                targetSelf              : 'Same Window (_self)', // MISSING
    107107                targetParent    : 'Parent Window (_parent)', // MISSING
     108                advanced                : 'Advanced', // MISSING
     109                langDirLTR              : 'Left to Right (LTR)', // MISSING
     110                langDirRTL              : 'Right to Left (RTL)', // MISSING
     111                styles                  : 'Style', // MISSING
     112                cssClasses              : 'Stylesheet Classes', // MISSING
    108113
    109114                // Put the voice-only part of the label in the span.
     
    745750
    746751        toolbarCollapse : 'Свернуть панель инструментов',
    747         toolbarExpand   : 'Развернуть панель инструментов'
     752        toolbarExpand   : 'Развернуть панель инструментов',
     753
     754        bidi :
     755        {
     756                ltr : 'Text direction from left to right', // MISSING
     757                rtl : 'Text direction from right to left' // MISSING
     758        }
    748759};
  • CKEditor/trunk/_source/lang/sk.js

    r5720 r5812  
    106106                targetSelf              : 'Same Window (_self)', // MISSING
    107107                targetParent    : 'Parent Window (_parent)', // MISSING
     108                advanced                : 'Advanced', // MISSING
     109                langDirLTR              : 'Left to Right (LTR)', // MISSING
     110                langDirRTL              : 'Right to Left (RTL)', // MISSING
     111                styles                  : 'Style', // MISSING
     112                cssClasses              : 'Stylesheet Classes', // MISSING
    108113
    109114                // Put the voice-only part of the label in the span.
     
    745750
    746751        toolbarCollapse : 'Collapse Toolbar', // MISSING
    747         toolbarExpand   : 'Expand Toolbar' // MISSING
     752        toolbarExpand   : 'Expand Toolbar', // MISSING
     753
     754        bidi :
     755        {
     756                ltr : 'Text direction from left to right', // MISSING
     757                rtl : 'Text direction from right to left' // MISSING
     758        }
    748759};
  • CKEditor/trunk/_source/lang/sl.js

    r5720 r5812  
    106106                targetSelf              : 'Same Window (_self)', // MISSING
    107107                targetParent    : 'Parent Window (_parent)', // MISSING
     108                advanced                : 'Advanced', // MISSING
     109                langDirLTR              : 'Left to Right (LTR)', // MISSING
     110                langDirRTL              : 'Right to Left (RTL)', // MISSING
     111                styles                  : 'Style', // MISSING
     112                cssClasses              : 'Stylesheet Classes', // MISSING
    108113
    109114                // Put the voice-only part of the label in the span.
     
    745750
    746751        toolbarCollapse : 'Collapse Toolbar', // MISSING
    747         toolbarExpand   : 'Expand Toolbar' // MISSING
     752        toolbarExpand   : 'Expand Toolbar', // MISSING
     753
     754        bidi :
     755        {
     756                ltr : 'Text direction from left to right', // MISSING
     757                rtl : 'Text direction from right to left' // MISSING
     758        }
    748759};
  • CKEditor/trunk/_source/lang/sr-latn.js

    r5720 r5812  
    106106                targetSelf              : 'Same Window (_self)', // MISSING
    107107                targetParent    : 'Parent Window (_parent)', // MISSING
     108                advanced                : 'Advanced', // MISSING
     109                langDirLTR              : 'Left to Right (LTR)', // MISSING
     110                langDirRTL              : 'Right to Left (RTL)', // MISSING
     111                styles                  : 'Style', // MISSING
     112                cssClasses              : 'Stylesheet Classes', // MISSING
    108113
    109114                // Put the voice-only part of the label in the span.
     
    745750
    746751        toolbarCollapse : 'Collapse Toolbar', // MISSING
    747         toolbarExpand   : 'Expand Toolbar' // MISSING
     752        toolbarExpand   : 'Expand Toolbar', // MISSING
     753
     754        bidi :
     755        {
     756                ltr : 'Text direction from left to right', // MISSING
     757                rtl : 'Text direction from right to left' // MISSING
     758        }
    748759};
  • CKEditor/trunk/_source/lang/sr.js

    r5720 r5812  
    106106                targetSelf              : 'Same Window (_self)', // MISSING
    107107                targetParent    : 'Parent Window (_parent)', // MISSING
     108                advanced                : 'Advanced', // MISSING
     109                langDirLTR              : 'Left to Right (LTR)', // MISSING
     110                langDirRTL              : 'Right to Left (RTL)', // MISSING
     111                styles                  : 'Style', // MISSING
     112                cssClasses              : 'Stylesheet Classes', // MISSING
    108113
    109114                // Put the voice-only part of the label in the span.
     
    745750
    746751        toolbarCollapse : 'Collapse Toolbar', // MISSING
    747         toolbarExpand   : 'Expand Toolbar' // MISSING
     752        toolbarExpand   : 'Expand Toolbar', // MISSING
     753
     754        bidi :
     755        {
     756                ltr : 'Text direction from left to right', // MISSING
     757                rtl : 'Text direction from right to left' // MISSING
     758        }
    748759};
  • CKEditor/trunk/_source/lang/sv.js

    r5720 r5812  
    106106                targetSelf              : 'Same Window (_self)', // MISSING
    107107                targetParent    : 'Parent Window (_parent)', // MISSING
     108                advanced                : 'Advanced', // MISSING
     109                langDirLTR              : 'Left to Right (LTR)', // MISSING
     110                langDirRTL              : 'Right to Left (RTL)', // MISSING
     111                styles                  : 'Style', // MISSING
     112                cssClasses              : 'Stylesheet Classes', // MISSING
    108113
    109114                // Put the voice-only part of the label in the span.
     
    745750
    746751        toolbarCollapse : 'Collapse Toolbar', // MISSING
    747         toolbarExpand   : 'Expand Toolbar' // MISSING
     752        toolbarExpand   : 'Expand Toolbar', // MISSING
     753
     754        bidi :
     755        {
     756                ltr : 'Text direction from left to right', // MISSING
     757                rtl : 'Text direction from right to left' // MISSING
     758        }
    748759};
  • CKEditor/trunk/_source/lang/th.js

    r5720 r5812  
    106106                targetSelf              : 'Same Window (_self)', // MISSING
    107107                targetParent    : 'Parent Window (_parent)', // MISSING
     108                advanced                : 'Advanced', // MISSING
     109                langDirLTR              : 'Left to Right (LTR)', // MISSING
     110                langDirRTL              : 'Right to Left (RTL)', // MISSING
     111                styles                  : 'Style', // MISSING
     112                cssClasses              : 'Stylesheet Classes', // MISSING
    108113
    109114                // Put the voice-only part of the label in the span.
     
    745750
    746751        toolbarCollapse : 'Collapse Toolbar', // MISSING
    747         toolbarExpand   : 'Expand Toolbar' // MISSING
     752        toolbarExpand   : 'Expand Toolbar', // MISSING
     753
     754        bidi :
     755        {
     756                ltr : 'Text direction from left to right', // MISSING
     757                rtl : 'Text direction from right to left' // MISSING
     758        }
    748759};
  • CKEditor/trunk/_source/lang/tr.js

    r5765 r5812  
    105105                targetSelf              : 'Aynı Pencere (_self)',
    106106                targetParent    : 'Ana Pencere (_parent)',
     107                advanced                : 'Advanced', // MISSING
     108                langDirLTR              : 'Left to Right (LTR)', // MISSING
     109                langDirRTL              : 'Right to Left (RTL)', // MISSING
     110                styles                  : 'Style', // MISSING
     111                cssClasses              : 'Stylesheet Classes', // MISSING
    107112
    108113                // Put the voice-only part of the label in the span.
     
    744749
    745750        toolbarCollapse : 'Toolbar\'ı topla',
    746         toolbarExpand   : 'Toolbar\'ı aç'
     751        toolbarExpand   : 'Toolbar\'ı aç',
     752
     753        bidi :
     754        {
     755                ltr : 'Text direction from left to right', // MISSING
     756                rtl : 'Text direction from right to left' // MISSING
     757        }
    747758};
  • CKEditor/trunk/_source/lang/uk.js

    r5720 r5812  
    106106                targetSelf              : 'Same Window (_self)', // MISSING
    107107                targetParent    : 'Parent Window (_parent)', // MISSING
     108                advanced                : 'Advanced', // MISSING
     109                langDirLTR              : 'Left to Right (LTR)', // MISSING
     110                langDirRTL              : 'Right to Left (RTL)', // MISSING
     111                styles                  : 'Style', // MISSING
     112                cssClasses              : 'Stylesheet Classes', // MISSING
    108113
    109114                // Put the voice-only part of the label in the span.
     
    745750
    746751        toolbarCollapse : 'Collapse Toolbar', // MISSING
    747         toolbarExpand   : 'Expand Toolbar' // MISSING
     752        toolbarExpand   : 'Expand Toolbar', // MISSING
     753
     754        bidi :
     755        {
     756                ltr : 'Text direction from left to right', // MISSING
     757                rtl : 'Text direction from right to left' // MISSING
     758        }
    748759};
  • CKEditor/trunk/_source/lang/vi.js

    r5720 r5812  
    106106                targetSelf              : 'Tại trang (_self)',
    107107                targetParent    : 'Cửa sổ cha (_parent)',
     108                advanced                : 'Advanced', // MISSING
     109                langDirLTR              : 'Left to Right (LTR)', // MISSING
     110                langDirRTL              : 'Right to Left (RTL)', // MISSING
     111                styles                  : 'Style', // MISSING
     112                cssClasses              : 'Stylesheet Classes', // MISSING
    108113
    109114                // Put the voice-only part of the label in the span.
     
    745750
    746751        toolbarCollapse : 'Thu gọn thanh công cụ',
    747         toolbarExpand   : 'Mở rộng thnah công cụ'
     752        toolbarExpand   : 'Mở rộng thnah công cụ',
     753
     754        bidi :
     755        {
     756                ltr : 'Text direction from left to right', // MISSING
     757                rtl : 'Text direction from right to left' // MISSING
     758        }
    748759};
  • CKEditor/trunk/_source/lang/zh-cn.js

    r5768 r5812  
    106106                targetSelf              : '本窗口 (_self)',
    107107                targetParent    : '父窗口 (_parent)',
     108                advanced                : 'Advanced', // MISSING
     109                langDirLTR              : 'Left to Right (LTR)', // MISSING
     110                langDirRTL              : 'Right to Left (RTL)', // MISSING
     111                styles                  : 'Style', // MISSING
     112                cssClasses              : 'Stylesheet Classes', // MISSING
    108113
    109114                // Put the voice-only part of the label in the span.
     
    745750
    746751        toolbarCollapse : '折叠工具栏',
    747         toolbarExpand   : '展开工具栏'
     752        toolbarExpand   : '展开工具栏',
     753
     754        bidi :
     755        {
     756                ltr : 'Text direction from left to right', // MISSING
     757                rtl : 'Text direction from right to left' // MISSING
     758        }
    748759};
  • CKEditor/trunk/_source/lang/zh.js

    r5720 r5812  
    106106                targetSelf              : 'Same Window (_self)', // MISSING
    107107                targetParent    : 'Parent Window (_parent)', // MISSING
     108                advanced                : 'Advanced', // MISSING
     109                langDirLTR              : 'Left to Right (LTR)', // MISSING
     110                langDirRTL              : 'Right to Left (RTL)', // MISSING
     111                styles                  : 'Style', // MISSING
     112                cssClasses              : 'Stylesheet Classes', // MISSING
    108113
    109114                // Put the voice-only part of the label in the span.
     
    745750
    746751        toolbarCollapse : 'Collapse Toolbar', // MISSING
    747         toolbarExpand   : 'Expand Toolbar' // MISSING
     752        toolbarExpand   : 'Expand Toolbar', // MISSING
     753
     754        bidi :
     755        {
     756                ltr : 'Text direction from left to right', // MISSING
     757                rtl : 'Text direction from right to left' // MISSING
     758        }
    748759};
  • CKEditor/trunk/_source/plugins/blockquote/plugin.js

    r5206 r5812  
    4848                        var state = editor.getCommand( 'blockquote' ).state,
    4949                                selection = editor.getSelection(),
    50                                 range = selection && selection.getRanges()[0];
     50                                range = selection && selection.getRanges( true )[0];
    5151
    5252                        if ( !range )
  • CKEditor/trunk/_source/plugins/clipboard/plugin.js

    r5534 r5812  
    387387                                        }
    388388
    389                                         editor.contextMenu.addListener( function()
     389                                        editor.contextMenu.addListener( function( element, selection )
    390390                                                {
     391                                                        var readOnly = selection.getCommonAncestor().isReadOnly();
    391392                                                        return {
    392                                                                 cut : stateFromNamedCommand( 'Cut' ),
    393 
    394                                                                 // Browser bug: 'Cut' has the correct states for both Copy and Cut.
    395                                                                 copy : stateFromNamedCommand( 'Cut' ),
    396                                                                 paste : CKEDITOR.env.webkit ? CKEDITOR.TRISTATE_OFF : stateFromNamedCommand( 'Paste' )
     393                                                                cut : !readOnly && stateFromNamedCommand( 'Cut' ),
     394                                                                copy : stateFromNamedCommand( 'Copy' ),
     395                                                                paste : !readOnly && ( CKEDITOR.env.webkit ? CKEDITOR.TRISTATE_OFF : stateFromNamedCommand( 'Paste' ) )
    397396                                                        };
    398397                                                });
  • CKEditor/trunk/_source/plugins/colordialog/dialogs/colordialog.js

    r5714 r5812  
    244244                var numbering = function( id )
    245245                        {
    246                                 return id + CKEDITOR.tools.getNextNumber();
     246                                return CKEDITOR.tools.getNextId() + '_' + id;
    247247                        },
    248248                        hicolorId = numbering( 'hicolor' ),
    249249                        hicolorTextId = numbering( 'hicolortext' ),
    250                         selHiColorId = numbering( 'selhicolor' );
     250                        selHiColorId = numbering( 'selhicolor' ),
     251                        tableLabelId = numbering( 'color_table_label' );
    251252
    252253                return {
     
    274275                                                                {
    275276                                                                        type : 'html',
    276                                                                         html : '<table role="listbox" aria-labelledby="color_table_label" onmouseout="CKEDITOR.tools.callFunction( ' + onMouseout + ' );">' + table.getHtml() + '</table>' +
    277                                                                                                 '<span id="color_table_label" class="cke_voice_label">' + lang.options +'</span>',
     277                                                                        html : '<table role="listbox" aria-labelledby="' + tableLabelId + '" onmouseout="CKEDITOR.tools.callFunction( ' + onMouseout + ' );">' + table.getHtml() + '</table>' +
     278                                                                                                '<span id="' + tableLabelId + '" class="cke_voice_label">' + lang.options +'</span>',
    278279                                                                        onLoad : function()
    279280                                                                        {
  • CKEditor/trunk/_source/plugins/dialog/plugin.js

    r5706 r5812  
    473473                // Insert the tabs and contents.
    474474                for ( var i = 0 ; i < definition.contents.length ; i++ )
    475                         this.addPage( definition.contents[i] );
     475                {
     476                        var page = definition.contents[i];
     477                        page && this.addPage( page );
     478                }
    476479
    477480                this.parts['tabs'].on( 'click', function( evt )
     
    481484                                        if ( target.hasClass( 'cke_dialog_tab' ) )
    482485                                        {
     486                                                // Get the ID of the tab, without the 'cke_' prefix and the unique number suffix.
    483487                                                var id = target.$.id;
    484                                                 this.selectPage( id.substr( 0, id.lastIndexOf( '_' ) ) );
     488                                                this.selectPage( id.substring( 4, id.lastIndexOf( '_' ) ) );
     489
    485490                                                if ( this._.tabBarMode )
    486491                                                {
     
    882887
    883888                        var env = CKEDITOR.env;
    884                         var tabId = contents.id + '_' + CKEDITOR.tools.getNextNumber(),
     889                        var tabId = 'cke_' + contents.id + '_' + CKEDITOR.tools.getNextNumber(),
    885890                                 tab = CKEDITOR.dom.element.createFromHtml( [
    886891                                        '<a class="cke_dialog_tab"',
     
    13871392                var contents = dialogDefinition.contents;
    13881393                for ( var i = 0, content ; ( content = contents[i] ) ; i++ )
    1389                         contents[ i ] = new contentObject( dialog, content );
     1394                        contents[ i ] = content && new contentObject( dialog, content );
    13901395
    13911396                CKEDITOR.tools.extend( this, dialogDefinition );
     
    20522057                                        attributes = ( attributesArg && attributesArg.call ? attributesArg( elementDefinition ) : attributesArg ) || {},
    20532058                                        innerHTML = ( contentsArg && contentsArg.call ? contentsArg.call( this, dialog, elementDefinition ) : contentsArg ) || '',
    2054                                         domId = this.domId = attributes.id || CKEDITOR.tools.getNextNumber() + '_uiElement',
     2059                                        domId = this.domId = attributes.id || CKEDITOR.tools.getNextId() + '_uiElement',
    20552060                                        id = this.id = elementDefinition.id,
    20562061                                        i;
  • CKEditor/trunk/_source/plugins/dialogui/plugin.js

    r5722 r5812  
    148148
    149149                                var _ = initPrivateObject.call( this, elementDefinition );
    150                                 _.labelId = CKEDITOR.tools.getNextNumber() + '_label';
     150                                _.labelId = CKEDITOR.tools.getNextId() + '_label';
    151151                                var children = this._.children = [];
    152152                                /** @ignore */
     
    224224
    225225                                initPrivateObject.call( this, elementDefinition );
    226                                 var domId = this._.inputId = CKEDITOR.tools.getNextNumber() + '_textInput',
     226                                var domId = this._.inputId = CKEDITOR.tools.getNextId() + '_textInput',
    227227                                        attributes = { 'class' : 'cke_dialog_ui_input_' + elementDefinition.type, id : domId, type : 'text' },
    228228                                        i;
     
    314314                                initPrivateObject.call( this, elementDefinition );
    315315                                var me = this,
    316                                         domId = this._.inputId = CKEDITOR.tools.getNextNumber() + '_textarea',
     316                                        domId = this._.inputId = CKEDITOR.tools.getNextId() + '_textarea',
    317317                                        attributes = {};
    318318
     
    371371                                        var myDefinition = CKEDITOR.tools.extend( {}, elementDefinition,
    372372                                                        {
    373                                                                 id : elementDefinition.id ? elementDefinition.id + '_checkbox' : CKEDITOR.tools.getNextNumber() + '_checkbox'
     373                                                                id : elementDefinition.id ? elementDefinition.id + '_checkbox' : CKEDITOR.tools.getNextId() + '_checkbox'
    374374                                                        }, true ),
    375375                                                html = [];
    376376
    377                                         var labelId = CKEDITOR.tools.getNextNumber() + '_label';
     377                                        var labelId = CKEDITOR.tools.getNextId() + '_label';
    378378                                        var attributes = { 'class' : 'cke_dialog_ui_checkbox_input', type : 'checkbox', 'aria-labelledby' : labelId };
    379379                                        cleanInnerDefinition( myDefinition );
     
    431431                                        var inputHtmlList = [], html = [],
    432432                                                commonAttributes = { 'class' : 'cke_dialog_ui_radio_item', 'aria-labelledby' : this._.labelId },
    433                                                 commonName = elementDefinition.id ? elementDefinition.id + '_radio' : CKEDITOR.tools.getNextNumber() + '_radio';
     433                                                commonName = elementDefinition.id ? elementDefinition.id + '_radio' : CKEDITOR.tools.getNextId() + '_radio';
    434434                                        for ( var i = 0 ; i < elementDefinition.items.length ; i++ )
    435435                                        {
     
    437437                                                        title = item[2] !== undefined ? item[2] : item[0],
    438438                                                        value = item[1] !== undefined ? item[1] : item[0],
    439                                                         inputId = CKEDITOR.tools.getNextNumber() + '_radio_input',
     439                                                        inputId = CKEDITOR.tools.getNextId() + '_radio_input',
    440440                                                        labelId = inputId + '_label',
    441441                                                        inputDefinition = CKEDITOR.tools.extend( {}, elementDefinition,
     
    541541                                delete outerDefinition.style;
    542542
    543                                 var labelId = CKEDITOR.tools.getNextNumber() + '_label';
     543                                var labelId = CKEDITOR.tools.getNextId() + '_label';
    544544                                CKEDITOR.ui.dialog.uiElement.call(
    545545                                        this,
     
    597597                                        this.validate = elementDefinition.validate;
    598598
    599                                 _.inputId = CKEDITOR.tools.getNextNumber() + '_select';
     599                                _.inputId = CKEDITOR.tools.getNextId() + '_select';
    600600                                /** @ignore */
    601601                                var innerHTML = function()
     
    603603                                        var myDefinition = CKEDITOR.tools.extend( {}, elementDefinition,
    604604                                                        {
    605                                                                 id : elementDefinition.id ? elementDefinition.id + '_select' : CKEDITOR.tools.getNextNumber() + '_select'
     605                                                                id : elementDefinition.id ? elementDefinition.id + '_select' : CKEDITOR.tools.getNextId() + '_select'
    606606                                                        }, true ),
    607607                                                html = [],
     
    664664                                var innerHTML = function()
    665665                                {
    666                                         _.frameId = CKEDITOR.tools.getNextNumber() + '_fileInput';
     666                                        _.frameId = CKEDITOR.tools.getNextId() + '_fileInput';
    667667
    668668                                        // Support for custom document.domain in IE.
  • CKEditor/trunk/_source/plugins/div/dialogs/div.js

    • Property svn:mergeinfo deleted
  • CKEditor/trunk/_source/plugins/div/plugin.js

    • Property svn:mergeinfo deleted
    r5548 r5812  
    9696                                        editor.contextMenu.addListener( function( element, selection )
    9797                                                {
    98                                                         if ( !element )
     98                                                        if ( !element || element.isReadOnly())
    9999                                                                return null;
    100100
  • CKEditor/trunk/_source/plugins/enterkey/plugin.js

    r5534 r5812  
    2424                        // Get the range for the current selection.
    2525                        range = range || getRange( editor );
     26
     27                        // We may not have valid ranges to work on, like when inside a
     28                        // contenteditable=false element.
     29                        if ( !range )
     30                                return;
    2631
    2732                        var doc = range.document;
     
    189194                        // Get the range for the current selection.
    190195                        range = range || getRange( editor );
     196
     197                        // We may not have valid ranges to work on, like when inside a
     198                        // contenteditable=false element.
     199                        if ( !range )
     200                                return;
    191201
    192202                        var doc = range.document;
     
    340350        {
    341351                // Get the selection ranges.
    342                 var ranges = editor.getSelection().getRanges();
     352                var ranges = editor.getSelection().getRanges( true );
    343353
    344354                // Delete the contents of all ranges except the first one.
  • CKEditor/trunk/_source/plugins/filebrowser/plugin.js

    r5231 r5812  
    389389                for ( var i in definition.contents )
    390390                {
    391                         element = definition.contents[ i ] ;
    392                         attachFileBrowser( evt.editor, evt.data.name, definition, element.elements );
    393                         if ( element.hidden && element.filebrowser )
    394                         {
    395                                 element.hidden = !isConfigured( definition, element[ 'id' ], element.filebrowser );
     391                        if ( ( element = definition.contents[ i ] ) )
     392                        {
     393                                attachFileBrowser( evt.editor, evt.data.name, definition, element.elements );
     394                                if ( element.hidden && element.filebrowser )
     395                                {
     396                                        element.hidden = !isConfigured( definition, element[ 'id' ], element.filebrowser );
     397                                }
    396398                        }
    397399                }
  • CKEditor/trunk/_source/plugins/find/dialogs/find.js

    r5570 r5812  
    66(function()
    77{
    8         function nonEmptyText( node )
     8        var isReplace;
     9
     10        function findEvaluator( node )
    911        {
    10                 return ( node.type == CKEDITOR.NODE_TEXT && node.getLength() > 0 );
     12                return node.type == CKEDITOR.NODE_TEXT && node.getLength() > 0 && ( !isReplace || !node.isReadOnly() );
    1113        }
    1214
     
    1416         * Elements which break characters been considered as sequence.
    1517        */
    16         function nonCharactersBoundary ( node )
     18        function nonCharactersBoundary( node )
    1719        {
    1820                return !( node.type == CKEDITOR.NODE_ELEMENT && node.isBlockBoundary(
     
    8587                                new CKEDITOR.dom.walker( range );
    8688                        walker.guard = matchWord ? nonCharactersBoundary : null;
    87                         walker[ 'evaluator' ] = nonEmptyText;
     89                        walker[ 'evaluator' ] = findEvaluator;
    8890                        walker.breakOnFalse = true;
    8991
     
    252254
    253255                                // Apply the highlight.
    254                                 var range = this.toDomRange();
     256                                var range = this.toDomRange(),
     257                                        bookmark = range.createBookmark();
    255258                                highlightStyle.applyToRange( range );
     259                                range.moveToBookmark( bookmark );
    256260                                this._.highlightRange = range;
    257261
     
    274278                                        return;
    275279
     280                                var bookmark = this._.highlightRange.createBookmark();
    276281                                highlightStyle.removeFromRange( this._.highlightRange );
     282                                this._.highlightRange.moveToBookmark( bookmark );
    277283                                this.updateFromDomRange( this._.highlightRange );
    278284                                this._.highlightRange = null;
     285                        },
     286
     287                        isReadOnly : function()
     288                        {
     289                                if ( !this._.highlightRange )
     290                                        return 0;
     291
     292                                return this._.highlightRange.startContainer.isReadOnly();
    279293                        },
    280294
     
    515529                                matchCyclic , isReplaceAll )
    516530                        {
     531                                isReplace = 1;
     532
    517533                                // Successiveness of current replace/find.
    518534                                var result = false;
     
    521537                                // 2. Otherwise perform the find but don't replace it immediately.
    522538                                if ( this.matchRange && this.matchRange.isMatched()
    523                                                 && !this.matchRange._.isReplaced )
     539                                                && !this.matchRange._.isReplaced && !this.matchRange.isReadOnly() )
    524540                                {
    525541                                        // Turn off highlight for a while when saving snapshots.
     
    551567                                        result = this.find( pattern, matchCase, matchWord, matchCyclic, !isReplaceAll );
    552568
     569                                isReplace = 0;
     570
    553571                                return result;
    554572                        }
  • CKEditor/trunk/_source/plugins/flash/dialogs/flash.js

    r5725 r5812  
    176176                var previewPreloader,
    177177                        previewAreaHtml = '<div>' + CKEDITOR.tools.htmlEncode( editor.lang.common.preview ) +'<br>' +
    178                         '<div id="FlashPreviewLoader' + CKEDITOR.tools.getNextNumber() + '" style="display:none"><div class="loading">&nbsp;</div></div>' +
    179                         '<div id="FlashPreviewBox' + CKEDITOR.tools.getNextNumber() + '" class="FlashPreviewBox"></div></div>';
     178                        '<div id="cke_FlashPreviewLoader' + CKEDITOR.tools.getNextNumber() + '" style="display:none"><div class="loading">&nbsp;</div></div>' +
     179                        '<div id="cke_FlashPreviewBox' + CKEDITOR.tools.getNextNumber() + '" class="FlashPreviewBox"></div></div>';
    180180
    181181                return {
  • CKEditor/trunk/_source/plugins/flash/plugin.js

    r5548 r5812  
    9191                                editor.contextMenu.addListener( function( element, selection )
    9292                                        {
    93                                                 if ( element && element.is( 'img' ) && element.getAttribute( '_cke_real_element_type' ) == 'flash' )
     93                                                if ( element && element.is( 'img' ) && !element.isReadOnly()
     94                                                                && element.getAttribute( '_cke_real_element_type' ) == 'flash' )
    9495                                                        return { flash : CKEDITOR.TRISTATE_OFF };
    9596                                        });
  • CKEditor/trunk/_source/plugins/forms/plugin.js

    r5637 r5812  
    132132                        editor.contextMenu.addListener( function( element )
    133133                                {
    134                                         if ( element && element.hasAscendant( 'form', true ) )
     134                                        if ( element && element.hasAscendant( 'form', true ) && !element.isReadOnly() )
    135135                                                return { form : CKEDITOR.TRISTATE_OFF };
    136136                                });
     
    138138                        editor.contextMenu.addListener( function( element )
    139139                                {
    140                                         if ( element )
     140                                        if ( element && !element.isReadOnly() )
    141141                                        {
    142142                                                var name = element.getName();
  • CKEditor/trunk/_source/plugins/image/dialogs/image.js

    r5679 r5812  
    251251                };
    252252
    253                 var numbering = function( id ){ return id + CKEDITOR.tools.getNextNumber(); },
     253                var numbering = function( id )
     254                        {
     255                                return CKEDITOR.tools.getNextId() + '_' + id;
     256                        },
    254257                        btnLockSizesId = numbering( 'btnLockSizes' ),
    255258                        btnResetSizeId = numbering( 'btnResetSize' ),
  • CKEditor/trunk/_source/plugins/image/plugin.js

    r5548 r5812  
    5454                        editor.contextMenu.addListener( function( element, selection )
    5555                                {
    56                                         if ( !element || !element.is( 'img' ) || element.getAttribute( '_cke_realelement' ) )
     56                                        if ( !element || !element.is( 'img' ) || element.getAttribute( '_cke_realelement' ) || element.isReadOnly() )
    5757                                                return null;
    5858
  • CKEditor/trunk/_source/plugins/indent/plugin.js

    r5714 r5812  
    5454                else
    5555                {
    56                         var indent = parseInt( firstBlock.getStyle( this.indentCssProperty ), 10 );
     56                        var indent = parseInt( firstBlock.getStyle( getIndentCssProperty( firstBlock ) ), 10 );
    5757                        if ( isNaN( indent ) )
    5858                                indent = 0;
     
    6262                }
    6363        }
    64 
    65         function indentList( editor, range, listNode )
    66         {
    67                 // Our starting and ending points of the range might be inside some blocks under a list item...
    68                 // So before playing with the iterator, we need to expand the block to include the list items.
    69                 var startContainer = range.startContainer,
    70                         endContainer = range.endContainer;
    71                 while ( startContainer && !startContainer.getParent().equals( listNode ) )
    72                         startContainer = startContainer.getParent();
    73                 while ( endContainer && !endContainer.getParent().equals( listNode ) )
    74                         endContainer = endContainer.getParent();
    75 
    76                 if ( !startContainer || !endContainer )
    77                         return;
    78 
    79                 // Now we can iterate over the individual items on the same tree depth.
    80                 var block = startContainer,
    81                         itemsToMove = [],
    82                         stopFlag = false;
    83                 while ( !stopFlag )
    84                 {
    85                         if ( block.equals( endContainer ) )
    86                                 stopFlag = true;
    87                         itemsToMove.push( block );
    88                         block = block.getNext();
    89                 }
    90                 if ( itemsToMove.length < 1 )
    91                         return;
    92 
    93                 // Do indent or outdent operations on the array model of the list, not the
    94                 // list's DOM tree itself. The array model demands that it knows as much as
    95                 // possible about the surrounding lists, we need to feed it the further
    96                 // ancestor node that is still a list.
    97                 var listParents = listNode.getParents( true );
    98                 for ( var i = 0 ; i < listParents.length ; i++ )
    99                 {
    100                         if ( listParents[i].getName && listNodeNames[ listParents[i].getName() ] )
    101                         {
    102                                 listNode = listParents[i];
    103                                 break;
    104                         }
    105                 }
    106                 var indentOffset = this.name == 'indent' ? 1 : -1,
    107                         startItem = itemsToMove[0],
    108                         lastItem = itemsToMove[ itemsToMove.length - 1 ],
    109                         database = {};
    110 
    111                 // Convert the list DOM tree into a one dimensional array.
    112                 var listArray = CKEDITOR.plugins.list.listToArray( listNode, database );
    113 
    114                 // Apply indenting or outdenting on the array.
    115                 var baseIndent = listArray[ lastItem.getCustomData( 'listarray_index' ) ].indent;
    116                 for ( i = startItem.getCustomData( 'listarray_index' ); i <= lastItem.getCustomData( 'listarray_index' ); i++ )
    117                 {
    118                         listArray[ i ].indent += indentOffset;
    119                         // Make sure the newly created sublist get a brand-new element of the same type. (#5372)
    120                         var listRoot = listArray[ i ].parent;
    121                         listArray[ i ].parent = new CKEDITOR.dom.element( listRoot.getName(), listRoot.getDocument() );
    122                 }
    123 
    124                 for ( i = lastItem.getCustomData( 'listarray_index' ) + 1 ;
    125                                 i < listArray.length && listArray[i].indent > baseIndent ; i++ )
    126                         listArray[i].indent += indentOffset;
    127 
    128                 // Convert the array back to a DOM forest (yes we might have a few subtrees now).
    129                 // And replace the old list with the new forest.
    130                 var newList = CKEDITOR.plugins.list.arrayToList( listArray, database, null, editor.config.enterMode, 0 );
    131 
    132                 // Avoid nested <li> after outdent even they're visually same,
    133                 // recording them for later refactoring.(#3982)
    134                 if ( this.name == 'outdent' )
    135                 {
    136                         var parentLiElement;
    137                         if ( ( parentLiElement = listNode.getParent() ) && parentLiElement.is( 'li' ) )
    138                         {
    139                                 var children = newList.listNode.getChildren(),
    140                                         pendingLis = [],
    141                                         count = children.count(),
    142                                         child;
    143 
    144                                 for ( i = count - 1 ; i >= 0 ; i-- )
    145                                 {
    146                                         if ( ( child = children.getItem( i ) ) && child.is && child.is( 'li' )  )
    147                                                 pendingLis.push( child );
    148                                 }
    149                         }
    150                 }
    151 
    152                 if ( newList )
    153                         newList.listNode.replace( listNode );
    154 
    155                 // Move the nested <li> to be appeared after the parent.
    156                 if ( pendingLis && pendingLis.length )
    157                 {
    158                         for (  i = 0; i < pendingLis.length ; i++ )
    159                         {
    160                                 var li = pendingLis[ i ],
    161                                         followingList = li;
    162 
    163                                 // Nest preceding <ul>/<ol> inside current <li> if any.
    164                                 while ( ( followingList = followingList.getNext() ) &&
    165                                            followingList.is &&
    166                                            followingList.getName() in listNodeNames )
    167                                 {
    168                                         // IE requires a filler NBSP for nested list inside empty list item,
    169                                         // otherwise the list item will be inaccessiable. (#4476)
    170                                         if ( CKEDITOR.env.ie && !li.getFirst( function( node ){ return isNotWhitespaces( node ) && isNotBookmark( node ); } ) )
    171                                                 li.append( range.document.createText( '\u00a0' ) );
    172 
    173                                         li.append( followingList );
    174                                 }
    175 
    176                                 li.insertAfter( parentLiElement );
    177                         }
    178                 }
    179 
    180                 // Clean up the markers.
    181                 CKEDITOR.dom.element.clearAllMarkers( database );
    182         }
    183 
    184         function indentBlock( editor, range )
    185         {
    186                 var iterator = range.createIterator(),
    187                         enterMode = editor.config.enterMode;
    188                 iterator.enforceRealBlocks = true;
    189                 iterator.enlargeBr = enterMode != CKEDITOR.ENTER_BR;
    190                 var block;
    191                 while ( ( block = iterator.getNextParagraph() ) )
    192                         indentElement.call( this, editor, block );
    193         }
    194 
    195         function indentElement( editor, element )
    196                 {
    197                         if ( this.useIndentClasses )
    198                         {
    199                                 // Transform current class name to indent step index.
    200                         var indentClass = element.$.className.match( this.classNameRegex ),
    201                                         indentStep = 0;
    202                                 if ( indentClass )
    203                                 {
    204                                         indentClass = indentClass[1];
    205                                         indentStep = this.indentClassMap[ indentClass ];
    206                                 }
    207 
    208                                 // Operate on indent step index, transform indent step index back to class
    209                                 // name.
    210                                 if ( this.name == 'outdent' )
    211                                         indentStep--;
    212                                 else
    213                                         indentStep++;
    214 
    215                         if ( indentStep < 0 )
    216                                 return false;
    217 
    218                                 indentStep = Math.min( indentStep, editor.config.indentClasses.length );
    219                                 indentStep = Math.max( indentStep, 0 );
    220                         var className = CKEDITOR.tools.ltrim( element.$.className.replace( this.classNameRegex, '' ) );
    221                                 if ( indentStep < 1 )
    222                                 element.$.className = className;
    223                                 else
    224                                 element.addClass( editor.config.indentClasses[ indentStep - 1 ] );
    225                         }
    226                         else
    227                         {
    228                         var currentOffset = parseInt( element.getStyle( this.indentCssProperty ), 10 );
    229                                 if ( isNaN( currentOffset ) )
    230                                         currentOffset = 0;
    231                                 currentOffset += ( this.name == 'indent' ? 1 : -1 ) * editor.config.indentOffset;
    232 
    233                         if ( currentOffset < 0 )
    234                                 return false;
    235 
    236                                 currentOffset = Math.max( currentOffset, 0 );
    237                                 currentOffset = Math.ceil( currentOffset / editor.config.indentOffset ) * editor.config.indentOffset;
    238                         element.setStyle( this.indentCssProperty, currentOffset ? currentOffset + editor.config.indentUnit : '' );
    239                         if ( element.getAttribute( 'style' ) === '' )
    240                                 element.removeAttribute( 'style' );
    241                         }
    242 
    243                 return true;
    244                 }
    24564
    24665        function indentCommand( editor, name )
     
    25574                                this.indentClassMap[ editor.config.indentClasses[i] ] = i + 1;
    25675                }
    257                 else
    258                         this.indentCssProperty = editor.config.contentsLangDirection == 'ltr' ? 'margin-left' : 'margin-right';
     76
    25977                this.startDisabled = name == 'outdent';
     78        }
     79
     80        // Returns the CSS property to be used for identing a given element.
     81        function getIndentCssProperty( element )
     82        {
     83                return element.getComputedStyle( 'direction' ) == 'ltr' ? 'margin-left' : 'margin-right';
    26084        }
    26185
     
    26892                exec : function( editor )
    26993                {
     94                        var self = this, database = {};
     95
     96                        function indentList( listNode )
     97                        {
     98                                // Our starting and ending points of the range might be inside some blocks under a list item...
     99                                // So before playing with the iterator, we need to expand the block to include the list items.
     100                                var startContainer = range.startContainer,
     101                                        endContainer = range.endContainer;
     102                                while ( startContainer && !startContainer.getParent().equals( listNode ) )
     103                                        startContainer = startContainer.getParent();
     104                                while ( endContainer && !endContainer.getParent().equals( listNode ) )
     105                                        endContainer = endContainer.getParent();
     106
     107                                if ( !startContainer || !endContainer )
     108                                        return;
     109
     110                                // Now we can iterate over the individual items on the same tree depth.
     111                                var block = startContainer,
     112                                        itemsToMove = [],
     113                                        stopFlag = false;
     114                                while ( !stopFlag )
     115                                {
     116                                        if ( block.equals( endContainer ) )
     117                                                stopFlag = true;
     118                                        itemsToMove.push( block );
     119                                        block = block.getNext();
     120                                }
     121                                if ( itemsToMove.length < 1 )
     122                                        return;
     123
     124                                // Do indent or outdent operations on the array model of the list, not the
     125                                // list's DOM tree itself. The array model demands that it knows as much as
     126                                // possible about the surrounding lists, we need to feed it the further
     127                                // ancestor node that is still a list.
     128                                var listParents = listNode.getParents( true );
     129                                for ( var i = 0 ; i < listParents.length ; i++ )
     130                                {
     131                                        if ( listParents[i].getName && listNodeNames[ listParents[i].getName() ] )
     132                                        {
     133                                                listNode = listParents[i];
     134                                                break;
     135                                        }
     136                                }
     137                                var indentOffset = self.name == 'indent' ? 1 : -1,
     138                                        startItem = itemsToMove[0],
     139                                        lastItem = itemsToMove[ itemsToMove.length - 1 ];
     140
     141                                // Convert the list DOM tree into a one dimensional array.
     142                                var listArray = CKEDITOR.plugins.list.listToArray( listNode, database );
     143
     144                                // Apply indenting or outdenting on the array.
     145                                var baseIndent = listArray[ lastItem.getCustomData( 'listarray_index' ) ].indent;
     146                                for ( i = startItem.getCustomData( 'listarray_index' ); i <= lastItem.getCustomData( 'listarray_index' ); i++ )
     147                                {
     148                                        listArray[ i ].indent += indentOffset;
     149                                        // Make sure the newly created sublist get a brand-new element of the same type. (#5372)
     150                                        var listRoot = listArray[ i ].parent;
     151                                        listArray[ i ].parent = new CKEDITOR.dom.element( listRoot.getName(), listRoot.getDocument() );
     152                                }
     153
     154                                for ( i = lastItem.getCustomData( 'listarray_index' ) + 1 ;
     155                                                i < listArray.length && listArray[i].indent > baseIndent ; i++ )
     156                                        listArray[i].indent += indentOffset;
     157
     158                                // Convert the array back to a DOM forest (yes we might have a few subtrees now).
     159                                // And replace the old list with the new forest.
     160                                var newList = CKEDITOR.plugins.list.arrayToList( listArray, database, null, editor.config.enterMode, 0 );
     161
     162                                // Avoid nested <li> after outdent even they're visually same,
     163                                // recording them for later refactoring.(#3982)
     164                                if ( self.name == 'outdent' )
     165                                {
     166                                        var parentLiElement;
     167                                        if ( ( parentLiElement = listNode.getParent() ) && parentLiElement.is( 'li' ) )
     168                                        {
     169                                                var children = newList.listNode.getChildren(),
     170                                                        pendingLis = [],
     171                                                        count = children.count(),
     172                                                        child;
     173
     174                                                for ( i = count - 1 ; i >= 0 ; i-- )
     175                                                {
     176                                                        if ( ( child = children.getItem( i ) ) && child.is && child.is( 'li' )  )
     177                                                                pendingLis.push( child );
     178                                                }
     179                                        }
     180                                }
     181
     182                                if ( newList )
     183                                        newList.listNode.replace( listNode );
     184
     185                                // Move the nested <li> to be appeared after the parent.
     186                                if ( pendingLis && pendingLis.length )
     187                                {
     188                                        for (  i = 0; i < pendingLis.length ; i++ )
     189                                        {
     190                                                var li = pendingLis[ i ],
     191                                                        followingList = li;
     192
     193                                                // Nest preceding <ul>/<ol> inside current <li> if any.
     194                                                while ( ( followingList = followingList.getNext() ) &&
     195                                                           followingList.is &&
     196                                                           followingList.getName() in listNodeNames )
     197                                                {
     198                                                        // IE requires a filler NBSP for nested list inside empty list item,
     199                                                        // otherwise the list item will be inaccessiable. (#4476)
     200                                                        if ( CKEDITOR.env.ie && !li.getFirst( function( node ){ return isNotWhitespaces( node ) && isNotBookmark( node ); } ) )
     201                                                                li.append( range.document.createText( '\u00a0' ) );
     202
     203                                                        li.append( followingList );
     204                                                }
     205
     206                                                li.insertAfter( parentLiElement );
     207                                        }
     208                                }
     209                        }
     210
     211                        function indentBlock()
     212                        {
     213                                var iterator = range.createIterator(),
     214                                        enterMode = editor.config.enterMode;
     215                                iterator.enforceRealBlocks = true;
     216                                iterator.enlargeBr = enterMode != CKEDITOR.ENTER_BR;
     217                                var block;
     218                                while ( ( block = iterator.getNextParagraph() ) )
     219                                        indentElement( block );
     220                        }
     221
     222                        function indentElement( element )
     223                        {
     224                                if ( element.getCustomData( 'indent_processed' ) )
     225                                        return false;
     226
     227                                if ( self.useIndentClasses )
     228                                {
     229                                        // Transform current class name to indent step index.
     230                                        var indentClass = element.$.className.match( self.classNameRegex ),
     231                                                        indentStep = 0;
     232                                        if ( indentClass )
     233                                        {
     234                                                indentClass = indentClass[1];
     235                                                indentStep = self.indentClassMap[ indentClass ];
     236                                        }
     237
     238                                        // Operate on indent step index, transform indent step index back to class
     239                                        // name.
     240                                        if ( self.name == 'outdent' )
     241                                                indentStep--;
     242                                        else
     243                                                indentStep++;
     244
     245                                        if ( indentStep < 0 )
     246                                                return false;
     247
     248                                        indentStep = Math.min( indentStep, editor.config.indentClasses.length );
     249                                        indentStep = Math.max( indentStep, 0 );
     250                                        var className = CKEDITOR.tools.ltrim( element.$.className.replace( self.classNameRegex, '' ) );
     251                                        if ( indentStep < 1 )
     252                                                element.$.className = className;
     253                                        else
     254                                                element.addClass( editor.config.indentClasses[ indentStep - 1 ] );
     255                                }
     256                                else
     257                                {
     258                                        var indentCssProperty = getIndentCssProperty( element );
     259                                        var currentOffset = parseInt( element.getStyle( indentCssProperty ), 10 );
     260                                        if ( isNaN( currentOffset ) )
     261                                                currentOffset = 0;
     262                                        currentOffset += ( self.name == 'indent' ? 1 : -1 ) * editor.config.indentOffset;
     263
     264                                        if ( currentOffset < 0 )
     265                                                return false;
     266
     267                                        currentOffset = Math.max( currentOffset, 0 );
     268                                        currentOffset = Math.ceil( currentOffset / editor.config.indentOffset ) * editor.config.indentOffset;
     269                                        element.setStyle( indentCssProperty, currentOffset ? currentOffset + editor.config.indentUnit : '' );
     270                                        if ( element.getAttribute( 'style' ) === '' )
     271                                                element.removeAttribute( 'style' );
     272                                }
     273
     274                                CKEDITOR.dom.element.setMarker( database, element, 'indent_processed', true );
     275                                return true;
     276                        }
     277
    270278                        var selection = editor.getSelection(),
    271                                 range = selection && selection.getRanges()[0];
    272 
    273                         var startContainer = range.startContainer,
    274                                 endContainer = range.endContainer,
    275                                 rangeRoot = range.getCommonAncestor(),
    276                                 nearestListBlock = rangeRoot;
    277 
    278                         while ( nearestListBlock && !( nearestListBlock.type == CKEDITOR.NODE_ELEMENT &&
    279                                 listNodeNames[ nearestListBlock.getName() ] ) )
    280                                 nearestListBlock = nearestListBlock.getParent();
    281 
    282                         // Avoid selection anchors under list root.
    283                         // <ul>[<li>...</li>]</ul> =>   <ul><li>[...]</li></ul>
    284                         if ( nearestListBlock && startContainer.type == CKEDITOR.NODE_ELEMENT
    285                                 && startContainer.getName() in listNodeNames )
    286                         {
    287                                 var walker = new CKEDITOR.dom.walker( range );
    288                                 walker.evaluator = isListItem;
    289                                 range.startContainer = walker.next();
    290                         }
    291 
    292                         if ( nearestListBlock && endContainer.type == CKEDITOR.NODE_ELEMENT
    293                                 && endContainer.getName() in listNodeNames )
    294                         {
    295                                 walker = new CKEDITOR.dom.walker( range );
    296                                 walker.evaluator = isListItem;
    297                                 range.endContainer = walker.previous();
    298                         }
    299 
    300                         var bookmarks = selection.createBookmarks( true );
    301 
    302                         if ( nearestListBlock  )
    303                         {
    304                                 var firstListItem = nearestListBlock.getFirst( function( node )
    305                                         {
    306                                                 return node.type == CKEDITOR.NODE_ELEMENT && node.is( 'li' );
    307                                         }),
    308                                         rangeStart = range.startContainer,
    309                                         indentWholeList = firstListItem.equals( rangeStart ) || firstListItem.contains( rangeStart );
    310 
    311                                 // Indent the entire list if  cursor is inside the first list item. (#3893)
    312                                 if ( !( indentWholeList && indentElement.call( this, editor, nearestListBlock ) ) )
    313                                 indentList.call( this, editor, range, nearestListBlock );
    314                         }
    315                         else
    316                                 indentBlock.call( this, editor, range );
    317 
    318                         editor.focus();
     279                                bookmarks = selection.createBookmarks( true ),
     280                                ranges = selection && selection.getRanges( true ),
     281                                range;
     282
     283                        var iterator = ranges.createIterator();
     284                        while ( ( range = iterator.getNextRange() ) )
     285                        {
     286                                var startContainer = range.startContainer,
     287                                        endContainer = range.endContainer,
     288                                        rangeRoot = range.getCommonAncestor(),
     289                                        nearestListBlock = rangeRoot;
     290
     291                                while ( nearestListBlock && !( nearestListBlock.type == CKEDITOR.NODE_ELEMENT &&
     292                                        listNodeNames[ nearestListBlock.getName() ] ) )
     293                                        nearestListBlock = nearestListBlock.getParent();
     294
     295                                // Avoid selection anchors under list root.
     296                                // <ul>[<li>...</li>]</ul> =>   <ul><li>[...]</li></ul>
     297                                if ( nearestListBlock && startContainer.type == CKEDITOR.NODE_ELEMENT
     298                                        && startContainer.getName() in listNodeNames )
     299                                {
     300                                        var walker = new CKEDITOR.dom.walker( range );
     301                                        walker.evaluator = isListItem;
     302                                        range.startContainer = walker.next();
     303                                }
     304
     305                                if ( nearestListBlock && endContainer.type == CKEDITOR.NODE_ELEMENT
     306                                        && endContainer.getName() in listNodeNames )
     307                                {
     308                                        walker = new CKEDITOR.dom.walker( range );
     309                                        walker.evaluator = isListItem;
     310                                        range.endContainer = walker.previous();
     311                                }
     312
     313                                if ( nearestListBlock  )
     314                                {
     315                                        var firstListItem = nearestListBlock.getFirst( function( node )
     316                                                {
     317                                                        return node.type == CKEDITOR.NODE_ELEMENT && node.is( 'li' );
     318                                                }),
     319                                                rangeStart = range.startContainer,
     320                                                indentWholeList = firstListItem.equals( rangeStart ) || firstListItem.contains( rangeStart );
     321
     322                                        // Indent the entire list if  cursor is inside the first list item. (#3893)
     323                                        if ( !( indentWholeList && indentElement( nearestListBlock ) ) )
     324                                                indentList( nearestListBlock );
     325                                }
     326                                else
     327                                        indentBlock();
     328                        }
     329
     330                        // Clean up the markers.
     331                        CKEDITOR.dom.element.clearAllMarkers( database );
     332
    319333                        editor.forceNextSelectionCheck();
    320334                        selection.selectBookmarks( bookmarks );
  • CKEditor/trunk/_source/plugins/justify/plugin.js

    r5206 r5812  
    1010(function()
    1111{
    12         var alignRemoveRegex = /(-moz-|-webkit-|start|auto)/i;
    13 
    1412        function getState( editor, path )
    1513        {
     
    1917                        return CKEDITOR.TRISTATE_OFF;
    2018
    21                 var currentAlign = firstBlock.getComputedStyle( 'text-align' ).replace( alignRemoveRegex, '' );
    22                 if ( ( !currentAlign && this.isDefaultAlign ) || currentAlign == this.value )
    23                         return CKEDITOR.TRISTATE_ON;
    24                 return CKEDITOR.TRISTATE_OFF;
     19                return ( getAlignment( firstBlock, editor.config.useComputedState ) == this.value ) ?
     20                        CKEDITOR.TRISTATE_ON :
     21                        CKEDITOR.TRISTATE_OFF;
     22        }
     23
     24        function getAlignment( element, useComputedState )
     25        {
     26                useComputedState = useComputedState === undefined || useComputedState;
     27
     28                var align = useComputedState ?
     29                        element.getComputedStyle( 'text-align' ) :
     30                        element.getStyle( 'text-align' ) || element.getAttribute( 'align' ) || '';
     31
     32                align && ( align = align.replace( /-moz-|-webkit-|start|auto/i, '' ) );
     33
     34                !align && useComputedState && ( align = element.getComputedStyle( 'direction' ) == 'rtl' ? 'right' : 'left' );
     35
     36                return align;
    2537        }
    2638
     
    3648                this.name = name;
    3749                this.value = value;
    38 
    39                 var contentDir = editor.config.contentsLangDirection;
    40                 this.isDefaultAlign = ( value == 'left' && contentDir == 'ltr' ) ||
    41                         ( value == 'right' && contentDir == 'rtl' );
    4250
    4351                var classes = editor.config.justifyClasses;
     
    7482
    7583                        var bookmarks = selection.createBookmarks(),
    76                                 ranges = selection.getRanges();
    77 
     84                                ranges = selection.getRanges( true );
    7885
    7986                        var cssClassName = this.cssClassName,
    8087                                iterator,
    8188                                block;
     89
     90                        var useComputedState = editor.config.useComputedState;
     91                        useComputedState = useComputedState === undefined || useComputedState;
     92
    8293                        for ( var i = ranges.length - 1 ; i >= 0 ; i-- )
    8394                        {
     
    8899                                {
    89100                                        block.removeAttribute( 'align' );
     101                                        block.removeStyle( 'text-align' );
     102
     103                                        // Remove any of the alignment classes from the className.
     104                                        var className = cssClassName && ( block.$.className =
     105                                                CKEDITOR.tools.ltrim( block.$.className.replace( this.cssClassRegex, '' ) ) );
     106
     107                                        var apply =
     108                                                ( this.state == CKEDITOR.TRISTATE_OFF ) &&
     109                                                ( !useComputedState || ( getAlignment( block, true ) != this.value ) );
    90110
    91111                                        if ( cssClassName )
    92112                                        {
    93                                                 // Remove any of the alignment classes from the className.
    94                                                 var className = block.$.className =
    95                                                         CKEDITOR.tools.ltrim( block.$.className.replace( this.cssClassRegex, '' ) );
    96 
    97113                                                // Append the desired class name.
    98                                                 if ( this.state == CKEDITOR.TRISTATE_OFF && !this.isDefaultAlign )
     114                                                if ( apply )
    99115                                                        block.addClass( cssClassName );
    100116                                                else if ( !className )
    101117                                                        block.removeAttribute( 'class' );
    102118                                        }
    103                                         else
    104                                         {
    105                                                 if ( this.state == CKEDITOR.TRISTATE_OFF && !this.isDefaultAlign )
    106                                                         block.setStyle( 'text-align', this.value );
    107                                                 else
    108                                                         block.removeStyle( 'text-align' );
    109                                         }
     119                                        else if ( apply )
     120                                                block.setStyle( 'text-align', this.value );
    110121                                }
    111122
  • CKEditor/trunk/_source/plugins/link/dialogs/link.js

    r5662 r5812  
    12951295                                // Create element if current selection is collapsed.
    12961296                                var selection = editor.getSelection(),
    1297                                         ranges = selection.getRanges();
     1297                                        ranges = selection.getRanges( true );
    12981298                                if ( ranges.length == 1 && ranges[0].collapsed )
    12991299                                {
  • CKEditor/trunk/_source/plugins/link/plugin.js

    r5637 r5812  
    5959                                 */
    6060                                var command = editor.getCommand( 'unlink' ),
    61                                         element = evt.data.path.lastElement.getAscendant( 'a', true );
     61                                        element = evt.data.path.lastElement && evt.data.path.lastElement.getAscendant( 'a', true );
    6262                                if ( element && element.getName() == 'a' && element.getAttribute( 'href' ) )
    6363                                        command.setState( CKEDITOR.TRISTATE_OFF );
     
    111111                        editor.contextMenu.addListener( function( element, selection )
    112112                                {
    113                                         if ( !element )
     113                                        if ( !element || element.isReadOnly() )
    114114                                                return null;
    115115
     
    178178        {
    179179                var range;
    180                 try { range  = editor.getSelection().getRanges()[ 0 ]; }
     180                try
     181                {
     182                        range  = editor.getSelection().getRanges( true )[ 0 ];
     183                        range.shrink( CKEDITOR.SHRINK_TEXT );
     184                        var root = range.getCommonAncestor();
     185                        return root.getAscendant( 'a', true );
     186                }
    181187                catch( e ) { return null; }
    182 
    183                 range.shrink( CKEDITOR.SHRINK_TEXT );
    184                 var root = range.getCommonAncestor();
    185                 return root.getAscendant( 'a', true );
    186188        }
    187189};
  • CKEditor/trunk/_source/plugins/list/plugin.js

    r5771 r5812  
    6868
    6969                // Convert our internal representation of a list back to a DOM forest.
    70                 arrayToList : function( listArray, database, baseIndex, paragraphMode )
     70                arrayToList : function( listArray, database, baseIndex, paragraphMode, dir )
    7171                {
    7272                        if ( !baseIndex )
     
    110110                                        {
    111111                                                // Create completely new blocks here, attributes are dropped.
    112                                                 if ( paragraphMode != CKEDITOR.ENTER_BR && item.grandparent.getName() != 'td' )
     112                                                if ( dir || ( paragraphMode != CKEDITOR.ENTER_BR && item.grandparent.getName() != 'td' ) )
     113                                                {
    113114                                                        currentListItem = doc.createElement( paragraphName );
     115                                                        if ( dir )
     116                                                                currentListItem.setAttribute( 'dir', dir );
     117                                                }
    114118                                                else
    115119                                                        currentListItem = new CKEDITOR.dom.documentFragment( doc );
     
    287291                // Insert the list to the DOM tree.
    288292                var insertAnchor = listContents[ listContents.length - 1 ].getNext(),
    289                         listNode = doc.createElement( this.type );
     293                        listNode = doc.createElement( this.type ),
     294                        dir;
    290295
    291296                listsCreated.push( listNode );
     
    300305                        else
    301306                        {
     307                                if ( contentBlock.hasAttribute( 'dir' ) )
     308                                {
     309                                        dir = dir || contentBlock.getAttribute( 'dir' );
     310                                        contentBlock.removeAttribute( 'dir' );
     311                                }
    302312                                contentBlock.copyAttributes( listItem );
    303313                                contentBlock.moveChildren( listItem );
     
    311321                                listItem.appendBogus();
    312322                }
     323
     324                if ( dir )
     325                        listNode.setAttribute( 'dir', dir );
     326
    313327                if ( insertAnchor )
    314328                        listNode.insertBefore( insertAnchor );
     
    360374                }
    361375
    362                 var newList = CKEDITOR.plugins.list.arrayToList( listArray, database, null, editor.config.enterMode );
     376                var newList = CKEDITOR.plugins.list.arrayToList( listArray, database, null, editor.config.enterMode,
     377                        groupObj.root.getAttribute( 'dir' ) );
    363378
    364379                // Compensate <br> before/after the list node if the surrounds are non-blocks.(#3836)
     
    392407                        var doc = editor.document,
    393408                                selection = editor.getSelection(),
    394                                 ranges = selection && selection.getRanges();
     409                                ranges = selection && selection.getRanges( true );
    395410
    396411                        // There should be at least one selected range.
     
    440455                        // or multiple lists have to be cancelled.
    441456                        var listGroups = [],
    442                                 database = {};
    443 
    444                         while ( ranges.length > 0 )
    445                         {
    446                                 range = ranges.shift();
     457                                database = {},
     458                                rangeIterator = ranges.createIterator(),
     459                                index = 0;
     460
     461                        while ( ( range = rangeIterator.getNextRange() ) && ++index )
     462                        {
     463                                var boundaryNodes = range.getBoundaryNodes(),
     464                                        startNode = boundaryNodes.startNode,
     465                                        endNode = boundaryNodes.endNode;
     466
     467                                if ( startNode.type == CKEDITOR.NODE_ELEMENT && startNode.getName() == 'td' )
     468                                        range.setStartAt( boundaryNodes.startNode, CKEDITOR.POSITION_AFTER_START );
     469
     470                                if ( endNode.type == CKEDITOR.NODE_ELEMENT && endNode.getName() == 'td' )
     471                                        range.setEndAt( boundaryNodes.endNode, CKEDITOR.POSITION_BEFORE_END );
     472
    447473                                var iterator = range.createIterator(),
    448474                                        block;
     
    452478                                while ( ( block = iterator.getNextParagraph() ) )
    453479                                {
     480                                        // Avoid duplicate blocks get processed across ranges.
     481                                        if( block.getCustomData( 'list_block' ) )
     482                                                continue;
     483                                        else
     484                                                CKEDITOR.dom.element.setMarker( database, block, 'list_block', 1 );
     485
    454486                                        var path = new CKEDITOR.dom.elementPath( block ),
    455487                                                pathElements = path.elements,
     
    471503                                                        // should belong to a different group of paragraphs before
    472504                                                        // the list. (Bug #1309)
    473                                                         blockLimit.removeCustomData( 'list_group_object' );
     505                                                        blockLimit.removeCustomData( 'list_group_object_' + index );
    474506
    475507                                                        var groupObj = element.getCustomData( 'list_group_object' );
     
    490522                                                continue;
    491523
    492                                         // No list ancestor? Group by block limit.
     524                                        // No list ancestor? Group by block limit, but don't mix contents from different ranges.
    493525                                        var root = blockLimit;
    494                                         if ( root.getCustomData( 'list_group_object' ) )
    495                                                 root.getCustomData( 'list_group_object' ).contents.push( block );
     526                                        if ( root.getCustomData( 'list_group_object_' + index ) )
     527                                                root.getCustomData( 'list_group_object_' + index ).contents.push( block );
    496528                                        else
    497529                                        {
    498530                                                groupObj = { root : root, contents : [ block ] };
    499                                                 CKEDITOR.dom.element.setMarker( database, root, 'list_group_object', groupObj );
     531                                                CKEDITOR.dom.element.setMarker( database, root, 'list_group_object_' + index, groupObj );
    500532                                                listGroups.push( groupObj );
    501533                                        }
     
    531563                                                'getPrevious' : 'getNext' ]( CKEDITOR.dom.walker.whitespaces( true ) );
    532564                                        if ( sibling && sibling.getName &&
    533                                             sibling.getName() == listCommand.type )
     565                                                sibling.getName() == listCommand.type )
    534566                                        {
    535567                                                sibling.remove();
  • CKEditor/trunk/_source/plugins/liststyle/plugin.js

    r5794 r5812  
    4444                                editor.contextMenu.addListener( function( element, selection )
    4545                                        {
     46                                                if ( !element || element.isReadOnly() )
     47                                                        return null;
     48
    4649                                                while ( element )
    4750                                                {
  • CKEditor/trunk/_source/plugins/pagebreak/plugin.js

    r5791 r5812  
    8383                breakObject = editor.createFakeElement( breakObject, 'cke_pagebreak', 'div' );
    8484
    85                 var ranges = editor.getSelection().getRanges();
     85                var ranges = editor.getSelection().getRanges( true );
    8686
    8787                editor.fire( 'saveSnapshot' );
    8888
    89                 for ( var range, i = 0 ; i < ranges.length ; i++ )
     89                for ( var range, i = ranges.length - 1 ; i >= 0; i-- )
    9090                {
    9191                        range = ranges[ i ];
    9292
    93                         if ( i > 0 )
     93                        if ( i < ranges.length -1 )
    9494                                breakObject = breakObject.clone( true );
    9595
  • CKEditor/trunk/_source/plugins/removeformat/plugin.js

    r5727 r5812  
    3636
    3737                                var filter = CKEDITOR.plugins.removeformat.filter;
    38                                 var ranges = editor.getSelection().getRanges();
     38                                var ranges = editor.getSelection().getRanges( true ),
     39                                        iterator = ranges.createIterator(),
     40                                        range;
    3941
    40                                 for ( var i = 0, range ; range = ranges[ i ] ; i++ )
     42                                while ( ( range = iterator.getNextRange() ) )
    4143                                {
    4244                                        if ( range.collapsed )
  • CKEditor/trunk/_source/plugins/scayt/plugin.js

    r5714 r5812  
    625625                        if ( editor.contextMenu && editor.addMenuItems )
    626626                        {
    627                                 editor.contextMenu.addListener( function(  )
    628                                         {
    629                                                 if ( !plugin.isScaytEnabled( editor ) )
     627                                editor.contextMenu.addListener( function( element, selection )
     628                                        {
     629                                                if ( !plugin.isScaytEnabled( editor )
     630                                                                || selection.getCommonAncestor().isReadOnly() )
    630631                                                        return null;
    631632
  • CKEditor/trunk/_source/plugins/selection/plugin.js

    r5799 r5812  
    526526                 * alert(ranges.length);
    527527                 */
    528                 getRanges :
    529                         CKEDITOR.env.ie ?
     528                getRanges : (function ()
     529                {
     530                        var func = CKEDITOR.env.ie ?
    530531                                ( function()
    531532                                {
     
    615616                                        return function()
    616617                                        {
    617                                                 var cache = this._.cache;
    618                                                 if ( cache.ranges )
    619                                                         return cache.ranges;
    620 
    621618                                                // IE doesn't have range support (in the W3C way), so we
    622619                                                // need to do some magic to transform selections into
     
    641638                                                        range.setEnd( new CKEDITOR.dom.node( boundaryInfo.container ), boundaryInfo.offset );
    642639
    643                                                         return ( cache.ranges = [ range ] );
     640                                                        return [ range ];
    644641                                                }
    645642                                                else if ( type == CKEDITOR.SELECTION_ELEMENT )
    646643                                                {
    647                                                         var retval = this._.cache.ranges = [];
     644                                                        var retval = [];
    648645
    649646                                                        for ( var i = 0 ; i < nativeRange.length ; i++ )
     
    666663                                                }
    667664
    668                                                 return ( cache.ranges = [] );
     665                                                return [];
    669666                                        };
    670667                                })()
     
    672669                                function()
    673670                                {
    674                                         var cache = this._.cache;
    675                                         if ( cache.ranges )
    676                                                 return cache.ranges;
    677671
    678672                                        // On browsers implementing the W3C range, we simply
     
    695689                                                ranges.push( range );
    696690                                        }
    697 
    698                                         return ( cache.ranges = ranges );
    699                                 },
     691                                        return ranges;
     692                                };
     693
     694                        return function( onlyEditables )
     695                        {
     696                                var cache = this._.cache;
     697                                if ( cache.ranges && !onlyEditables )
     698                                        return cache.ranges;
     699                                else if ( !cache.ranges )
     700                                        cache.ranges = new CKEDITOR.dom.rangeList( func.call( this ) );
     701
     702                                // Split range into multiple by read-only nodes.
     703                                if ( onlyEditables )
     704                                {
     705                                        var ranges = cache.ranges;
     706                                        for ( var i = 0; i < ranges.length; i++ )
     707                                        {
     708                                                var range = ranges[ i ];
     709
     710                                                // Drop range spans inside one ready-only node.
     711                                                var parent = range.getCommonAncestor();
     712                                                if ( parent.isReadOnly())
     713                                                        ranges.splice( i, 1 );
     714
     715                                                if ( range.collapsed )
     716                                                        continue;
     717
     718                                                var startContainer = range.startContainer,
     719                                                        endContainer = range.endContainer,
     720                                                        startOffset = range.startOffset,
     721                                                        endOffset = range.endOffset,
     722                                                        walkerRange = range.clone();
     723
     724                                                // Range may start inside a non-editable element, restart range
     725                                                // by the end of it.
     726                                                var readOnly;
     727                                                if ( ( readOnly = startContainer.isReadOnly() ) )
     728                                                        range.setStartAfter( readOnly );
     729
     730                                                // Enlarge range start/end with text node to avoid walker
     731                                                // being DOM destructive, it doesn't interfere our checking
     732                                                // of elements below as well.
     733                                                if ( startContainer && startContainer.type == CKEDITOR.NODE_TEXT )
     734                                                {
     735                                                        if ( startOffset >= startContainer.getLength() )
     736                                                                walkerRange.setStartAfter( startContainer );
     737                                                        else
     738                                                                walkerRange.setStartBefore( startContainer );
     739                                                }
     740
     741                                                if ( endContainer && endContainer.type == CKEDITOR.NODE_TEXT )
     742                                                {
     743                                                        if ( !endOffset )
     744                                                                walkerRange.setEndBefore( endContainer );
     745                                                        else
     746                                                                walkerRange.setEndAfter( endContainer );
     747                                                }
     748
     749                                                // Looking for non-editable element inside the range.
     750                                                var walker = new CKEDITOR.dom.walker( walkerRange );
     751                                                walker.evaluator = function( node )
     752                                                {
     753                                                        if ( node.type == CKEDITOR.NODE_ELEMENT
     754                                                                && node.getAttribute( 'contenteditable' ) == 'false' )
     755                                                        {
     756                                                                var newRange = range.clone();
     757                                                                range.setEndBefore( node );
     758
     759                                                                // Drop collapsed range around read-only elements,
     760                                                                // it make sure the range list empty when selecting
     761                                                                // only non-editable elements.
     762                                                                if ( range.collapsed )
     763                                                                        ranges.splice( i--, 1 );
     764
     765                                                                // Avoid creating invalid range.
     766                                                                if ( !( node.getPosition( walkerRange.endContainer ) & CKEDITOR.POSITION_CONTAINS ) )
     767                                                                {
     768                                                                        newRange.setStartAfter( node );
     769                                                                        if ( !newRange.collapsed )
     770                                                                                ranges.splice( i + 1, 0, newRange );
     771                                                                }
     772
     773                                                                return true;
     774                                                        }
     775
     776                                                        return false;
     777                                                };
     778
     779                                                walker.next();
     780                                        }
     781                                }
     782
     783                                return cache.ranges;
     784                        };
     785                })(),
    700786
    701787                /**
     
    901987                                this._.cache.selectedElement = element;
    902988                                this._.cache.startElement = element;
    903                                 this._.cache.ranges = [ range ];
     989                                this._.cache.ranges = new CKEDITOR.dom.rangeList( range );
    904990                                this._.cache.type = CKEDITOR.SELECTION_ELEMENT;
    905991
     
    9571043                        {
    9581044                                this._.cache.selectedElement = null;
    959                                 this._.cache.startElement = ranges[ 0 ].getTouchedStartNode();
    960                                 this._.cache.ranges = ranges;
     1045                                this._.cache.startElement = ranges[ 0 ] && ranges[ 0 ].getTouchedStartNode();
     1046                                this._.cache.ranges = new CKEDITOR.dom.rangeList( ranges );
    9611047                                this._.cache.type = CKEDITOR.SELECTION_TEXT;
    9621048
     
    9661052                        if ( CKEDITOR.env.ie )
    9671053                        {
    968                                 // IE doesn't accept multiple ranges selection, so we just
    969                                 // select the first one.
     1054                                if ( ranges.length > 1 )
     1055                                {
     1056                                        // IE doesn't accept multiple ranges selection, so we join all into one.
     1057                                        var last = ranges[ ranges.length -1 ] ;
     1058                                        ranges[ 0 ].setEnd( last.endContainer, last.endOffset );
     1059                                        ranges.length = 1;
     1060                                }
     1061
    9701062                                if ( ranges[ 0 ] )
    9711063                                        ranges[ 0 ].select();
     
    9761068                        {
    9771069                                var sel = this.getNative();
    978                                 sel.removeAllRanges();
     1070
     1071                                if ( ranges.length )
     1072                                        sel.removeAllRanges();
    9791073
    9801074                                for ( var i = 0 ; i < ranges.length ; i++ )
    9811075                                {
     1076                                        // Joining sequential ranges introduced by
     1077                                        // readonly elements protection.
     1078                                        if ( i < ranges.length -1 )
     1079                                        {
     1080                                                var left = ranges[ i ], right = ranges[ i +1 ],
     1081                                                                between = left.clone();
     1082                                                between.setStart( left.endContainer, left.endOffset );
     1083                                                between.setEnd( right.startContainer, right.startOffset );
     1084
     1085                                                // Don't confused by Firefox adjancent multi-ranges
     1086                                                // introduced by table cells selection.
     1087                                                if ( !between.collapsed )
     1088                                                {
     1089                                                        between.shrink( CKEDITOR.NODE_ELEMENT, true );
     1090                                                        if ( between.getCommonAncestor().isReadOnly())
     1091                                                        {
     1092                                                                right.setStart( left.startContainer, left.startOffset );
     1093                                                                ranges.splice( i--, 1 );
     1094                                                                continue;
     1095                                                        }
     1096                                                }
     1097                                        }
     1098
    9821099                                        var range = ranges[ i ];
    9831100                                        var nativeRange = this.document.$.createRange();
     
    10141131                createBookmarks : function( serializable )
    10151132                {
    1016                         var retval = [],
    1017                                 ranges = this.getRanges(),
    1018                                 length = ranges.length,
    1019                                 bookmark;
    1020                         for ( var i = 0; i < length ; i++ )
    1021                         {
    1022                             retval.push( bookmark = ranges[ i ].createBookmark( serializable, true ) );
    1023 
    1024                                 serializable = bookmark.serializable;
    1025 
    1026                                 var bookmarkStart = serializable ? this.document.getById( bookmark.startNode ) : bookmark.startNode,
    1027                                         bookmarkEnd = serializable ? this.document.getById( bookmark.endNode ) : bookmark.endNode;
    1028 
    1029                             // Updating the offset values for rest of ranges which have been mangled(#3256).
    1030                             for ( var j = i + 1 ; j < length ; j++ )
    1031                             {
    1032                                 var dirtyRange = ranges[ j ],
    1033                                        rangeStart = dirtyRange.startContainer,
    1034                                        rangeEnd = dirtyRange.endContainer;
    1035 
    1036                                rangeStart.equals( bookmarkStart.getParent() ) && dirtyRange.startOffset++;
    1037                                rangeStart.equals( bookmarkEnd.getParent() ) && dirtyRange.startOffset++;
    1038                                rangeEnd.equals( bookmarkStart.getParent() ) && dirtyRange.endOffset++;
    1039                                rangeEnd.equals( bookmarkEnd.getParent() ) && dirtyRange.endOffset++;
    1040                             }
    1041                         }
    1042 
    1043                         return retval;
     1133                        return this.getRanges().createBookmarks( serializable );
    10441134                },
    10451135
     
    10521142                createBookmarks2 : function( normalized )
    10531143                {
    1054                         var bookmarks = [],
    1055                                 ranges = this.getRanges();
    1056 
    1057                         for ( var i = 0 ; i < ranges.length ; i++ )
    1058                                 bookmarks.push( ranges[i].createBookmark2( normalized ) );
    1059 
    1060                         return bookmarks;
     1144                        return this.getRanges().createBookmarks2( normalized );
    10611145                },
    10621146
  • CKEditor/trunk/_source/plugins/showborders/plugin.js

    • Property svn:mergeinfo deleted
    r5770 r5812  
    162162                                        };
    163163                        } );
     164
     165                        var advTab = dialogDefinition.getContents( 'advanced' ),
     166                                classField = advTab && advTab.get( 'advCSSClasses' );
     167
     168                        if ( classField )
     169                        {
     170                                classField.setup = CKEDITOR.tools.override( classField.setup, function( originalSetup )
     171                                        {
     172                                                return function()
     173                                                        {
     174                                                                originalSetup.apply( this, arguments );
     175                                                                this.setValue( this.getValue().replace( /cke_show_border/, '' ) );
     176                                                        };
     177                                        });
     178
     179                                classField.commit = CKEDITOR.tools.override( classField.commit, function( originalCommit )
     180                                        {
     181                                                return function( data, element )
     182                                                        {
     183                                                                originalCommit.apply( this, arguments );
     184
     185                                                                if ( !parseInt( element.getAttribute( 'border' ), 10 ) )
     186                                                                        element.addClass( 'cke_show_border' );
     187                                                        };
     188                                        });
     189                        }
    164190                }
    165191        });
  • CKEditor/trunk/_source/plugins/smiley/dialogs/smiley.js

    r5683 r5812  
    132132
    133133        // Build the HTML for the smiley images table.
    134         var labelId = 'smiley_emtions_label' + CKEDITOR.tools.getNextNumber();
     134        var labelId = CKEDITOR.tools.getNextId() + '_smiley_emtions_label';
    135135        var html =
    136136        [
  • CKEditor/trunk/_source/plugins/specialchar/dialogs/specialchar.js

    r5504 r5812  
    1616        {
    1717                var selection = editor.getSelection(),
    18                         ranges    = selection.getRanges(),
     18                        ranges = selection.getRanges( true ),
    1919                        range, textNode;
    2020
    2121                editor.fire( 'saveSnapshot' );
    2222
    23                 for ( var i = 0, len = ranges.length ; i < len ; i++ )
     23                for ( var i = ranges.length - 1; i >= 0 ; i-- )
    2424                {
    2525                        range = ranges[ i ];
    2626                        range.deleteContents();
    2727
    28                         textNode =  CKEDITOR.dom.element.createFromHtml( specialChar );
     28                        textNode = CKEDITOR.dom.element.createFromHtml( specialChar );
    2929                        range.insertNode( textNode );
    3030                }
    3131
    32                 range.moveToPosition( textNode, CKEDITOR.POSITION_AFTER_END );
    33                 range.select();
     32                if ( range )
     33                {
     34                        range.moveToPosition( textNode, CKEDITOR.POSITION_AFTER_END );
     35                        range.select();
     36                }
    3437
    3538                editor.fire( 'saveSnapshot' );
     
    263266                                chars = this.definition.chars;
    264267
    265                         var charsTableLabel =  'specialchar_table_label' + CKEDITOR.tools.getNextNumber();
     268                        var charsTableLabel =  CKEDITOR.tools.getNextId() + '_specialchar_table_label';
    266269                        var html = [ '<table role="listbox" aria-labelledby="' + charsTableLabel + '"' +
    267270                                                                        ' style="width: 320px; height: 100%; border-collapse: separate;"' +
  • CKEditor/trunk/_source/plugins/styles/plugin.js

    r5714 r5812  
    377377                var dtd = CKEDITOR.dtd[ elementName ] || ( isUnknownElement = true, CKEDITOR.dtd.span );
    378378
    379                 // Bookmark the range so we can re-select it after processing.
    380                 var bookmark = range.createBookmark();
    381 
    382379                // Expand the range.
    383380                range.enlarge( CKEDITOR.ENLARGE_ELEMENT );
     
    545542                }
    546543
    547                 firstNode.remove();
    548                 lastNode.remove();
    549                 range.moveToBookmark( bookmark );
     544                // Remove the bookmark nodes.
     545                range.moveToBookmark( boundaryNodes );
     546
    550547                // Minimize the result range to exclude empty text nodes. (#5374)
    551548                range.shrink( CKEDITOR.SHRINK_TEXT );
     
    586583                                if ( this.checkElementRemovable( element ) )
    587584                                {
    588                                         var endOfElement = range.checkBoundaryOfElement( element, CKEDITOR.END ),
    589                                                         startOfElement = !endOfElement && range.checkBoundaryOfElement( element, CKEDITOR.START );
    590                                         if ( startOfElement || endOfElement )
     585                                        var isStart;
     586
     587                                        if ( range.collapsed && (
     588                                                 range.checkBoundaryOfElement( element, CKEDITOR.END ) ||
     589                                                 ( isStart = range.checkBoundaryOfElement( element, CKEDITOR.START ) ) ) )
    591590                                        {
    592591                                                boundaryElement = element;
    593                                                 boundaryElement.match = startOfElement ? 'start' : 'end';
     592                                                boundaryElement.match = isStart ? 'start' : 'end';
    594593                                        }
    595594                                        else
     
    12751274        function applyStyle( document, remove )
    12761275        {
    1277                 // Get all ranges from the selection.
    1278                 var selection = document.getSelection();
    1279                 var ranges = selection.getRanges();
    1280                 var func = remove ? this.removeFromRange : this.applyToRange;
    1281 
    1282                 // Apply the style to the ranges.
    1283                 for ( var i = 0 ; i < ranges.length ; i++ )
    1284                         func.call( this, ranges[ i ] );
    1285 
    1286                 // Select the ranges again.
    1287                 selection.selectRanges( ranges );
     1276                var selection = document.getSelection(),
     1277                        // Bookmark the range so we can re-select it after processing.
     1278                        bookmarks = selection.createBookmarks(),
     1279                        ranges = selection.getRanges( true ),
     1280                        func = remove ? this.removeFromRange : this.applyToRange,
     1281                        range;
     1282
     1283                var iterator = ranges.createIterator();
     1284                while ( ( range = iterator.getNextRange() ) )
     1285                        func.call( this, range );
     1286
     1287                if ( bookmarks.length == 1 && bookmarks[0].collapsed )
     1288                {
     1289                        selection.selectRanges( ranges );
     1290                        bookmarks[0].startNode.remove();
     1291                }
     1292                else
     1293                        selection.selectBookmarks( bookmarks );
    12881294        }
    12891295})();
  • CKEditor/trunk/_source/plugins/tab/plugin.js

    r5548 r5812  
    2828                };
    2929
     30        function selectNextCellCommand( backward )
     31        {
     32                return {
     33                        editorFocus : false,
     34                        canUndo : false,
     35                        modes : { wysiwyg : 1 },
     36                        exec : function( editor )
     37                        {
     38                                if ( editor.focusManager.hasFocus )
     39                                {
     40                                        var sel = editor.getSelection(),
     41                                                        ancestor = sel.getCommonAncestor(),
     42                                                        cell;
     43
     44                                        if ( ( cell = ( ancestor.getAscendant( 'td', true ) || ancestor.getAscendant( 'th', true ) ) ) )
     45                                        {
     46                                                var resultRange = new CKEDITOR.dom.range( editor.document ),
     47                                                                next = CKEDITOR.tools.tryThese( function()
     48                                                                {
     49                                                                        var row = cell.getParent(),
     50                                                                                        next = row.$.cells[ cell.$.cellIndex + ( backward ? - 1 : 1 ) ];
     51
     52                                                                        // Invalid any empty value.
     53                                                                        next.parentNode.parentNode;
     54                                                                        return next;
     55                                                                },
     56                                                                function()
     57                                                                {
     58                                                                        var row = cell.getParent(),
     59                                                                                        table = row.getAscendant( 'table' ),
     60                                                                                        nextRow = table.$.rows[ row.$.rowIndex + ( backward ? - 1 : 1 ) ];
     61
     62                                                                        return nextRow.cells[ backward? nextRow.cells.length -1 : 0 ];
     63                                                                });
     64
     65                                                // Clone one more row at the end of table and select the first newly established cell.
     66                                                if ( ! ( next || backward ) )
     67                                                {
     68                                                        var table = cell.getAscendant( 'table' ).$,
     69                                                                        cells = cell.getParent().$.cells;
     70
     71                                                        var newRow = new CKEDITOR.dom.element( table.insertRow( -1 ), editor.document );
     72
     73                                                        for ( var i = 0, count = cells.length ; i < count; i++ )
     74                                                        {
     75                                                                var newCell = newRow.append( new CKEDITOR.dom.element(
     76                                                                                cells[ i ], editor.document ).clone( false, false ) );
     77                                                                !CKEDITOR.env.ie && newCell.appendBogus();
     78                                                        }
     79
     80                                                        resultRange.moveToElementEditStart( newRow );
     81                                                }
     82                                                else if ( next )
     83                                                {
     84                                                        next = new CKEDITOR.dom.element( next );
     85                                                        resultRange.moveToElementEditStart( next );
     86                                                        // Avoid selecting empty block makes the cursor blind.
     87                                                        if ( !( resultRange.checkStartOfBlock() && resultRange.checkEndOfBlock() ) )
     88                                                                resultRange.selectNodeContents( next );
     89                                                }
     90                                                else
     91                                                        return true;
     92
     93                                                resultRange.select( true );
     94                                                return true;
     95                                        }
     96                                }
     97                                return false;
     98                        }
     99                };
     100        }
     101
    30102        CKEDITOR.plugins.add( 'tab',
    31103        {
     
    34106                init : function( editor )
    35107                {
    36                         var tabSpaces = editor.config.tabSpaces || 0,
     108                        var tabTools = editor.config.enableTabKeyTools !== false,
     109                                tabSpaces = editor.config.tabSpaces || 0,
    37110                                tabText = '';
    38111
     
    52125                        }
    53126
     127                        if ( tabTools )
     128                        {
     129                                editor.on( 'key', function( ev )
     130                                {
     131                                        if ( ev.data.keyCode == 9 && editor.execCommand( 'selectNextCell' ) ||  // TAB
     132                                                        ev.data.keyCode == ( CKEDITOR.SHIFT + 9 ) && editor.execCommand( 'selectPreviousCell' ) )       // SHIFT+TAB
     133                                                ev.cancel();
     134                                });
     135                        }
     136
    54137                        if ( CKEDITOR.env.webkit || CKEDITOR.env.gecko )
    55138                        {
     
    74157                        editor.addCommand( 'blur', CKEDITOR.tools.extend( blurCommand, meta ) );
    75158                        editor.addCommand( 'blurBack', CKEDITOR.tools.extend( blurBackCommand, meta ) );
     159                        editor.addCommand( 'selectNextCell', selectNextCellCommand() );
     160                        editor.addCommand( 'selectPreviousCell', selectNextCellCommand( true ) );
    76161                }
    77162        });
     
    260345 * config.tabSpaces = 4;
    261346 */
     347
     348/**
     349 * Allow context-sensitive tab key behaviors, including the following scenarios:
     350 * <h5>When selection is anchored inside <b>table cells</b>:</h5>
     351 * <ul>
     352 *              <li>If TAB is pressed, select the contents of the "next" cell. If in the last cell in the table, add a new row to it and focus its first cell.</li>
     353 *              <li>If SHIFT+TAB is pressed, select the contents of the "previous" cell. Do nothing when it's in the first cell.</li>
     354 * </ul>
     355 * @name CKEDITOR.config.enableTabKeyTools
     356 * @type Boolean
     357 * @default true
     358 * @example
     359 * config.enableTabKeyTools = false;
     360 */
     361
     362// If the TAB key is not supposed to be enabled for navigation, the following
     363// settings could be used alternatively:
     364// config.keystrokes.push(
     365//      [ CKEDITOR.ALT + 38 /*Arrow Up*/, 'selectPreviousCell' ],
     366//      [ CKEDITOR.ALT + 40 /*Arrow Down*/, 'selectNextCell' ]
     367// );
  • CKEditor/trunk/_source/plugins/table/dialogs/table.js

    r5723 r5812  
    1919        function tableDialog( editor, command )
    2020        {
    21                 var makeElement = function( name ){ return new CKEDITOR.dom.element( name, editor.document ); };
     21                var makeElement = function( name )
     22                        {
     23                                return new CKEDITOR.dom.element( name, editor.document );
     24                        };
     25
     26                var dialogadvtab = editor.plugins.dialogadvtab;
    2227
    2328                return {
     
    2530                        minWidth : 310,
    2631                        minHeight : CKEDITOR.env.ie ? 310 : 280,
     32
     33                        onLoad : function()
     34                        {
     35                                var dialog = this,
     36                                        isUpdating;
     37
     38                                var styles = dialog.getContentElement( 'advanced', 'advStyles' );
     39
     40                                if ( styles )
     41                                {
     42                                        styles.on( 'change', function( evt )
     43                                                {
     44                                                        if ( isUpdating )
     45                                                                return;
     46
     47                                                        // Flag to avoid recursion.
     48                                                        isUpdating = 1;
     49
     50                                                        // Synchronize width value.
     51                                                        var width = this.getStyle( 'width', '' ),
     52                                                                txtWidth = dialog.getContentElement( 'info', 'txtWidth' ),
     53                                                                cmbWidthType = dialog.getContentElement( 'info', 'cmbWidthType' ),
     54                                                                isPx = 1;
     55
     56                                                        if ( width )
     57                                                        {
     58                                                                isPx = ( width.length < 3 || width.substr( width.length - 1 ) != '%' );
     59                                                                width = parseInt( width, 10 );
     60                                                        }
     61
     62                                                        txtWidth && txtWidth.setValue( width );
     63                                                        cmbWidthType && cmbWidthType.setValue( isPx ? 'pixels' : 'percents' );
     64
     65                                                        // Synchronize height value.
     66                                                        var height = this.getStyle( 'height', '' ),
     67                                                                txtHeight = dialog.getContentElement( 'info', 'txtHeight' );
     68
     69                                                        height && ( height = parseInt( height, 10 ) );
     70                                                        txtHeight && txtHeight.setValue( height );
     71
     72                                                        isUpdating = 0;
     73                                                });
     74                                }
     75                        },
     76
    2777                        onShow : function()
    2878                        {
     
    3484                                var rowsInput = this.getContentElement( 'info', 'txtRows' ),
    3585                                        colsInput = this.getContentElement( 'info', 'txtCols' ),
    36                                         widthInput = this.getContentElement( 'info', 'txtWidth' );
     86                                        widthInput = this.getContentElement( 'info', 'txtWidth' ),
     87                                        heightInput = this.getContentElement( 'info', 'txtHeight' );
     88
    3789                                if ( command == 'tableProperties' )
    3890                                {
     
    71123                                        rowsInput && rowsInput.select();
    72124                                }
     125
     126                                // Call the onChange method for the widht and height fields so
     127                                // they get reflected into the Advanced tab.
     128                                widthInput && widthInput.onChange();
     129                                heightInput && heightInput.onChange();
    73130                        },
    74131                        onOk : function()
     
    381438                                                                                                        style : 'width:5em',
    382439                                                                                                        label : editor.lang.table.width,
    383                                                                                                         'default' : 200,
     440                                                                                                        'default' : 500,
    384441                                                                                                        validate : CKEDITOR.dialog.validate['number']( editor.lang.table.invalidWidth ),
    385442
     
    393450
    394451                                                                                                                inputElement.setAttribute( 'aria-labelledby', [ ariaLabelledByAttr, labelElement.$.id ].join( ' ' ) );
     452                                                                                                        },
     453
     454                                                                                                        onChange : function()
     455                                                                                                        {
     456                                                                                                                var styles = this.getDialog().getContentElement( 'advanced', 'advStyles' );
     457
     458                                                                                                                if ( styles )
     459                                                                                                                {
     460                                                                                                                        var value = this.getValue();
     461
     462                                                                                                                        if ( value )
     463                                                                                                                                value += this.getDialog().getContentElement( 'info', 'cmbWidthType' ).getValue() == 'percents' ? '%' : 'px';
     464
     465                                                                                                                        styles.updateStyle( 'width', value );
     466                                                                                                                }
    395467                                                                                                        },
    396468
     
    422494                                                                                                                        this.setValue( widthMatch[2] == 'px' ? 'pixels' : 'percents' );
    423495                                                                                                        },
     496                                                                                                        onChange : function()
     497                                                                                                        {
     498                                                                                                                this.getDialog().getContentElement( 'info', 'txtWidth' ).onChange();
     499                                                                                                        },
    424500                                                                                                        commit : commitValue
    425501                                                                                                }
     
    448524
    449525                                                                                                                inputElement.setAttribute( 'aria-labelledby', [ ariaLabelledByAttr, labelElement.$.id ].join( ' ' ) );
     526                                                                                                        },
     527
     528                                                                                                        onChange : function()
     529                                                                                                        {
     530                                                                                                                var styles = this.getDialog().getContentElement( 'advanced', 'advStyles' );
     531
     532                                                                                                                if ( styles )
     533                                                                                                                {
     534                                                                                                                        var value = this.getValue();
     535                                                                                                                        styles.updateStyle( 'height', value && ( value + 'px' ) );
     536                                                                                                                }
    450537                                                                                                        },
    451538
     
    583670                                                }
    584671                                        ]
    585                                 }
     672                                },
     673                                dialogadvtab && dialogadvtab.createAdvancedTab( editor )
    586674                        ]
    587675                };
  • CKEditor/trunk/_source/plugins/table/plugin.js

    r5548 r5812  
    5959                        editor.contextMenu.addListener( function( element, selection )
    6060                                {
    61                                         if ( !element )
     61                                        if ( !element || element.isReadOnly())
    6262                                                return null;
    6363
  • CKEditor/trunk/_source/plugins/tabletools/plugin.js

    r5778 r5812  
    399399                }
    400400                range.select( true );
    401         }
    402 
    403         function buildTableMap( table )
    404         {
    405 
    406                 var aRows = table.$.rows ;
    407 
    408                 // Row and Column counters.
    409                 var r = -1 ;
    410 
    411                 var aMap = [];
    412 
    413                 for ( var i = 0 ; i < aRows.length ; i++ )
    414                 {
    415                         r++ ;
    416                         !aMap[r] && ( aMap[r] = [] );
    417 
    418                         var c = -1 ;
    419 
    420                         for ( var j = 0 ; j < aRows[i].cells.length ; j++ )
    421                         {
    422                                 var oCell = aRows[i].cells[j] ;
    423 
    424                                 c++ ;
    425                                 while ( aMap[r][c] )
    426                                         c++ ;
    427 
    428                                 var iColSpan = isNaN( oCell.colSpan ) ? 1 : oCell.colSpan ;
    429                                 var iRowSpan = isNaN( oCell.rowSpan ) ? 1 : oCell.rowSpan ;
    430 
    431                                 for ( var rs = 0 ; rs < iRowSpan ; rs++ )
    432                                 {
    433                                         if ( !aMap[r + rs] )
    434                                                 aMap[r + rs] = new Array() ;
    435 
    436                                         for ( var cs = 0 ; cs < iColSpan ; cs++ )
    437                                         {
    438                                                 aMap[r + rs][c + cs] = aRows[i].cells[j] ;
    439                                         }
    440                                 }
    441 
    442                                 c += iColSpan - 1 ;
    443                         }
    444                 }
    445                 return aMap ;
    446401        }
    447402
     
    499454                        firstCell = cells[ 0 ],
    500455                        table = firstCell.getAscendant( 'table' ),
    501                         map = buildTableMap( table ),
     456                        map = CKEDITOR.tools.buildTableMap( table ),
    502457                        mapHeight = map.length,
    503458                        mapWidth = map[ 0 ].length,
     
    634589                        tr = cell.getParent(),
    635590                        table = tr.getAscendant( 'table' ),
    636                         map = buildTableMap( table ),
     591                        map = CKEDITOR.tools.buildTableMap( table ),
    637592                        rowIndex = tr.$.rowIndex,
    638593                        colIndex = cellInRow( map, rowIndex, cell ),
     
    710665                        tr = cell.getParent(),
    711666                        table = tr.getAscendant( 'table' ),
    712                         map = buildTableMap( table ),
     667                        map = CKEDITOR.tools.buildTableMap( table ),
    713668                        rowIndex = tr.$.rowIndex,
    714669                        colIndex = cellInRow( map, rowIndex, cell ),
     
    10891044                                editor.contextMenu.addListener( function( element, selection )
    10901045                                        {
    1091                                                 if ( !element )
     1046                                                if ( !element || element.isReadOnly() )
    10921047                                                        return null;
    10931048
     
    11151070        CKEDITOR.plugins.add( 'tabletools', CKEDITOR.plugins.tabletools );
    11161071})();
     1072
     1073/**
     1074 * Create a two-dimension array that reflects the actual layout of table cells,
     1075 * with cell spans, with mappings to the original td elements.
     1076 * @param table {CKEDITOR.dom.element}
     1077 */
     1078CKEDITOR.tools.buildTableMap = function ( table )
     1079{
     1080        var aRows = table.$.rows ;
     1081
     1082        // Row and Column counters.
     1083        var r = -1 ;
     1084
     1085        var aMap = [];
     1086
     1087        for ( var i = 0 ; i < aRows.length ; i++ )
     1088        {
     1089                r++ ;
     1090                !aMap[r] && ( aMap[r] = [] );
     1091
     1092                var c = -1 ;
     1093
     1094                for ( var j = 0 ; j < aRows[i].cells.length ; j++ )
     1095                {
     1096                        var oCell = aRows[i].cells[j] ;
     1097
     1098                        c++ ;
     1099                        while ( aMap[r][c] )
     1100                                c++ ;
     1101
     1102                        var iColSpan = isNaN( oCell.colSpan ) ? 1 : oCell.colSpan ;
     1103                        var iRowSpan = isNaN( oCell.rowSpan ) ? 1 : oCell.rowSpan ;
     1104
     1105                        for ( var rs = 0 ; rs < iRowSpan ; rs++ )
     1106                        {
     1107                                if ( !aMap[r + rs] )
     1108                                        aMap[r + rs] = [];
     1109
     1110                                for ( var cs = 0 ; cs < iColSpan ; cs++ )
     1111                                {
     1112                                        aMap[r + rs][c + cs] = aRows[i].cells[j] ;
     1113                                }
     1114                        }
     1115
     1116                        c += iColSpan - 1 ;
     1117                }
     1118        }
     1119        return aMap ;
     1120};
  • CKEditor/trunk/_source/plugins/toolbar/plugin.js

    r5336 r5812  
    434434        ['NumberedList','BulletedList','-','Outdent','Indent','Blockquote','CreateDiv'],
    435435        ['JustifyLeft','JustifyCenter','JustifyRight','JustifyBlock'],
     436        ['BidiLtr', 'BidiRtl'],
    436437        ['Link','Unlink','Anchor'],
    437438        ['Image','Flash','Table','HorizontalRule','Smiley','SpecialChar','PageBreak'],
  • CKEditor/trunk/_source/plugins/wysiwygarea/plugin.js

    r5785 r5812  
    1919        var notWhitespaceEval = CKEDITOR.dom.walker.whitespaces( true );
    2020
     21        function checkReadOnly( selection )
     22        {
     23                if ( selection.getType() == CKEDITOR.SELECTION_ELEMENT )
     24                        return selection.getSelectedElement().isReadOnly();
     25                else
     26                        return selection.getCommonAncestor().isReadOnly();
     27        }
     28
    2129        function onInsertHtml( evt )
    2230        {
     
    2432                {
    2533                        this.focus();
     34
     35                        var selection = this.getSelection();
     36                        if ( checkReadOnly( selection ) )
     37                                return;
     38
     39                        var data = evt.data;
    2640                        this.fire( 'saveSnapshot' );
    27 
    28                         var selection = this.getSelection(),
    29                                 data = evt.data;
    3041
    3142                        if ( this.dataProcessor )
     
    4051
    4152                                var $sel = selection.getNative();
     53
     54                                // Delete control selections to avoid IE bugs on pasteHTML.
    4255                                if ( $sel.type == 'Control' )
    4356                                        $sel.clear();
     57                                else if  ( selection.getType() == CKEDITOR.SELECTION_TEXT )
     58                                {
     59                                        // Due to IE bugs on handling contenteditable=false blocks
     60                                        // (#6005), we need to make some checks and eventually
     61                                        // delete the selection first.
     62
     63                                        var range = selection.getRanges()[0],
     64                                                endContainer = range && range.endContainer;
     65
     66                                        if ( endContainer &&
     67                                                 endContainer.type == CKEDITOR.NODE_ELEMENT &&
     68                                                 endContainer.getAttribute( 'contenteditable' ) == 'false' &&
     69                                                 range.checkBoundaryOfElement( endContainer, CKEDITOR.END ) )
     70                                        {
     71                                                range.setEndAfter( range.endContainer );
     72                                                range.deleteContents();
     73                                        }
     74                                }
     75
    4476                                $sel.createRange().pasteHTML( data );
    4577
     
    71103                {
    72104                        this.focus();
     105
     106                        var selection = this.getSelection();
     107                        if ( checkReadOnly( selection ) )
     108                                return;
     109
    73110                        this.fire( 'saveSnapshot' );
    74111
    75                         var element = evt.data,
     112                        var ranges = selection.getRanges(),
     113                                element = evt.data,
    76114                                elementName = element.getName(),
    77115                                isBlock = CKEDITOR.dtd.$block[ elementName ];
    78 
    79                         var selection = this.getSelection(),
    80                                 ranges = selection.getRanges();
    81116
    82117                        var selIsLocked = selection.isLocked;
     
    378413                                                        '></iframe>' );
    379414
     415                                                // #5689 Running inside of Firefox chrome the load event doesn't bubble like in a normal page
     416                                                if (document.location.protocol == 'chrome:')
     417                                                        CKEDITOR.event.useCapture = true;
     418
    380419                                                // With FF, it's better to load the data on iframe.load. (#3894,#4058)
    381420              &n