/** * Not type checking this file because flow doesn't like attaching * properties to Elements. */ import { isTextInputType } from 'web/util/element' import { looseEqual, looseIndexOf } from 'shared/util' import { warn, isAndroid, isIE9, isIE, isEdge } from 'core/util/index' /* istanbul ignore if */ if (isIE9) { // http://www.matts411.com/post/internet-explorer-9-oninput/ document.addEventListener('selectionchange', () => { const el = document.activeElement if (el && el.vmodel) { trigger(el, 'input') } }) } export default { inserted (el, binding, vnode) { if (vnode.tag === 'select') { setSelected(el, binding, vnode.context) el._vOptions = [].map.call(el.options, getValue) } else if (vnode.tag === 'textarea' || isTextInputType(el.type)) { el._vModifiers = binding.modifiers if (!binding.modifiers.lazy) { // Safari < 10.2 & UIWebView doesn't fire compositionend when // switching focus before confirming composition choice // this also fixes the issue where some browsers e.g. iOS Chrome // fires "change" instead of "input" on autocomplete. el.addEventListener('change', onCompositionEnd) if (!isAndroid) { el.addEventListener('compositionstart', onCompositionStart) el.addEventListener('compositionend', onCompositionEnd) } /* istanbul ignore if */ if (isIE9) { el.vmodel = true } } } }, componentUpdated (el, binding, vnode) { if (vnode.tag === 'select') { setSelected(el, binding, vnode.context) // in case the options rendered by v-for have changed, // it's possible that the value is out-of-sync with the rendered options. // detect such cases and filter out values that no longer has a matching // option in the DOM. const prevOptions = el._vOptions const curOptions = el._vOptions = [].map.call(el.options, getValue) if (curOptions.some((o, i) => !looseEqual(o, prevOptions[i]))) { // trigger change event if // no matching option found for at least one value const needReset = el.multiple ? binding.value.some(v => hasNoMatchingOption(v, curOptions)) : binding.value !== binding.oldValue && hasNoMatchingOption(binding.value, curOptions) if (needReset) { trigger(el, 'change') } } } } } function setSelected (el, binding, vm) { actuallySetSelected(el, binding, vm) /* istanbul ignore if */ if (isIE || isEdge) { setTimeout(() => { actuallySetSelected(el, binding, vm) }, 0) } } function actuallySetSelected (el, binding, vm) { const value = binding.value const isMultiple = el.multiple if (isMultiple && !Array.isArray(value)) { process.env.NODE_ENV !== 'production' && warn( `