JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
vanilla ckeditor-3.3
[ckeditor.git] / _source / plugins / indent / plugin.js
index d175e46..80fc71d 100644 (file)
@@ -21,38 +21,13 @@ For licensing, see LICENSE.html or http://ckeditor.com/license
 \r
        function onSelectionChange( evt )\r
        {\r
-               var elements = evt.data.path.elements,\r
-                       listNode, listItem,\r
-                       editor = evt.editor;\r
+               var editor = evt.editor;\r
 \r
-               for ( var i = 0 ; i < elements.length ; i++ )\r
-               {\r
-                       if ( elements[i].getName() == 'li' )\r
-                       {\r
-                               listItem = elements[i];\r
-                               continue;\r
-                       }\r
-                       if ( listNodeNames[ elements[i].getName() ] )\r
-                       {\r
-                               listNode = elements[i];\r
-                               break;\r
-                       }\r
-               }\r
+               var elementPath = evt.data.path,\r
+                               list = elementPath && elementPath.contains( listNodeNames );\r
 \r
-               if ( listNode )\r
-               {\r
-                       if ( this.name == 'outdent' )\r
+               if ( list )\r
                                return setState.call( this, editor, CKEDITOR.TRISTATE_OFF );\r
-                       else\r
-                       {\r
-                               while ( listItem && ( listItem = listItem.getPrevious( CKEDITOR.dom.walker.whitespaces( true ) ) ) )\r
-                               {\r
-                                       if ( listItem.getName && listItem.getName() == 'li' )\r
-                                               return setState.call( this, editor, CKEDITOR.TRISTATE_OFF );\r
-                               }\r
-                               return setState.call( this, editor, CKEDITOR.TRISTATE_DISABLED );\r
-                       }\r
-               }\r
 \r
                if ( !this.useIndentClasses && this.name == 'indent' )\r
                        return setState.call( this, editor, CKEDITOR.TRISTATE_OFF );\r
@@ -214,12 +189,15 @@ For licensing, see LICENSE.html or http://ckeditor.com/license
                iterator.enlargeBr = enterMode != CKEDITOR.ENTER_BR;\r
                var block;\r
                while ( ( block = iterator.getNextParagraph() ) )\r
-               {\r
+                       indentElement.call( this, editor, block );\r
+       }\r
 \r
+       function indentElement( editor, element )\r
+               {\r
                        if ( this.useIndentClasses )\r
                        {\r
                                // Transform current class name to indent step index.\r
-                               var indentClass = block.$.className.match( this.classNameRegex ),\r
+                       var indentClass = element.$.className.match( this.classNameRegex ),\r
                                        indentStep = 0;\r
                                if ( indentClass )\r
                                {\r
@@ -233,28 +211,37 @@ For licensing, see LICENSE.html or http://ckeditor.com/license
                                        indentStep--;\r
                                else\r
                                        indentStep++;\r
+\r
+                       if ( indentStep < 0 )\r
+                               return false;\r
+\r
                                indentStep = Math.min( indentStep, editor.config.indentClasses.length );\r
                                indentStep = Math.max( indentStep, 0 );\r
-                               var className = CKEDITOR.tools.ltrim( block.$.className.replace( this.classNameRegex, '' ) );\r
+                       var className = CKEDITOR.tools.ltrim( element.$.className.replace( this.classNameRegex, '' ) );\r
                                if ( indentStep < 1 )\r
-                                       block.$.className = className;\r
+                               element.$.className = className;\r
                                else\r
-                                       block.$.className = CKEDITOR.tools.ltrim( className + ' ' + editor.config.indentClasses[ indentStep - 1 ] );\r
+                               element.addClass( editor.config.indentClasses[ indentStep - 1 ] );\r
                        }\r
                        else\r
                        {\r
-                               var currentOffset = parseInt( block.getStyle( this.indentCssProperty ), 10 );\r
+                       var currentOffset = parseInt( element.getStyle( this.indentCssProperty ), 10 );\r
                                if ( isNaN( currentOffset ) )\r
                                        currentOffset = 0;\r
                                currentOffset += ( this.name == 'indent' ? 1 : -1 ) * editor.config.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
-                               block.setStyle( this.indentCssProperty, currentOffset ? currentOffset + editor.config.indentUnit : '' );\r
-                               if ( block.getAttribute( 'style' ) === '' )\r
-                                       block.removeAttribute( 'style' );\r
+                       element.setStyle( this.indentCssProperty, currentOffset ? currentOffset + editor.config.indentUnit : '' );\r
+                       if ( element.getAttribute( 'style' ) === '' )\r
+                               element.removeAttribute( 'style' );\r
                        }\r
+\r
+               return true;\r
                }\r
-       }\r
 \r
        function indentCommand( editor, name )\r
        {\r
@@ -272,24 +259,59 @@ For licensing, see LICENSE.html or http://ckeditor.com/license
                this.startDisabled = name == 'outdent';\r
        }\r
 \r
+       function isListItem( node )\r
+       {\r
+               return node.type = CKEDITOR.NODE_ELEMENT && node.is( 'li' );\r
+       }\r
+\r
        indentCommand.prototype = {\r
                exec : function( editor )\r
                {\r
                        var selection = editor.getSelection(),\r
                                range = selection && selection.getRanges()[0];\r
 \r
-                       if ( !selection || !range )\r
-                               return;\r
-\r
-                       var bookmarks = selection.createBookmarks( true ),\r
-                               nearestListBlock = range.getCommonAncestor();\r
+                       var startContainer = range.startContainer,\r
+                               endContainer = range.endContainer,\r
+                               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
-                       if ( nearestListBlock )\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
+                       {\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
+                       {\r
+                               walker = new CKEDITOR.dom.walker( range );\r
+                               walker.evaluator = isListItem;\r
+                               range.endContainer = walker.previous();\r
+                       }\r
+\r
+                       var bookmarks = selection.createBookmarks( true );\r
+\r
+                       if ( nearestListBlock  )\r
+                       {\r
+                               var firstListItem = nearestListBlock.getFirst( function( node )\r
+                                       {\r
+                                               return node.type == CKEDITOR.NODE_ELEMENT && node.is( 'li' );\r
+                                       }),\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.call( this, editor, nearestListBlock ) ) )\r
                                indentList.call( this, editor, range, nearestListBlock );\r
+                       }\r
                        else\r
                                indentBlock.call( this, editor, range );\r
 \r
@@ -324,6 +346,17 @@ For licensing, see LICENSE.html or http://ckeditor.com/license
                        // Register the state changing handlers.\r
                        editor.on( 'selectionChange', CKEDITOR.tools.bind( onSelectionChange, indent ) );\r
                        editor.on( 'selectionChange', CKEDITOR.tools.bind( onSelectionChange, outdent ) );\r
+\r
+                       // [IE6/7] Raw lists are using margin instead of padding for visual indentation in wysiwyg mode. (#3893)\r
+                       if ( CKEDITOR.env.ie6Compat || CKEDITOR.env.ie7Compat )\r
+                       {\r
+                               editor.addCss(\r
+                                       "ul,ol" +\r
+                                       "{" +\r
+                                       "       margin-left: 0px;" +\r
+                                       "       padding-left: 40px;" +\r
+                                       "}" );\r
+                       }\r
                },\r
 \r
                requires : [ 'domiterator', 'list' ]\r