JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
vanilla ckeditor-3.1.1
[ckeditor.git] / _source / plugins / selection / plugin.js
index e7c24b7..85981fa 100644 (file)
@@ -1,5 +1,5 @@
 /*\r
-Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved.\r
+Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved.\r
 For licensing, see LICENSE.html or http://ckeditor.com/license\r
 */\r
 \r
@@ -92,7 +92,8 @@ For licensing, see LICENSE.html or http://ckeditor.com/license
                {\r
                        editor.on( 'contentDom', function()\r
                                {\r
-                                       var doc = editor.document;\r
+                                       var doc = editor.document,\r
+                                               body = doc.getBody();\r
 \r
                                        if ( CKEDITOR.env.ie )\r
                                        {\r
@@ -107,7 +108,7 @@ For licensing, see LICENSE.html or http://ckeditor.com/license
                                                // "onfocusin" is fired before "onfocus". It makes it\r
                                                // possible to restore the selection before click\r
                                                // events get executed.\r
-                                               doc.on( 'focusin', function()\r
+                                               body.on( 'focusin', function()\r
                                                        {\r
                                                                // If we have saved a range, restore it at this\r
                                                                // point.\r
@@ -133,25 +134,16 @@ For licensing, see LICENSE.html or http://ckeditor.com/license
                                                                saveSelection();\r
                                                        });\r
 \r
-                                               // Check document selection before 'blur' fired, this\r
-                                               // will prevent us from breaking text selection somewhere\r
-                                               // else on the host page.(#3909)\r
-                                               editor.document.on( 'beforedeactivate', function()\r
+                                               body.on( 'beforedeactivate', function()\r
                                                        {\r
                                                                // Disable selections from being saved.\r
                                                                saveEnabled = false;\r
-\r
-                                                               // IE may leave the selection still inside the\r
-                                                               // document. Let's force it to be removed.\r
-                                                               // TODO: The following has effect for\r
-                                                               // collapsed selections.\r
-                                                               editor.document.$.execCommand( 'Unselect' );\r
                                                        });\r
 \r
                                                // IE fires the "selectionchange" event when clicking\r
                                                // inside a selection. We don't want to capture that.\r
-                                               doc.on( 'mousedown', disableSave );\r
-                                               doc.on( 'mouseup',\r
+                                               body.on( 'mousedown', disableSave );\r
+                                               body.on( 'mouseup',\r
                                                        function()\r
                                                        {\r
                                                                saveEnabled = true;\r
@@ -162,8 +154,8 @@ For licensing, see LICENSE.html or http://ckeditor.com/license
                                                                        0 );\r
                                                        });\r
 \r
-                                               doc.on( 'keydown', disableSave );\r
-                                               doc.on( 'keyup',\r
+                                               body.on( 'keydown', disableSave );\r
+                                               body.on( 'keyup',\r
                                                        function()\r
                                                        {\r
                                                                saveEnabled = true;\r
@@ -333,7 +325,7 @@ For licensing, see LICENSE.html or http://ckeditor.com/license
 \r
        var styleObjectElements =\r
        {\r
-               img:1,hr:1,li:1,table:1,tr:1,td:1,embed:1,object:1,ol:1,ul:1,\r
+               img:1,hr:1,li:1,table:1,tr:1,td:1,th:1,embed:1,object:1,ol:1,ul:1,\r
                a:1, input:1, form:1, select:1, textarea:1, button:1, fieldset:1, th:1, thead:1, tfoot:1\r
        };\r
 \r
@@ -467,17 +459,21 @@ For licensing, see LICENSE.html or http://ckeditor.com/license
                                                                testRange = range.duplicate();\r
 \r
                                                                testRange.moveToElementText( child );\r
-                                                               testRange.collapse();\r
 \r
-                                                               var comparison = testRange.compareEndPoints( 'StartToStart', range );\r
+                                                               var comparisonStart = testRange.compareEndPoints( 'StartToStart', range ),\r
+                                                                       comparisonEnd = testRange.compareEndPoints( 'EndToStart', range );\r
+\r
+                                                               testRange.collapse();\r
 \r
-                                                               if ( comparison > 0 )\r
+                                                               if ( comparisonStart > 0 )\r
                                                                        break;\r
-                                                               else if ( comparison === 0 )\r
-                                                                       return {\r
-                                                                               container : parent,\r
-                                                                               offset : i\r
-                                                                       };\r
+                                                               // When selection stay at the side of certain self-closing elements, e.g. BR,\r
+                                                               // our comparison will never shows an equality. (#4824)\r
+                                                               else if ( !comparisonStart\r
+                                                                       || comparisonEnd == 1 && comparisonStart == -1 )\r
+                                                                       return { container : parent, offset : i };\r
+                                                               else if ( !comparisonEnd )\r
+                                                                       return { container : parent, offset : i + 1 };\r
 \r
                                                                testRange = null;\r
                                                        }\r
@@ -496,8 +492,17 @@ For licensing, see LICENSE.html or http://ckeditor.com/license
                                                // breaking character counting logic below. (#3949)\r
                                                var distance = testRange.text.replace( /(\r\n|\r)/g, '\n' ).length;\r
 \r
-                                               while ( distance > 0 )\r
-                                                       distance -= siblings[ --i ].nodeValue.length;\r
+                                               try\r
+                                               {\r
+                                                       while ( distance > 0 )\r
+                                                               distance -= siblings[ --i ].nodeValue.length;\r
+                                               }\r
+                                               // Measurement in IE could be somtimes wrong because of <select> element. (#4611)\r
+                                               catch( e )\r
+                                               {\r
+                                                       distance = 0;\r
+                                               }\r
+\r
 \r
                                                if ( distance === 0 )\r
                                                {\r
@@ -636,12 +641,14 @@ For licensing, see LICENSE.html or http://ckeditor.com/license
                                                        // Decrease the range content to exclude particial\r
                                                        // selected node on the start which doesn't have\r
                                                        // visual impact. ( #3231 )\r
-                                                       while( true )\r
+                                                       while ( true )\r
                                                        {\r
                                                                var startContainer = range.startContainer,\r
                                                                        startOffset = range.startOffset;\r
+                                                               // Limit the fix only to non-block elements.(#3950)\r
                                                                if ( startOffset == ( startContainer.getChildCount ?\r
-                                                                       startContainer.getChildCount() : startContainer.getLength() ) )\r
+                                                                        startContainer.getChildCount() : startContainer.getLength() )\r
+                                                                        && !startContainer.isBlockBoundary() )\r
                                                                        range.setStartAfter( startContainer );\r
                                                                else break;\r
                                                        }\r
@@ -678,7 +685,7 @@ For licensing, see LICENSE.html or http://ckeditor.com/license
                                        {\r
                                                node = sel.anchorNode;\r
 \r
-                                               if ( node.nodeType != 1 )\r
+                                               if ( node && node.nodeType != 1 )\r
                                                        node = node.parentNode;\r
                                        }\r
                        }\r
@@ -939,9 +946,30 @@ For licensing, see LICENSE.html or http://ckeditor.com/license
                        }\r
                        this.selectRanges( ranges );\r
                        return this;\r
+               },\r
+\r
+               getCommonAncestor : function()\r
+               {\r
+                       var ranges = this.getRanges(),\r
+                               startNode = ranges[ 0 ].startContainer,\r
+                               endNode = ranges[ ranges.length - 1 ].endContainer;\r
+                       return startNode.getCommonAncestor( endNode );\r
+               },\r
+\r
+               // Moving scroll bar to the current selection's start position.\r
+               scrollIntoView : function()\r
+               {\r
+                       // If we have split the block, adds a temporary span at the\r
+                       // range position and scroll relatively to it.\r
+                       var start = this.getStartElement();\r
+                       start.scrollIntoView();\r
                }\r
        };\r
 })();\r
+( function()\r
+{\r
+var notWhitespaces = CKEDITOR.dom.walker.whitespaces( true );\r
+var fillerTextRegex = /\ufeff|\u00a0/;\r
 \r
 CKEDITOR.dom.range.prototype.select =\r
        CKEDITOR.env.ie ?\r
@@ -986,7 +1014,9 @@ CKEDITOR.dom.range.prototype.select =
                                // will expand and that the cursor will be blinking on the right place.\r
                                // Actually, we are using this flag just to avoid using this hack in all\r
                                // situations, but just on those needed.\r
-                               isStartMarkerAlone = forceExpand || !startNode.hasPrevious() || ( startNode.getPrevious().is && startNode.getPrevious().is( 'br' ) );\r
+                               var next = startNode.getNext( notWhitespaces );\r
+                               isStartMarkerAlone = ( !( next && next.getText && next.getText().match( fillerTextRegex ) )     // already a filler there?\r
+                                                                         && ( forceExpand || !startNode.hasPrevious() || ( startNode.getPrevious().is && startNode.getPrevious().is( 'br' ) ) ) );\r
 \r
                                // Append a temporary <span>&#65279;</span> before the selection.\r
                                // This is needed to avoid IE destroying selections inside empty\r
@@ -1070,3 +1100,4 @@ CKEDITOR.dom.range.prototype.select =
                        selection.removeAllRanges();\r
                        selection.addRange( nativeRange );\r
                };\r
+} )();\r