Changeset 846
- Timestamp:
- 09/19/07 16:50:29 (6 years ago)
- Location:
- FCKeditor/trunk/editor/_source
- Files:
-
- 2 edited
-
commandclasses/fckindentcommands.js (modified) (4 diffs)
-
internals/fckdomtools.js (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
FCKeditor/trunk/editor/_source/commandclasses/fckindentcommands.js
r837 r846 85 85 var listNode = FCKDomTools.GetCommonParentNode( startContainer, endContainer, ['ul','ol'] ) ; 86 86 87 if ( ( ! FCKIndentCommand._UseIndentClasses && this.Name.IEquals( 'indent' ) ) || listNode ) 87 if ( listNode ) 88 { 89 if ( this.Name.IEquals( 'outdent' ) ) 90 return FCK_TRISTATE_OFF ; 91 var firstItem = FCKTools.GetElementAscensor( startContainer, 'li' ) ; 92 if ( !firstItem || !firstItem.previousSibling ) 93 return FCK_TRISTATE_DISABLED ; 94 return FCK_TRISTATE_OFF ; 95 } 96 if ( ! FCKIndentCommand._UseIndentClasses && this.Name.IEquals( 'indent' ) ) 88 97 return FCK_TRISTATE_OFF; 89 98 … … 166 175 currentOffset += this.Offset ; 167 176 currentOffset = Math.max( currentOffset, 0 ) ; 168 block.style[this.IndentCSSProperty] = currentOffset + 'px' ; 177 currentOffset = Math.ceil( currentOffset / this.Offset ) * this.Offset ; 178 block.style[this.IndentCSSProperty] = currentOffset ? currentOffset + 'px' : '' ; 179 if ( block.getAttribute( 'style' ) == '' ) 180 block.removeAttribute( 'style' ) ; 169 181 } 170 182 } … … 177 189 var startContainer = range.StartContainer ; 178 190 var endContainer = range.EndContainer ; 179 while ( startContainer && ! startContainer.nodeName.IEquals( ['li', 'ul', 'ol'] ))191 while ( startContainer && startContainer.parentNode != listNode ) 180 192 startContainer = startContainer.parentNode ; 181 while ( endContainer && ! endContainer.nodeName.IEquals( ['li', 'ul', 'ol'] ))193 while ( endContainer && endContainer.parentNode != listNode ) 182 194 endContainer = endContainer.parentNode ; 183 195 … … 185 197 return ; 186 198 187 range.SetStart( startContainer, 1 ) ; 188 range.SetEnd( endContainer, 2 ) ; 189 190 // Now we can iterate over the individual items. 191 var iterator = new FCKDomRangeIterator( range ) ; 192 var block ; 199 // Now we can iterate over the individual items on the same tree depth. 200 var block = startContainer ; 193 201 var itemsToMove = [] ; 194 while ( ( block = iterator.GetNextParagraph() ) ) 195 { 196 if ( block.parentNode == listNode ) 197 itemsToMove.push( block ) ; 202 var stopFlag = false ; 203 while ( stopFlag == false ) 204 { 205 if ( block == endContainer ) 206 stopFlag = true ; 207 itemsToMove.push( block ) ; 208 block = block.nextSibling ; 198 209 } 199 210 if ( itemsToMove.length < 1 ) 200 211 return ; 212 213 // Do indent or outdent operations on the array model of the list, not the list's DOM tree itself. 214 // The array model demands that it knows as much as possible about the surrounding lists, we need 215 // to feed it the further ancestor node that is still a list. 216 var listParents = FCKDomTools.GetParents( listNode ) ; 217 for ( var i = 0 ; i < listParents.length ; i++ ) 218 { 219 if ( listParents[i].nodeName.IEquals( ['ul', 'ol'] ) ) 220 { 221 listNode = listParents[i] ; 222 break ; 223 } 224 } 225 var indentOffset = this.Name.IEquals( 'indent' ) ? 1 : -1 ; 226 var startItem = itemsToMove[0] ; 201 227 var lastItem = itemsToMove[ itemsToMove.length - 1 ] ; 202 203 if ( this.Name.IEquals( 'indent' ) ) 204 { 205 // Indent is easy... just clone the list node, add under the original, and 206 // move the contents inside the clone. 207 var indentList = listNode.cloneNode( false ) ; 208 FCKDomTools.InsertAfterNode( lastItem, indentList ) ; 209 while ( itemsToMove.length > 0 ) 210 indentList.appendChild( itemsToMove.shift() ) ; 211 } 212 else if ( this.Name.IEquals( 'outdent' ) ) 213 { 214 var startItem = itemsToMove[0] ; 215 216 // If we're in the middle of the list, we will have to split the list into two. 217 if ( startItem.previousSibling && lastItem.nextSibling ) 218 { 219 range.SetStart( startItem, 3 ) ; 220 range.SetEnd( startItem, 3 ) ; 221 listNode = range.SplitBlock().NextBlock ; 222 } 223 224 // Remove the list items. 225 for ( var i = 0 ; i < itemsToMove.length ; i++ ) 226 itemsToMove[i].parentNode.removeChild( itemsToMove[i] ) ; 227 228 // If the parent of listNode is not another list, then we need to convert the 229 // listItems into paragraphs, depending on EnterMode. 230 if ( ! listNode.parentNode.nodeName.IEquals( ['ul', 'ol'] ) ) 231 { 232 for ( var i = 0 ; i < itemsToMove.length ; i++ ) 228 var markerObj = {} ; 229 230 // Convert the list DOM tree into a one dimensional array. 231 var listArray = FCKDomTools.ListToArray( listNode, null, null, markerObj ) ; 232 233 // Apply indenting or outdenting on the array. 234 var baseIndent = listArray[lastItem._FCK_ListArray_Index].indent ; 235 for ( var i = startItem._FCK_ListArray_Index ; i <= lastItem._FCK_ListArray_Index ; i++ ) 236 listArray[i].indent += indentOffset ; 237 for ( var i = lastItem._FCK_ListArray_Index + 1 ; i < listArray.length && listArray[i].indent > baseIndent ; i++ ) 238 listArray[i].indent += indentOffset ; 239 240 /* For debug use only 241 var PrintArray = function( listArray, doc ) 242 { 243 var s = [] ; 244 for ( var i = 0 ; i < listArray.length ; i++ ) 245 { 246 for ( var j in listArray[i] ) 233 247 { 234 var container ; 235 if ( FCKConfig.EnterMode.IEquals( ['p', 'div'] ) ) 236 container = listNode.ownerDocument.createElement( FCKConfig.EnterMode ) ; 248 if ( j != 'contents' ) 249 s.push( j + ":" + listArray[i][j] + "; " ) ; 237 250 else 238 251 { 239 container = listNode.ownerDocument.createDocumentFragment() ; 240 container.appendChild( listNode.ownerDocument.createElement( 'br' ) ) ; 252 var docFrag = doc.createDocumentFragment() ; 253 var tmpNode = doc.createElement( 'span' ) ; 254 for ( var k = 0 ; k < listArray[i][j].length ; k++ ) 255 docFrag.appendChild( listArray[i][j][k].cloneNode( true ) ) ; 256 tmpNode.appendChild( docFrag ) ; 257 s.push( j + ":" + tmpNode.innerHTML + "; ") ; 241 258 } 242 243 var listItem = itemsToMove[i] ;244 while ( listItem.lastChild )245 {246 var node = listItem.removeChild( listItem.lastChild ) ;247 container.insertBefore( node, container.firstChild ) ;248 }249 itemsToMove[i] = container ;250 259 } 251 } 252 253 // Insert the content nodes to listNode's parent. 254 while ( itemsToMove.length > 0 ) 255 listNode.parentNode.insertBefore( itemsToMove.shift(), listNode ) ; 256 257 // Cleanup: if the listNode becomes empty, remove it. 258 if ( ! listNode.lastChild ) 259 listNode.parentNode.removeChild( listNode ) ; 260 } 260 s.push( '\n' ) ; 261 } 262 alert( s.join('') ) ; 263 } 264 PrintArray( listArray, FCK.EditorDocument ) ; 265 */ 266 267 // Convert the array back to a DOM forest (yes we might have a few subtrees now). 268 // And replace the old list with the new forest. 269 var newList = FCKDomTools.ArrayToList( listArray ) ; 270 listNode.parentNode.replaceChild( newList.listNode, listNode ) ; 271 272 // Clean up the markers. 273 FCKDomTools.ClearElementMarkers( markerObj ) ; 261 274 } 262 275 } ; -
FCKeditor/trunk/editor/_source/internals/fckdomtools.js
r824 r846 575 575 576 576 return element ; 577 }, 578 579 ClearElementJSProperty : function( element, attrName ) 580 { 581 if ( FCKBrowserInfo.IsIE ) 582 element.removeAttribute( attrName ) ; 583 else 584 delete element[attrName] ; 585 }, 586 587 SetElementMarker : function ( markObj, element, attrName, value) 588 { 589 var id = String( parseInt( Math.random() * 0xfffffff, 10 ) ) ; 590 element._FCKMarkerId = id ; 591 element[attrName] = value ; 592 if ( ! markObj[id] ) 593 markObj[id] = { 'element' : element, 'markers' : {} } ; 594 markObj[id]['markers'][attrName] = value ; 595 }, 596 597 ClearElementMarkers : function( markObj ) 598 { 599 for ( var i in markObj ) 600 { 601 var element = markObj[i]['element'] ; 602 this.ClearElementJSProperty( element, '_FCKMarkerId' ) ; 603 for ( var j in markObj[i]['markers'] ) 604 this.ClearElementJSProperty( element, j ) ; 605 delete markObj[i] ; 606 } 607 }, 608 609 // Convert a DOM list tree into a data structure that is easier to manipulate. 610 // This operation should be non-intrusive in the sense that it does not change the DOM tree, 611 // with the exception that it may add some markers to the list item nodes when markerObj is specified. 612 ListToArray : function( listNode, baseArray, baseIndentLevel, markerObj ) 613 { 614 if ( ! listNode.nodeName.IEquals( ['ul', 'ol'] ) ) 615 return [] ; 616 617 if ( ! baseIndentLevel ) 618 baseIndentLevel = 0 ; 619 if ( ! baseArray ) 620 baseArray = [] ; 621 // Iterate over all list items to get their contents and look for inner lists. 622 for ( var i = 0 ; i < listNode.childNodes.length ; i++ ) 623 { 624 var listItem = listNode.childNodes[i] ; 625 if ( ! listItem.nodeName.IEquals( 'li' ) ) 626 continue ; 627 var itemObj = { 'grandparent' : listNode.parentNode, 'parent' : listNode, 'indent' : baseIndentLevel, 'contents' : [] } ; 628 if ( itemObj.grandparent && itemObj.grandparent.nodeName.IEquals( 'li' ) ) 629 itemObj.grandparent = itemObj.grandparent.parentNode ; 630 if ( markerObj ) 631 this.SetElementMarker( markerObj, listItem, '_FCK_ListArray_Index', baseArray.length ) ; 632 baseArray.push( itemObj ) ; 633 for ( var j = 0 ; j < listItem.childNodes.length ; j++ ) 634 { 635 var child = listItem.childNodes[j] ; 636 if ( child.nodeName.IEquals( ['ul', 'ol'] ) ) 637 // Note the recursion here, it pushes inner list items with +1 indentation in the correct 638 // order. 639 this.ListToArray( child, baseArray, baseIndentLevel + 1, markerObj ) ; 640 else 641 itemObj.contents.push( child ) ; 642 } 643 } 644 return baseArray ; 645 }, 646 647 // Convert our internal representation of a list back to a DOM tree. 648 ArrayToList : function( listArray, baseIndex ) 649 { 650 if ( baseIndex == undefined ) 651 baseIndex = 0 ; 652 if ( ! listArray || listArray.length < baseIndex + 1 ) 653 return null ; 654 var retval = listArray[baseIndex].parent.ownerDocument.createDocumentFragment() ; 655 var rootNode = listArray[baseIndex].parent.cloneNode( false ) ; 656 retval.appendChild( rootNode ) ; 657 var currentIndex = baseIndex ; 658 var indentLevel = listArray[baseIndex].indent ; 659 var currentListItem = null ; 660 while ( true ) 661 { 662 var item = listArray[currentIndex] ; 663 if ( item.indent == indentLevel ) 664 { 665 if ( ! rootNode || listArray[currentIndex].parent.nodeName != rootNode.nodeName ) 666 { 667 rootNode = listArray[currentIndex].parent.cloneNode( false ) ; 668 retval.appendChild( rootNode ) ; 669 } 670 currentListItem = rootNode.ownerDocument.createElement( 'li' ) ; 671 rootNode.appendChild( currentListItem ) ; 672 for ( var i = 0 ; i < item.contents.length ; i++ ) 673 currentListItem.appendChild( item.contents[i].cloneNode( true ) ) ; 674 currentIndex++ ; 675 } 676 else if ( item.indent == Math.max( indentLevel, 0 ) + 1 ) 677 { 678 var listData = this.ArrayToList( listArray, currentIndex ) ; 679 currentListItem.appendChild( listData.listNode ) ; 680 currentIndex = listData.nextIndex ; 681 } 682 else if ( item.indent == -1 && baseIndex == 0 && item.grandparent ) 683 { 684 var currentListItem ; 685 if ( item.grandparent.nodeName.IEquals( ['ul', 'ol'] ) ) 686 currentListItem = rootNode.ownerDocument.createElement( 'li' ) ; 687 else 688 { 689 if ( FCKConfig.EnterMode.IEquals( ['div', 'p'] ) ) 690 currentListItem = rootNode.ownerDocument.createElement( FCKConfig.EnterMode ) ; 691 else 692 currentListItem = rootNode.ownerDocument.createDocumentFragment() ; 693 } 694 item.grandparent.appendChild( currentListItem ) ; 695 for ( var i = 0 ; i < item.contents.length ; i++ ) 696 currentListItem.appendChild( item.contents[i].cloneNode( true ) ) ; 697 if ( currentListItem.nodeType == 11 ) 698 currentListItem.appendChild( currentListItem.ownerDocument.createElement( 'br' ) ) ; 699 retval.appendChild( currentListItem ) ; 700 rootNode = null ; 701 currentIndex++ ; 702 } 703 else 704 break ; 705 706 if ( listArray.length <= currentIndex || Math.max( listArray[currentIndex].indent, 0 ) < indentLevel ) 707 { 708 break ; 709 } 710 } 711 return { 'listNode' : retval, 'nextIndex' : currentIndex } ; 577 712 } 578 713 } ; 714
Note: See TracChangeset
for help on using the changeset viewer.
