X-Git-Url: https://jasonwoof.com/gitweb/?a=blobdiff_plain;f=_source%2Fplugins%2Fselection%2Fplugin.js;h=f0d2c4456ffa10d94a892dc55aea9f01df9d69ac;hb=c9fdde67e6384bd5a66adc2b3bba5c4ce9db56c7;hp=a78bb36f8dc040eb180dab36e3fdfb3188cb66ec;hpb=941b0a9ba4e673e292510d80a5a86806994b8ea6;p=ckeditor.git diff --git a/_source/plugins/selection/plugin.js b/_source/plugins/selection/plugin.js index a78bb36..f0d2c44 100644 --- a/_source/plugins/selection/plugin.js +++ b/_source/plugins/selection/plugin.js @@ -17,7 +17,7 @@ For licensing, see LICENSE.html or http://ckeditor.com/license // In IE, the "selectionchange" event may still get thrown when // releasing the WYSIWYG mode, so we need to check it first. var sel = this.getSelection(); - if ( !sel ) + if ( !sel || !sel.document.getWindow().$ ) return; var firstElement = sel.getStartElement(); @@ -72,6 +72,7 @@ For licensing, see LICENSE.html or http://ckeditor.com/license var selectAllCmd = { + modes : { wysiwyg : 1, source : 1 }, exec : function( editor ) { switch ( editor.mode ) @@ -80,7 +81,18 @@ For licensing, see LICENSE.html or http://ckeditor.com/license editor.document.$.execCommand( 'SelectAll', false, null ); break; case 'source' : - // TODO + // Select the contents of the textarea + var textarea = editor.textarea.$ ; + if ( CKEDITOR.env.ie ) + { + textarea.createTextRange().execCommand( 'SelectAll' ) ; + } + else + { + textarea.selectionStart = 0 ; + textarea.selectionEnd = textarea.value.length ; + } + textarea.focus() ; } }, canUndo : false @@ -93,7 +105,8 @@ For licensing, see LICENSE.html or http://ckeditor.com/license editor.on( 'contentDom', function() { var doc = editor.document, - body = doc.getBody(); + body = doc.getBody(), + html = doc.getDocumentElement(); if ( CKEDITOR.env.ie ) { @@ -103,30 +116,39 @@ For licensing, see LICENSE.html or http://ckeditor.com/license // than firing the selection change event. var savedRange, - saveEnabled; + saveEnabled, + restoreEnabled = 1; // "onfocusin" is fired before "onfocus". It makes it // possible to restore the selection before click // events get executed. - body.on( 'focusin', function() + body.on( 'focusin', function( evt ) { + // If there are elements with layout they fire this event but + // it must be ignored to allow edit its contents #4682 + if ( evt.data.$.srcElement.nodeName != 'BODY' ) + return; + // If we have saved a range, restore it at this // point. if ( savedRange ) { - // Well not break because of this. - try + if ( restoreEnabled ) { - savedRange.select(); + // Well not break because of this. + try + { + savedRange.select(); + } + catch (e) + {} } - catch (e) - {} savedRange = null; } }); - editor.window.on( 'focus', function() + body.on( 'focus', function() { // Enable selections to be saved. saveEnabled = true; @@ -134,18 +156,85 @@ For licensing, see LICENSE.html or http://ckeditor.com/license saveSelection(); }); - body.on( 'beforedeactivate', function() + body.on( 'beforedeactivate', function( evt ) { + // Ignore this event if it's caused by focus switch between + // internal editable control type elements, e.g. layouted paragraph. (#4682) + if ( evt.data.$.toElement ) + return; + // Disable selections from being saved. saveEnabled = false; + restoreEnabled = 1; + }); + + // IE before version 8 will leave cursor blinking inside the document after + // editor blurred unless we clean up the selection. (#4716) + if ( CKEDITOR.env.ie && CKEDITOR.env.version < 8 ) + { + editor.on( 'blur', function( evt ) + { + editor.document && editor.document.$.selection.empty(); }); + } + + // Listening on document element ensures that + // scrollbar is included. (#5280) + html.on( 'mousedown', function () + { + // Lock restore selection now, as we have + // a followed 'click' event which introduce + // new selection. (#5735) + restoreEnabled = 0; + }); + + html.on( 'mouseup', function () + { + restoreEnabled = 1; + }); + + // In IE6/7 the blinking cursor appears, but contents are + // not editable. (#5634) + if ( CKEDITOR.env.ie && ( CKEDITOR.env.ie7Compat || CKEDITOR.env.version < 8 || CKEDITOR.env.quirks ) ) + { + // The 'click' event is not fired when clicking the + // scrollbars, so we can use it to check whether + // the empty space following has been clicked. + html.on( 'click', function( evt ) + { + if ( evt.data.getTarget().getName() == 'html' ) + editor.getSelection().getRanges()[ 0 ].select(); + }); + } + var scroll; // IE fires the "selectionchange" event when clicking // inside a selection. We don't want to capture that. - body.on( 'mousedown', disableSave ); + body.on( 'mousedown', function( evt ) + { + // IE scrolls document to top on right mousedown + // when editor has no focus, remember this scroll + // position and revert it before context menu opens. (#5778) + if ( evt.data.$.button == 2 ) + { + var sel = editor.document.$.selection; + if ( sel.type == 'None' ) + scroll = editor.window.getScrollPosition(); + } + disableSave(); + }); + body.on( 'mouseup', - function() + function( evt ) { + // Restore recorded scroll position when needed on right mouseup. + if ( evt.data.$.button == 2 && scroll ) + { + editor.document.$.documentElement.scrollLeft = scroll.x; + editor.document.$.documentElement.scrollTop = scroll.y; + } + scroll = null; + saveEnabled = true; setTimeout( function() { @@ -177,7 +266,8 @@ For licensing, see LICENSE.html or http://ckeditor.com/license if ( saveEnabled ) { var doc = editor.document, - sel = doc && doc.$.selection; + sel = editor.getSelection(), + nativeSel = sel && sel.getNative(); // There is a very specific case, when clicking // inside a text selection. In that case, the @@ -187,7 +277,7 @@ For licensing, see LICENSE.html or http://ckeditor.com/license // range at the very start of the document. In // such situation we have to test the range, to // be sure it's valid. - if ( testIt && sel && sel.type == 'None' ) + if ( testIt && nativeSel && nativeSel.type == 'None' ) { // The "InsertImage" command can be used to // test whether the selection is good or not. @@ -200,7 +290,18 @@ For licensing, see LICENSE.html or http://ckeditor.com/license } } - savedRange = sel && sel.createRange(); + // Avoid saving selection from within text input. (#5747) + var parentTag; + if ( nativeSel && nativeSel.type && nativeSel.type != 'Control' + && ( parentTag = nativeSel.createRange() ) + && ( parentTag = parentTag.parentElement() ) + && ( parentTag = parentTag.nodeName ) + && parentTag.toLowerCase() in { input: 1, textarea : 1 } ) + { + return; + } + + savedRange = nativeSel && sel.getRanges()[ 0 ]; checkSelectionChangeTimeout.call( editor ); } @@ -433,8 +534,18 @@ For licensing, see LICENSE.html or http://ckeditor.com/license return ( cache.type = type ); }, - getRanges : - CKEDITOR.env.ie ? + /** + * Retrieve the {@link CKEDITOR.dom.range} instances that represent the current selection. + * Note: Some browsers returns multiple ranges even on a sequent selection, e.g. Firefox returns + * one range for each table cell when one or more table row is selected. + * @return {Array} + * @example + * var ranges = selection.getRanges(); + * alert(ranges.length); + */ + getRanges : (function () + { + var func = CKEDITOR.env.ie ? ( function() { // Finds the container and offset for a specific boundary @@ -459,17 +570,21 @@ For licensing, see LICENSE.html or http://ckeditor.com/license testRange = range.duplicate(); testRange.moveToElementText( child ); - testRange.collapse(); - var comparison = testRange.compareEndPoints( 'StartToStart', range ); + var comparisonStart = testRange.compareEndPoints( 'StartToStart', range ), + comparisonEnd = testRange.compareEndPoints( 'EndToStart', range ); + + testRange.collapse(); - if ( comparison > 0 ) + if ( comparisonStart > 0 ) break; - else if ( comparison === 0 ) - return { - container : parent, - offset : i - }; + // 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 }; testRange = null; } @@ -488,8 +603,17 @@ For licensing, see LICENSE.html or http://ckeditor.com/license // breaking character counting logic below. (#3949) var distance = testRange.text.replace( /(\r\n|\r)/g, '\n' ).length; - while ( distance > 0 ) - distance -= siblings[ --i ].nodeValue.length; + try + { + while ( distance > 0 ) + distance -= siblings[ --i ].nodeValue.length; + } + // Measurement in IE could be somtimes wrong because of