|
|
@@ -5,6 +5,7 @@ module.exports = {
|
|
|
bind: function () {
|
|
|
var self = this
|
|
|
var el = this.el
|
|
|
+ var isRange = el.type === 'range'
|
|
|
|
|
|
// check params
|
|
|
// - lazy: update model on "change" instead of "input"
|
|
|
@@ -22,7 +23,7 @@ module.exports = {
|
|
|
// Chinese, but instead triggers them for spelling
|
|
|
// suggestions... (see Discussion/#162)
|
|
|
var composing = false
|
|
|
- if (!_.isAndroid) {
|
|
|
+ if (!_.isAndroid && !isRange) {
|
|
|
this.onComposeStart = function () {
|
|
|
composing = true
|
|
|
}
|
|
|
@@ -37,63 +38,38 @@ module.exports = {
|
|
|
_.on(el, 'compositionend', this.onComposeEnd)
|
|
|
}
|
|
|
|
|
|
- function syncToModel () {
|
|
|
- var val = number
|
|
|
- ? _.toNumber(el.value)
|
|
|
- : el.value
|
|
|
- self.set(val)
|
|
|
- }
|
|
|
-
|
|
|
- // if the directive has filters, we need to
|
|
|
- // record cursor position and restore it after updating
|
|
|
- // the input with the filtered value.
|
|
|
- // also force update for type="range" inputs to enable
|
|
|
- // "lock in range" (see #506)
|
|
|
- if (this.hasRead || el.type === 'range') {
|
|
|
- this.listener = function () {
|
|
|
- if (composing) return
|
|
|
- var charsOffset
|
|
|
- // some HTML5 input types throw error here
|
|
|
- try {
|
|
|
- // record how many chars from the end of input
|
|
|
- // the cursor was at
|
|
|
- charsOffset = el.value.length - el.selectionStart
|
|
|
- } catch (e) {}
|
|
|
- // Fix IE10/11 infinite update cycle
|
|
|
- // https://github.com/yyx990803/vue/issues/592
|
|
|
- /* istanbul ignore if */
|
|
|
- if (charsOffset < 0) {
|
|
|
- return
|
|
|
- }
|
|
|
- syncToModel()
|
|
|
- _.nextTick(function () {
|
|
|
- // force a value update, because in
|
|
|
- // certain cases the write filters output the
|
|
|
- // same result for different input values, and
|
|
|
- // the Observer set events won't be triggered.
|
|
|
- var newVal = self._watcher.value
|
|
|
- self.update(newVal)
|
|
|
- if (charsOffset != null) {
|
|
|
- var cursorPos =
|
|
|
- _.toString(newVal).length - charsOffset
|
|
|
- el.setSelectionRange(cursorPos, cursorPos)
|
|
|
- }
|
|
|
- })
|
|
|
+ // prevent messing with the input when user is typing,
|
|
|
+ // and force update on blur.
|
|
|
+ this.focused = false
|
|
|
+ if (!isRange) {
|
|
|
+ this.onFocus = function () {
|
|
|
+ self.focused = true
|
|
|
}
|
|
|
- } else {
|
|
|
- this.listener = function () {
|
|
|
- if (composing) return
|
|
|
- syncToModel()
|
|
|
+ this.onBlur = function () {
|
|
|
+ self.focused = false
|
|
|
+ self.listener()
|
|
|
}
|
|
|
+ _.on(el, 'focus', this.onFocus)
|
|
|
+ _.on(el, 'blur', this.onBlur)
|
|
|
}
|
|
|
|
|
|
+ // Now attach the main listener
|
|
|
+ this.listener = function () {
|
|
|
+ if (composing) return
|
|
|
+ var val = number || isRange
|
|
|
+ ? _.toNumber(el.value)
|
|
|
+ : el.value
|
|
|
+ self.set(val)
|
|
|
+ // force update here, because the watcher may not
|
|
|
+ // run when the value is the same.
|
|
|
+ _.nextTick(function () {
|
|
|
+ self.update(self._watcher.value)
|
|
|
+ })
|
|
|
+ }
|
|
|
if (debounce) {
|
|
|
this.listener = _.debounce(this.listener, debounce)
|
|
|
}
|
|
|
|
|
|
- // Now attach the main listener
|
|
|
-
|
|
|
- this.event = lazy ? 'change' : 'input'
|
|
|
// Support jQuery events, since jQuery.trigger() doesn't
|
|
|
// trigger native events in some cases and some plugins
|
|
|
// rely on $.trigger()
|
|
|
@@ -106,9 +82,15 @@ module.exports = {
|
|
|
// jQuery variable in tests.
|
|
|
this.hasjQuery = typeof jQuery === 'function'
|
|
|
if (this.hasjQuery) {
|
|
|
- jQuery(el).on(this.event, this.listener)
|
|
|
+ jQuery(el).on('change', this.listener)
|
|
|
+ if (!lazy) {
|
|
|
+ jQuery(el).on('input', this.listener)
|
|
|
+ }
|
|
|
} else {
|
|
|
- _.on(el, this.event, this.listener)
|
|
|
+ _.on(el, 'change', this.listener)
|
|
|
+ if (!lazy) {
|
|
|
+ _.on(el, 'input', this.listener)
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
// IE9 doesn't fire input event on backspace/del/cut
|
|
|
@@ -137,15 +119,19 @@ module.exports = {
|
|
|
},
|
|
|
|
|
|
update: function (value) {
|
|
|
- this.el.value = _.toString(value)
|
|
|
+ if (!this.focused) {
|
|
|
+ this.el.value = _.toString(value)
|
|
|
+ }
|
|
|
},
|
|
|
|
|
|
unbind: function () {
|
|
|
var el = this.el
|
|
|
if (this.hasjQuery) {
|
|
|
- jQuery(el).off(this.event, this.listener)
|
|
|
+ jQuery(el).off('change', this.listener)
|
|
|
+ jQuery(el).off('input', this.listener)
|
|
|
} else {
|
|
|
- _.off(el, this.event, this.listener)
|
|
|
+ _.off(el, 'change', this.listener)
|
|
|
+ _.off(el, 'input', this.listener)
|
|
|
}
|
|
|
if (this.onComposeStart) {
|
|
|
_.off(el, 'compositionstart', this.onComposeStart)
|
|
|
@@ -155,5 +141,9 @@ module.exports = {
|
|
|
_.off(el, 'cut', this.onCut)
|
|
|
_.off(el, 'keyup', this.onDel)
|
|
|
}
|
|
|
+ if (this.onFocus) {
|
|
|
+ _.off(el, 'focus', this.onFocus)
|
|
|
+ _.off(el, 'blur', this.onBlur)
|
|
|
+ }
|
|
|
}
|
|
|
}
|