combobox onchanging event reporting incorrect value when typing "fast"

XMLWordPrintable

    • Type: Bug
    • Resolution: Unresolved
    • Priority: Normal
    • None
    • Affects Version/s: 9.6.4
    • Component/s: Components
    • Security Level: Jimmy
    • None

      Steps to Reproduce

      run this example

      <zk>
          <combobox
                    instantSelect="false"
                    autodrop="true"
                    autocomplete="true"
                    onChanging='Clients.log(event.name + ": " + event.value)'
                    onSelect='Clients.log(event.name + ": " + (self.selectedItem == null ? null : self.selectedItem.value))'>
              <comboitem value="Authorize" label="${self.value}"/>
              <comboitem value="Alpha" label="${self.value}"/>
              <comboitem value="Beta" label="${self.value}"/>
              <comboitem value="Beer" label="${self.value}"/>
              <comboitem value="Beef" label="${self.value}"/>
          </combobox>
      </zk>
      

       

      Type "a" in the input field

      Wait a few seconds to make onChanging is complete.

      Type "ctrl" and release "ctrl" without making changes to the input value (or other non-character keys such as ctrl, alt, num lock. etc)

      Current Result

      Pressing a releasing a key causes typeAhead to trigger.

      Pressing a releasing "a" cause onChanging value to be sent 

      onChanging: a

      pressing and releasing "ctrl" causes typeAhead to trigger again, but uses the current already autocompleted value "authorize" as the input value, which in turns causes

      onChanging: authorize
      

      Note:

      A different outcome of the same effect also happen if multiple character keys are pressed in sequence

      For example, the sequence

      Keydown: A

      Keydown: U

      KeyUp: A

      KeyUp: U

      will trigger 2 typeAhead invocations on the input when the content of the input is already "au"

      The first invocation will autocomplete the input to "authorize" and send onchanging: au

      the 2nd invocation will not trigger while the input value is already "authorize" and will send onchanging: authorize

      Expected Result

      OnChanging shouldn't trigger inconsistently when multiple keyUp events are resolved in sequence if the actual typed value didn't change in between.

      Debug Information

      doKeyUp_ will fire _typeahead

      typeahead will store the last human-typed value into this.valueEnter_

      the first invocation of typeahead stores the actual human-typed value in this.valueEnter_, then set the input value to the autocomplete string

      the 2nd invocation of typeahead uses the autocomplete value currently in the input as the last human-typed value incorrectly and stores it into this.valueEnter_

      When onChanging triggers, it reads the this.valueEnter_, which currently holds the autocompleted value instead of the last human-typed value.

      Workaround

      partial workaround: counts concurrently pressed keys, and only fire keyUp once no keys are currently held.

      This prevents multiple typeAheads being sent during rapid typing, but doesn't prevent typeahead on already autocompleted value when pressing non-character keys like ctrl, alt, num lock. etc

      <script><![CDATA[
      	zk.afterLoad("zul.inp", function () {
      	    var _xCombobox = {};
      	    zk.override(zul.inp.Combobox.prototype, _xCombobox, {
      	        doKeyDown_: function doKeyDown_(evt) {
      	        	if(!this.keys){
      	        		this.keys = new Map();
      	        	}
      	        	this.keys.set(evt.key, true);
      	            if (!this._disabled) {
      	                this._doKeyDown(evt);
      
      	                if (!evt.stopped) this.$supers('doKeyDown_', arguments);
      	              }
      	            },
      	        doKeyUp_: function doKeyUp_(evt) {
                  	this.keys.delete(evt.key)
                      if (!this._disabled && !this.keys.size) {
                        if (!this._readonly && !this._autoCompleteSuppressed) {
                          var keyCode = evt.keyCode,
                              bDel = keyCode == 8
                          /*BS*/
                          || keyCode == 46;
                          /*DEL*/
                          // ZK-3607: The value is not ready in onKeyDown, but is ready in onKeyUp
      
                          this._typeahead(bDel);
                        }
      
                        this.$supers('doKeyUp_', arguments);
                      }
                    }
      	     });
      	});
      ]]></script>
      

            Assignee:
            Unassigned
            Reporter:
            cor3000
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated: