JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
vanilla ckeditor-3.2.2
[ckeditor.git] / _source / plugins / selection / plugin.js
index a78bb36..04be631 100644 (file)
@@ -72,6 +72,7 @@ For licensing, see LICENSE.html or http://ckeditor.com/license
 \r
        var selectAllCmd =\r
        {\r
+               modes : { wysiwyg : 1, source : 1 },\r
                exec : function( editor )\r
                {\r
                        switch ( editor.mode )\r
@@ -80,7 +81,18 @@ For licensing, see LICENSE.html or http://ckeditor.com/license
                                        editor.document.$.execCommand( 'SelectAll', false, null );\r
                                        break;\r
                                case 'source' :\r
-                                       // TODO\r
+                                       // Select the contents of the textarea\r
+                                       var textarea = editor.textarea.$ ;\r
+                                       if ( CKEDITOR.env.ie )\r
+                                       {\r
+                                               textarea.createTextRange().execCommand( 'SelectAll' ) ;\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               textarea.selectionStart = 0 ;\r
+                                               textarea.selectionEnd = textarea.value.length ;\r
+                                       }\r
+                                       textarea.focus() ;\r
                        }\r
                },\r
                canUndo : false\r
@@ -108,8 +120,13 @@ 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
-                                               body.on( 'focusin', function()\r
+                                               body.on( 'focusin', function( evt )\r
                                                        {\r
+                                                               // If there are elements with layout they fire this event but\r
+                                                               // it must be ignored to allow edit its contents #4682\r
+                                                               if ( evt.data.$.srcElement.nodeName != 'BODY' )\r
+                                                                       return;\r
+\r
                                                                // If we have saved a range, restore it at this\r
                                                                // point.\r
                                                                if ( savedRange )\r
@@ -126,7 +143,7 @@ For licensing, see LICENSE.html or http://ckeditor.com/license
                                                                }\r
                                                        });\r
 \r
-                                               editor.window.on( 'focus', function()\r
+                                               body.on( 'focus', function()\r
                                                        {\r
                                                                // Enable selections to be saved.\r
                                                                saveEnabled = true;\r
@@ -134,12 +151,27 @@ For licensing, see LICENSE.html or http://ckeditor.com/license
                                                                saveSelection();\r
                                                        });\r
 \r
-                                               body.on( 'beforedeactivate', function()\r
+                                               body.on( 'beforedeactivate', function( evt )\r
                                                        {\r
+                                                               // Ignore this event if it's caused by focus switch between\r
+                                                               // internal editable control type elements, e.g. layouted paragraph. (#4682)\r
+                                                               if ( evt.data.$.toElement )\r
+                                                                       return;\r
+\r
                                                                // Disable selections from being saved.\r
                                                                saveEnabled = false;\r
                                                        });\r
 \r
+                                               // IE before version 8 will leave cursor blinking inside the document after\r
+                                               // editor blurred unless we clean up the selection. (#4716)\r
+                                               if ( CKEDITOR.env.ie && CKEDITOR.env.version < 8 )\r
+                                               {\r
+                                                       doc.getWindow().on( 'blur', function( evt )\r
+                                                       {\r
+                                                               editor.document.$.selection.empty();\r
+                                                       });\r
+                                               }\r
+\r
                                                // IE fires the "selectionchange" event when clicking\r
                                                // inside a selection. We don't want to capture that.\r
                                                body.on( 'mousedown', disableSave );\r
@@ -177,7 +209,8 @@ For licensing, see LICENSE.html or http://ckeditor.com/license
                                                        if ( saveEnabled )\r
                                                        {\r
                                                                var doc = editor.document,\r
-                                                                       sel = doc && doc.$.selection;\r
+                                                                       sel = editor.getSelection(),\r
+                                                                       nativeSel = sel && sel.getNative();\r
 \r
                                                                // There is a very specific case, when clicking\r
                                                                // inside a text selection. In that case, the\r
@@ -187,7 +220,7 @@ For licensing, see LICENSE.html or http://ckeditor.com/license
                                                                // range at the very start of the document. In\r
                                                                // such situation we have to test the range, to\r
                                                                // be sure it's valid.\r
-                                                               if ( testIt && sel && sel.type == 'None' )\r
+                                                               if ( testIt && nativeSel && nativeSel.type == 'None' )\r
                                                                {\r
                                                                        // The "InsertImage" command can be used to\r
                                                                        // test whether the selection is good or not.\r
@@ -200,7 +233,16 @@ For licensing, see LICENSE.html or http://ckeditor.com/license
                                                                        }\r
                                                                }\r
 \r
-                                                               savedRange = sel && sel.createRange();\r
+                                                               // Avoid saving selection from within text input. (#5747)\r
+                                                               var parentTag;\r
+                                                               if ( nativeSel.type == 'Text'\r
+                                                                       && ( parentTag = nativeSel.createRange().parentElement().nodeName.toLowerCase() )\r
+                                                                       && parentTag in { input: 1, textarea : 1 } )\r
+                                                               {\r
+                                                                       return;\r
+                                                               }\r
+\r
+                                                               savedRange = nativeSel && sel.getRanges()[ 0 ];\r
 \r
                                                                checkSelectionChangeTimeout.call( editor );\r
                                                        }\r
@@ -459,17 +501,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
-                                                               if ( comparison > 0 )\r
+                                                               testRange.collapse();\r
+\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
@@ -488,8 +534,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
@@ -628,7 +683,7 @@ 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
@@ -695,26 +750,34 @@ For licensing, see LICENSE.html or http://ckeditor.com/license
                        if ( cache.selectedElement !== undefined )\r
                                return cache.selectedElement;\r
 \r
-                       var node;\r
-\r
-                       if ( this.getType() == CKEDITOR.SELECTION_ELEMENT )\r
-                       {\r
-                               var sel = this.getNative();\r
+                       var self = this;\r
 \r
-                               if ( CKEDITOR.env.ie )\r
+                       var node = CKEDITOR.tools.tryThese(\r
+                               // Is it native IE control type selection?\r
+                               function()\r
                                {\r
-                                       try\r
+                                       return self.getNative().createRange().item( 0 );\r
+                               },\r
+                               // Figure it out by checking if there's a single enclosed\r
+                               // node of the range.\r
+                               function()\r
+                               {\r
+                                       var range  = self.getRanges()[ 0 ],\r
+                                               enclosed,\r
+                                               selected;\r
+\r
+                                       // Check first any enclosed element, e.g. <ul>[<li><a href="#">item</a></li>]</ul>\r
+                                       for ( var i = 2; i && !( ( enclosed = range.getEnclosedNode() )\r
+                                               && ( enclosed.type == CKEDITOR.NODE_ELEMENT )\r
+                                               && styleObjectElements[ enclosed.getName() ]\r
+                                               && ( selected = enclosed ) ); i-- )\r
                                        {\r
-                                               node = sel.createRange().item(0);\r
+                                               // Then check any deep wrapped element, e.g. [<b><i><img /></i></b>]\r
+                                               range.shrink( CKEDITOR.SHRINK_ELEMENT );\r
                                        }\r
-                                       catch(e) {}\r
-                               }\r
-                               else\r
-                               {\r
-                                       var range = sel.getRangeAt( 0 );\r
-                                       node = range.startContainer.childNodes[ range.startOffset ];\r
-                               }\r
-                       }\r
+\r
+                                       return  selected.$;\r
+                               });\r
 \r
                        return cache.selectedElement = ( node ? new CKEDITOR.dom.element( node ) : null );\r
                },\r
@@ -807,6 +870,10 @@ For licensing, see LICENSE.html or http://ckeditor.com/license
                                        range.moveToElementText( element.$ );\r
                                        range.select();\r
                                }\r
+                               finally\r
+                               {\r
+                                       this.document.fire( 'selectionchange' );\r
+                               }\r
 \r
                                this.reset();\r
                        }\r
@@ -957,6 +1024,7 @@ For licensing, see LICENSE.html or http://ckeditor.com/license
 {\r
 var notWhitespaces = CKEDITOR.dom.walker.whitespaces( true );\r
 var fillerTextRegex = /\ufeff|\u00a0/;\r
+var nonCells = { table:1,tbody:1,tr:1 };\r
 \r
 CKEDITOR.dom.range.prototype.select =\r
        CKEDITOR.env.ie ?\r
@@ -967,6 +1035,14 @@ CKEDITOR.dom.range.prototype.select =
                        var isStartMarkerAlone;\r
                        var dummySpan;\r
 \r
+                       // IE doesn't support selecting the entire table row/cell, move the selection into cells, e.g.\r
+                       // <table><tbody><tr>[<td>cell</b></td>... => <table><tbody><tr><td>[cell</td>...\r
+                       if ( this.startContainer.type == CKEDITOR.NODE_ELEMENT && this.startContainer.getName() in nonCells\r
+                               || this.endContainer.type == CKEDITOR.NODE_ELEMENT && this.endContainer.getName() in nonCells )\r
+                       {\r
+                               this.shrink( CKEDITOR.NODE_ELEMENT, true );\r
+                       }\r
+\r
                        var bookmark = this.createBookmark();\r
 \r
                        // Create marker tags for the start and end boundaries.\r
@@ -1043,6 +1119,7 @@ CKEDITOR.dom.range.prototype.select =
                                else\r
                                        ieRange.select();\r
 \r
+                               this.moveToPosition( dummySpan, CKEDITOR.POSITION_BEFORE_START );\r
                                dummySpan.remove();\r
                        }\r
                        else\r
@@ -1051,6 +1128,8 @@ CKEDITOR.dom.range.prototype.select =
                                endNode.remove();\r
                                ieRange.select();\r
                        }\r
+\r
+                       this.document.fire( 'selectionchange' );\r
                }\r
        :\r
                function()\r