public/ckeditor/4.4dev/core/editable.js
function prepareRangeToDataInsertion( that ) {
			var range = that.range,
				mergeCandidates = that.mergeCandidates,
				node, marker, path, startPath, endPath, previous, bm;

			// If range starts in inline element then insert a marker, so empty
			// inline elements won't be removed while range.deleteContents
			// and we will be able to move range back into this element.
			// E.g. 'aa<b>[bb</b>]cc' -> (after deleting) 'aa<b><span/></b>cc'
			if ( that.type == 'text' && range.shrink( CKEDITOR.SHRINK_ELEMENT, true, false ) ) {
				marker = CKEDITOR.dom.element.createFromHtml( '<span>&nbsp;</span>', range.document );
				range.insertNode( marker );
				range.setStartAfter( marker );
			}

			// By using path we can recover in which element was startContainer
			// before deleting contents.
			// Start and endPathElements will be used to squash selected blocks, after removing
			// selection contents. See rule 5.
			startPath = new CKEDITOR.dom.elementPath( range.startContainer );
			that.endPath = endPath = new CKEDITOR.dom.elementPath( range.endContainer );

			if ( !range.collapsed ) {
				// Anticipate the possibly empty block at the end of range after deletion.
				node = endPath.block || endPath.blockLimit;
				var ancestor = range.getCommonAncestor();
				if ( node && !( node.equals( ancestor ) || node.contains( ancestor ) ) && range.checkEndOfBlock() ) {
					that.zombies.push( node );
				}

				range.deleteContents();
			}

			// Rule 4.
			// Move range into the previous block.
			while (
				( previous = getRangePrevious( range ) ) && checkIfElement( previous ) && previous.isBlockBoundary() &&
				// Check if previousNode was parent of range's startContainer before deleteContents.
				startPath.contains( previous )
			)
				range.moveToPosition( previous, CKEDITOR.POSITION_BEFORE_END );

			// Rule 5.
			mergeAncestorElementsOfSelectionEnds( range, that.blockLimit, startPath, endPath );

			// Rule 1.
			if ( marker ) {
				// If marker was created then move collapsed range into its place.
				range.setEndBefore( marker );
				range.collapse();
				marker.remove();
			}

			// Split inline elements so HTML will be inserted with its own styles.
			path = range.startPath();
			if ( ( node = path.contains( isInline, false, 1 ) ) ) {
				range.splitElement( node );
				that.inlineStylesRoot = node;
				that.inlineStylesPeak = path.lastElement;
			}

			// Record inline merging candidates for later cleanup in place.
			bm = range.createBookmark();

			// 1. Inline siblings.
			node = bm.startNode.getPrevious( isNotEmpty );
			node && checkIfElement( node ) && isInline( node ) && mergeCandidates.push( node );
			node = bm.startNode.getNext( isNotEmpty );
			node && checkIfElement( node ) && isInline( node ) && mergeCandidates.push( node );

			// 2. Inline parents.
			node = bm.startNode;
			while ( ( node = node.getParent() ) && isInline( node ) )
				mergeCandidates.push( node );

			range.moveToBookmark( bm );
		}
function prepareRangeToDataInsertion( that ) {
			var range = that.range,
				mergeCandidates = that.mergeCandidates,
				node, marker, path, startPath, endPath, previous, bm;

			// If range starts in inline element then insert a marker, so empty
			// inline elements won't be removed while range.deleteContents
			// and we will be able to move range back into this element.
			// E.g. 'aa<b>[bb</b>]cc' -> (after deleting) 'aa<b><span/></b>cc'
			if ( that.type == 'text' && range.shrink( CKEDITOR.SHRINK_ELEMENT, true, false ) ) {
				marker = CKEDITOR.dom.element.createFromHtml( '<span>&nbsp;</span>', range.document );
				range.insertNode( marker );
				range.setStartAfter( marker );
			}

			// By using path we can recover in which element was startContainer
			// before deleting contents.
			// Start and endPathElements will be used to squash selected blocks, after removing
			// selection contents. See rule 5.
			startPath = new CKEDITOR.dom.elementPath( range.startContainer );
			that.endPath = endPath = new CKEDITOR.dom.elementPath( range.endContainer );

			if ( !range.collapsed ) {
				// Anticipate the possibly empty block at the end of range after deletion.
				node = endPath.block || endPath.blockLimit;
				var ancestor = range.getCommonAncestor();
				if ( node && !( node.equals( ancestor ) || node.contains( ancestor ) ) && range.checkEndOfBlock() ) {
					that.zombies.push( node );
				}

				range.deleteContents();
			}

			// Rule 4.
			// Move range into the previous block.
			while (
				( previous = getRangePrevious( range ) ) && checkIfElement( previous ) && previous.isBlockBoundary() &&
				// Check if previousNode was parent of range's startContainer before deleteContents.
				startPath.contains( previous )
			)
				range.moveToPosition( previous, CKEDITOR.POSITION_BEFORE_END );

			// Rule 5.
			mergeAncestorElementsOfSelectionEnds( range, that.blockLimit, startPath, endPath );

			// Rule 1.
			if ( marker ) {
				// If marker was created then move collapsed range into its place.
				range.setEndBefore( marker );
				range.collapse();
				marker.remove();
			}

			// Split inline elements so HTML will be inserted with its own styles.
			path = range.startPath();
			if ( ( node = path.contains( isInline, false, 1 ) ) ) {
				range.splitElement( node );
				that.inlineStylesRoot = node;
				that.inlineStylesPeak = path.lastElement;
			}

			// Record inline merging candidates for later cleanup in place.
			bm = range.createBookmark();

			// 1. Inline siblings.
			node = bm.startNode.getPrevious( isNotEmpty );
			node && checkIfElement( node ) && isInline( node ) && mergeCandidates.push( node );
			node = bm.startNode.getNext( isNotEmpty );
			node && checkIfElement( node ) && isInline( node ) && mergeCandidates.push( node );

			// 2. Inline parents.
			node = bm.startNode;
			while ( ( node = node.getParent() ) && isInline( node ) )
				mergeCandidates.push( node );

			range.moveToBookmark( bm );
		}
function prepareRangeToDataInsertion ( that ) { var range = that . range , mergeCandidates = that . mergeCandidates , node , marker , path , startPath , endPath , previous , bm ; // If range starts in inline element then insert a marker, so empty // inline elements won't be removed while range.deleteContents // and we will be able to move range back into this element. // E.g. 'aa<b>[bb</b>]cc' -> (after deleting) 'aa<b><span/></b>cc' if ( that . type == 'text' && range . shrink ( CKEDITOR . SHRINK_ELEMENT , true , false ) ) { marker = CKEDITOR . dom . element . createFromHtml ( '<span>&nbsp;</span>' , range . document ) ; range . insertNode ( marker ) ; range . setStartAfter ( marker ) ; } // By using path we can recover in which element was startContainer // before deleting contents. // Start and endPathElements will be used to squash selected blocks, after removing // selection contents. See rule 5. startPath = new CKEDITOR . dom . elementPath ( range . startContainer ) ; that . endPath = endPath = new CKEDITOR . dom . elementPath ( range . endContainer ) ; if ( ! range . collapsed ) { // Anticipate the possibly empty block at the end of range after deletion. node = endPath . block || endPath . blockLimit ; var ancestor = range . getCommonAncestor ( ) ; if ( node && ! ( node . equals ( ancestor ) || node . contains ( ancestor ) ) && range . checkEndOfBlock ( ) ) { that . zombies . push ( node ) ; } range . deleteContents ( ) ; } // Rule 4. // Move range into the previous block. while ( ( previous = getRangePrevious ( range ) ) && checkIfElement ( previous ) && previous . isBlockBoundary ( ) && // Check if previousNode was parent of range's startContainer before deleteContents. startPath . contains ( previous ) ) range . moveToPosition ( previous , CKEDITOR . POSITION_BEFORE_END ) ; // Rule 5. mergeAncestorElementsOfSelectionEnds ( range , that . blockLimit , startPath , endPath ) ; // Rule 1. if ( marker ) { // If marker was created then move collapsed range into its place. range . setEndBefore ( marker ) ; range . collapse ( ) ; marker . remove ( ) ; } // Split inline elements so HTML will be inserted with its own styles. path = range . startPath ( ) ; if ( ( node = path . contains ( isInline , false , 1 ) ) ) { range . splitElement ( node ) ; that . inlineStylesRoot = node ; that . inlineStylesPeak = path . lastElement ; } // Record inline merging candidates for later cleanup in place. bm = range . createBookmark ( ) ; // 1. Inline siblings. node = bm . startNode . getPrevious ( isNotEmpty ) ; node && checkIfElement ( node ) && isInline ( node ) && mergeCandidates . push ( node ) ; node = bm . startNode . getNext ( isNotEmpty ) ; node && checkIfElement ( node ) && isInline ( node ) && mergeCandidates . push ( node ) ; // 2. Inline parents. node = bm . startNode ; while ( ( node = node . getParent ( ) ) && isInline ( node ) ) mergeCandidates . push ( node ) ; range . moveToBookmark ( bm ) ; }
Prepare range to its data deletion. Delete its contents. Prepare it to insertion.
Prepare range to its data deletion . Delete its contents . Prepare it to insertion .