X-Git-Url: https://jasonwoof.com/gitweb/?p=ckeditor.git;a=blobdiff_plain;f=_source%2Fplugins%2Fselection%2Fplugin.js;h=39c6db7d76f77510f4ffd627ce136cde2f049f8e;hp=d8888c19dae88b213abeec2e1aca5c14eecf7f17;hb=e73319a12b56100b29ef456fd74114fe5519e01c;hpb=f0610347140239143439a511ee2bd48cb784f470 diff --git a/_source/plugins/selection/plugin.js b/_source/plugins/selection/plugin.js index d8888c1..39c6db7 100644 --- a/_source/plugins/selection/plugin.js +++ b/_source/plugins/selection/plugin.js @@ -463,6 +463,7 @@ For licensing, see LICENSE.html or http://ckeditor.com/license doc.on( 'mouseup', checkSelectionChangeTimeout, editor ); doc.on( 'keyup', checkSelectionChangeTimeout, editor ); + doc.on( 'selectionchange', checkSelectionChangeTimeout, editor ); } }); @@ -489,10 +490,10 @@ For licensing, see LICENSE.html or http://ckeditor.com/license /** * Gets the current selection from the editing area when in WYSIWYG mode. - * @returns {CKEDITOR.dom.selection} A selection object or null if not on + * @returns {CKEDITOR.dom.selection} A selection object or null if not in * WYSIWYG mode or no selection is available. * @example - * var selection = CKEDITOR.instances.editor1.getSelection(); + * var selection = CKEDITOR.instances.editor1.getSelection(); * alert( selection.getType() ); */ CKEDITOR.editor.prototype.getSelection = function() @@ -509,7 +510,7 @@ For licensing, see LICENSE.html or http://ckeditor.com/license * Gets the current selection from the document. * @returns {CKEDITOR.dom.selection} A selection object. * @example - * var selection = CKEDITOR.instances.editor1.document.getSelection(); + * var selection = CKEDITOR.instances.editor1.document.getSelection(); * alert( selection.getType() ); */ CKEDITOR.dom.document.prototype.getSelection = function() @@ -528,11 +529,11 @@ For licensing, see LICENSE.html or http://ckeditor.com/license CKEDITOR.SELECTION_NONE = 1; /** - * Text or collapsed selection. + * A text or a collapsed selection. * @constant * @example * if ( editor.getSelection().getType() == CKEDITOR.SELECTION_TEXT ) - * alert( 'Text is selected' ); + * alert( 'A text is selected' ); */ CKEDITOR.SELECTION_TEXT = 2; @@ -548,7 +549,9 @@ For licensing, see LICENSE.html or http://ckeditor.com/license /** * Manipulates the selection in a DOM document. * @constructor + * @param {CKEDITOR.dom.document} document The DOM document that contains the selection. * @example + * var sel = new CKEDITOR.dom.selection( CKEDITOR.document ); */ CKEDITOR.dom.selection = function( document ) { @@ -566,7 +569,7 @@ For licensing, see LICENSE.html or http://ckeditor.com/license /** * IE BUG: The selection's document may be a different document than the - * editor document. Return null if that's the case. + * editor document. Return null if that is the case. */ if ( CKEDITOR.env.ie ) { @@ -593,9 +596,9 @@ For licensing, see LICENSE.html or http://ckeditor.com/license /** * Gets the native selection object from the browser. * @function - * @returns {Object} The native selection object. + * @returns {Object} The native browser selection object. * @example - * var selection = editor.getSelection().getNative(); + * var selection = editor.getSelection().getNative(); */ getNative : CKEDITOR.env.ie ? @@ -613,19 +616,19 @@ For licensing, see LICENSE.html or http://ckeditor.com/license * Gets the type of the current selection. The following values are * available: * * @function * @returns {Number} One of the following constant values: - * {@link CKEDITOR.SELECTION_NONE}, {@link CKEDITOR.SELECTION_TEXT} or - * {@link CKEDITOR.SELECTION_ELEMENT}. + * {@link CKEDITOR.SELECTION_NONE}, {@link CKEDITOR.SELECTION_TEXT}, or + * {@link CKEDITOR.SELECTION_ELEMENT}. * @example - * if ( editor.getSelection().getType() == CKEDITOR.SELECTION_TEXT ) - * alert( 'Text is selected' ); + * if ( editor.getSelection().getType() == CKEDITOR.SELECTION_TEXT ) + * alert( 'A text is selected' ); */ getType : CKEDITOR.env.ie ? @@ -693,13 +696,15 @@ For licensing, see LICENSE.html or http://ckeditor.com/license }, /** - * 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} + * Retrieves the {@link CKEDITOR.dom.range} instances that represent the current selection. + * Note: Some browsers return multiple ranges even for a continuous selection. Firefox, for example, returns + * one range for each table cell when one or more table rows are selected. + * @function + * @param {Boolean} [onlyEditables] If set to true, this function retrives editable ranges only. + * @return {Array} Range instances that represent the current selection. * @example - * var ranges = selection.getRanges(); - * alert(ranges.length); + * var ranges = selection.getRanges(); + * alert( ranges.length ); */ getRanges : (function() { @@ -957,18 +962,30 @@ For licensing, see LICENSE.html or http://ckeditor.com/license if ( range.collapsed ) continue; + // Range may start inside a non-editable element, + // replace the range start after it. + if ( range.startContainer.isReadOnly() ) + { + var current = range.startContainer; + while( current ) + { + if ( current.is( 'body' ) || !current.isReadOnly() ) + break; + + if ( current.type == CKEDITOR.NODE_ELEMENT + && current.getAttribute( 'contentEditable' ) == 'false' ) + range.setStartAfter( current ); + + current = current.getParent(); + } + } + var startContainer = range.startContainer, endContainer = range.endContainer, startOffset = range.startOffset, endOffset = range.endOffset, walkerRange = range.clone(); - // Range may start inside a non-editable element, restart range - // by the end of it. - var readOnly; - if ( ( readOnly = startContainer.isReadOnly() ) ) - range.setStartAfter( readOnly ); - // Enlarge range start/end with text node to avoid walker // being DOM destructive, it doesn't interfere our checking // of elements below as well. @@ -1031,7 +1048,7 @@ For licensing, see LICENSE.html or http://ckeditor.com/license * @returns {CKEDITOR.dom.element} The element at the beginning of the * selection. * @example - * var element = editor.getSelection().getStartElement(); + * var element = editor.getSelection().getStartElement(); * alert( element.getName() ); */ getStartElement : function() @@ -1107,12 +1124,12 @@ For licensing, see LICENSE.html or http://ckeditor.com/license }, /** - * Gets the current selected element. + * Gets the currently selected element. * @returns {CKEDITOR.dom.element} The selected element. Null if no * selection is available or the selection type is not - * {@link CKEDITOR.SELECTION_ELEMENT}. + * {@link CKEDITOR.SELECTION_ELEMENT}. * @example - * var element = editor.getSelection().getSelectedElement(); + * var element = editor.getSelection().getSelectedElement(); * alert( element.getName() ); */ getSelectedElement : function() @@ -1129,6 +1146,74 @@ For licensing, see LICENSE.html or http://ckeditor.com/license { return self.getNative().createRange().item( 0 ); }, + // If a table or list is fully selected. + function() + { + var root, + retval, + range = self.getRanges()[ 0 ], + ancestor = range.getCommonAncestor( 1, 1 ), + tags = { table:1,ul:1,ol:1,dl:1 }; + + for ( var t in tags ) + { + if ( root = ancestor.getAscendant( t, 1 ) ) + break; + } + + if ( root ) + { + // Enlarging the start boundary. + var testRange = new CKEDITOR.dom.range( this.document ); + testRange.setStartAt( root, CKEDITOR.POSITION_AFTER_START ); + testRange.setEnd( range.startContainer, range.startOffset ); + + var enlargeables = CKEDITOR.tools.extend( tags, CKEDITOR.dtd.$listItem, CKEDITOR.dtd.$tableContent ), + walker = new CKEDITOR.dom.walker( testRange ), + // Check the range is at the inner boundary of the structural element. + guard = function( walker, isEnd ) + { + return function( node, isWalkOut ) + { + if ( node.type == CKEDITOR.NODE_TEXT && ( !CKEDITOR.tools.trim( node.getText() ) || node.getParent().data( 'cke-bookmark' ) ) ) + return true; + + var tag; + if ( node.type == CKEDITOR.NODE_ELEMENT ) + { + tag = node.getName(); + + // Bypass bogus br at the end of block. + if ( tag == 'br' && isEnd && node.equals( node.getParent().getBogus() ) ) + return true; + + if ( isWalkOut && tag in enlargeables || tag in CKEDITOR.dtd.$removeEmpty ) + return true; + } + + walker.halted = 1; + return false; + }; + }; + + walker.guard = guard( walker ); + + if ( walker.checkBackward() && !walker.halted ) + { + walker = new CKEDITOR.dom.walker( testRange ); + testRange.setStart( range.endContainer, range.endOffset ); + testRange.setEndAt( root, CKEDITOR.POSITION_BEFORE_END ); + walker.guard = guard( walker, 1 ); + if ( walker.checkForward() && !walker.halted ) + retval = root.$; + } + } + + if ( !retval ) + throw 0; + + return retval; + }, // Figure it out by checking if there's a single enclosed // node of the range. function() @@ -1154,11 +1239,11 @@ For licensing, see LICENSE.html or http://ckeditor.com/license }, /** - * Retrieves the text contained within the range, empty string is returned for non-text selection. - * @returns {String} string of text within the current selection. + * Retrieves the text contained within the range. An empty string is returned for non-text selection. + * @returns {String} A string of text within the current selection. * @since 3.6.1 * @example - * var text = editor.getSelectedText(); + * var text = editor.getSelection().getSelectedText(); * alert( text ); */ getSelectedText : function() @@ -1175,6 +1260,14 @@ For licensing, see LICENSE.html or http://ckeditor.com/license return ( cache.selectedText = text ); }, + /** + * Locks the selection made in the editor in order to make it possible to + * manipulate it without browser interference. A locked selection is + * cached and remains unchanged until it is released with the #unlock + * method. + * @example + * editor.getSelection().lock(); + */ lock : function() { // Call all cacheable function. @@ -1192,6 +1285,13 @@ For licensing, see LICENSE.html or http://ckeditor.com/license this.document.setCustomData( 'cke_locked_selection', this ); }, + /** + * Unlocks the selection made in the editor and locked with the #lock method. + * An unlocked selection is no longer cached and can be changed. + * @param {Boolean} [restore] If set to true, the selection is restored back to the selection saved earlier by using the #lock method. + * @example + * editor.getSelection().unlock(); + */ unlock : function( restore ) { var doc = this.document, @@ -1225,14 +1325,22 @@ For licensing, see LICENSE.html or http://ckeditor.com/license } }, + /** + * Clears the selection cache. + * @example + * editor.getSelection().reset(); + */ reset : function() { this._.cache = {}; }, /** - * Make the current selection of type {@link CKEDITOR.SELECTION_ELEMENT} by enclosing the specified element. - * @param element + * Makes the current selection of type {@link CKEDITOR.SELECTION_ELEMENT} by enclosing the specified element. + * @param {CKEDITOR.dom.element} element The element to enclose in the selection. + * @example + * var element = editor.document.getById( 'sampleElement' ); + * editor.getSelection.selectElement( element ); */ selectElement : function( element ) { @@ -1261,9 +1369,12 @@ For licensing, see LICENSE.html or http://ckeditor.com/license }, /** - * Adding the specified ranges to document selection preceding - * by clearing up the original selection. - * @param {CKEDITOR.dom.range} ranges + * Clears the original selection and adds the specified ranges + * to the document selection. + * @param {Array} ranges An array of {@link CKEDITOR.dom.range} instances representing ranges to be added to the document. + * @example + * var ranges = new CKEDITOR.dom.range( editor.document ); + * editor.getSelection().selectRanges( [ ranges ] ); */ selectRanges : function( ranges ) { @@ -1402,15 +1513,20 @@ For licensing, see LICENSE.html or http://ckeditor.com/license sel.addRange( nativeRange ); } + // Don't miss selection change event for non-IEs. + this.document.fire( 'selectionchange' ); this.reset(); } }, /** - * Create bookmark for every single of this selection range (from #getRanges) - * by calling the {@link CKEDITOR.dom.range.prototype.createBookmark} method, - * with extra cares to avoid interferon among those ranges. Same arguments are - * received as with the underlay range method. + * Creates a bookmark for each range of this selection (from #getRanges) + * by calling the {@link CKEDITOR.dom.range.prototype.createBookmark} method, + * with extra care taken to avoid interference among those ranges. The arguments + * received are the same as with the underlying range method. + * @returns {Array} Array of bookmarks for each range. + * @example + * var bookmarks = editor.getSelection().createBookmarks(); */ createBookmarks : function( serializable ) { @@ -1418,10 +1534,13 @@ For licensing, see LICENSE.html or http://ckeditor.com/license }, /** - * Create bookmark for every single of this selection range (from #getRanges) - * by calling the {@link CKEDITOR.dom.range.prototype.createBookmark2} method, - * with extra cares to avoid interferon among those ranges. Same arguments are - * received as with the underlay range method. + * Creates a bookmark for each range of this selection (from #getRanges) + * by calling the {@link CKEDITOR.dom.range.prototype.createBookmark2} method, + * with extra care taken to avoid interference among those ranges. The arguments + * received are the same as with the underlying range method. + * @returns {Array} Array of bookmarks for each range. + * @example + * var bookmarks = editor.getSelection().createBookmarks2(); */ createBookmarks2 : function( normalized ) { @@ -1429,8 +1548,12 @@ For licensing, see LICENSE.html or http://ckeditor.com/license }, /** - * Select the virtual ranges denote by the bookmarks by calling #selectRanges. - * @param bookmarks + * Selects the virtual ranges denoted by the bookmarks by calling #selectRanges. + * @param {Array} bookmarks The bookmarks representing ranges to be selected. + * @returns {CKEDITOR.dom.selection} This selection object, after the ranges were selected. + * @example + * var bookmarks = editor.getSelection().createBookmarks(); + * editor.getSelection().selectBookmarks( bookmarks ); */ selectBookmarks : function( bookmarks ) { @@ -1446,7 +1569,10 @@ For licensing, see LICENSE.html or http://ckeditor.com/license }, /** - * Retrieve the common ancestor node of the first range and the last range. + * Retrieves the common ancestor node of the first range and the last range. + * @returns {CKEDITOR.dom.element} The common ancestor of the selection. + * @example + * var ancestor = editor.getSelection().getCommonAncestor(); */ getCommonAncestor : function() { @@ -1457,7 +1583,9 @@ For licensing, see LICENSE.html or http://ckeditor.com/license }, /** - * Moving scroll bar to the current selection's start position. + * Moves the scrollbar to the starting position of the current selection. + * @example + * editor.getSelection().scrollIntoView(); */ scrollIntoView : function() {