X-Git-Url: https://jasonwoof.com/gitweb/?a=blobdiff_plain;ds=sidebyside;f=_source%2Fcore%2Fdom%2Frange.js;h=fedbfb97e45684a2612f0d548a5921c3e1fe1fe6;hb=48b1db88210b4160dce439c6e3e32e14af8c106b;hp=8f10980e472a859f093ce39bc09249c49e4af736;hpb=614511639979907ceb0da3614122a4d8eb963ad4;p=ckeditor.git
diff --git a/_source/core/dom/range.js b/_source/core/dom/range.js
index 8f10980..fedbfb9 100644
--- a/_source/core/dom/range.js
+++ b/_source/core/dom/range.js
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved.
+Copyright (c) 2003-2011, CKSource - Frederico Knabben. All rights reserved.
For licensing, see LICENSE.html or http://ckeditor.com/license
*/
@@ -32,7 +32,7 @@ CKEDITOR.dom.range = function( document )
// This is a shared function used to delete, extract and clone the range
// contents.
// V2
- var execContentsAction = function( range, action, docFrag )
+ var execContentsAction = function( range, action, docFrag, mergeThen )
{
range.optimizeBookmark();
@@ -247,7 +247,17 @@ CKEDITOR.dom.range = function( document )
if ( removeStartNode && topEnd.$.parentNode == startNode.$.parentNode )
endIndex--;
- range.setStart( topEnd.getParent(), endIndex );
+ // Merge splitted parents.
+ if ( mergeThen && topStart.type == CKEDITOR.NODE_ELEMENT )
+ {
+ var span = CKEDITOR.dom.element.createFromHtml( ' ', range.document );
+ span.insertAfter( topStart );
+ topStart.mergeSiblings( false );
+ range.moveToBookmark( { startNode : span } );
+ }
+ else
+ range.setStart( topEnd.getParent(), endIndex );
}
// Collapse it to the start.
@@ -280,7 +290,7 @@ CKEDITOR.dom.range = function( document )
// If there's any visible text, then we're not at the start.
if ( CKEDITOR.tools.trim( node.getText() ).length )
return false;
- }
+ }
else if ( node.type == CKEDITOR.NODE_ELEMENT )
{
// If there are non-empty inline elements (e.g. ), then we're not
@@ -308,7 +318,7 @@ CKEDITOR.dom.range = function( document )
return node.type != CKEDITOR.NODE_TEXT
&& node.getName() in CKEDITOR.dtd.$removeEmpty
|| !CKEDITOR.tools.trim( node.getText() )
- || node.getParent().hasAttribute( '_cke_bookmark' );
+ || !!node.getParent().data( 'cke-bookmark' );
}
var whitespaceEval = new CKEDITOR.dom.walker.whitespaces(),
@@ -367,25 +377,27 @@ CKEDITOR.dom.range = function( document )
/**
* Deletes the content nodes of the range permanently from the DOM tree.
+ * @param {Boolean} [mergeThen] Merge any splitted elements result in DOM true due to partial selection.
*/
- deleteContents : function()
+ deleteContents : function( mergeThen )
{
if ( this.collapsed )
return;
- execContentsAction( this, 0 );
+ execContentsAction( this, 0, null, mergeThen );
},
/**
* The content nodes of the range are cloned and added to a document fragment,
* meanwhile they're removed permanently from the DOM tree.
+ * @param {Boolean} [mergeThen] Merge any splitted elements result in DOM true due to partial selection.
*/
- extractContents : function()
+ extractContents : function( mergeThen )
{
var docFrag = new CKEDITOR.dom.documentFragment( this.document );
if ( !this.collapsed )
- execContentsAction( this, 1, docFrag );
+ execContentsAction( this, 1, docFrag, mergeThen );
return docFrag;
},
@@ -413,7 +425,7 @@ CKEDITOR.dom.range = function( document )
var collapsed = this.collapsed;
startNode = this.document.createElement( 'span' );
- startNode.setAttribute( '_cke_bookmark', 1 );
+ startNode.data( 'cke-bookmark', 1 );
startNode.setStyle( 'display', 'none' );
// For IE, it must have something inside, otherwise it may be
@@ -723,10 +735,10 @@ CKEDITOR.dom.range = function( document )
endNode = this.endContainer;
if ( startNode.is && startNode.is( 'span' )
- && startNode.hasAttribute( '_cke_bookmark' ) )
+ && startNode.data( 'cke-bookmark' ) )
this.setStartAt( startNode, CKEDITOR.POSITION_BEFORE_START );
if ( endNode && endNode.is && endNode.is( 'span' )
- && endNode.hasAttribute( '_cke_bookmark' ) )
+ && endNode.data( 'cke-bookmark' ) )
this.setEndAt( endNode, CKEDITOR.POSITION_AFTER_END );
},
@@ -811,7 +823,12 @@ CKEDITOR.dom.range = function( document )
}
},
- enlarge : function( unit )
+ /**
+ * Expands the range so that partial units are completely contained.
+ * @param unit {Number} The unit type to expand with.
+ * @param {Boolean} [excludeBrs=false] Whether include line-breaks when expanding.
+ */
+ enlarge : function( unit, excludeBrs )
{
switch ( unit )
{
@@ -932,7 +949,8 @@ CKEDITOR.dom.range = function( document )
// If this is a visible element.
// We need to check for the bookmark attribute because IE insists on
// rendering the display:none nodes we use for bookmarks. (#3363)
- if ( sibling.$.offsetWidth > 0 && !sibling.getAttribute( '_cke_bookmark' ) )
+ // Line-breaks (br) are rendered with zero width, which we don't want to include. (#7041)
+ if ( ( sibling.$.offsetWidth > 0 || excludeBrs && sibling.is( 'br' ) ) && !sibling.data( 'cke-bookmark' ) )
{
// We'll accept it only if we need
// whitespace, and this is an inline
@@ -1091,7 +1109,8 @@ CKEDITOR.dom.range = function( document )
// If this is a visible element.
// We need to check for the bookmark attribute because IE insists on
// rendering the display:none nodes we use for bookmarks. (#3363)
- if ( sibling.$.offsetWidth > 0 && !sibling.getAttribute( '_cke_bookmark' ) )
+ // Line-breaks (br) are rendered with zero width, which we don't want to include. (#7041)
+ if ( ( sibling.$.offsetWidth > 0 || excludeBrs && sibling.is( 'br' ) ) && !sibling.data( 'cke-bookmark' ) )
{
// We'll accept it only if we need
// whitespace, and this is an inline
@@ -1755,6 +1774,47 @@ CKEDITOR.dom.range = function( document )
},
/**
+ * Check if elements at which the range boundaries anchor are read-only,
+ * with respect to "contenteditable" attribute.
+ */
+ checkReadOnly : ( function()
+ {
+ function checkNodesEditable( node, anotherEnd )
+ {
+ while( node )
+ {
+ if ( node.type == CKEDITOR.NODE_ELEMENT )
+ {
+ if ( node.getAttribute( 'contentEditable' ) == 'false'
+ && !node.data( 'cke-editable' ) )
+ {
+ return 0;
+ }
+ // Range enclosed entirely in an editable element.
+ else if ( node.is( 'body' )
+ || node.getAttribute( 'contentEditable' ) == 'true'
+ && ( node.contains( anotherEnd ) || node.equals( anotherEnd ) ) )
+ {
+ break;
+ }
+ }
+ node = node.getParent();
+ }
+
+ return 1;
+ }
+
+ return function()
+ {
+ var startNode = this.startContainer,
+ endNode = this.endContainer;
+
+ // Check if elements path at both boundaries are editable.
+ return !( checkNodesEditable( startNode, endNode ) && checkNodesEditable( endNode, startNode ) );
+ };
+ })(),
+
+ /**
* Moves the range boundaries to the first/end editing point inside an
* element. For example, in an element tree like
* "<p><b><i></i></b> Text</p>", the start editing point is