JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
vanilla ckeditor-3.4.3
[ckeditor.git] / _source / plugins / indent / plugin.js
index e60a29e..c49ce88 100644 (file)
@@ -78,9 +78,9 @@ For licensing, see LICENSE.html or http://ckeditor.com/license
        }\r
 \r
        // Returns the CSS property to be used for identing a given element.\r
-       function getIndentCssProperty( element )\r
+       function getIndentCssProperty( element, dir )\r
        {\r
-               return element.getComputedStyle( 'direction' ) == 'ltr' ? 'margin-left' : 'margin-right';\r
+               return ( dir || element.getComputedStyle( 'direction' ) ) == 'ltr' ? 'margin-left' : 'margin-right';\r
        }\r
 \r
        function isListItem( node )\r
@@ -157,7 +157,7 @@ For licensing, see LICENSE.html or http://ckeditor.com/license
 \r
                                // Convert the array back to a DOM forest (yes we might have a few subtrees now).\r
                                // And replace the old list with the new forest.\r
-                               var newList = CKEDITOR.plugins.list.arrayToList( listArray, database, null, editor.config.enterMode, 0 );\r
+                               var newList = CKEDITOR.plugins.list.arrayToList( listArray, database, null, editor.config.enterMode, listNode.getDirection() );\r
 \r
                                // Avoid nested <li> after outdent even they're visually same,\r
                                // recording them for later refactoring.(#3982)\r
@@ -219,7 +219,7 @@ For licensing, see LICENSE.html or http://ckeditor.com/license
                                        indentElement( block );\r
                        }\r
 \r
-                       function indentElement( element )\r
+                       function indentElement( element, dir )\r
                        {\r
                                if ( element.getCustomData( 'indent_processed' ) )\r
                                        return false;\r
@@ -247,81 +247,95 @@ For licensing, see LICENSE.html or http://ckeditor.com/license
 \r
                                        indentStep = Math.min( indentStep, editor.config.indentClasses.length );\r
                                        indentStep = Math.max( indentStep, 0 );\r
-                                       var className = CKEDITOR.tools.ltrim( element.$.className.replace( self.classNameRegex, '' ) );\r
-                                       if ( indentStep < 1 )\r
-                                               element.$.className = className;\r
-                                       else\r
+                                       element.$.className = CKEDITOR.tools.ltrim( element.$.className.replace( self.classNameRegex, '' ) );\r
+                                       if ( indentStep > 0 )\r
                                                element.addClass( editor.config.indentClasses[ indentStep - 1 ] );\r
                                }\r
                                else\r
                                {\r
-                                       var indentCssProperty = getIndentCssProperty( element );\r
-                                       var currentOffset = parseInt( element.getStyle( indentCssProperty ), 10 );\r
+                                       var indentCssProperty = getIndentCssProperty( element, dir ),\r
+                                               currentOffset = parseInt( element.getStyle( indentCssProperty ), 10 );\r
                                        if ( isNaN( currentOffset ) )\r
                                                currentOffset = 0;\r
-                                       currentOffset += ( self.name == 'indent' ? 1 : -1 ) * editor.config.indentOffset;\r
+                                       var indentOffset = editor.config.indentOffset || 40;\r
+                                       currentOffset += ( self.name == 'indent' ? 1 : -1 ) * indentOffset;\r
 \r
                                        if ( currentOffset < 0 )\r
                                                return false;\r
 \r
                                        currentOffset = Math.max( currentOffset, 0 );\r
-                                       currentOffset = Math.ceil( currentOffset / editor.config.indentOffset ) * editor.config.indentOffset;\r
-                                       element.setStyle( indentCssProperty, currentOffset ? currentOffset + editor.config.indentUnit : '' );\r
+                                       currentOffset = Math.ceil( currentOffset / indentOffset ) * indentOffset;\r
+                                       element.setStyle( indentCssProperty, currentOffset ? currentOffset + ( editor.config.indentUnit || 'px' ) : '' );\r
                                        if ( element.getAttribute( 'style' ) === '' )\r
                                                element.removeAttribute( 'style' );\r
                                }\r
 \r
-                               CKEDITOR.dom.element.setMarker( database, element, 'indent_processed', true );\r
+                               CKEDITOR.dom.element.setMarker( database, element, 'indent_processed', 1 );\r
                                return true;\r
                        }\r
 \r
                        var selection = editor.getSelection(),\r
-                               bookmarks = selection.createBookmarks( true ),\r
-                               ranges = selection && selection.getRanges( true ),\r
+                               bookmarks = selection.createBookmarks( 1 ),\r
+                               ranges = selection && selection.getRanges( 1 ),\r
                                range;\r
 \r
+\r
                        var iterator = ranges.createIterator();\r
                        while ( ( range = iterator.getNextRange() ) )\r
                        {\r
-                               var startContainer = range.startContainer,\r
-                                       endContainer = range.endContainer,\r
-                                       rangeRoot = range.getCommonAncestor(),\r
+                               var rangeRoot = range.getCommonAncestor(),\r
                                        nearestListBlock = rangeRoot;\r
 \r
                                while ( nearestListBlock && !( nearestListBlock.type == CKEDITOR.NODE_ELEMENT &&\r
                                        listNodeNames[ nearestListBlock.getName() ] ) )\r
                                        nearestListBlock = nearestListBlock.getParent();\r
 \r
+                               // Avoid having selection enclose the entire list. (#6138)\r
+                               // [<ul><li>...</li></ul>] =><ul><li>[...]</li></ul>\r
+                               if ( !nearestListBlock )\r
+                               {\r
+                                       var selectedNode = range.getEnclosedNode();\r
+                                       if ( selectedNode\r
+                                               && selectedNode.type == CKEDITOR.NODE_ELEMENT\r
+                                               && selectedNode.getName() in listNodeNames)\r
+                                       {\r
+                                               range.setStartAt( selectedNode, CKEDITOR.POSITION_AFTER_START );\r
+                                               range.setEndAt( selectedNode, CKEDITOR.POSITION_BEFORE_END );\r
+                                               nearestListBlock = selectedNode;\r
+                                       }\r
+                               }\r
+\r
                                // Avoid selection anchors under list root.\r
                                // <ul>[<li>...</li>]</ul> =>   <ul><li>[...]</li></ul>\r
-                               if ( nearestListBlock && startContainer.type == CKEDITOR.NODE_ELEMENT\r
-                                       && startContainer.getName() in listNodeNames )\r
+                               if ( nearestListBlock && range.startContainer.type == CKEDITOR.NODE_ELEMENT\r
+                                       && range.startContainer.getName() in listNodeNames )\r
                                {\r
                                        var walker = new CKEDITOR.dom.walker( range );\r
                                        walker.evaluator = isListItem;\r
                                        range.startContainer = walker.next();\r
                                }\r
 \r
-                               if ( nearestListBlock && endContainer.type == CKEDITOR.NODE_ELEMENT\r
-                                       && endContainer.getName() in listNodeNames )\r
+                               if ( nearestListBlock && range.endContainer.type == CKEDITOR.NODE_ELEMENT\r
+                                       && range.endContainer.getName() in listNodeNames )\r
                                {\r
                                        walker = new CKEDITOR.dom.walker( range );\r
                                        walker.evaluator = isListItem;\r
                                        range.endContainer = walker.previous();\r
                                }\r
 \r
-                               if ( nearestListBlock  )\r
+                               if ( nearestListBlock )\r
                                {\r
-                                       var firstListItem = nearestListBlock.getFirst( function( node )\r
-                                               {\r
-                                                       return node.type == CKEDITOR.NODE_ELEMENT && node.is( 'li' );\r
-                                               }),\r
+                                       var firstListItem = nearestListBlock.getFirst( isListItem ),\r
+                                               hasMultipleItems = !!firstListItem.getNext( isListItem ),\r
                                                rangeStart = range.startContainer,\r
                                                indentWholeList = firstListItem.equals( rangeStart ) || firstListItem.contains( rangeStart );\r
 \r
-                                       // Indent the entire list if  cursor is inside the first list item. (#3893)\r
-                                       if ( !( indentWholeList && indentElement( nearestListBlock ) ) )\r
-                                               indentList( nearestListBlock );\r
+                                       // Indent the entire list if cursor is inside the first list item. (#3893)\r
+                                       // Only do that for indenting or when using indent classes or when there is something to outdent. (#6141)\r
+                                       if ( !( indentWholeList &&\r
+                                               ( self.name == 'indent' || self.useIndentClasses || parseInt( nearestListBlock.getStyle( getIndentCssProperty( nearestListBlock ) ), 10 ) ) &&\r
+                                                       indentElement( nearestListBlock, !hasMultipleItems && firstListItem.getDirection() ) ) )\r
+                                                               indentList( nearestListBlock );\r
                                }\r
                                else\r
                                        indentBlock();\r
@@ -371,46 +385,62 @@ For licensing, see LICENSE.html or http://ckeditor.com/license
                                        "       padding-left: 40px;" +\r
                                        "}" );\r
                        }\r
-               },\r
 \r
-               requires : [ 'domiterator', 'list' ]\r
-       } );\r
-})();\r
+                       // Register dirChanged listener.\r
+                       editor.on( 'dirChanged', function( e )\r
+                       {\r
+                               var range = new CKEDITOR.dom.range( editor.document );\r
+                               range.setStartBefore( e.data.node );\r
+                               range.setEndAfter( e.data.node );\r
 \r
-CKEDITOR.tools.extend( CKEDITOR.config,\r
-       {\r
-               indentOffset : 40,\r
-               indentUnit : 'px',\r
-               indentClasses : null\r
-       });\r
+                               var walker = new CKEDITOR.dom.walker( range ),\r
+                                       node;\r
 \r
-/**\r
- * Size of each indentation step\r
- * @type Number\r
- * @example\r
- * config.indentOffset = 40;\r
- */\r
+                               while ( ( node = walker.next() ) )\r
+                               {\r
+                                       if ( node.type == CKEDITOR.NODE_ELEMENT )\r
+                                       {\r
+                                               // A child with the defined dir is to be ignored.\r
+                                               if ( !node.equals( e.data.node ) && node.getDirection() )\r
+                                               {\r
+                                                       range.setStartAfter( node );\r
+                                                       walker = new CKEDITOR.dom.walker( range );\r
+                                                       continue;\r
+                                               }\r
 \r
- /**\r
- * Unit for the indentation style\r
- * @type String\r
- * @example\r
- * config.indentUnit = 'px';\r
- */\r
+                                               // Switch alignment classes.\r
+                                               var classes = editor.config.indentClasses;\r
+                                               if ( classes )\r
+                                               {\r
+                                                       var suffix = ( e.data.dir == 'ltr' ) ? [ '_rtl', '' ] : [ '', '_rtl' ];\r
+                                                       for ( var i = 0; i < classes.length; i++ )\r
+                                                       {\r
+                                                               if ( node.hasClass( classes[ i ] + suffix[ 0 ] ) )\r
+                                                               {\r
+                                                                       node.removeClass( classes[ i ] + suffix[ 0 ] );\r
+                                                                       node.addClass( classes[ i ] + suffix[ 1 ] );\r
+                                                               }\r
+                                                       }\r
+                                               }\r
 \r
- /**\r
- * List of classes to use for indenting the contents.\r
- * @type Array\r
- * @example\r
- * // Don't use classes for indenting. (this is the default value)\r
- * config.indentClasses = null;\r
- * @example\r
- * // Use the classes 'Indent1', 'Indent2', 'Indent3'\r
- * config.indentClasses = ['Indent1', 'Indent2', 'Indent3'];\r
- */\r
+                                               // Switch the margins.\r
+                                               var marginLeft = node.getStyle( 'margin-right' ),\r
+                                                       marginRight = node.getStyle( 'margin-left' );\r
+\r
+                                               marginLeft ? node.setStyle( 'margin-left', marginLeft ) : node.removeStyle( 'margin-left' );\r
+                                               marginRight ? node.setStyle( 'margin-right', marginRight ) : node.removeStyle( 'margin-right' );\r
+                                       }\r
+                               }\r
+                       });\r
+               },\r
+\r
+               requires : [ 'domiterator', 'list' ]\r
+       } );\r
+})();\r
 \r
 /**\r
  * Size of each indentation step\r
+ * @name CKEDITOR.config.indentOffset\r
  * @type Number\r
  * @default 40\r
  * @example\r
@@ -419,6 +449,7 @@ CKEDITOR.tools.extend( CKEDITOR.config,
 \r
  /**\r
  * Unit for the indentation style\r
+ * @name CKEDITOR.config.indentUnit\r
  * @type String\r
  * @default 'px'\r
  * @example\r
@@ -428,6 +459,7 @@ CKEDITOR.tools.extend( CKEDITOR.config,
  /**\r
  * List of classes to use for indenting the contents. If it's null, no classes will be used\r
  * and instead the {@link #indentUnit} and {@link #indentOffset} properties will be used.\r
+ * @name CKEDITOR.config.indentClasses\r
  * @type Array\r
  * default null\r
  * @example\r