source: branches/2.2/filemanager/tp/ckeditor/_source/plugins/indent/plugin.js @ 3019

Revision 3019, 10.0 KB checked in by amuller, 14 years ago (diff)

Ticket #1135 - Corrigindo CSS e adicionando filemanager

Line 
1/*
2Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.html or http://ckeditor.com/license
4*/
5
6/**
7 * @file Increse and decrease indent commands.
8 */
9
10(function()
11{
12        var listNodeNames = { ol : 1, ul : 1 };
13
14        function setState( editor, state )
15        {
16                editor.getCommand( this.name ).setState( state );
17        }
18
19        function onSelectionChange( evt )
20        {
21                var elements = evt.data.path.elements,
22                        listNode, listItem,
23                        editor = evt.editor;
24
25                for ( var i = 0 ; i < elements.length ; i++ )
26                {
27                        if ( elements[i].getName() == 'li' )
28                        {
29                                listItem = elements[i];
30                                continue;
31                        }
32                        if ( listNodeNames[ elements[i].getName() ] )
33                        {
34                                listNode = elements[i];
35                                break;
36                        }
37                }
38
39                if ( listNode )
40                {
41                        if ( this.name == 'outdent' )
42                                return setState.call( this, editor, CKEDITOR.TRISTATE_OFF );
43                        else
44                        {
45                                while ( listItem && ( listItem = listItem.getPrevious( CKEDITOR.dom.walker.whitespaces( true ) ) ) )
46                                {
47                                        if ( listItem.getName && listItem.getName() == 'li' )
48                                                return setState.call( this, editor, CKEDITOR.TRISTATE_OFF );
49                                }
50                                return setState.call( this, editor, CKEDITOR.TRISTATE_DISABLED );
51                        }
52                }
53
54                if ( !this.useIndentClasses && this.name == 'indent' )
55                        return setState.call( this, editor, CKEDITOR.TRISTATE_OFF );
56
57                var path = evt.data.path,
58                        firstBlock = path.block || path.blockLimit;
59                if ( !firstBlock )
60                        return setState.call( this, editor, CKEDITOR.TRISTATE_DISABLED );
61
62                if ( this.useIndentClasses )
63                {
64                        var indentClass = firstBlock.$.className.match( this.classNameRegex ),
65                                indentStep = 0;
66                        if ( indentClass )
67                        {
68                                indentClass = indentClass[1];
69                                indentStep = this.indentClassMap[ indentClass ];
70                        }
71                        if ( ( this.name == 'outdent' && !indentStep ) ||
72                                        ( this.name == 'indent' && indentStep == editor.config.indentClasses.length ) )
73                                return setState.call( this, editor, CKEDITOR.TRISTATE_DISABLED );
74                        return setState.call( this, editor, CKEDITOR.TRISTATE_OFF );
75                }
76                else
77                {
78                        var indent = parseInt( firstBlock.getStyle( this.indentCssProperty ), 10 );
79                        if ( isNaN( indent ) )
80                                indent = 0;
81                        if ( indent <= 0 )
82                                return setState.call( this, editor, CKEDITOR.TRISTATE_DISABLED );
83                        return setState.call( this, editor, CKEDITOR.TRISTATE_OFF );
84                }
85        }
86
87        function indentList( editor, range, listNode )
88        {
89                // Our starting and ending points of the range might be inside some blocks under a list item...
90                // So before playing with the iterator, we need to expand the block to include the list items.
91                var startContainer = range.startContainer,
92                        endContainer = range.endContainer;
93                while ( startContainer && !startContainer.getParent().equals( listNode ) )
94                        startContainer = startContainer.getParent();
95                while ( endContainer && !endContainer.getParent().equals( listNode ) )
96                        endContainer = endContainer.getParent();
97
98                if ( !startContainer || !endContainer )
99                        return;
100
101                // Now we can iterate over the individual items on the same tree depth.
102                var block = startContainer,
103                        itemsToMove = [],
104                        stopFlag = false;
105                while ( !stopFlag )
106                {
107                        if ( block.equals( endContainer ) )
108                                stopFlag = true;
109                        itemsToMove.push( block );
110                        block = block.getNext();
111                }
112                if ( itemsToMove.length < 1 )
113                        return;
114
115                // Do indent or outdent operations on the array model of the list, not the
116                // list's DOM tree itself. The array model demands that it knows as much as
117                // possible about the surrounding lists, we need to feed it the further
118                // ancestor node that is still a list.
119                var listParents = listNode.getParents( true );
120                for ( var i = 0 ; i < listParents.length ; i++ )
121                {
122                        if ( listParents[i].getName && listNodeNames[ listParents[i].getName() ] )
123                        {
124                                listNode = listParents[i];
125                                break;
126                        }
127                }
128                var indentOffset = this.name == 'indent' ? 1 : -1,
129                        startItem = itemsToMove[0],
130                        lastItem = itemsToMove[ itemsToMove.length - 1 ],
131                        database = {};
132
133                // Convert the list DOM tree into a one dimensional array.
134                var listArray = CKEDITOR.plugins.list.listToArray( listNode, database );
135
136                // Apply indenting or outdenting on the array.
137                var baseIndent = listArray[ lastItem.getCustomData( 'listarray_index' ) ].indent;
138                for ( i = startItem.getCustomData( 'listarray_index' ) ; i <= lastItem.getCustomData( 'listarray_index' ) ; i++ )
139                        listArray[i].indent += indentOffset;
140                for ( i = lastItem.getCustomData( 'listarray_index' ) + 1 ;
141                                i < listArray.length && listArray[i].indent > baseIndent ; i++ )
142                        listArray[i].indent += indentOffset;
143
144                // Convert the array back to a DOM forest (yes we might have a few subtrees now).
145                // And replace the old list with the new forest.
146                var newList = CKEDITOR.plugins.list.arrayToList( listArray, database, null, editor.config.enterMode, 0 );
147
148                // Avoid nested <li> after outdent even they're visually same,
149                // recording them for later refactoring.(#3982)
150                if ( this.name == 'outdent' )
151                {
152                        var parentLiElement;
153                        if ( ( parentLiElement = listNode.getParent() ) && parentLiElement.is( 'li' ) )
154                        {
155                                var children = newList.listNode.getChildren(),
156                                        pendingLis = [],
157                                        count = children.count(),
158                                        child;
159
160                                for ( i = count - 1 ; i >= 0 ; i-- )
161                                {
162                                        if( ( child = children.getItem( i ) ) && child.is && child.is( 'li' )  )
163                                                pendingLis.push( child );
164                                }
165                        }
166                }
167
168                if ( newList )
169                        newList.listNode.replace( listNode );
170
171                // Move the nested <li> to be appeared after the parent.
172                if ( pendingLis && pendingLis.length )
173                {
174                        for (  i = 0; i < pendingLis.length ; i++ )
175                        {
176                                var li = pendingLis[ i ],
177                                        followingList = li;
178
179                                // Nest preceding <ul>/<ol> inside current <li> if any.
180                                while( ( followingList = followingList.getNext() ) &&
181                                           followingList.is &&
182                                           followingList.getName() in listNodeNames )
183                                {
184                                        li.append( followingList );
185                                }
186
187                                li.insertAfter( parentLiElement );
188                        }
189                }
190
191                // Clean up the markers.
192                CKEDITOR.dom.element.clearAllMarkers( database );
193        }
194
195        function indentBlock( editor, range )
196        {
197                var iterator = range.createIterator(),
198                        enterMode = editor.config.enterMode;
199                iterator.enforceRealBlocks = true;
200                iterator.enlargeBr = enterMode != CKEDITOR.ENTER_BR;
201                var block;
202                while ( ( block = iterator.getNextParagraph() ) )
203                {
204
205                        if ( this.useIndentClasses )
206                        {
207                                // Transform current class name to indent step index.
208                                var indentClass = block.$.className.match( this.classNameRegex ),
209                                        indentStep = 0;
210                                if ( indentClass )
211                                {
212                                        indentClass = indentClass[1];
213                                        indentStep = this.indentClassMap[ indentClass ];
214                                }
215
216                                // Operate on indent step index, transform indent step index back to class
217                                // name.
218                                if ( this.name == 'outdent' )
219                                        indentStep--;
220                                else
221                                        indentStep++;
222                                indentStep = Math.min( indentStep, editor.config.indentClasses.length );
223                                indentStep = Math.max( indentStep, 0 );
224                                var className = CKEDITOR.tools.ltrim( block.$.className.replace( this.classNameRegex, '' ) );
225                                if ( indentStep < 1 )
226                                        block.$.className = className;
227                                else
228                                        block.addClass( editor.config.indentClasses[ indentStep - 1 ] );
229                        }
230                        else
231                        {
232                                var currentOffset = parseInt( block.getStyle( this.indentCssProperty ), 10 );
233                                if ( isNaN( currentOffset ) )
234                                        currentOffset = 0;
235                                currentOffset += ( this.name == 'indent' ? 1 : -1 ) * editor.config.indentOffset;
236                                currentOffset = Math.max( currentOffset, 0 );
237                                currentOffset = Math.ceil( currentOffset / editor.config.indentOffset ) * editor.config.indentOffset;
238                                block.setStyle( this.indentCssProperty, currentOffset ? currentOffset + editor.config.indentUnit : '' );
239                                if ( block.getAttribute( 'style' ) === '' )
240                                        block.removeAttribute( 'style' );
241                        }
242                }
243        }
244
245        function indentCommand( editor, name )
246        {
247                this.name = name;
248                this.useIndentClasses = editor.config.indentClasses && editor.config.indentClasses.length > 0;
249                if ( this.useIndentClasses )
250                {
251                        this.classNameRegex = new RegExp( '(?:^|\\s+)(' + editor.config.indentClasses.join( '|' ) + ')(?=$|\\s)' );
252                        this.indentClassMap = {};
253                        for ( var i = 0 ; i < editor.config.indentClasses.length ; i++ )
254                                this.indentClassMap[ editor.config.indentClasses[i] ] = i + 1;
255                }
256                else
257                        this.indentCssProperty = editor.config.contentsLangDirection == 'ltr' ? 'margin-left' : 'margin-right';
258        }
259
260        indentCommand.prototype = {
261                exec : function( editor )
262                {
263                        var selection = editor.getSelection(),
264                                range = selection && selection.getRanges()[0];
265
266                        if ( !selection || !range )
267                                return;
268
269                        var bookmarks = selection.createBookmarks( true ),
270                                nearestListBlock = range.getCommonAncestor();
271
272                        while ( nearestListBlock && !( nearestListBlock.type == CKEDITOR.NODE_ELEMENT &&
273                                listNodeNames[ nearestListBlock.getName() ] ) )
274                                nearestListBlock = nearestListBlock.getParent();
275
276                        if ( nearestListBlock )
277                                indentList.call( this, editor, range, nearestListBlock );
278                        else
279                                indentBlock.call( this, editor, range );
280
281                        editor.focus();
282                        editor.forceNextSelectionCheck();
283                        selection.selectBookmarks( bookmarks );
284                }
285        };
286
287        CKEDITOR.plugins.add( 'indent',
288        {
289                init : function( editor )
290                {
291                        // Register commands.
292                        var indent = new indentCommand( editor, 'indent' ),
293                                outdent = new indentCommand( editor, 'outdent' );
294                        editor.addCommand( 'indent', indent );
295                        editor.addCommand( 'outdent', outdent );
296
297                        // Register the toolbar buttons.
298                        editor.ui.addButton( 'Indent',
299                                {
300                                        label : editor.lang.indent,
301                                        command : 'indent'
302                                });
303                        editor.ui.addButton( 'Outdent',
304                                {
305                                        label : editor.lang.outdent,
306                                        command : 'outdent'
307                                });
308
309                        // Register the state changing handlers.
310                        editor.on( 'selectionChange', CKEDITOR.tools.bind( onSelectionChange, indent ) );
311                        editor.on( 'selectionChange', CKEDITOR.tools.bind( onSelectionChange, outdent ) );
312                },
313
314                requires : [ 'domiterator', 'list' ]
315        } );
316})();
317
318CKEDITOR.tools.extend( CKEDITOR.config,
319        {
320                indentOffset : 40,
321                indentUnit : 'px',
322                indentClasses : null
323        });
Note: See TracBrowser for help on using the repository browser.