@@ -15,23 +15,29 @@ module.exports = {
1515 var debounce = parseInt ( this . _checkParam ( 'debounce' ) , 10 )
1616
1717 // handle composition events.
18- // http://blog.evanyou.me/2014/01/03/composition-event/
19- var cpLocked = false
20- this . cpLock = function ( ) {
21- cpLocked = true
22- }
23- this . cpUnlock = function ( ) {
24- cpLocked = false
25- // in IE11 the "compositionend" event fires AFTER
26- // the "input" event, so the input handler is blocked
27- // at the end... have to call it here.
28- set ( )
18+ // http://blog.evanyou.me/2014/01/03/composition-event/
19+ // skip this for Android because it handles composition
20+ // events quite differently. Android doesn't trigger
21+ // composition events for language input methods e.g.
22+ // Chinese, but instead triggers them for spelling
23+ // suggestions... (see Discussion/#162)
24+ var composing = false
25+ if ( ! _ . isAndroid ) {
26+ this . onComposeStart = function ( ) {
27+ composing = true
28+ }
29+ this . onComposeEnd = function ( ) {
30+ composing = false
31+ // in IE11 the "compositionend" event fires AFTER
32+ // the "input" event, so the input handler is blocked
33+ // at the end... have to call it here.
34+ self . listener ( )
35+ }
36+ _ . on ( el , 'compositionstart' , this . onComposeStart )
37+ _ . on ( el , 'compositionend' , this . onComposeEnd )
2938 }
30- _ . on ( el , 'compositionstart' , this . cpLock )
31- _ . on ( el , 'compositionend' , this . cpUnlock )
3239
33- // shared setter
34- function set ( ) {
40+ function syncToModel ( ) {
3541 var val = number
3642 ? _ . toNumber ( el . value )
3743 : el . value
@@ -43,46 +49,50 @@ module.exports = {
4349 // the input with the filtered value.
4450 // also force update for type="range" inputs to enable
4551 // "lock in range" (see #506)
46- var hasReadFilter = this . filters && this . filters . read
47- this . listener = hasReadFilter || el . type === 'range'
48- ? function textInputListener ( ) {
49- if ( cpLocked ) return
50- var charsOffset
51- // some HTML5 input types throw error here
52- try {
53- // record how many chars from the end of input
54- // the cursor was at
55- charsOffset = el . value . length - el . selectionStart
56- } catch ( e ) { }
57- // Fix IE10/11 infinite update cycle
58- // https://github.com/yyx990803/vue/issues/592
59- /* istanbul ignore if */
60- if ( charsOffset < 0 ) {
61- return
62- }
63- set ( )
64- _ . nextTick ( function ( ) {
65- // force a value update, because in
66- // certain cases the write filters output the
67- // same result for different input values, and
68- // the Observer set events won't be triggered.
69- var newVal = self . _watcher . value
70- self . update ( newVal )
71- if ( charsOffset != null ) {
72- var cursorPos =
73- _ . toString ( newVal ) . length - charsOffset
74- el . setSelectionRange ( cursorPos , cursorPos )
75- }
76- } )
77- }
78- : function textInputListener ( ) {
79- if ( cpLocked ) return
80- set ( )
52+ if ( ( this . filters && this . filters . read ) || el . type === 'range' ) {
53+ this . listener = function ( ) {
54+ if ( composing ) return
55+ var charsOffset
56+ // some HTML5 input types throw error here
57+ try {
58+ // record how many chars from the end of input
59+ // the cursor was at
60+ charsOffset = el . value . length - el . selectionStart
61+ } catch ( e ) { }
62+ // Fix IE10/11 infinite update cycle
63+ // https://github.com/yyx990803/vue/issues/592
64+ /* istanbul ignore if */
65+ if ( charsOffset < 0 ) {
66+ return
8167 }
68+ syncToModel ( )
69+ _ . nextTick ( function ( ) {
70+ // force a value update, because in
71+ // certain cases the write filters output the
72+ // same result for different input values, and
73+ // the Observer set events won't be triggered.
74+ var newVal = self . _watcher . value
75+ self . update ( newVal )
76+ if ( charsOffset != null ) {
77+ var cursorPos =
78+ _ . toString ( newVal ) . length - charsOffset
79+ el . setSelectionRange ( cursorPos , cursorPos )
80+ }
81+ } )
82+ }
83+ } else {
84+ this . listener = function ( ) {
85+ if ( composing ) return
86+ syncToModel ( )
87+ }
88+ }
8289
8390 if ( debounce ) {
8491 this . listener = _ . debounce ( this . listener , debounce )
8592 }
93+
94+ // Now attach the main listener
95+
8696 this . event = lazy ? 'change' : 'input'
8797 // Support jQuery events, since jQuery.trigger() doesn't
8898 // trigger native events in some cases and some plugins
@@ -137,8 +147,10 @@ module.exports = {
137147 } else {
138148 _ . off ( el , this . event , this . listener )
139149 }
140- _ . off ( el , 'compositionstart' , this . cpLock )
141- _ . off ( el , 'compositionend' , this . cpUnlock )
150+ if ( this . onComposeStart ) {
151+ _ . off ( el , 'compositionstart' , this . onComposeStart )
152+ _ . off ( el , 'compositionend' , this . onComposeEnd )
153+ }
142154 if ( this . onCut ) {
143155 _ . off ( el , 'cut' , this . onCut )
144156 _ . off ( el , 'keyup' , this . onDel )
0 commit comments