Skip to content

Clicking a language tab scrolls the page edit interface (AdminThemeUikit) #2303

Description

@adrianbj

Short description

Clicking a language tab scrolls the page edit interface. The field whose tab you clicked gets scrolled to the top of the viewport, and #langTab_… is left in the address bar.

It's most obvious inside a Repeater Matrix item partway down a long page, where it yanks the repeater item header, field label and tab row off the top of the screen. Present since the introduction of AdminThemeUikit.

Expected behavior

Clicking a language tab switches the visible language input and leaves the scroll position alone.

Actual behavior

The page scrolls so the newly shown language input sits at the top of the viewport.

Steps to reproduce

  1. Multi-language site using AdminThemeUikit, with a multi-language text field inside a Repeater Matrix item.
  2. Edit a page and scroll down to the repeater item.
  3. Click a language tab on that field — the page jumps.

Details / cause

LanguageTabs::addTab() renders each tab as a real fragment anchor:

"<a data-lang='$language->id' class='$aClass' href='#langTab_$id'>$title</a>"

and LanguageSupport::wrapInputfieldOutput() gives the matching per-language wrapper div that exact id:

$out = "<div class='$class' id='langTab_$id' data-language='$language->id'>" . …

so the fragment always resolves. The click handler in LanguageTabs.js (~line 110) switches the visible tab but never calls preventDefault(), so after it runs the browser follows the fragment and scrolls the just-shown div to the top of the viewport.

This was masked under the old default admin theme: jQueryUI is true there, $this.tabs() runs, and jQuery UI's _eventHandler calls event.preventDefault() unconditionally. AdminThemeUikit/init.php sets 'jQueryUI' => false, so no widget intercepts the click — and UIkit's own tab component deliberately won't either, since its maybeDefaultPreventClick() only suppresses href="#" and href="", not real fragments.

It actually fires on every language tab click, but only moves the page where there is room to scroll. That's why it reads as Repeater Matrix specific rather than universal: on a short form with title/body near the top there's little or nothing to scroll.

Also affects file/image description language tabs, which use the same pattern (InputfieldFile.module builds langTab_{id}__{language}).

Fix

e.preventDefault() in that click handler — preventDefault() rather than return false, so propagation stays intact for UIkit's delegated handler on the <ul uk-tab>. Verified on a live install.

PR: processwire/processwire#338

Setup / Environment

  • ProcessWire 3.0.270 (dev)
  • AdminThemeUikit
  • LanguageSupport / LanguageSupportFields, FieldtypeRepeaterMatrix

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions