PluginProbe
Wp-Insert / 1.7.2
Wp-Insert v1.7.2
trunk 1.0 1.1 1.2 1.2.1 1.2.2 1.3.0 1.3.1 1.3.3 1.4 1.5.0 1.5.1 1.5.2 1.5.3 1.6.0 1.6.1 1.6.2 1.7 1.7.1 1.7.2 1.7.3 1.7.4 1.7.5 1.7.6 2.0 All 63 releases
wp-insert / fckeditor / editor / _source / commandclasses / fckindentcommands.js

fckindentcommands.js in Wp-Insert 1.7.2, at fckeditor/editor/_source/commandclasses/fckindentcommands.js

283 lines 9.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /*
2 * FCKeditor - The text editor for Internet - http://www.fckeditor.net
3 * Copyright (C) 2003-2009 Frederico Caldeira Knabben
4 *
5 * == BEGIN LICENSE ==
6 *
7 * Licensed under the terms of any of the following licenses at your
8 * choice:
9 *
10 * - GNU General Public License Version 2 or later (the "GPL")
11 * http://www.gnu.org/licenses/gpl.html
12 *
13 * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
14 * http://www.gnu.org/licenses/lgpl.html
15 *
16 * - Mozilla Public License Version 1.1 or later (the "MPL")
17 * http://www.mozilla.org/MPL/MPL-1.1.html
18 *
19 * == END LICENSE ==
20 *
21 * FCKIndentCommand Class: controls block indentation.
22 */
23
24 var FCKIndentCommand = function( name, offset )
25 {
26 this.Name = name ;
27 this.Offset = offset ;
28 this.IndentCSSProperty = FCKConfig.ContentLangDirection.IEquals( 'ltr' ) ? 'marginLeft' : 'marginRight' ;
29 }
30
31 FCKIndentCommand._InitIndentModeParameters = function()
32 {
33 if ( FCKConfig.IndentClasses && FCKConfig.IndentClasses.length > 0 )
34 {
35 this._UseIndentClasses = true ;
36 this._IndentClassMap = {} ;
37 for ( var i = 0 ; i < FCKConfig.IndentClasses.length ;i++ )
38 this._IndentClassMap[FCKConfig.IndentClasses[i]] = i + 1 ;
39 this._ClassNameRegex = new RegExp( '(?:^|\\s+)(' + FCKConfig.IndentClasses.join( '|' ) + ')(?=$|\\s)' ) ;
40 }
41 else
42 this._UseIndentClasses = false ;
43 }
44
45
46 FCKIndentCommand.prototype =
47 {
48 Execute : function()
49 {
50 // Save an undo snapshot before doing anything.
51 FCKUndo.SaveUndoStep() ;
52
53 var range = new FCKDomRange( FCK.EditorWindow ) ;
54 range.MoveToSelection() ;
55 var bookmark = range.CreateBookmark() ;
56
57 // Two cases to handle here: either we're in a list, or not.
58 // If we're in a list, then the indent/outdent operations would be done on the list nodes.
59 // Otherwise, apply the operation on the nearest block nodes.
60 var nearestListBlock = FCKDomTools.GetCommonParentNode( range.StartNode || range.StartContainer ,
61 range.EndNode || range.EndContainer,
62 ['ul', 'ol'] ) ;
63 if ( nearestListBlock )
64 this._IndentList( range, nearestListBlock ) ;
65 else
66 this._IndentBlock( range ) ;
67
68 range.MoveToBookmark( bookmark ) ;
69 range.Select() ;
70
71 FCK.Focus() ;
72 FCK.Events.FireEvent( 'OnSelectionChange' ) ;
73 },
74
75 GetState : function()
76 {
77 // Disabled if not WYSIWYG.
78 if ( FCK.EditMode != FCK_EDITMODE_WYSIWYG || ! FCK.EditorWindow )
79 return FCK_TRISTATE_DISABLED ;
80
81 // Initialize parameters if not already initialzed.
82 if ( FCKIndentCommand._UseIndentClasses == undefined )
83 FCKIndentCommand._InitIndentModeParameters() ;
84
85 // If we're not in a list, and the starting block's indentation is zero, and the current
86 // command is the outdent command, then we should return FCK_TRISTATE_DISABLED.
87 var startContainer = FCKSelection.GetBoundaryParentElement( true ) ;
88 var endContainer = FCKSelection.GetBoundaryParentElement( false ) ;
89 var listNode = FCKDomTools.GetCommonParentNode( startContainer, endContainer, ['ul','ol'] ) ;
90
91 if ( listNode )
92 {
93 if ( this.Name.IEquals( 'outdent' ) )
94 return FCK_TRISTATE_OFF ;
95 var firstItem = FCKTools.GetElementAscensor( startContainer, 'li' ) ;
96 if ( !firstItem || !firstItem.previousSibling )
97 return FCK_TRISTATE_DISABLED ;
98 return FCK_TRISTATE_OFF ;
99 }
100 if ( ! FCKIndentCommand._UseIndentClasses && this.Name.IEquals( 'indent' ) )
101 return FCK_TRISTATE_OFF;
102
103 var path = new FCKElementPath( startContainer ) ;
104 var firstBlock = path.Block || path.BlockLimit ;
105 if ( !firstBlock )
106 return FCK_TRISTATE_DISABLED ;
107
108 if ( FCKIndentCommand._UseIndentClasses )
109 {
110 var indentClass = firstBlock.className.match( FCKIndentCommand._ClassNameRegex ) ;
111 var indentStep = 0 ;
112 if ( indentClass != null )
113 {
114 indentClass = indentClass[1] ;
115 indentStep = FCKIndentCommand._IndentClassMap[indentClass] ;
116 }
117 if ( ( this.Name == 'outdent' && indentStep == 0 ) ||
118 ( this.Name == 'indent' && indentStep == FCKConfig.IndentClasses.length ) )
119 return FCK_TRISTATE_DISABLED ;
120 return FCK_TRISTATE_OFF ;
121 }
122 else
123 {
124 var indent = parseInt( firstBlock.style[this.IndentCSSProperty], 10 ) ;
125 if ( isNaN( indent ) )
126 indent = 0 ;
127 if ( indent <= 0 )
128 return FCK_TRISTATE_DISABLED ;
129 return FCK_TRISTATE_OFF ;
130 }
131 },
132
133 _IndentBlock : function( range )
134 {
135 var iterator = new FCKDomRangeIterator( range ) ;
136 iterator.EnforceRealBlocks = true ;
137
138 range.Expand( 'block_contents' ) ;
139 var commonParents = FCKDomTools.GetCommonParents( range.StartContainer, range.EndContainer ) ;
140 var nearestParent = commonParents[commonParents.length - 1] ;
141 var block ;
142
143 while ( ( block = iterator.GetNextParagraph() ) )
144 {
145 // We don't want to indent subtrees recursively, so only perform the indent operation
146 // if the block itself is the nearestParent, or the block's parent is the nearestParent.
147 if ( ! ( block == nearestParent || block.parentNode == nearestParent ) )
148 continue ;
149
150 if ( FCKIndentCommand._UseIndentClasses )
151 {
152 // Transform current class name to indent step index.
153 var indentClass = block.className.match( FCKIndentCommand._ClassNameRegex ) ;
154 var indentStep = 0 ;
155 if ( indentClass != null )
156 {
157 indentClass = indentClass[1] ;
158 indentStep = FCKIndentCommand._IndentClassMap[indentClass] ;
159 }
160
161 // Operate on indent step index, transform indent step index back to class name.
162 if ( this.Name.IEquals( 'outdent' ) )
163 indentStep-- ;
164 else if ( this.Name.IEquals( 'indent' ) )
165 indentStep++ ;
166 indentStep = Math.min( indentStep, FCKConfig.IndentClasses.length ) ;
167 indentStep = Math.max( indentStep, 0 ) ;
168 var className = block.className.replace( FCKIndentCommand._ClassNameRegex, '' ) ;
169 if ( indentStep < 1 )
170 block.className = className ;
171 else
172 block.className = ( className.length > 0 ? className + ' ' : '' ) +
173 FCKConfig.IndentClasses[indentStep - 1] ;
174 }
175 else
176 {
177 // Offset distance is assumed to be in pixels for now.
178 var currentOffset = parseInt( block.style[this.IndentCSSProperty], 10 ) ;
179 if ( isNaN( currentOffset ) )
180 currentOffset = 0 ;
181 currentOffset += this.Offset ;
182 currentOffset = Math.max( currentOffset, 0 ) ;
183 currentOffset = Math.ceil( currentOffset / this.Offset ) * this.Offset ;
184 block.style[this.IndentCSSProperty] = currentOffset ? currentOffset + FCKConfig.IndentUnit : '' ;
185 if ( block.getAttribute( 'style' ) == '' )
186 block.removeAttribute( 'style' ) ;
187 }
188 }
189 },
190
191 _IndentList : function( range, listNode )
192 {
193 // Our starting and ending points of the range might be inside some blocks under a list item...
194 // So before playing with the iterator, we need to expand the block to include the list items.
195 var startContainer = range.StartContainer ;
196 var endContainer = range.EndContainer ;
197 while ( startContainer && startContainer.parentNode != listNode )
198 startContainer = startContainer.parentNode ;
199 while ( endContainer && endContainer.parentNode != listNode )
200 endContainer = endContainer.parentNode ;
201
202 if ( ! startContainer || ! endContainer )
203 return ;
204
205 // Now we can iterate over the individual items on the same tree depth.
206 var block = startContainer ;
207 var itemsToMove = [] ;
208 var stopFlag = false ;
209 while ( stopFlag == false )
210 {
211 if ( block == endContainer )
212 stopFlag = true ;
213 itemsToMove.push( block ) ;
214 block = block.nextSibling ;
215 }
216 if ( itemsToMove.length < 1 )
217 return ;
218
219 // Do indent or outdent operations on the array model of the list, not the list's DOM tree itself.
220 // The array model demands that it knows as much as possible about the surrounding lists, we need
221 // to feed it the further ancestor node that is still a list.
222 var listParents = FCKDomTools.GetParents( listNode ) ;
223 for ( var i = 0 ; i < listParents.length ; i++ )
224 {
225 if ( listParents[i].nodeName.IEquals( ['ul', 'ol'] ) )
226 {
227 listNode = listParents[i] ;
228 break ;
229 }
230 }
231 var indentOffset = this.Name.IEquals( 'indent' ) ? 1 : -1 ;
232 var startItem = itemsToMove[0] ;
233 var lastItem = itemsToMove[ itemsToMove.length - 1 ] ;
234 var markerObj = {} ;
235
236 // Convert the list DOM tree into a one dimensional array.
237 var listArray = FCKDomTools.ListToArray( listNode, markerObj ) ;
238
239 // Apply indenting or outdenting on the array.
240 var baseIndent = listArray[lastItem._FCK_ListArray_Index].indent ;
241 for ( var i = startItem._FCK_ListArray_Index ; i <= lastItem._FCK_ListArray_Index ; i++ )
242 listArray[i].indent += indentOffset ;
243 for ( var i = lastItem._FCK_ListArray_Index + 1 ; i < listArray.length && listArray[i].indent > baseIndent ; i++ )
244 listArray[i].indent += indentOffset ;
245
246 /* For debug use only
247 var PrintArray = function( listArray, doc )
248 {
249 var s = [] ;
250 for ( var i = 0 ; i < listArray.length ; i++ )
251 {
252 for ( var j in listArray[i] )
253 {
254 if ( j != 'contents' )
255 s.push( j + ":" + listArray[i][j] + "; " ) ;
256 else
257 {
258 var docFrag = doc.createDocumentFragment() ;
259 var tmpNode = doc.createElement( 'span' ) ;
260 for ( var k = 0 ; k < listArray[i][j].length ; k++ )
261 docFrag.appendChild( listArray[i][j][k].cloneNode( true ) ) ;
262 tmpNode.appendChild( docFrag ) ;
263 s.push( j + ":" + tmpNode.innerHTML + "; ") ;
264 }
265 }
266 s.push( '\n' ) ;
267 }
268 alert( s.join('') ) ;
269 }
270 PrintArray( listArray, FCK.EditorDocument ) ;
271 */
272
273 // Convert the array back to a DOM forest (yes we might have a few subtrees now).
274 // And replace the old list with the new forest.
275 var newList = FCKDomTools.ArrayToList( listArray ) ;
276 if ( newList )
277 listNode.parentNode.replaceChild( newList.listNode, listNode ) ;
278
279 // Clean up the markers.
280 FCKDomTools.ClearAllMarkers( markerObj ) ;
281 }
282 } ;
283