diff options
author | Volker E <volker.e@wikimedia.org> | 2023-05-18 10:13:26 -0700 |
---|---|---|
committer | Volker E <volker.e@wikimedia.org> | 2023-05-18 12:03:32 -0700 |
commit | 5c683fbc1b0b6ede62a0edc72850d9fc5d1b25fd (patch) | |
tree | 604dcad86312c454db27b5b6e7fbddfc2f6ce8fc /resources/lib/ooui/oojs-ui-widgets.js | |
parent | d8d768b874eb297af87b885c8eea15df6e7e27eb (diff) | |
download | mediawikicore-5c683fbc1b0b6ede62a0edc72850d9fc5d1b25fd.tar.gz mediawikicore-5c683fbc1b0b6ede62a0edc72850d9fc5d1b25fd.zip |
Update OOUI to v0.47.0
Release notes:
https://gerrit.wikimedia.org/g/oojs/ui/+/v0.47.0/History.md
Bug: T53229
Bug: T285252
Bug: T285252
Bug: T309916
Bug: T313804
Bug: T314661
Bug: T324449
Bug: T326706
Bug: T328492
Bug: T328492
Bug: T328492
Bug: T328492
Bug: T328741
Bug: T329383
Bug: T330424
Bug: T331403
Bug: T333155
Bug: T334492
Bug: T335082
Bug: T335082
Bug: T335214
Depends-On: Ic1c9bf8948e63956119c3bd4befe7f6436f82095
Change-Id: I57a8ccc9b7e6b9a6b68a43085e3c7b5201c516a4
Diffstat (limited to 'resources/lib/ooui/oojs-ui-widgets.js')
-rw-r--r-- | resources/lib/ooui/oojs-ui-widgets.js | 178 |
1 files changed, 173 insertions, 5 deletions
diff --git a/resources/lib/ooui/oojs-ui-widgets.js b/resources/lib/ooui/oojs-ui-widgets.js index be98d8fe93f7..68e8f2370b0e 100644 --- a/resources/lib/ooui/oojs-ui-widgets.js +++ b/resources/lib/ooui/oojs-ui-widgets.js @@ -1,12 +1,12 @@ /*! - * OOUI v0.46.3 + * OOUI v0.47.0 * https://www.mediawiki.org/wiki/OOUI * * Copyright 2011–2023 OOUI Team and other contributors. * Released under the MIT license * http://oojs.mit-license.org * - * Date: 2023-02-07T00:43:59Z + * Date: 2023-05-18T02:15:42Z */ ( function ( OO ) { @@ -1344,6 +1344,8 @@ OO.ui.PageLayout.prototype.setActive = function ( active ) { * @cfg {boolean} [continuous=false] Show all panels, one after another. By default, only one panel * is displayed at a time. * @cfg {OO.ui.Layout[]} [items] Panel layouts to add to the stack layout. + * @cfg {boolean} [hideUntilFound] Hide panels using hidden="until-found", meaning they will be + * shown when matched with the browser's find-and-replace feature if supported. */ OO.ui.StackLayout = function OoUiStackLayout( config ) { // Configuration initialization @@ -1360,6 +1362,7 @@ OO.ui.StackLayout = function OoUiStackLayout( config ) { // Properties this.currentItem = null; this.continuous = !!config.continuous; + this.hideUntilFound = !!config.hideUntilFound; // Initialization this.$element.addClass( 'oo-ui-stackLayout' ); @@ -1413,6 +1416,17 @@ OO.ui.StackLayout.prototype.unsetCurrentItem = function () { }; /** + * Set the hideUntilFound config (see contructor) + * + * @param {boolean} hideUntilFound + */ +OO.ui.StackLayout.prototype.setHideUntilFound = function ( hideUntilFound ) { + this.hideUntilFound = hideUntilFound; + // Force an update of the attributes used to hide/show items + this.updateHiddenState( this.items, this.currentItem ); +}; + +/** * Add panel layouts to the stack layout. * * Panels will be added to the end of the stack layout array unless the optional index parameter @@ -1559,12 +1573,14 @@ OO.ui.StackLayout.prototype.updateHiddenState = function ( items, selectedItem ) if ( !this.continuous ) { for ( var i = 0, len = items.length; i < len; i++ ) { if ( !selectedItem || selectedItem !== items[ i ] ) { - items[ i ].toggle( false ); + // jQuery "fixes" the value of the hidden attribute to always be "hidden" + // Browsers which don't support 'until-found' will still hide the element + items[ i ].$element[ 0 ].setAttribute( 'hidden', this.hideUntilFound ? 'until-found' : 'hidden' ); items[ i ].$element.attr( 'aria-hidden', 'true' ); } } if ( selectedItem ) { - selectedItem.toggle( true ); + selectedItem.$element[ 0 ].removeAttribute( 'hidden' ); selectedItem.$element.removeAttr( 'aria-hidden' ); } } @@ -2466,6 +2482,8 @@ OO.ui.BookletLayout.prototype.selectFirstSelectablePage = function () { * @cfg {boolean} [autoFocus=true] Focus on the first focusable element when a new tab panel is * displayed. Disabled on mobile. * @cfg {boolean} [framed=true] Render the tabs with frames + * @cfg {boolean} [openMatchedPanels=true] Automatically switch to a panel when the browser's + * find-in-page feature matches content there, in browsers that support it. */ OO.ui.IndexLayout = function OoUiIndexLayout( config ) { // Configuration initialization @@ -2478,15 +2496,29 @@ OO.ui.IndexLayout = function OoUiIndexLayout( config ) { this.currentTabPanelName = null; // Allow infused widgets to pass existing tabPanels this.tabPanels = config.tabPanels || {}; + this.openMatchedPanels = config.openMatchedPanels === undefined || !!config.openMatchedPanels; this.ignoreFocus = false; + if ( this.contentPanel ) { + this.contentPanel.setHideUntilFound( this.openMatchedPanels ); + } this.stackLayout = this.contentPanel || new OO.ui.StackLayout( { continuous: !!config.continuous, - expanded: this.expanded + expanded: this.expanded, + hideUntilFound: this.openMatchedPanels } ); this.setContentPanel( this.stackLayout ); this.autoFocus = config.autoFocus === undefined || !!config.autoFocus; + if ( config.tabSelectWidget ) { + // If we are using a custom tabSelectWidget (e.g. infusing) then + // ensure the tabPanels are linked to tabItems + this.stackLayout.getItems().forEach( function ( tabPanel, i ) { + if ( !tabPanel.getTabItem() ) { + tabPanel.setTabItem( config.tabSelectWidget.items[ i ] || null ); + } + } ); + } // Allow infused widgets to pass an existing tabSelectWidget this.tabSelectWidget = config.tabSelectWidget || new OO.ui.TabSelectWidget( { framed: config.framed === undefined || config.framed @@ -2502,6 +2534,9 @@ OO.ui.IndexLayout = function OoUiIndexLayout( config ) { this.stackLayout.connect( this, { set: 'onStackLayoutSet' } ); + if ( this.openMatchedPanels ) { + this.stackLayout.$element.on( 'beforematch', this.onStackLayoutBeforeMatch.bind( this ) ); + } this.tabSelectWidget.connect( this, { select: 'onTabSelectWidgetSelect' } ); @@ -2589,6 +2624,29 @@ OO.ui.IndexLayout.prototype.onStackLayoutSet = function ( tabPanel ) { }; /** + * Handle beforematch events triggered by the browser's find-in-page feature + * + * @param {Event} event 'beforematch' event + */ +OO.ui.IndexLayout.prototype.onStackLayoutBeforeMatch = function ( event ) { + var tabPanel; + // Find TabPanel from DOM node + this.stackLayout.getItems().some( function ( item ) { + if ( item.$element[ 0 ] === event.target ) { + tabPanel = item; + return true; + } + return false; + } ); + if ( tabPanel ) { + var tabItem = tabPanel.getTabItem(); + if ( tabItem ) { + this.tabSelectWidget.selectItem( tabItem ); + } + } +}; + +/** * Focus the first input in the current tab panel. * * If no tab panel is selected, the first selectable tab panel will be selected. @@ -2900,6 +2958,111 @@ OO.ui.IndexLayout.prototype.selectFirstSelectableTabPanel = function () { }; /** + * CopyTextLayout is an action field layout containing some readonly text and a button to copy + * it to the clipboard. + * + * @class + * @extends OO.ui.ActionFieldLayout + * + * @constructor + * @param {Object} [config] Configuration options + * @cfg {string} copyText Text to copy, can also be provided as textInput.value + * @cfg {Object} textInput Config for text input + * @cfg {Object} button Config for button + */ +OO.ui.CopyTextLayout = function OoUiCopyTextLayout( config ) { + var TextClass; + config = config || {}; + + // Properties + TextClass = config.multiline ? OO.ui.MultilineTextInputWidget : OO.ui.TextInputWidget; + this.textInput = new TextClass( $.extend( { + value: config.copyText, + readOnly: true + }, config.textInput ) ); + this.button = new OO.ui.ButtonWidget( $.extend( { + label: OO.ui.msg( 'ooui-copytextlayout-copy' ), + icon: 'articles' + }, config.button ) ); + + // Parent constructor + OO.ui.CopyTextLayout.super.call( this, this.textInput, this.button, config ); + + // HACK: When using a multiline text input, remove classes which connect widgets + if ( config.multiline ) { + this.$input.removeClass( 'oo-ui-actionFieldLayout-input' ); + this.$button + .removeClass( 'oo-ui-actionFieldLayout-button' ) + .addClass( 'oo-ui-copyTextLayout-multiline-button' ); + } + + // Events + this.button.connect( this, { click: 'onButtonClick' } ); + this.textInput.$input.on( 'focus', this.onInputFocus.bind( this ) ); + + this.$element.addClass( 'oo-ui-copyTextLayout' ); +}; + +/* Inheritance */ + +OO.inheritClass( OO.ui.CopyTextLayout, OO.ui.ActionFieldLayout ); + +/* Events */ + +/** + * When the user has executed a copy command + * + * @event copy + * @param {boolean} Whether the copy command succeeded + */ + +/* Methods */ + +/** + * Handle button click events + * + * @fires copy + */ +OO.ui.CopyTextLayout.prototype.onButtonClick = function () { + var copied; + + this.selectText(); + + try { + copied = document.execCommand( 'copy' ); + } catch ( e ) { + copied = false; + } + this.emit( 'copy', copied ); +}; + +/** + * Handle text widget focus events + */ +OO.ui.CopyTextLayout.prototype.onInputFocus = function () { + if ( !this.selecting ) { + this.selectText(); + } +}; + +/** + * Select the text to copy + */ +OO.ui.CopyTextLayout.prototype.selectText = function () { + var input = this.textInput.$input[ 0 ], + scrollTop = input.scrollTop, + scrollLeft = input.scrollLeft; + + this.selecting = true; + this.textInput.select(); + this.selecting = false; + + // Restore scroll position + input.scrollTop = scrollTop; + input.scrollLeft = scrollLeft; +}; + +/** * ToggleWidget implements basic behavior of widgets with an on/off state. * Please see OO.ui.ToggleButtonWidget and OO.ui.ToggleSwitchWidget for examples. * @@ -5450,10 +5613,15 @@ OO.ui.MenuTagMultiselectWidget.prototype.onResize = function () { * @inheritdoc */ OO.ui.MenuTagMultiselectWidget.prototype.onInputFocus = function () { + var valid = this.isValid(); + // Parent method OO.ui.MenuTagMultiselectWidget.super.prototype.onInputFocus.call( this ); this.menu.toggle( true ); + if ( !valid ) { + this.menu.highlightItem(); + } }; /** |