Merge "wfProfileOut() for new return added in c6396 (c4e407c)"
[lhc/web/wiklou.git] / resources / jquery / jquery.textSelection.js
index 8a1f44b..91b6e75 100644 (file)
@@ -2,6 +2,26 @@
  * These plugins provide extra functionality for interaction with textareas.
  */
 ( function( $ ) {
+
+if (document.selection && document.selection.createRange) {
+       // On IE, patch the focus() method to restore the windows' scroll position
+       // (bug 32241)
+       $.fn.extend({
+               focus : (function ( _focus ) {
+                       return function () {
+                               if ( arguments.length == 0 ) {
+                                       var $w = $( window );
+                                       var state = {top: $w.scrollTop(), left: $w.scrollLeft()};
+                                       var result = _focus.apply( this, arguments );
+                                       window.scrollTo( state.top, state.left );
+                                       return result;
+                               }
+                               return _focus.apply( this, arguments );
+                       };
+               })( $.fn.focus )
+       });
+}
+
 $.fn.textSelection = function( command, options ) {
 
 /**
@@ -17,6 +37,19 @@ function rangeForElementIE( e ) {
        }
 }
 
+/**
+ * Helper function for IE for activating the textarea. Called only in the
+ * IE-specific code paths below; makes use of IE-specific non-standard
+ * function setActive() if possible to avoid screen flicker.
+ */
+function activateElementOnIE( element ) {
+       if ( element.setActive ) {
+               element.setActive(); // bug 32241: doesn't scroll
+       } else {
+               $( element ).focus(); // may scroll (but we patched it above)
+       }
+}
+
 var fn = {
 /**
  * Get the contents of the textarea
@@ -34,7 +67,7 @@ getSelection: function() {
        if ( $(e).is( ':hidden' ) ) {
                // Do nothing
        } else if ( document.selection && document.selection.createRange ) {
-               e.focus();
+               activateElementOnIE( e );
                var range = document.selection.createRange();
                retval = range.text;
        } else if ( e.selectionStart || e.selectionStart == '0' ) {
@@ -98,8 +131,58 @@ encapsulateSelection: function( options ) {
                var isSample = false;
                if ( this.style.display == 'none' ) {
                        // Do nothing
+               } else if ( document.selection && document.selection.createRange ) {
+                       // IE
+
+                       // Note that IE9 will trigger the next section unless we check this first.
+                       // See bug 35201.
+
+                       activateElementOnIE( this );
+                       if ( context ) {
+                               context.fn.restoreCursorAndScrollTop();
+                       }
+                       if ( options.selectionStart !== undefined ) {
+                               $(this).textSelection( 'setSelection', { 'start': options.selectionStart, 'end': options.selectionEnd } );
+                       }
+
+                       var selText = $(this).textSelection( 'getSelection' );
+                       var scrollTop = this.scrollTop;
+                       var range = document.selection.createRange();
+
+                       checkSelectedText();
+                       var insertText = pre + selText + post;
+                       if ( options.splitlines ) {
+                               insertText = doSplitLines( selText, pre, post );
+                       }
+                       if ( options.ownline && range.moveStart ) {
+                               var range2 = document.selection.createRange();
+                               range2.collapse();
+                               range2.moveStart( 'character', -1 );
+                               // FIXME: Which check is correct?
+                               if ( range2.text != "\r" && range2.text != "\n" && range2.text != "" ) {
+                                       insertText = "\n" + insertText;
+                                       pre += "\n";
+                               }
+                               var range3 = document.selection.createRange();
+                               range3.collapse( false );
+                               range3.moveEnd( 'character', 1 );
+                               if ( range3.text != "\r" && range3.text != "\n" && range3.text != "" ) {
+                                       insertText += "\n";
+                                       post += "\n";
+                               }
+                       }
+
+                       range.text = insertText;
+                       if ( isSample && options.selectPeri && range.moveStart ) {
+                               range.moveStart( 'character', - post.length - selText.length );
+                               range.moveEnd( 'character', - post.length );
+                       }
+                       range.select();
+                       // Restore the scroll position
+                       this.scrollTop = scrollTop;
                } else if ( this.selectionStart || this.selectionStart == '0' ) {
                        // Mozilla/Opera
+
                        $(this).focus();
                        if ( options.selectionStart !== undefined ) {
                                $(this).textSelection( 'setSelection', { 'start': options.selectionStart, 'end': options.selectionEnd } );
@@ -149,51 +232,6 @@ encapsulateSelection: function( options ) {
                                this.selectionStart = startPos + insertText.length;
                                this.selectionEnd = this.selectionStart;
                        }
-               } else if ( document.selection && document.selection.createRange ) {
-                       // IE
-                       $(this).focus();
-                       if ( context ) {
-                               context.fn.restoreCursorAndScrollTop();
-                       }
-                       if ( options.selectionStart !== undefined ) {
-                               $(this).textSelection( 'setSelection', { 'start': options.selectionStart, 'end': options.selectionEnd } );
-                       }
-                       
-                       var selText = $(this).textSelection( 'getSelection' );
-                       var scrollTop = this.scrollTop;
-                       var range = document.selection.createRange();
-
-                       checkSelectedText();
-                       var insertText = pre + selText + post;
-                       if ( options.splitlines ) {
-                               insertText = doSplitLines( selText, pre, post );
-                       }
-                       if ( options.ownline && range.moveStart ) {
-                               var range2 = document.selection.createRange();
-                               range2.collapse();
-                               range2.moveStart( 'character', -1 );
-                               // FIXME: Which check is correct?
-                               if ( range2.text != "\r" && range2.text != "\n" && range2.text != "" ) {
-                                       insertText = "\n" + insertText;
-                                       pre += "\n";
-                               }
-                               var range3 = document.selection.createRange();
-                               range3.collapse( false );
-                               range3.moveEnd( 'character', 1 );
-                               if ( range3.text != "\r" && range3.text != "\n" && range3.text != "" ) {
-                                       insertText += "\n";
-                                       post += "\n";
-                               }
-                       }
-
-                       range.text = insertText;
-                       if ( isSample && options.selectPeri && range.moveStart ) {
-                               range.moveStart( 'character', - post.length - selText.length );
-                               range.moveEnd( 'character', - post.length );
-                       }
-                       range.select();
-                       // Restore the scroll position
-                       this.scrollTop = scrollTop;
                }
                $(this).trigger( 'encapsulateSelection', [ options.pre, options.peri, options.post, options.ownline,
                        options.replace, options.spitlines ] );
@@ -208,12 +246,20 @@ encapsulateSelection: function( options ) {
  * Get the position (in resolution of bytes not nessecarily characters)
  * in a textarea
  *
+ * Will focus the textarea in some browsers (IE/Opera)
+ *
  * @fixme document the options parameters
  */
  getCaretPosition: function( options ) {
        function getCaret( e ) {
                var caretPos = 0, endPos = 0;
-               if ( $.browser.msie ) {
+               if ( document.selection && document.selection.createRange ) {
+                       // IE doesn't properly report non-selected caret position through
+                       // the selection ranges when textarea isn't focused. This can
+                       // lead to saving a bogus empty selection, which then screws up
+                       // whatever we do later (bug 31847).
+                       activateElementOnIE( e );
+
                        // IE Support
                        var preFinished = false;
                        var periFinished = false;