UNPKG

silk-gui

Version:

GUI for developers and Node OS

148 lines (136 loc) 4.53 kB
var _ = require('../../util') module.exports = { bind: function () { var self = this var el = this.el // check params // - lazy: update model on "change" instead of "input" var lazy = this._checkParam('lazy') != null // - number: cast value into number when updating model. var number = this._checkParam('number') != null // - debounce: debounce the input listener var debounce = parseInt(this._checkParam('debounce'), 10) // handle composition events. // http://blog.evanyou.me/2014/01/03/composition-event/ var cpLocked = false this.cpLock = function () { cpLocked = true } this.cpUnlock = function () { cpLocked = false // in IE11 the "compositionend" event fires AFTER // the "input" event, so the input handler is blocked // at the end... have to call it here. set() } _.on(el,'compositionstart', this.cpLock) _.on(el,'compositionend', this.cpUnlock) // shared setter function set () { self.set( number ? _.toNumber(el.value) : el.value, true ) } // 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) var hasReadFilter = this.filters && this.filters.read this.listener = hasReadFilter || el.type === 'range' ? function textInputListener () { if (cpLocked) 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 } set() _.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) } }) } : function textInputListener () { if (cpLocked) return set() } if (debounce) { this.listener = _.debounce(this.listener, debounce) } 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() // // We want to make sure if a listener is attached using // jQuery, it is also removed with jQuery, that's why // we do the check for each directive instance and // store that check result on itself. This also allows // easier test coverage control by unsetting the global // jQuery variable in tests. this.hasjQuery = typeof jQuery === 'function' if (this.hasjQuery) { jQuery(el).on(this.event, this.listener) } else { _.on(el, this.event, this.listener) } // IE9 doesn't fire input event on backspace/del/cut if (!lazy && _.isIE9) { this.onCut = function () { _.nextTick(self.listener) } this.onDel = function (e) { if (e.keyCode === 46 || e.keyCode === 8) { self.listener() } } _.on(el, 'cut', this.onCut) _.on(el, 'keyup', this.onDel) } // set initial value if present if ( el.hasAttribute('value') || (el.tagName === 'TEXTAREA' && el.value.trim()) ) { this._initValue = number ? _.toNumber(el.value) : el.value } }, update: function (value) { this.el.value = _.toString(value) }, unbind: function () { var el = this.el if (this.hasjQuery) { jQuery(el).off(this.event, this.listener) } else { _.off(el, this.event, this.listener) } _.off(el,'compositionstart', this.cpLock) _.off(el,'compositionend', this.cpUnlock) if (this.onCut) { _.off(el,'cut', this.onCut) _.off(el,'keyup', this.onDel) } } }