From 19b108db83a7e578d0c8b36a59b862ba1c5dfa02 Mon Sep 17 00:00:00 2001
From: tangjinzhou <415800467@qq.com>
Date: Fri, 9 Feb 2018 18:42:19 +0800
Subject: [PATCH] fix select

---
 components/_util/vnode.js             |  8 ++-
 components/trigger/Popup.vue          |  7 +-
 components/vc-menu/MenuItem.vue       |  2 +-
 components/vc-select/DropdownMenu.vue |  7 +-
 components/vc-select/Option.vue       |  1 +
 components/vc-select/Select.vue       | 92 ++++++++++++++++++---------
 6 files changed, 79 insertions(+), 38 deletions(-)

diff --git a/components/_util/vnode.js b/components/_util/vnode.js
index 079c31522..c3619a14f 100644
--- a/components/_util/vnode.js
+++ b/components/_util/vnode.js
@@ -59,19 +59,23 @@ export function cloneElement (n, nodeProps, clone) {
     return null
   }
   const node = clone ? cloneVNode(ele, true) : ele
-  const { props = {}, key, on = {}} = nodeProps
+  const { props = {}, key, on = {}, children } = nodeProps
   const data = node.data || {}
   const { style = data.style,
     class: cls = data.class,
     attrs = data.attrs,
     ref,
+    domProps = data.domProps,
   } = nodeProps
-  node.data = Object.assign({}, data, { style, attrs, class: cls })
+  node.data = Object.assign({}, data, { style, attrs, class: cls, domProps })
   if (node.componentOptions) {
     node.componentOptions.propsData = node.componentOptions.propsData || {}
     node.componentOptions.listeners = node.componentOptions.listeners || {}
     node.componentOptions.propsData = { ...node.componentOptions.propsData, ...props }
     node.componentOptions.listeners = { ...node.componentOptions.listeners, ...on }
+    if (children) {
+      node.componentOptions.children = children
+    }
   } else {
     node.data.on = { ...(node.data.on || {}), ...on }
   }
diff --git a/components/trigger/Popup.vue b/components/trigger/Popup.vue
index e50d39a7f..9f8e959ed 100644
--- a/components/trigger/Popup.vue
+++ b/components/trigger/Popup.vue
@@ -118,13 +118,14 @@ export default {
         ref: 'popupInstance',
         style: { ...this.getZIndexStyle(), ...popupStyle },
       }
-      const transitionProps = {
+      let transitionProps = {
         props: Object.assign({
           appear: true,
           css: false,
         }),
       }
       const transitionName = getTransitionName()
+      let useTransition = !!transitionName
       const transitionEvent = {
         beforeEnter: (el) => {
           el.style.display = el.__vOriginalDisplay
@@ -144,6 +145,7 @@ export default {
       }
 
       if (typeof animation === 'object') {
+        useTransition = true
         const { on = {}, props = {}} = animation
         transitionProps.props = { ...transitionProps.props, ...props }
         transitionProps.on = { ...transitionEvent, ...on, afterLeave: (el) => {
@@ -153,6 +155,9 @@ export default {
       } else {
         transitionProps.on = transitionEvent
       }
+      if (!useTransition) {
+        transitionProps = {}
+      }
       return (<transition
         {...transitionProps}
       >
diff --git a/components/vc-menu/MenuItem.vue b/components/vc-menu/MenuItem.vue
index fa3f56b2d..52c548ec5 100644
--- a/components/vc-menu/MenuItem.vue
+++ b/components/vc-menu/MenuItem.vue
@@ -33,7 +33,7 @@ const MenuItem = {
     onKeyDown (e) {
       const keyCode = e.keyCode
       if (keyCode === KeyCode.ENTER) {
-        this.__emit('click', e)
+        this.onClick(e)
         return true
       }
     },
diff --git a/components/vc-select/DropdownMenu.vue b/components/vc-select/DropdownMenu.vue
index b974b9b12..46a51d9bc 100644
--- a/components/vc-select/DropdownMenu.vue
+++ b/components/vc-select/DropdownMenu.vue
@@ -5,6 +5,7 @@ import scrollIntoView from 'dom-scroll-into-view'
 import { getSelectKeys, preventDefaultEvent } from './util'
 import { cloneElement } from '../_util/vnode'
 import BaseMixin from '../_util/BaseMixin'
+import { hasProp, getSlotOptions } from '../_util/props-util'
 
 export default {
   name: 'DropdownMenu',
@@ -144,9 +145,9 @@ export default {
           }
 
           clonedMenuItems = menuItems.map(item => {
-            if (item.type.isMenuItemGroup) {
-              const children = item.$slots.default.map(clone)
-              return cloneElement(item, {}, children)
+            if (getSlotOptions(item).isMenuItemGroup) {
+              const children = item.componentOptions.children.map(clone)
+              return cloneElement(item, { children })
             }
             return clone(item)
           })
diff --git a/components/vc-select/Option.vue b/components/vc-select/Option.vue
index af6f3ab5b..d6f4d899a 100644
--- a/components/vc-select/Option.vue
+++ b/components/vc-select/Option.vue
@@ -7,6 +7,7 @@ export default {
       PropTypes.string,
       PropTypes.number,
     ]),
+    disabled: PropTypes.bool,
   },
   isSelectOption: true,
 }
diff --git a/components/vc-select/Select.vue b/components/vc-select/Select.vue
index 0fe9c5dc4..8118cd3d6 100644
--- a/components/vc-select/Select.vue
+++ b/components/vc-select/Select.vue
@@ -31,7 +31,6 @@ import {
 } from './util'
 import SelectTrigger from './SelectTrigger'
 import { SelectPropTypes } from './PropTypes'
-import { setTimeout } from 'timers'
 
 function noop () {}
 
@@ -128,7 +127,7 @@ export default {
             })
           }
         }
-        this.adjustOpenState()
+        // this.adjustOpenState()
       },
       deep: true,
     },
@@ -190,6 +189,7 @@ export default {
     },
 
     onDropdownVisibleChange (open) {
+      console.log('onDropdownVisibleChange', open)
       if (open && !this._focused) {
         this.clearBlurTime()
         this.timeoutFocus()
@@ -321,10 +321,10 @@ export default {
     },
 
     onArrowClick (e) {
-      // e.stopPropagation()
-      // if (!this.disabled) {
-      //   this.setOpenState(!this.openStatus, !this.openStatus)
-      // }
+      e.stopPropagation()
+      if (!this.disabled) {
+        this.setOpenState(!this.openStatus, !this.openStatus)
+      }
     },
 
     onPlaceholderClick (e) {
@@ -363,11 +363,13 @@ export default {
     },
 
     onOuterBlur (e) {
+      console.log('onOuterBlur')
       if (this.disabled) {
         e.preventDefault()
         return
       }
       this.blurTimer = setTimeout(() => {
+        console.log('onOuterBlur setTimeout')
         this._focused = false
         this.updateFocusClassName()
         const props = this.$props
@@ -399,6 +401,7 @@ export default {
         this.__emit('blur', this.getVLForOnChange(sValue))
         this.setOpenState(false)
       }, 10)
+      console.log('this.blurTimer', this.blurTimer)
     },
 
     onClearSelection (event) {
@@ -406,15 +409,21 @@ export default {
       if (disabled) {
         return
       }
-      event.stopPropagation()
       if (inputValue || sValue.length) {
         if (sValue.length) {
           this.fireChange([])
         }
-        this.setOpenState(false, true)
+        // this.setOpenState(false, true)
         if (inputValue) {
           this.setInputValue('')
         }
+        if (this._focused) {
+          this._focused = false
+        } else {
+          event.stopPropagation()
+        }
+      } else {
+        event.stopPropagation()
       }
     },
 
@@ -516,9 +525,6 @@ export default {
       }
       if (placeholder) {
         const p = {
-          props: {
-
-          },
           on: {
             mousedown: preventDefaultEvent,
             click: this.onPlaceholderClick,
@@ -540,37 +546,47 @@ export default {
     },
     inputClick (e) {
       if (this._focused) {
-        e.stopPropagation()
+        if (this.openStatus) {
+          e.stopPropagation()
+        } else {
+          this._focused = false
+        }
       }
     },
     inputBlur (e) {
-      // console.log(e.target)
       this.clearBlurTime()
       this.blurTimer = setTimeout(() => {
-        this.onOuterBlur()
         if (!this.disabled) {
-          this.setOpenState(!this.openStatus, !this.openStatus)
+          this._focused = false
+          this.setOpenState(false, false)
         }
       }, 10)
     },
+    inputFocus (e) {
+      this.clearBlurTime()
+    },
     _getInputElement () {
       const props = this.$props
       const inputElement = props.getInputElement
         ? props.getInputElement()
-        : <input id={props.id} autoComplete='off' />
+        : <input id={props.id} autoComplete='off' value='1111'/>
       const inputCls = classnames(getClass(inputElement), {
         [`${props.prefixCls}-search__field`]: true,
       })
       const inputEvents = getEvents(inputElement)
       // https://github.com/ant-design/ant-design/issues/4992#issuecomment-281542159
       // Add space to the end of the inputValue as the width measurement tolerance
+      inputElement.data = inputElement.data || {}
       return (
         <div class={`${props.prefixCls}-search__field__wrap`}>
           {cloneElement(inputElement, {
             attrs: {
-              value: this.inputValue,
+              ...(inputElement.data.attrs || {}),
               disabled: props.disabled,
             },
+            domProps: {
+              value: this.inputValue,
+            },
             class: inputCls,
             ref: 'inputRef',
             on: {
@@ -580,10 +596,10 @@ export default {
                 inputEvents.keydown || noop,
                 this.$listeners.inputKeydown
               ),
-              // focus: chaining(
-              //   this.onOuterFocus,
-              //   inputEvents.focus || noop,
-              // ),
+              focus: chaining(
+                this.inputFocus,
+                inputEvents.focus || noop,
+              ),
               blur: chaining(
                 this.inputBlur,
                 inputEvents.blur || noop,
@@ -622,9 +638,9 @@ export default {
       return this.$refs.selectTriggerRef.getInnerMenu()
     },
 
-    setOpenState (open, needFocus) {
+    setOpenState (open, needFocus, forceSet) {
       const { $props: props, openStatus } = this
-      if (openStatus === open) {
+      if (!forceSet && openStatus === open) {
         this.maybeFocus(open, needFocus)
         return
       }
@@ -894,9 +910,7 @@ export default {
       // If hidden menu due to no options, then it should be calculated again
       if (sOpen || this.hiddenForNoOptions) {
         options = this.renderFilterOptions()
-        console.log('options', options)
       }
-      console.log('options1', options)
       this._options = options
 
       if (isMultipleOrTagsOrCombobox($props) || !showSearch) {
@@ -915,15 +929,16 @@ export default {
     getOptionsAndOpenStatus () {
       let sOpen = this.sOpen
       if (this.skipAdjustOpen) {
+        this.openStatus = sOpen
         return {
-          option: this._options,
+          options: this._options,
           open: sOpen,
         }
       }
       const { $props, showSearch } = this
       let options = []
       // If hidden menu due to no options, then it should be calculated again
-      if (true || sOpen || this.hiddenForNoOptions) {
+      if (sOpen || this.hiddenForNoOptions) {
         options = this.renderFilterOptions()
       }
       this._options = options
@@ -1299,6 +1314,21 @@ export default {
         // this.getInputDOMNode().focus()
       }
     },
+    selectionRefClick (e) {
+      e.stopPropagation()
+      this.clearBlurTime()
+      if (!this.disabled) {
+        if (this._focused && this.openStatus) {
+          this._focused = false
+          this.setOpenState(false, false, true)
+          this.getInputDOMNode().blur()
+        } else {
+          this._focused = true
+          this.setOpenState(true, true, true)
+          this.getInputDOMNode().focus()
+        }
+      }
+    },
   },
 
   render () {
@@ -1324,7 +1354,6 @@ export default {
       [`${prefixCls}-enabled`]: !disabled,
       [`${prefixCls}-allow-clear`]: !!props.allowClear,
     }
-    console.log(options)
     return (
       <SelectTrigger
         dropdownAlign={props.dropdownAlign}
@@ -1360,8 +1389,9 @@ export default {
           ref='rootRef'
           // onBlur={this.onOuterBlur}
           // onFocus={this.onOuterFocus}
-          onClick={this.rootRefClick}
+          // onClick={this.rootRefClick}
           class={classnames(rootCls)}
+          // tabindex='-1'
         >
           <div
             ref='selectionRef'
@@ -1373,7 +1403,7 @@ export default {
             aria-haspopup='true'
             aria-expanded={openStatus}
             {...extraSelectionProps}
-            // onClick={this.stopPropagation}
+            onClick={this.selectionRefClick}
           >
             {ctrlNode}
             {this.renderClear()}
@@ -1383,7 +1413,7 @@ export default {
                 class={`${prefixCls}-arrow`}
                 style={UNSELECTABLE_STYLE}
                 unselectable='unselectable'
-                onClick={this.onArrowClick}
+                // onClick={this.onArrowClick}
               >
                 <b />
               </span>)}