X-Git-Url: https://scm.cri.ensmp.fr/git/ckeditor.git/blobdiff_plain/256592bf803e851aa7fc953e08a6e9e58d970f8c..871bad8291b6dbc29d489d95d185458caab25158:/skins/ckeditor/_source/plugins/indent/plugin.js diff --git a/skins/ckeditor/_source/plugins/indent/plugin.js b/skins/ckeditor/_source/plugins/indent/plugin.js new file mode 100644 index 0000000..330af61 --- /dev/null +++ b/skins/ckeditor/_source/plugins/indent/plugin.js @@ -0,0 +1,461 @@ +/* +Copyright (c) 2003-2011, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.html or http://ckeditor.com/license +*/ + +/** + * @file Increse and decrease indent commands. + */ + +(function() +{ + var listNodeNames = { ol : 1, ul : 1 }, + isNotWhitespaces = CKEDITOR.dom.walker.whitespaces( true ), + isNotBookmark = CKEDITOR.dom.walker.bookmark( false, true ); + + function onSelectionChange( evt ) + { + if ( evt.editor.readOnly ) + return null; + + var editor = evt.editor, + elementPath = evt.data.path, + list = elementPath && elementPath.contains( listNodeNames ), + firstBlock = elementPath.block || elementPath.blockLimit; + + if ( list ) + return this.setState( CKEDITOR.TRISTATE_OFF ); + + if ( !this.useIndentClasses && this.name == 'indent' ) + return this.setState( CKEDITOR.TRISTATE_OFF ); + + if ( !firstBlock ) + return this.setState( CKEDITOR.TRISTATE_DISABLED ); + + if ( this.useIndentClasses ) + { + var indentClass = firstBlock.$.className.match( this.classNameRegex ), + indentStep = 0; + if ( indentClass ) + { + indentClass = indentClass[1]; + indentStep = this.indentClassMap[ indentClass ]; + } + if ( ( this.name == 'outdent' && !indentStep ) || + ( this.name == 'indent' && indentStep == editor.config.indentClasses.length ) ) + return this.setState( CKEDITOR.TRISTATE_DISABLED ); + return this.setState( CKEDITOR.TRISTATE_OFF ); + } + else + { + var indent = parseInt( firstBlock.getStyle( getIndentCssProperty( firstBlock ) ), 10 ); + if ( isNaN( indent ) ) + indent = 0; + if ( indent <= 0 ) + return this.setState( CKEDITOR.TRISTATE_DISABLED ); + return this.setState( CKEDITOR.TRISTATE_OFF ); + } + } + + function indentCommand( editor, name ) + { + this.name = name; + this.useIndentClasses = editor.config.indentClasses && editor.config.indentClasses.length > 0; + if ( this.useIndentClasses ) + { + this.classNameRegex = new RegExp( '(?:^|\\s+)(' + editor.config.indentClasses.join( '|' ) + ')(?=$|\\s)' ); + this.indentClassMap = {}; + for ( var i = 0 ; i < editor.config.indentClasses.length ; i++ ) + this.indentClassMap[ editor.config.indentClasses[i] ] = i + 1; + } + + this.startDisabled = name == 'outdent'; + } + + // Returns the CSS property to be used for identing a given element. + function getIndentCssProperty( element, dir ) + { + return ( dir || element.getComputedStyle( 'direction' ) ) == 'ltr' ? 'margin-left' : 'margin-right'; + } + + function isListItem( node ) + { + return node.type = CKEDITOR.NODE_ELEMENT && node.is( 'li' ); + } + + indentCommand.prototype = { + exec : function( editor ) + { + var self = this, database = {}; + + function indentList( listNode ) + { + // Our starting and ending points of the range might be inside some blocks under a list item... + // So before playing with the iterator, we need to expand the block to include the list items. + var startContainer = range.startContainer, + endContainer = range.endContainer; + while ( startContainer && !startContainer.getParent().equals( listNode ) ) + startContainer = startContainer.getParent(); + while ( endContainer && !endContainer.getParent().equals( listNode ) ) + endContainer = endContainer.getParent(); + + if ( !startContainer || !endContainer ) + return; + + // Now we can iterate over the individual items on the same tree depth. + var block = startContainer, + itemsToMove = [], + stopFlag = false; + while ( !stopFlag ) + { + if ( block.equals( endContainer ) ) + stopFlag = true; + itemsToMove.push( block ); + block = block.getNext(); + } + if ( itemsToMove.length < 1 ) + return; + + // Do indent or outdent operations on the array model of the list, not the + // list's DOM tree itself. The array model demands that it knows as much as + // possible about the surrounding lists, we need to feed it the further + // ancestor node that is still a list. + var listParents = listNode.getParents( true ); + for ( var i = 0 ; i < listParents.length ; i++ ) + { + if ( listParents[i].getName && listNodeNames[ listParents[i].getName() ] ) + { + listNode = listParents[i]; + break; + } + } + var indentOffset = self.name == 'indent' ? 1 : -1, + startItem = itemsToMove[0], + lastItem = itemsToMove[ itemsToMove.length - 1 ]; + + // Convert the list DOM tree into a one dimensional array. + var listArray = CKEDITOR.plugins.list.listToArray( listNode, database ); + + // Apply indenting or outdenting on the array. + var baseIndent = listArray[ lastItem.getCustomData( 'listarray_index' ) ].indent; + for ( i = startItem.getCustomData( 'listarray_index' ); i <= lastItem.getCustomData( 'listarray_index' ); i++ ) + { + listArray[ i ].indent += indentOffset; + // Make sure the newly created sublist get a brand-new element of the same type. (#5372) + var listRoot = listArray[ i ].parent; + listArray[ i ].parent = new CKEDITOR.dom.element( listRoot.getName(), listRoot.getDocument() ); + } + + for ( i = lastItem.getCustomData( 'listarray_index' ) + 1 ; + i < listArray.length && listArray[i].indent > baseIndent ; i++ ) + listArray[i].indent += indentOffset; + + // Convert the array back to a DOM forest (yes we might have a few subtrees now). + // And replace the old list with the new forest. + var newList = CKEDITOR.plugins.list.arrayToList( listArray, database, null, editor.config.enterMode, listNode.getDirection() ); + + // Avoid nested
  • after outdent even they're visually same, + // recording them for later refactoring.(#3982) + if ( self.name == 'outdent' ) + { + var parentLiElement; + if ( ( parentLiElement = listNode.getParent() ) && parentLiElement.is( 'li' ) ) + { + var children = newList.listNode.getChildren(), + pendingLis = [], + count = children.count(), + child; + + for ( i = count - 1 ; i >= 0 ; i-- ) + { + if ( ( child = children.getItem( i ) ) && child.is && child.is( 'li' ) ) + pendingLis.push( child ); + } + } + } + + if ( newList ) + newList.listNode.replace( listNode ); + + // Move the nested
  • to be appeared after the parent. + if ( pendingLis && pendingLis.length ) + { + for ( i = 0; i < pendingLis.length ; i++ ) + { + var li = pendingLis[ i ], + followingList = li; + + // Nest preceding