0byt3m1n1 - D7net
0byt3m1n1 - D7net
Path:
/
home
/
s13cf5ef
/
www
/
tuscamisetaspersonalizadas.es
/
admin
/
fckeditor
/
editor
/
_source
/
commandclasses
/
[
Home
]
Name File: fcklistcommands.js
< back
/* * FCKeditor - The text editor for Internet - http://www.fckeditor.net * Copyright (C) 2003-2007 Frederico Caldeira Knabben * * == BEGIN LICENSE == * * Licensed under the terms of any of the following licenses at your * choice: * * - GNU General Public License Version 2 or later (the "GPL") * http://www.gnu.org/licenses/gpl.html * * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") * http://www.gnu.org/licenses/lgpl.html * * - Mozilla Public License Version 1.1 or later (the "MPL") * http://www.mozilla.org/MPL/MPL-1.1.html * * == END LICENSE == * * Implementation for the "Insert/Remove Ordered/Unordered List" commands. */ var FCKListCommand = function( name, tagName ) { this.Name = name ; this.TagName = tagName ; } FCKListCommand.prototype = { GetState : function() { // Disabled if not WYSIWYG. if ( FCK.EditMode != FCK_EDITMODE_WYSIWYG || ! FCK.EditorWindow ) return FCK_TRISTATE_DISABLED ; // We'll use the style system's convention to determine list state here... // If the starting block is a descendant of an <ol> or <ul> node, then we're in a list. var startContainer = FCKSelection.GetBoundaryParentElement( true ) ; var listNode = startContainer ; while ( listNode ) { if ( listNode.nodeName.IEquals( [ 'ul', 'ol' ] ) ) break ; listNode = listNode.parentNode ; } if ( listNode && listNode.nodeName.IEquals( this.TagName ) ) return FCK_TRISTATE_ON ; else return FCK_TRISTATE_OFF ; }, Execute : function() { FCKUndo.SaveUndoStep() ; var doc = FCK.EditorDocument ; var range = new FCKDomRange( FCK.EditorWindow ) ; range.MoveToSelection() ; var state = this.GetState() ; // Midas lists rule #1 says we can create a list even in an empty document. // But FCKDomRangeIterator wouldn't run if the document is really empty. // So create a paragraph if the document is empty and we're going to create a list. if ( state == FCK_TRISTATE_OFF ) { FCKDomTools.TrimNode( doc.body ) ; if ( ! doc.body.firstChild ) { var paragraph = doc.createElement( 'p' ) ; doc.body.appendChild( paragraph ) ; range.MoveToNodeContents( paragraph ) ; } } var bookmark = range.CreateBookmark() ; // Group the blocks up because there are many cases where multiple lists have to be created, // or multiple lists have to be cancelled. var listGroups = [] ; var markerObj = {} ; var iterator = new FCKDomRangeIterator( range ) ; var block ; iterator.ForceBrBreak = ( state == FCK_TRISTATE_OFF ) ; var nextRangeExists = true ; var rangeQueue = null ; while ( nextRangeExists ) { while ( ( block = iterator.GetNextParagraph() ) ) { var path = new FCKElementPath( block ) ; var listNode = null ; var processedFlag = false ; var blockLimit = path.BlockLimit ; // First, try to group by a list ancestor. for ( var i = path.Elements.length - 1 ; i >= 0 ; i-- ) { var el = path.Elements[i] ; if ( el.nodeName.IEquals( ['ol', 'ul'] ) ) { // If we've encountered a list inside a block limit // The last group object of the block limit element should // no longer be valid. Since paragraphs after the list // should belong to a different group of paragraphs before // the list. (Bug #1309) if ( blockLimit._FCK_ListGroupObject ) blockLimit._FCK_ListGroupObject = null ; var groupObj = el._FCK_ListGroupObject ; if ( groupObj ) groupObj.contents.push( block ) ; else { groupObj = { 'root' : el, 'contents' : [ block ] } ; listGroups.push( groupObj ) ; FCKDomTools.SetElementMarker( markerObj, el, '_FCK_ListGroupObject', groupObj ) ; } processedFlag = true ; break ; } } if ( processedFlag ) continue ; // No list ancestor? Group by block limit. var root = blockLimit ; if ( root._FCK_ListGroupObject ) root._FCK_ListGroupObject.contents.push( block ) ; else { var groupObj = { 'root' : root, 'contents' : [ block ] } ; FCKDomTools.SetElementMarker( markerObj, root, '_FCK_ListGroupObject', groupObj ) ; listGroups.push( groupObj ) ; } } if ( FCKBrowserInfo.IsIE ) nextRangeExists = false ; else { if ( rangeQueue == null ) { rangeQueue = [] ; var selectionObject = FCK.EditorWindow.getSelection() ; if ( selectionObject && listGroups.length == 0 ) rangeQueue.push( selectionObject.getRangeAt( 0 ) ) ; for ( var i = 1 ; selectionObject && i < selectionObject.rangeCount ; i++ ) rangeQueue.push( selectionObject.getRangeAt( i ) ) ; } if ( rangeQueue.length < 1 ) nextRangeExists = false ; else { var internalRange = FCKW3CRange.CreateFromRange( doc, rangeQueue.shift() ) ; range._Range = internalRange ; range._UpdateElementInfo() ; if ( range.StartNode.nodeName.IEquals( 'td' ) ) range.SetStart( range.StartNode, 1 ) ; if ( range.EndNode.nodeName.IEquals( 'td' ) ) range.SetEnd( range.EndNode, 2 ) ; iterator = new FCKDomRangeIterator( range ) ; iterator.ForceBrBreak = ( state == FCK_TRISTATE_OFF ) ; } } } // Now we have two kinds of list groups, groups rooted at a list, and groups rooted at a block limit element. // We either have to build lists or remove lists, for removing a list does not makes sense when we are looking // at the group that's not rooted at lists. So we have three cases to handle. var listsCreated = [] ; while ( listGroups.length > 0 ) { var groupObj = listGroups.shift() ; if ( state == FCK_TRISTATE_OFF ) { if ( groupObj.root.nodeName.IEquals( ['ul', 'ol'] ) ) this._ChangeListType( groupObj, markerObj, listsCreated ) ; else this._CreateList( groupObj, listsCreated ) ; } else if ( state == FCK_TRISTATE_ON && groupObj.root.nodeName.IEquals( ['ul', 'ol'] ) ) this._RemoveList( groupObj, markerObj ) ; } // For all new lists created, merge adjacent, same type lists. for ( var i = 0 ; i < listsCreated.length ; i++ ) { var listNode = listsCreated[i] ; var stopFlag = false ; var currentNode = listNode ; while ( ! stopFlag ) { currentNode = currentNode.nextSibling ; if ( currentNode && currentNode.nodeType == 3 && currentNode.nodeValue.search( /^[\n\r\t ]*$/ ) == 0 ) continue ; stopFlag = true ; } if ( currentNode && currentNode.nodeName.IEquals( this.TagName ) ) { currentNode.parentNode.removeChild( currentNode ) ; while ( currentNode.firstChild ) listNode.appendChild( currentNode.removeChild( currentNode.firstChild ) ) ; } stopFlag = false ; currentNode = listNode ; while ( ! stopFlag ) { currentNode = currentNode.previousSibling ; if ( currentNode && currentNode.nodeType == 3 && currentNode.nodeValue.search( /^[\n\r\t ]*$/ ) == 0 ) continue ; stopFlag = true ; } if ( currentNode && currentNode.nodeName.IEquals( this.TagName ) ) { currentNode.parentNode.removeChild( currentNode ) ; while ( currentNode.lastChild ) listNode.insertBefore( currentNode.removeChild( currentNode.lastChild ), listNode.firstChild ) ; } } // Clean up, restore selection and update toolbar button states. FCKDomTools.ClearAllMarkers( markerObj ) ; range.MoveToBookmark( bookmark ) ; range.Select() ; FCK.Focus() ; FCK.Events.FireEvent( 'OnSelectionChange' ) ; }, _ChangeListType : function( groupObj, markerObj, listsCreated ) { // This case is easy... // 1. Convert the whole list into a one-dimensional array. // 2. Change the list type by modifying the array. // 3. Recreate the whole list by converting the array to a list. // 4. Replace the original list with the recreated list. var listArray = FCKDomTools.ListToArray( groupObj.root, markerObj ) ; var selectedListItems = [] ; for ( var i = 0 ; i < groupObj.contents.length ; i++ ) { var itemNode = groupObj.contents[i] ; itemNode = FCKTools.GetElementAscensor( itemNode, 'li' ) ; if ( ! itemNode || itemNode._FCK_ListItem_Processed ) continue ; selectedListItems.push( itemNode ) ; FCKDomTools.SetElementMarker( markerObj, itemNode, '_FCK_ListItem_Processed', true ) ; } var fakeParent = groupObj.root.ownerDocument.createElement( this.TagName ) ; for ( var i = 0 ; i < selectedListItems.length ; i++ ) { var listIndex = selectedListItems[i]._FCK_ListArray_Index ; listArray[listIndex].parent = fakeParent ; } var newList = FCKDomTools.ArrayToList( listArray, markerObj ) ; for ( var i = 0 ; i < newList.listNode.childNodes.length ; i++ ) { if ( newList.listNode.childNodes[i].nodeName.IEquals( this.TagName ) ) listsCreated.push( newList.listNode.childNodes[i] ) ; } groupObj.root.parentNode.replaceChild( newList.listNode, groupObj.root ) ; }, _CreateList : function( groupObj, listsCreated ) { var contents = groupObj.contents ; var doc = groupObj.root.ownerDocument ; var listContents = [] ; // It is possible to have the contents returned by DomRangeIterator to be the same as the root. // e.g. when we're running into table cells. // In such a case, enclose the childNodes of contents[0] into a <div>. if ( contents.length == 1 && contents[0] == groupObj.root ) { var divBlock = doc.createElement( 'div' ); while ( contents[0].firstChild ) divBlock.appendChild( contents[0].removeChild( contents[0].firstChild ) ) ; contents[0].appendChild( divBlock ) ; contents[0] = divBlock ; } // Calculate the common parent node of all content blocks. var commonParent = groupObj.contents[0].parentNode ; for ( var i = 0 ; i < contents.length ; i++ ) commonParent = FCKDomTools.GetCommonParents( commonParent, contents[i].parentNode ).pop() ; // We want to insert things that are in the same tree level only, so calculate the contents again // by expanding the selected blocks to the same tree level. for ( var i = 0 ; i < contents.length ; i++ ) { var contentNode = contents[i] ; while ( contentNode.parentNode ) { if ( contentNode.parentNode == commonParent ) { listContents.push( contentNode ) ; break ; } contentNode = contentNode.parentNode ; } } if ( listContents.length < 1 ) return ; // Insert the list to the DOM tree. var insertAnchor = listContents[listContents.length - 1].nextSibling ; var listNode = doc.createElement( this.TagName ) ; listsCreated.push( listNode ) ; while ( listContents.length ) { var contentBlock = listContents.shift() ; var docFrag = doc.createDocumentFragment() ; while ( contentBlock.firstChild ) docFrag.appendChild( contentBlock.removeChild( contentBlock.firstChild ) ) ; contentBlock.parentNode.removeChild( contentBlock ) ; var listItem = doc.createElement( 'li' ) ; listItem.appendChild( docFrag ) ; listNode.appendChild( listItem ) ; } commonParent.insertBefore( listNode, insertAnchor ) ; }, _RemoveList : function( groupObj, markerObj ) { // This is very much like the change list type operation. // Except that we're changing the selected items' indent to -1 in the list array. var listArray = FCKDomTools.ListToArray( groupObj.root, markerObj ) ; var selectedListItems = [] ; for ( var i = 0 ; i < groupObj.contents.length ; i++ ) { var itemNode = groupObj.contents[i] ; itemNode = FCKTools.GetElementAscensor( itemNode, 'li' ) ; if ( ! itemNode || itemNode._FCK_ListItem_Processed ) continue ; selectedListItems.push( itemNode ) ; FCKDomTools.SetElementMarker( markerObj, itemNode, '_FCK_ListItem_Processed', true ) ; } var lastListIndex = null ; for ( var i = 0 ; i < selectedListItems.length ; i++ ) { var listIndex = selectedListItems[i]._FCK_ListArray_Index ; listArray[listIndex].indent = -1 ; lastListIndex = listIndex ; } // After cutting parts of the list out with indent=-1, we still have to maintain the array list // model's nextItem.indent <= currentItem.indent + 1 invariant. Otherwise the array model of the // list cannot be converted back to a real DOM list. for ( var i = lastListIndex + 1; i < listArray.length ; i++ ) { if ( listArray[i].indent > listArray[i-1].indent + 1 ) { var indentOffset = listArray[i-1].indent + 1 - listArray[i].indent ; var oldIndent = listArray[i].indent ; while ( listArray[i] && listArray[i].indent >= oldIndent) { listArray[i].indent += indentOffset ; i++ ; } i-- ; } } var newList = FCKDomTools.ArrayToList( listArray, markerObj ) ; // If groupObj.root is the last element in its parent, or its nextSibling is a <br>, then we should // not add a <br> after the final item. So, check for the cases and trim the <br>. if ( groupObj.root.nextSibling == null || groupObj.root.nextSibling.nodeName.IEquals( 'br' ) ) { if ( newList.listNode.lastChild.nodeName.IEquals( 'br' ) ) newList.listNode.removeChild( newList.listNode.lastChild ) ; } groupObj.root.parentNode.replaceChild( newList.listNode, groupObj.root ) ; } };
©
2018. | Recode by D7net