Skip to content

Combobox (<f:combobox>) flashes its suggestion list on click and immediately closes; typing works fine #26920

@Anexus5919

Description

@Anexus5919

Jenkins and plugins versions report

Pre-existing on current master (verified at master 063b6a7, Jenkins 2.568+; combobox component src/main/js/components/dropdowns/combo-box.js, tippy.js 6.3.7). Not introduced by #26884 (the appendTo change does not affect this flash). Client-side / web-UI only. Affects <f:combobox> (INPUT.combobox2); INPUT.auto-complete is not affected. Most visible when the combobox is rendered inside a <dialog>.

What Operating System are you using (both controller, and any agents involved in the problem)?

Controller OS is irrelevant (client-side). Reproduces in any modern browser with a mouse. (Originally reported for a combobox shown inside a dialog.)

Reproduction steps

  1. Open a page that renders an <f:combobox>, ideally inside a <dialog> (a plugin descriptor config opened via an "Add"/config dialog, for example the credentials add/config flow). The same structural code path is exercised in core at /project-relationship (projectRelationship.jelly:47,52).
  2. Click (mouse) into the combobox input.
  3. Observe the suggestion list. For contrast, instead type a character into the same field.

Expected Results

Clicking into the combobox opens the suggestion list and keeps it open, the same as typing does.

Actual Results

On click, the suggestion list appears and immediately disappears (a flash), and a second click is needed to keep it open. Typing in the same field opens the list normally with no flash.

Anything else?

Root cause, verified against the source. Single true cause: the Jenkins document "click" listener in utils.js hides the dropdown because the combobox's tippy reference is the sibling <div>, not the clicked <input>.

Structural setup (combobox-specific):

  • src/main/js/components/dropdowns/combo-box.js:63-64 inserts a sibling DIV after the input (e.parentNode.insertBefore(div, e.nextElementSibling)), and combo-box.js:29 calls Utils.generateDropdown(div, …), so the tippy reference is the DIV (div.contains(input) is false).
  • combo-box.js:77 shows the dropdown when the input is focused/clicked: e.addEventListener("focus", () => updateSuggestions(e, div, items)), which calls e.dropdown.show() (combo-box.js:41). It is shown programmatically, not via tippy's trigger:"click".

The hide that causes the flash, src/main/js/components/dropdowns/utils.js:31-42:

document.addEventListener("click", (event) => {
  const isClickOnReference = instance.reference.contains(event.target);
  const isSelect = event.target.tagName === "SELECT";
  if (!isClickOnReference && !isSelect) {
    instance.clickToHide = true;
    instance.hide();
  }
});

instance.reference is the DIV; event.target is the INPUT (a sibling, outside the DIV), so isClickOnReference is false, the target is not a SELECT, and instance.hide() runs.

Sequence on one click (mousedown, focus, mouseup, click):

  1. focus (combo-box.js:77) calls e.dropdown.show(), so the items become visible.
  2. The same click's click phase bubbles to document and hits the utils.js:31 listener; the reference (DIV) does not contain the input, so instance.hide() runs.
  3. Net within one click: show (focus), then hide (document-click), which is the flash. This runs on every click outside the DIV and is sufficient on its own.

Why typing does not flash: typing shows the list via the input event (combo-box.js:85-90), which dispatches no click, so the utils.js:31 listener never fires.

Why it is combobox-specific (autocomplete never flashes):

  1. Autocomplete's reference is the input (autocomplete.js:39-40 passes e), so a click on the input gives instance.reference.contains(event.target) === true and the hide branch is skipped.
  2. Autocomplete has no focus-to-show handler (only input + focusout, autocomplete.js:103-111), so a bare click opens nothing to flash.

Ruled out: tippy's own onDocumentPress/hideOnClick (default hideOnClick: true, not overridden) is not decisive, because the list is shown programmatically and the deterministic hide is the app's utils.js:31 listener; tippy trigger:"click" toggling is not involved, because tippy binds its click trigger to the DIV reference, which the user never clicks.

Fix direction: at utils.js:32, treat a click on the combobox's associated input as "on reference" (for example instance.reference.parentNode.contains(event.target), or check the reference's sibling input), or make the combobox's tippy reference the input itself like autocomplete (combo-box.js:29), or guard the focus-to-show so it does not re-open within the same click. No automated coverage (HtmlUnit ComboBoxTest.java cannot render the popper); verify manually in a browser.

Are you interested in contributing a fix?

Yes. Targeted fix at the utils.js document-click containment check (and/or making the combobox reference the input), per the analysis above.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions