Файловый менеджер - Редактировать - /var/www/html/mediawiki-1.43.1/resources/src/mediawiki.rcfilters/ui/MenuSelectWidget.js
Ðазад
const FilterMenuHeaderWidget = require( './FilterMenuHeaderWidget.js' ), HighlightPopupWidget = require( './HighlightPopupWidget.js' ), FilterMenuSectionOptionWidget = require( './FilterMenuSectionOptionWidget.js' ), FilterMenuOptionWidget = require( './FilterMenuOptionWidget.js' ); /** * A floating menu widget for the filter list. * * @class mw.rcfilters.ui.MenuSelectWidget * @ignore * @extends OO.ui.MenuSelectWidget * * @param {mw.rcfilters.Controller} controller Controller * @param {mw.rcfilters.dm.FiltersViewModel} model View model * @param {Object} [config] Configuration object * @param {boolean} [config.isMobile] a boolean flag determining whether the menu * should display a header or not (the header is omitted on mobile). * @param {jQuery} [config.$overlay] A jQuery object serving as overlay for popups * @param {Object[]} [config.footers] An array of objects defining the footers for * this menu, with a definition whether they appear per specific views. * The expected structure is: * [ * { * name: {string} A unique name for the footer object * $element: {jQuery} A jQuery object for the content of the footer * views: {string[]} Optional. An array stating which views this footer is * active on. Use null or omit to display this on all views. * } * ] */ const MenuSelectWidget = function MwRcfiltersUiMenuSelectWidget( controller, model, config ) { config = config || {}; this.controller = controller; this.model = model; this.currentView = ''; this.views = {}; this.userSelecting = false; this.menuInitialized = false; this.$overlay = config.$overlay || this.$element; this.$body = $( '<div>' ).addClass( 'mw-rcfilters-ui-menuSelectWidget-body' ); this.footers = []; // Parent MenuSelectWidget.super.call( this, Object.assign( config, { $autoCloseIgnore: this.$overlay, width: config.isMobile ? undefined : 650, // Our filtering is done through the model filterFromInput: false } ) ); this.setGroupElement( $( '<div>' ) .addClass( 'mw-rcfilters-ui-menuSelectWidget-group' ) ); let header; if ( !config.isMobile ) { // When hiding the header (i.e. mobile mode) avoid problems // with clippable and the menu's fixed width. this.setClippableElement( this.$body ); this.setClippableContainer( this.$element ); header = new FilterMenuHeaderWidget( this.controller, this.model, { $overlay: this.$overlay } ); } this.noResults = new OO.ui.LabelWidget( { label: mw.msg( 'rcfilters-filterlist-noresults' ), classes: [ 'mw-rcfilters-ui-menuSelectWidget-noresults' ] } ); // Events this.model.connect( this, { initialize: 'onModelInitialize', searchChange: 'onModelSearchChange' } ); // Initialization this.$element .addClass( 'mw-rcfilters-ui-menuSelectWidget' ) .attr( 'aria-label', mw.msg( 'rcfilters-filterlist-title' ) ) .append( config.isMobile ? undefined : header.$element ) .append( this.$body .append( this.$group, this.noResults.$element ) ); // Append all footers; we will control their visibility // based on view config.footers = config.isMobile ? [] : config.footers || []; config.footers.forEach( ( footerData ) => { const isSticky = footerData.sticky === undefined ? true : !!footerData.sticky, adjustedData = { // Wrap the element with our own footer wrapper // The following classes are used here: // * mw-rcfilters-ui-menuSelectWidget-footer-viewSelect // * and no others (currently) $element: $( '<div>' ) .addClass( 'mw-rcfilters-ui-menuSelectWidget-footer' ) .addClass( 'mw-rcfilters-ui-menuSelectWidget-footer-' + footerData.name ) .append( footerData.$element ), views: footerData.views }; if ( !footerData.disabled ) { this.footers.push( adjustedData ); if ( isSticky ) { this.$element.append( adjustedData.$element ); } else { this.$body.append( adjustedData.$element ); } } } ); // Switch to the correct view this.updateView(); }; /* Initialize */ OO.inheritClass( MenuSelectWidget, OO.ui.MenuSelectWidget ); /* Events */ /* Methods */ MenuSelectWidget.prototype.onModelSearchChange = function () { this.updateView(); }; /** * @inheritdoc */ MenuSelectWidget.prototype.toggle = function ( show ) { this.lazyMenuCreation(); MenuSelectWidget.super.prototype.toggle.call( this, show ); // Always open this menu downwards. FilterTagMultiselectWidget scrolls it into view. this.setVerticalPosition( 'below' ); }; /** * lazy creation of the menu */ MenuSelectWidget.prototype.lazyMenuCreation = function () { const widget = this, items = [], viewGroupCount = {}, groups = this.model.getFilterGroups(); if ( this.menuInitialized ) { return; } this.menuInitialized = true; // Create shared popup for highlight buttons this.highlightPopup = new HighlightPopupWidget( this.controller ); this.$overlay.append( this.highlightPopup.$element ); // Count groups per view // eslint-disable-next-line no-jquery/no-each-util $.each( groups, ( groupName, groupModel ) => { if ( !groupModel.isHidden() ) { viewGroupCount[ groupModel.getView() ] = viewGroupCount[ groupModel.getView() ] || 0; viewGroupCount[ groupModel.getView() ]++; } } ); // eslint-disable-next-line no-jquery/no-each-util $.each( groups, ( groupName, groupModel ) => { const currentItems = [], view = groupModel.getView(); if ( !groupModel.isHidden() ) { if ( viewGroupCount[ view ] > 1 ) { // Only add a section header if there is more than // one group currentItems.push( // Group section new FilterMenuSectionOptionWidget( widget.controller, groupModel, { $overlay: widget.$overlay } ) ); } // Add items widget.model.getGroupFilters( groupName ).forEach( ( filterItem ) => { currentItems.push( new FilterMenuOptionWidget( widget.controller, widget.model, widget.model.getInvertModel( view ), filterItem, widget.highlightPopup, { $overlay: widget.$overlay } ) ); } ); // Cache the items per view, so we can switch between them // without rebuilding the widgets each time widget.views[ view ] = widget.views[ view ] || []; widget.views[ view ] = widget.views[ view ].concat( currentItems ); items.push( ...currentItems ); } } ); this.addItems( items ); this.updateView(); }; /** * Respond to model initialize event. Populate the menu from the model */ MenuSelectWidget.prototype.onModelInitialize = function () { this.menuInitialized = false; // Set timeout for the menu to lazy build. setTimeout( this.lazyMenuCreation.bind( this ) ); }; /** * Update view */ MenuSelectWidget.prototype.updateView = function () { const viewName = this.model.getCurrentView(); if ( this.views[ viewName ] && this.currentView !== viewName ) { this.updateFooterVisibility( viewName ); // The following classes are used here: // * mw-rcfilters-ui-menuSelectWidget-view-default // * mw-rcfilters-ui-menuSelectWidget-view-namespaces // * mw-rcfilters-ui-menuSelectWidget-view-tags this.$element .data( 'view', viewName ) .removeClass( 'mw-rcfilters-ui-menuSelectWidget-view-' + this.currentView ) .addClass( 'mw-rcfilters-ui-menuSelectWidget-view-' + viewName ); this.currentView = viewName; this.scrollToTop(); } this.postProcessItems(); this.clip(); }; /** * Go over the available footers and decide which should be visible * for this view * * @param {string} [currentView] Current view */ MenuSelectWidget.prototype.updateFooterVisibility = function ( currentView ) { currentView = currentView || this.model.getCurrentView(); this.footers.forEach( ( data ) => { data.$element.toggle( // This footer should only be shown if it is configured // for all views or for this specific view !data.views || data.views.length === 0 || data.views.indexOf( currentView ) > -1 ); } ); }; /** * Post-process items after the visibility changed. Make sure * that we always have an item selected, and that the no-results * widget appears if the menu is empty. */ MenuSelectWidget.prototype.postProcessItems = function () { let itemWasSelected = false; const items = this.getItems(); // If we are not already selecting an item, always make sure // that the top item is selected if ( !this.userSelecting ) { // Select the first item in the list for ( let i = 0; i < items.length; i++ ) { if ( !( items[ i ] instanceof OO.ui.MenuSectionOptionWidget ) && items[ i ].isVisible() ) { itemWasSelected = true; this.selectItem( items[ i ] ); break; } } if ( !itemWasSelected ) { this.selectItem( null ); } } this.noResults.toggle( !this.getItems().some( ( item ) => item.isVisible() ) ); }; /** * Get the option widget that matches the model given * * @ignore * @param {mw.rcfilters.dm.ItemModel} model Item model * @return {mw.rcfilters.ui.ItemMenuOptionWidget} Option widget */ MenuSelectWidget.prototype.getItemFromModel = function ( model ) { this.lazyMenuCreation(); return this.views[ model.getGroupModel().getView() ].filter( ( item ) => item.getName() === model.getName() )[ 0 ]; }; /** * @inheritdoc */ MenuSelectWidget.prototype.onDocumentKeyDown = function ( e ) { const currentItem = this.findHighlightedItem() || this.findSelectedItem(); let nextItem; // Call parent MenuSelectWidget.super.prototype.onDocumentKeyDown.call( this, e ); // We want to select the item on arrow movement // rather than just highlight it, like the menu // does by default if ( !this.isDisabled() && this.isVisible() ) { switch ( e.keyCode ) { case OO.ui.Keys.UP: case OO.ui.Keys.LEFT: // Get the next item nextItem = this.findRelativeSelectableItem( currentItem, -1 ); break; case OO.ui.Keys.DOWN: case OO.ui.Keys.RIGHT: // Get the next item nextItem = this.findRelativeSelectableItem( currentItem, 1 ); break; } nextItem = nextItem && nextItem.constructor.static.selectable ? nextItem : null; // Select the next item this.selectItem( nextItem ); } }; /** * Scroll to the top of the menu */ MenuSelectWidget.prototype.scrollToTop = function () { this.$body.scrollTop( 0 ); }; /** * Set whether the user is currently selecting an item. * This is important when the user selects an item that is in between * different views, and makes sure we do not re-select a different * item (like the item on top) when this is happening. * * @param {boolean} isSelecting User is selecting */ MenuSelectWidget.prototype.setUserSelecting = function ( isSelecting ) { this.userSelecting = !!isSelecting; }; module.exports = MenuSelectWidget;
| ver. 1.1 | |
.
| PHP 8.4.18 | Ð“ÐµÐ½ÐµÑ€Ð°Ñ†Ð¸Ñ Ñтраницы: 0 |
proxy
|
phpinfo
|
ÐаÑтройка