X-Git-Url: https://jasonwoof.com/gitweb/?p=ckeditor.git;a=blobdiff_plain;f=_source%2Fplugins%2Fselection%2Fplugin.js;h=3a4eb8071798121b9da958da1d06602752ed9f51;hp=17e2c52eeff55d92fa90f8a731ed0ce859c4c712;hb=48b1db88210b4160dce439c6e3e32e14af8c106b;hpb=9afde8772159bd3436f1f5b7862960307710ae5a diff --git a/_source/plugins/selection/plugin.js b/_source/plugins/selection/plugin.js index 17e2c52..3a4eb80 100644 --- a/_source/plugins/selection/plugin.js +++ b/_source/plugins/selection/plugin.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 */ @@ -79,20 +79,21 @@ For licensing, see LICENSE.html or http://ckeditor.com/license { case 'wysiwyg' : editor.document.$.execCommand( 'SelectAll', false, null ); + // Force triggering selectionChange (#7008) + editor.forceNextSelectionCheck(); + editor.selectionChange(); break; case 'source' : // Select the contents of the textarea - var textarea = editor.textarea.$ ; + var textarea = editor.textarea.$; if ( CKEDITOR.env.ie ) - { - textarea.createTextRange().execCommand( 'SelectAll' ) ; - } + textarea.createTextRange().execCommand( 'SelectAll' ); else { - textarea.selectionStart = 0 ; - textarea.selectionEnd = textarea.value.length ; + textarea.selectionStart = 0; + textarea.selectionEnd = textarea.value.length; } - textarea.focus() ; + textarea.focus(); } }, canUndo : false @@ -556,6 +557,8 @@ For licensing, see LICENSE.html or http://ckeditor.com/license var func = CKEDITOR.env.ie ? ( function() { + function getNodeIndex( node ) { return new CKEDITOR.dom.node( node ).getIndex(); } + // Finds the container and offset for a specific boundary // of an IE range. var getBoundaryInformation = function( range, start ) @@ -566,76 +569,103 @@ For licensing, see LICENSE.html or http://ckeditor.com/license // Gets the element that encloses the range entirely. var parent = range.parentElement(); - var siblings = parent.childNodes; - var testRange; - - for ( var i = 0 ; i < siblings.length ; i++ ) + // Empty parent element, e.g. ^ + if ( !parent.hasChildNodes() ) + return { container : parent, offset : 0 }; + + var siblings = parent.children, + child, + testRange = range.duplicate(), + startIndex = 0, + endIndex = siblings.length - 1, + index = -1, + position, + distance; + + // Binary search over all element childs to test the range to see whether + // range is right on the boundary of one element. + while ( startIndex <= endIndex ) { - var child = siblings[ i ]; - if ( child.nodeType == 1 ) - { - testRange = range.duplicate(); + index = Math.floor( ( startIndex + endIndex ) / 2 ); + child = siblings[ index ]; + testRange.moveToElementText( child ); + position = testRange.compareEndPoints( 'StartToStart', range ); + + if ( position > 0 ) + endIndex = index - 1; + else if ( position < 0 ) + startIndex = index + 1; + else + return { container : parent, offset : getNodeIndex( child ) }; + } - testRange.moveToElementText( child ); + // All childs are text nodes, + // or to the right hand of test range are all text nodes. (#6992) + if ( index == -1 || index == siblings.length - 1 && position < 0 ) + { + // Adapt test range to embrace the entire parent contents. + testRange.moveToElementText( parent ); + testRange.setEndPoint( 'StartToStart', range ); - var comparisonStart = testRange.compareEndPoints( 'StartToStart', range ), - comparisonEnd = testRange.compareEndPoints( 'EndToStart', range ); + // IE report line break as CRLF with range.text but + // only LF with textnode.nodeValue, normalize them to avoid + // breaking character counting logic below. (#3949) + distance = testRange.text.replace( /(\r\n|\r)/g, '\n' ).length; - testRange.collapse(); + siblings = parent.childNodes; - if ( comparisonStart > 0 ) - break; - // When selection stay at the side of certain self-closing elements, e.g. BR, - // our comparison will never shows an equality. (#4824) - else if ( !comparisonStart - || comparisonEnd == 1 && comparisonStart == -1 ) - return { container : parent, offset : i }; - else if ( !comparisonEnd ) - return { container : parent, offset : i + 1 }; + // Actual range anchor right beside test range at the boundary of text node. + if ( !distance ) + { + child = siblings[ siblings.length - 1 ]; - testRange = null; + if ( child.nodeType == CKEDITOR.NODE_ELEMENT ) + return { container : parent, offset : siblings.length }; + else + return { container : child, offset : child.nodeValue.length }; } - } - - if ( !testRange ) - { - testRange = range.duplicate(); - testRange.moveToElementText( parent ); - testRange.collapse( false ); - } - testRange.setEndPoint( 'StartToStart', range ); - // IE report line break as CRLF with range.text but - // only LF with textnode.nodeValue, normalize them to avoid - // breaking character counting logic below. (#3949) - var distance = testRange.text.replace( /(\r\n|\r)/g, '\n' ).length; - - try - { + // Start the measuring until distance overflows, meanwhile count the text nodes. + var i = siblings.length; while ( distance > 0 ) distance -= siblings[ --i ].nodeValue.length; - } - // Measurement in IE could be somtimes wrong because of element. (#4611) + catch( e ) + { + return { container : parent, offset : getNodeIndex( child ) }; + } + } + + return { container : child, offset : position > 0 ? -distance : child.nodeValue.length + distance }; } }; @@ -797,7 +827,7 @@ For licensing, see LICENSE.html or http://ckeditor.com/license walker.evaluator = function( node ) { if ( node.type == CKEDITOR.NODE_ELEMENT - && node.getAttribute( 'contenteditable' ) == 'false' ) + && node.isReadOnly() ) { var newRange = range.clone(); range.setEndBefore( node ); @@ -1126,7 +1156,13 @@ For licensing, see LICENSE.html or http://ckeditor.com/license if ( !between.collapsed ) { between.shrink( CKEDITOR.NODE_ELEMENT, true ); - if ( between.getCommonAncestor().isReadOnly()) + var ancestor = between.getCommonAncestor(), + enclosed = between.getEnclosedNode(); + + // The following cases has to be considered: + // 1. [placeholder] + // 2. (#6621) + if ( ancestor.isReadOnly() || enclosed && enclosed.isReadOnly() ) { right.setStart( left.startContainer, left.startOffset ); ranges.splice( i--, 1 ); @@ -1369,7 +1405,11 @@ For licensing, see LICENSE.html or http://ckeditor.com/license } var selection = this.document.getSelection().getNative(); - selection.removeAllRanges(); - selection.addRange( nativeRange ); + // getSelection() returns null in case when iframe is "display:none" in FF. (#6577) + if ( selection ) + { + selection.removeAllRanges(); + selection.addRange( nativeRange ); + } }; } )();