diff options
Diffstat (limited to 'vendor/oojs/oojs-ui/src/layouts/IndexLayout.js')
-rw-r--r-- | vendor/oojs/oojs-ui/src/layouts/IndexLayout.js | 452 |
1 files changed, 0 insertions, 452 deletions
diff --git a/vendor/oojs/oojs-ui/src/layouts/IndexLayout.js b/vendor/oojs/oojs-ui/src/layouts/IndexLayout.js deleted file mode 100644 index 4cda00a9..00000000 --- a/vendor/oojs/oojs-ui/src/layouts/IndexLayout.js +++ /dev/null @@ -1,452 +0,0 @@ -/** - * IndexLayouts contain {@link OO.ui.CardLayout card layouts} as well as - * {@link OO.ui.TabSelectWidget tabs} that allow users to easily navigate through the cards and - * select which one to display. By default, only one card is displayed at a time. When a user - * navigates to a new card, the index layout automatically focuses on the first focusable element, - * unless the default setting is changed. - * - * TODO: This class is similar to BookletLayout, we may want to refactor to reduce duplication - * - * @example - * // Example of a IndexLayout that contains two CardLayouts. - * - * function CardOneLayout( name, config ) { - * CardOneLayout.super.call( this, name, config ); - * this.$element.append( '<p>First card</p>' ); - * } - * OO.inheritClass( CardOneLayout, OO.ui.CardLayout ); - * CardOneLayout.prototype.setupTabItem = function () { - * this.tabItem.setLabel( 'Card One' ); - * }; - * - * function CardTwoLayout( name, config ) { - * CardTwoLayout.super.call( this, name, config ); - * this.$element.append( '<p>Second card</p>' ); - * } - * OO.inheritClass( CardTwoLayout, OO.ui.CardLayout ); - * CardTwoLayout.prototype.setupTabItem = function () { - * this.tabItem.setLabel( 'Card Two' ); - * }; - * - * var card1 = new CardOneLayout( 'one' ), - * card2 = new CardTwoLayout( 'two' ); - * - * var index = new OO.ui.IndexLayout(); - * - * index.addCards ( [ card1, card2 ] ); - * $( 'body' ).append( index.$element ); - * - * @class - * @extends OO.ui.MenuLayout - * - * @constructor - * @param {Object} [config] Configuration options - * @cfg {boolean} [continuous=false] Show all cards, one after another - * @cfg {boolean} [autoFocus=true] Focus on the first focusable element when a new card is displayed. - */ -OO.ui.IndexLayout = function OoUiIndexLayout( config ) { - // Configuration initialization - config = $.extend( {}, config, { menuPosition: 'top' } ); - - // Parent constructor - OO.ui.IndexLayout.super.call( this, config ); - - // Properties - this.currentCardName = null; - this.cards = {}; - this.ignoreFocus = false; - this.stackLayout = new OO.ui.StackLayout( { continuous: !!config.continuous } ); - this.$content.append( this.stackLayout.$element ); - this.autoFocus = config.autoFocus === undefined || !!config.autoFocus; - - this.tabSelectWidget = new OO.ui.TabSelectWidget(); - this.tabPanel = new OO.ui.PanelLayout(); - this.$menu.append( this.tabPanel.$element ); - - this.toggleMenu( true ); - - // Events - this.stackLayout.connect( this, { set: 'onStackLayoutSet' } ); - this.tabSelectWidget.connect( this, { select: 'onTabSelectWidgetSelect' } ); - if ( this.autoFocus ) { - // Event 'focus' does not bubble, but 'focusin' does - this.stackLayout.$element.on( 'focusin', this.onStackLayoutFocus.bind( this ) ); - } - - // Initialization - this.$element.addClass( 'oo-ui-indexLayout' ); - this.stackLayout.$element.addClass( 'oo-ui-indexLayout-stackLayout' ); - this.tabPanel.$element - .addClass( 'oo-ui-indexLayout-tabPanel' ) - .append( this.tabSelectWidget.$element ); -}; - -/* Setup */ - -OO.inheritClass( OO.ui.IndexLayout, OO.ui.MenuLayout ); - -/* Events */ - -/** - * A 'set' event is emitted when a card is {@link #setCard set} to be displayed by the index layout. - * @event set - * @param {OO.ui.CardLayout} card Current card - */ - -/** - * An 'add' event is emitted when cards are {@link #addCards added} to the index layout. - * - * @event add - * @param {OO.ui.CardLayout[]} card Added cards - * @param {number} index Index cards were added at - */ - -/** - * A 'remove' event is emitted when cards are {@link #clearCards cleared} or - * {@link #removeCards removed} from the index. - * - * @event remove - * @param {OO.ui.CardLayout[]} cards Removed cards - */ - -/* Methods */ - -/** - * Handle stack layout focus. - * - * @private - * @param {jQuery.Event} e Focusin event - */ -OO.ui.IndexLayout.prototype.onStackLayoutFocus = function ( e ) { - var name, $target; - - // Find the card that an element was focused within - $target = $( e.target ).closest( '.oo-ui-cardLayout' ); - for ( name in this.cards ) { - // Check for card match, exclude current card to find only card changes - if ( this.cards[ name ].$element[ 0 ] === $target[ 0 ] && name !== this.currentCardName ) { - this.setCard( name ); - break; - } - } -}; - -/** - * Handle stack layout set events. - * - * @private - * @param {OO.ui.PanelLayout|null} card The card panel that is now the current panel - */ -OO.ui.IndexLayout.prototype.onStackLayoutSet = function ( card ) { - var layout = this; - if ( card ) { - card.scrollElementIntoView( { complete: function () { - if ( layout.autoFocus ) { - layout.focus(); - } - } } ); - } -}; - -/** - * Focus the first input in the current card. - * - * If no card is selected, the first selectable card will be selected. - * If the focus is already in an element on the current card, nothing will happen. - * @param {number} [itemIndex] A specific item to focus on - */ -OO.ui.IndexLayout.prototype.focus = function ( itemIndex ) { - var $input, card, - items = this.stackLayout.getItems(); - - if ( itemIndex !== undefined && items[ itemIndex ] ) { - card = items[ itemIndex ]; - } else { - card = this.stackLayout.getCurrentItem(); - } - - if ( !card ) { - this.selectFirstSelectableCard(); - card = this.stackLayout.getCurrentItem(); - } - if ( !card ) { - return; - } - // Only change the focus if is not already in the current card - if ( !card.$element.find( ':focus' ).length ) { - $input = card.$element.find( ':input:first' ); - if ( $input.length ) { - $input[ 0 ].focus(); - } - } -}; - -/** - * Find the first focusable input in the index layout and focus - * on it. - */ -OO.ui.IndexLayout.prototype.focusFirstFocusable = function () { - var i, len, - found = false, - items = this.stackLayout.getItems(), - checkAndFocus = function () { - if ( OO.ui.isFocusableElement( $( this ) ) ) { - $( this ).focus(); - found = true; - return false; - } - }; - - for ( i = 0, len = items.length; i < len; i++ ) { - if ( found ) { - break; - } - // Find all potentially focusable elements in the item - // and check if they are focusable - items[i].$element - .find( 'input, select, textarea, button, object' ) - .each( checkAndFocus ); - } -}; - -/** - * Handle tab widget select events. - * - * @private - * @param {OO.ui.OptionWidget|null} item Selected item - */ -OO.ui.IndexLayout.prototype.onTabSelectWidgetSelect = function ( item ) { - if ( item ) { - this.setCard( item.getData() ); - } -}; - -/** - * Get the card closest to the specified card. - * - * @param {OO.ui.CardLayout} card Card to use as a reference point - * @return {OO.ui.CardLayout|null} Card closest to the specified card - */ -OO.ui.IndexLayout.prototype.getClosestCard = function ( card ) { - var next, prev, level, - cards = this.stackLayout.getItems(), - index = $.inArray( card, cards ); - - if ( index !== -1 ) { - next = cards[ index + 1 ]; - prev = cards[ index - 1 ]; - // Prefer adjacent cards at the same level - level = this.tabSelectWidget.getItemFromData( card.getName() ).getLevel(); - if ( - prev && - level === this.tabSelectWidget.getItemFromData( prev.getName() ).getLevel() - ) { - return prev; - } - if ( - next && - level === this.tabSelectWidget.getItemFromData( next.getName() ).getLevel() - ) { - return next; - } - } - return prev || next || null; -}; - -/** - * Get the tabs widget. - * - * @return {OO.ui.TabSelectWidget} Tabs widget - */ -OO.ui.IndexLayout.prototype.getTabs = function () { - return this.tabSelectWidget; -}; - -/** - * Get a card by its symbolic name. - * - * @param {string} name Symbolic name of card - * @return {OO.ui.CardLayout|undefined} Card, if found - */ -OO.ui.IndexLayout.prototype.getCard = function ( name ) { - return this.cards[ name ]; -}; - -/** - * Get the current card. - * - * @return {OO.ui.CardLayout|undefined} Current card, if found - */ -OO.ui.IndexLayout.prototype.getCurrentCard = function () { - var name = this.getCurrentCardName(); - return name ? this.getCard( name ) : undefined; -}; - -/** - * Get the symbolic name of the current card. - * - * @return {string|null} Symbolic name of the current card - */ -OO.ui.IndexLayout.prototype.getCurrentCardName = function () { - return this.currentCardName; -}; - -/** - * Add cards to the index layout - * - * When cards are added with the same names as existing cards, the existing cards will be - * automatically removed before the new cards are added. - * - * @param {OO.ui.CardLayout[]} cards Cards to add - * @param {number} index Index of the insertion point - * @fires add - * @chainable - */ -OO.ui.IndexLayout.prototype.addCards = function ( cards, index ) { - var i, len, name, card, item, currentIndex, - stackLayoutCards = this.stackLayout.getItems(), - remove = [], - items = []; - - // Remove cards with same names - for ( i = 0, len = cards.length; i < len; i++ ) { - card = cards[ i ]; - name = card.getName(); - - if ( Object.prototype.hasOwnProperty.call( this.cards, name ) ) { - // Correct the insertion index - currentIndex = $.inArray( this.cards[ name ], stackLayoutCards ); - if ( currentIndex !== -1 && currentIndex + 1 < index ) { - index--; - } - remove.push( this.cards[ name ] ); - } - } - if ( remove.length ) { - this.removeCards( remove ); - } - - // Add new cards - for ( i = 0, len = cards.length; i < len; i++ ) { - card = cards[ i ]; - name = card.getName(); - this.cards[ card.getName() ] = card; - item = new OO.ui.TabOptionWidget( { data: name } ); - card.setTabItem( item ); - items.push( item ); - } - - if ( items.length ) { - this.tabSelectWidget.addItems( items, index ); - this.selectFirstSelectableCard(); - } - this.stackLayout.addItems( cards, index ); - this.emit( 'add', cards, index ); - - return this; -}; - -/** - * Remove the specified cards from the index layout. - * - * To remove all cards from the index, you may wish to use the #clearCards method instead. - * - * @param {OO.ui.CardLayout[]} cards An array of cards to remove - * @fires remove - * @chainable - */ -OO.ui.IndexLayout.prototype.removeCards = function ( cards ) { - var i, len, name, card, - items = []; - - for ( i = 0, len = cards.length; i < len; i++ ) { - card = cards[ i ]; - name = card.getName(); - delete this.cards[ name ]; - items.push( this.tabSelectWidget.getItemFromData( name ) ); - card.setTabItem( null ); - } - if ( items.length ) { - this.tabSelectWidget.removeItems( items ); - this.selectFirstSelectableCard(); - } - this.stackLayout.removeItems( cards ); - this.emit( 'remove', cards ); - - return this; -}; - -/** - * Clear all cards from the index layout. - * - * To remove only a subset of cards from the index, use the #removeCards method. - * - * @fires remove - * @chainable - */ -OO.ui.IndexLayout.prototype.clearCards = function () { - var i, len, - cards = this.stackLayout.getItems(); - - this.cards = {}; - this.currentCardName = null; - this.tabSelectWidget.clearItems(); - for ( i = 0, len = cards.length; i < len; i++ ) { - cards[ i ].setTabItem( null ); - } - this.stackLayout.clearItems(); - - this.emit( 'remove', cards ); - - return this; -}; - -/** - * Set the current card by symbolic name. - * - * @fires set - * @param {string} name Symbolic name of card - */ -OO.ui.IndexLayout.prototype.setCard = function ( name ) { - var selectedItem, - $focused, - card = this.cards[ name ]; - - if ( name !== this.currentCardName ) { - selectedItem = this.tabSelectWidget.getSelectedItem(); - if ( selectedItem && selectedItem.getData() !== name ) { - this.tabSelectWidget.selectItemByData( name ); - } - if ( card ) { - if ( this.currentCardName && this.cards[ this.currentCardName ] ) { - this.cards[ this.currentCardName ].setActive( false ); - // Blur anything focused if the next card doesn't have anything focusable - this - // is not needed if the next card has something focusable because once it is focused - // this blur happens automatically - if ( this.autoFocus && !card.$element.find( ':input' ).length ) { - $focused = this.cards[ this.currentCardName ].$element.find( ':focus' ); - if ( $focused.length ) { - $focused[ 0 ].blur(); - } - } - } - this.currentCardName = name; - this.stackLayout.setItem( card ); - card.setActive( true ); - this.emit( 'set', card ); - } - } -}; - -/** - * Select the first selectable card. - * - * @chainable - */ -OO.ui.IndexLayout.prototype.selectFirstSelectableCard = function () { - if ( !this.tabSelectWidget.getSelectedItem() ) { - this.tabSelectWidget.selectItem( this.tabSelectWidget.getFirstSelectableItem() ); - } - - return this; -}; |