1/* 2 * FCKeditor - The text editor for Internet - http://www.fckeditor.net 3 * Copyright (C) 2003-2007 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 * Tool object to manage HTML lists items (UL, OL and LI). 22 */ 23 24var FCKListHandler = 25{ 26 OutdentListItem : function( listItem ) 27 { 28 var eParent = listItem.parentNode ; 29 30 // It may happen that a LI is not in a UL or OL (Orphan). 31 if ( eParent.tagName.toUpperCase().Equals( 'UL','OL' ) ) 32 { 33 var oDocument = FCKTools.GetElementDocument( listItem ) ; 34 var oDogFrag = new FCKDocumentFragment( oDocument ) ; 35 36 // All children and successive siblings will be moved to a a DocFrag. 37 var eNextSiblings = oDogFrag.RootNode ; 38 var eHasLiSibling = false ; 39 40 // If we have nested lists inside it, let's move it to the list of siblings. 41 var eChildList = FCKDomTools.GetFirstChild( listItem, ['UL','OL'] ) ; 42 if ( eChildList ) 43 { 44 eHasLiSibling = true ; 45 46 var eChild ; 47 // The extra () is to avoid a warning with strict error checking. This is ok. 48 while ( (eChild = eChildList.firstChild) ) 49 eNextSiblings.appendChild( eChildList.removeChild( eChild ) ) ; 50 51 FCKDomTools.RemoveNode( eChildList ) ; 52 } 53 54 // Move all successive siblings. 55 var eSibling ; 56 var eHasSuccessiveLiSibling = false ; 57 // The extra () is to avoid a warning with strict error checking. This is ok. 58 while ( (eSibling = listItem.nextSibling) ) 59 { 60 if ( !eHasLiSibling && eSibling.nodeType == 1 && eSibling.nodeName.toUpperCase() == 'LI' ) 61 eHasSuccessiveLiSibling = eHasLiSibling = true ; 62 63 eNextSiblings.appendChild( eSibling.parentNode.removeChild( eSibling ) ) ; 64 65 // If a sibling is a incorrectly nested UL or OL, consider only its children. 66 if ( !eHasSuccessiveLiSibling && eSibling.nodeType == 1 && eSibling.nodeName.toUpperCase().Equals( 'UL','OL' ) ) 67 FCKDomTools.RemoveNode( eSibling, true ) ; 68 } 69 70 // If we are in a list chain. 71 var sParentParentTag = eParent.parentNode.tagName.toUpperCase() ; 72 var bWellNested = ( sParentParentTag == 'LI' ) ; 73 if ( bWellNested || sParentParentTag.Equals( 'UL','OL' ) ) 74 { 75 if ( eHasLiSibling ) 76 { 77 var eChildList = eParent.cloneNode( false ) ; 78 oDogFrag.AppendTo( eChildList ) ; 79 listItem.appendChild( eChildList ) ; 80 } 81 else if ( bWellNested ) 82 oDogFrag.InsertAfterNode( eParent.parentNode ) ; 83 else 84 oDogFrag.InsertAfterNode( eParent ) ; 85 86 // Move the LI after its parent.parentNode (the upper LI in the hierarchy). 87 if ( bWellNested ) 88 FCKDomTools.InsertAfterNode( eParent.parentNode, eParent.removeChild( listItem ) ) ; 89 else 90 FCKDomTools.InsertAfterNode( eParent, eParent.removeChild( listItem ) ) ; 91 } 92 else 93 { 94 if ( eHasLiSibling ) 95 { 96 var eNextList = eParent.cloneNode( false ) ; 97 oDogFrag.AppendTo( eNextList ) ; 98 FCKDomTools.InsertAfterNode( eParent, eNextList ) ; 99 } 100 101 var eBlock = oDocument.createElement( FCKConfig.EnterMode == 'p' ? 'p' : 'div' ) ; 102 FCKDomTools.MoveChildren( eParent.removeChild( listItem ), eBlock ) ; 103 FCKDomTools.InsertAfterNode( eParent, eBlock ) ; 104 105 if ( FCKConfig.EnterMode == 'br' ) 106 { 107 // We need the bogus to make it work properly. In Gecko, we 108 // need it before the new block, on IE, after it. 109 if ( FCKBrowserInfo.IsGecko ) 110 eBlock.parentNode.insertBefore( FCKTools.CreateBogusBR( oDocument ), eBlock ) ; 111 else 112 FCKDomTools.InsertAfterNode( eBlock, FCKTools.CreateBogusBR( oDocument ) ) ; 113 114 FCKDomTools.RemoveNode( eBlock, true ) ; 115 } 116 } 117 118 if ( this.CheckEmptyList( eParent ) ) 119 FCKDomTools.RemoveNode( eParent, true ) ; 120 } 121 }, 122 123 CheckEmptyList : function( listElement ) 124 { 125 return ( FCKDomTools.GetFirstChild( listElement, 'LI' ) == null ) ; 126 }, 127 128 // Check if the list has contents (excluding nested lists). 129 CheckListHasContents : function( listElement ) 130 { 131 var eChildNode = listElement.firstChild ; 132 133 while ( eChildNode ) 134 { 135 switch ( eChildNode.nodeType ) 136 { 137 case 1 : 138 if ( !eChildNode.nodeName.IEquals( 'UL','LI' ) ) 139 return true ; 140 break ; 141 142 case 3 : 143 if ( eChildNode.nodeValue.Trim().length > 0 ) 144 return true ; 145 } 146 147 eChildNode = eChildNode.nextSibling ; 148 } 149 150 return false ; 151 } 152} ;