https://www.mediawiki.org/wiki/Special:Code/MediaWiki/112269

Revision: 112269
Author:   rmoen
Date:     2012-02-23 23:20:47 +0000 (Thu, 23 Feb 2012)
Log Message:
-----------
Rework general input to no longer clear during IME.  Polling interval for non 
keyDown text comparison. Chunked text insertion for all normal keys which makes 
nice transactions and clears input.

Modified Paths:
--------------
    trunk/extensions/VisualEditor/modules/ve/es/ve.es.Surface.js

Modified: trunk/extensions/VisualEditor/modules/ve/es/ve.es.Surface.js
===================================================================
--- trunk/extensions/VisualEditor/modules/ve/es/ve.es.Surface.js        
2012-02-23 23:20:35 UTC (rev 112268)
+++ trunk/extensions/VisualEditor/modules/ve/es/ve.es.Surface.js        
2012-02-23 23:20:47 UTC (rev 112269)
@@ -1,6 +1,6 @@
 /**
  * Creates an ve.es.Surface object.
- * 
+ *
  * @class
  * @constructor
  * @param {jQuery} $container DOM Container to render surface into
@@ -56,7 +56,11 @@
                selecting: false,
                cursorAnchor: null,
                keydownTimeout: null,
-               keys: { shift: false }
+               keys: { shift: false },
+               readInterval: null,
+               prevInput: '',
+               undoCount: 0,
+               chunkSize: 3
        };
        this.dimensions = {
                width: this.$.width(),
@@ -77,7 +81,6 @@
                        _this.$input.val( 
_this.documentView.model.getContentText( selection ) ).select();
                        _this.clearInsertionAnnotations();
                } else {
-                       _this.$input.val('').select();
                        _this.loadInsertionAnnotations();
                }
        } );
@@ -90,39 +93,42 @@
        this.$.mousedown( function(e) {
                return _this.onMouseDown( e );
        } );
+
        this.$input.bind( {
-                       'focus': function() {
+                       'focus': function( e ) {
                                // Make sure we aren't double-binding
                                $document.unbind( '.es-surfaceView' );
                                // Bind mouse and key events to the document to 
ensure we don't miss anything
                                $document.bind( {
-                                       'mousemove.es-surfaceView': function(e) 
{
+                                       'mousemove.es-surfaceView': function( e 
) {
                                                return _this.onMouseMove( e );
                                        },
-                                       'mouseup.es-surfaceView': function(e) {
+                                       'mouseup.es-surfaceView': function( e ) 
{
                                                return _this.onMouseUp( e );
                                        },
                                        'keydown.es-surfaceView': function( e ) 
{
-                                               return _this.onKeyDown( e );    
                
+                                               return _this.onKeyDown( e );
                                        },
                                        'keyup.es-surfaceView': function( e ) {
-                                               return _this.onKeyUp( e );      
        
+                                               return _this.onKeyUp( e );
                                        },
                                        'copy.es-surfaceView': function( e ) {
-                                               return _this.onCopy( e );       
        
+                                               return _this.onCopy( e );
                                        },
                                        'cut.es-surfaceView': function( e ) {
-                                               return _this.onCut( e );        
        
+                                               return _this.onCut( e );
                                        },
                                        'paste.es-surfaceView': function( e ) {
-                                               return _this.onPaste( e );      
        
+                                               return _this.onPaste( e );
                                        }
                                } );
+                               return _this.onFocus( e );
                        },
                        'blur': function( e ) {
                                // Release our event handlers when not focused
                                $document.unbind( '.es-surfaceView' );
                                _this.hideCursor();
+                               return _this.onBlur( e );
                        },
                        'paste': function() {
                                setTimeout( function() {
@@ -237,7 +243,7 @@
                                        if( node === endNode ) {
                                                return false;
                                        }
-                               }, startNode );                 
+                               }, startNode );
                        }
                }
                _this.emit( 'cursor', annotations, nodes );
@@ -320,11 +326,11 @@
                }
                var _this = this;
                this.emitUpdateTimeout = setTimeout( function() {
-                       _this.emit( 'update' ); 
+                       _this.emit( 'update' );
                        _this.emitUpdateTimeout = undefined;
                }, delay );
        } else {
-               this.emit( 'update' );  
+               this.emit( 'update' );
        }
 };
 
@@ -374,6 +380,9 @@
                        );
                        this.mouse.selectedRange = selection.clone();
                }
+               //cancel ime mode by losing focus
+               this.$input.blur();
+               this.$input.focus();
        }
        
        var _this = this;
@@ -442,7 +451,7 @@
                                selection.to = 
this.model.getDocument().getRelativeContentOffset(
                                        nodeRange.to, -1
                                );
-                       }       
+                       }
                }
                // Apply new selection
                this.model.select( selection, true );
@@ -450,7 +459,7 @@
 };
 
 ve.es.Surface.prototype.onMouseUp = function( e ) {
-       if ( e.which === 1 ) { // left mouse button 
+       if ( e.which === 1 ) { // left mouse button
                this.mouse.selectingMode = this.mouse.selectedRange = null;
                this.model.select( this.currentSelection, true );
                if ( this.contextView ) {
@@ -479,6 +488,41 @@
        return true;
 };
 
+ve.es.Surface.prototype.onFocus = function( e ) {
+       var _this = this;
+       this.keyboard.prevInput = _this.$input.val();
+       //start polling
+       this.keyboard.readInterval = setInterval( function(){
+               _this.readInput( _this );
+       }, 10 );
+};
+
+ve.es.Surface.prototype.onBlur = function( e ) {
+       //stop polling
+       if ( this.keyboard.readInterval ) {
+               clearInterval( this.readInterval );
+       }
+};
+
+ve.es.Surface.prototype.readInput = function( _this ) {
+       var             selection = _this.currentSelection.clone(),
+                       text = _this.$input.val();
+       
+       //Do nothing if the text is the same.
+       if ( text == _this.keyboard.prevInput ) {
+               return false;
+       }
+
+       //transfer text
+       _this.keyboard.prevInput = text;
+       _this.handleInsert();
+};
+
+ve.es.Surface.prototype.resetText = function( e ) {
+       this.$input.val( '' );
+       this.keyboard.undoCount = 0;
+};
+
 ve.es.Surface.prototype.onKeyDown = function( e ) {
        switch ( e.keyCode ) {
                // Tab
@@ -486,6 +530,7 @@
                        if ( !e.metaKey && !e.ctrlKey && !e.altKey ) {
                                this.$input.val( '\t' );
                                this.handleInsert();
+                               this.resetText();
                                e.preventDefault();
                                return false;
                        }
@@ -587,10 +632,12 @@
                        if ( this.keyboard.keys.shift ) {
                                this.$input.val( '\n' );
                                this.handleInsert();
+                               this.resetText();
                                e.preventDefault();
                                return false;
                        }
                        this.handleEnter();
+                       this.resetText();
                        e.preventDefault();
                        break;
                // Insert content (maybe)
@@ -608,6 +655,7 @@
                                                        this.model.redo();
                                                } else {
                                                        this.model.undo();
+                                                       this.resetText();
                                                }
                                                return false;
                                        // a (select all)
@@ -643,8 +691,11 @@
                                                return false;
                                }
                        }
-                       // Regular text insertion
-                       this.handleInsert();
+                       // Ignore chrome 229 IME event.
+                       if (e.which !== 229) {
+                               // Chunked insert
+                               this.handleInsert( this.keyboard.chunkSize ); 
//three character chunk
+                       }
                        break;
        }
        return true;
@@ -659,13 +710,13 @@
        }
 };
 
-ve.es.Surface.prototype.handleInsert = function() {
+ve.es.Surface.prototype.handleInsert = function( chunkSize ) {
        var _this = this;
        if ( _this.keyboard.keydownTimeout ) {
                clearTimeout( _this.keyboard.keydownTimeout );
        }
        _this.keyboard.keydownTimeout = setTimeout( function () {
-               _this.insertFromInput();
+               _this.insertFromInput( chunkSize );
        }, 10 );
 };
 
@@ -676,6 +727,7 @@
                sourceSplitableNode,
                targetSplitableNode,
                tx;
+       this.resetText();
        if ( selection.from === selection.to ) {
                if ( backspace ) {
                        sourceOffset = selection.to;
@@ -757,7 +809,7 @@
                        [ { 'type': 'paragraph' }, { 'type': '/paragraph' } ]
                );
                this.model.transact( tx );
-               selection.from = selection.to = nodeOffset + 
node.getElementLength() + 1;       
+               selection.from = selection.to = nodeOffset + 
node.getElementLength() + 1;
        } else {
                var     stack = [],
                        splitable = false;
@@ -790,44 +842,88 @@
        this.model.select( selection );
 };
 
-ve.es.Surface.prototype.insertFromInput = function() {
-       var selection = this.currentSelection.clone(),
-               val = this.$input.val();
+ve.es.Surface.prototype.insertFromInput = function( chunkSize ) {
+       var             selection = this.currentSelection.clone(),
+                       val = this.$input.val(),
+                       chunkThis = '',
+                       chunked = [],
+                       slice,
+                       data,
+                       tx;
+
        if ( val.length > 0 ) {
                // Check if there was any effective input
                var input = this.$input[0],
                        // Internet Explorer
                        range = document.selection && 
document.selection.createRange();
                if (
+                       // Be sure text is being selected so IME updates are 
not blocked
+                       ( this.mouse.selectingMode || this.keyboard.selection ) 
&&
                        // DOM 3.0
-                       ( 'selectionStart' in input && input.selectionEnd - 
input.selectionStart ) ||
+                       (( 'selectionStart' in input && input.selectionEnd - 
input.selectionStart ) ||
                        // Internet Explorer
-                       ( range && range.text.length )
+                       ( range && range.text.length ))
                ) {
                        // The input is still selected, so the key must not 
have inserted anything
                        return;
                }
 
-               // Clear the value for more input
-               this.$input.val( '' );
+               //process undo count
+               while ( this.keyboard.undoCount > 0 ) {
+                       this.keyboard.undoCount--;
+                       this.model.undo();
+               }
+               //reset selection
+               selection = this.currentSelection.clone();
 
-               // Prepare and process a transaction
-               var tx;
+               // Prepare and process a selection removal.
                if ( selection.from != selection.to ) {
                        tx = this.model.getDocument().prepareRemoval( selection 
);
                        this.model.transact( tx, true );
                        selection.from = selection.to =
                                Math.min( selection.from, selection.to );
                }
-               var data = val.split('');
-               ve.dm.DocumentNode.addAnnotationsToData( data, 
this.getInsertionAnnotations() );
-               tx = this.model.getDocument().prepareInsertion( selection.from, 
data );
-               this.model.transact( tx );
+               //Chunking text only on keyDown.
+               if (chunkSize !== null && val.length > chunkSize && chunkSize > 
1) {
+                       chunkThis = val;
+                       //build a chunked array
+                       while ( chunkThis.length > 0 ) {
+                               slice = chunkThis.substring( 0, chunkSize );
+                               chunkThis = chunkThis.substring( chunkSize );
+                               chunked.push( slice );
+                       }
+                       //chunked transactions
+                       for ( var chunk in chunked ) {
+                               this.model.breakpoint();
+                               data = chunked[chunk].split('');
+                               selection = this.currentSelection.clone();
+                               ve.dm.DocumentNode.addAnnotationsToData( data, 
this.getInsertionAnnotations() );
+                               tx = this.model.getDocument().prepareInsertion( 
selection.from, data );
+                               this.model.transact( tx );
+                               // Move the selection
+                               selection.from += chunked[chunk].length;
+                               selection.to += chunked[chunk].length;
+                               this.model.select( selection );
+                               this.model.breakpoint();
+                       }
 
-               // Move the selection
-               selection.from += val.length;
-               selection.to += val.length;
-               this.model.select( selection );
+                       //set the working text to the last chunk
+                       this.$input.val( chunked[chunked.length - 1] );
+                       this.keyboard.undoCount = 1;
+               } else {
+                       this.model.breakpoint();
+                       data = val.split('');
+                       ve.dm.DocumentNode.addAnnotationsToData( data, 
this.getInsertionAnnotations() );
+                       tx = this.model.getDocument().prepareInsertion( 
selection.from, data );
+                       this.model.transact( tx );
+                       // Move the selection
+                       selection.from += val.length;
+                       selection.to += val.length;
+                       this.model.select( selection );
+                       this.keyboard.undoCount++;
+                       this.model.breakpoint();
+               }
+
        }
 };
 
@@ -877,7 +973,6 @@
                                        break;
                                default:
                                        throw new Error( 'unrecognized cursor 
movement unit' );
-                                       break;
                        }
                        break;
                case 'up':
@@ -941,7 +1036,7 @@
                                default:
                                        throw new Error( 'unrecognized cursor 
movement unit' );
                        }
-                       break;  
+                       break;
                default:
                        throw new Error( 'unrecognized cursor direction' );
        }
@@ -956,15 +1051,16 @@
                selection.from = selection.to = to;
        }
        this.model.select( selection, true );
+       this.resetText();
 };
 
 /**
  * Shows the cursor in a new position.
- * 
+ *
  * @method
  * @param offset {Integer} Position to show the cursor at
  */
-ve.es.Surface.prototype.showCursor = function() {      
+ve.es.Surface.prototype.showCursor = function() {
        var $window = $( window ),
                position = this.documentView.getRenderedPositionFromOffset(
                        this.currentSelection.to, this.cursor.initialBias
@@ -982,7 +1078,7 @@
 
        // Auto scroll to cursor
        var inputTop = this.$input.offset().top,
-               inputBottom = inputTop + position.bottom - position.top;        
+               inputBottom = inputTop + position.bottom - position.top;
        if ( inputTop - this.dimensions.toolbarHeight < 
this.dimensions.scrollTop ) {
                $window.scrollTop( inputTop - this.dimensions.toolbarHeight );
        } else if ( inputBottom > ( this.dimensions.scrollTop + 
this.dimensions.height ) ) {
@@ -1004,7 +1100,7 @@
 
 /**
  * Hides the cursor.
- * 
+ *
  * @method
  */
 ve.es.Surface.prototype.hideCursor = function() {


_______________________________________________
MediaWiki-CVS mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-cvs

Reply via email to