mediawiki-extensions-Echo/modules/ui/mw.echo.ui.PaginationWidget.js

180 lines
5 KiB
JavaScript
Raw Normal View History

( function ( $, mw ) {
/**
* A pagination widget allowing the user to go forward, backwards,
* and after a couple of pages, go back to home.
*
* @class
* @extends OO.ui.Widget
*
* @constructor
* @param {mw.echo.dm.PaginationModel} paginationModel Pagination model
* @param {Object} [config] Configuration object
* @cfg {number} [itemsPerPage=25] Number of items per page
* @cfg {number} [showFirstButton=true] Show a button that allows the user
* to go back to the first page.
* @cfg {number} [showFirstButtonAfter=2] Pick the number of pages that it
* takes to show the button that takes the user back to the first set
* of results.
* @cfg {string} [startButtonLabel] The label used for the start button
*/
mw.echo.ui.PaginationWidget = function MwEchoUiPaginationWidget( paginationModel, config ) {
config = config || {};
// Parent
mw.echo.ui.PaginationWidget.parent.call( this, config );
this.model = paginationModel;
this.showFirstButton = config.showFirstButton === undefined ? true : !!config.showFirstButton;
this.showFirstButtonAfter = config.showFirstButtonAfter || 2;
this.itemsPerPage = config.itemsPerPage || 25;
// Pagination elements
this.labelWidget = new OO.ui.LabelWidget( {
classes: [ 'mw-echo-ui-paginationWidget-label' ]
} );
this.startButton = new OO.ui.ButtonWidget( {
classes: [ 'mw-echo-ui-paginationWidget-start' ],
label: config.startButtonLabel || mw.msg( 'notification-timestamp-today' ),
data: 'start'
} );
this.dirSelectWidget = new OO.ui.ButtonSelectWidget( {
classes: [ 'mw-echo-ui-paginationWidget-direction' ],
items: [
new OO.ui.ButtonOptionWidget( {
icon: 'previous',
data: 'prev'
} ),
new OO.ui.ButtonOptionWidget( {
icon: 'next',
data: 'next'
} )
]
} );
// Events
this.startButton.connect( this, { click: [ 'emit', 'change', 'start' ] } );
this.dirSelectWidget.connect( this, { choose: 'onDirSelectWidgetChoose' } );
this.model.connect( this, { update: 'updateWidgetState' } );
// Initialization
this.updateWidgetState();
this.$element
.addClass( 'mw-echo-ui-paginationWidget' )
.append(
$( '<div>' )
.addClass( 'mw-echo-ui-paginationWidget-row' )
.append(
this.labelWidget.$element,
this.startButton.$element,
this.dirSelectWidget.$element
)
);
};
/* Initialization */
OO.inheritClass( mw.echo.ui.PaginationWidget, OO.ui.Widget );
/* Events */
/**
* @event change
* @param {string} direction Direction of movement 'prev',
* 'next' or 'start'
*
* Pagination changed
*/
/* Methods */
/**
* Respond to dir select widget choose event
*
* @param {OO.ui.ButtonOptionWidget} item Chosen button
* @fires change
*/
mw.echo.ui.PaginationWidget.prototype.onDirSelectWidgetChoose = function ( item ) {
var dir = item && item.getData();
if ( dir ) {
this.emit( 'change', dir );
item.setSelected( false );
}
};
/**
* Update the state - disabled and visibility - of the sub widgets.
*/
mw.echo.ui.PaginationWidget.prototype.updateWidgetState = function () {
this.dirSelectWidget.getItemFromData( 'prev' )
.setDisabled( this.isDisabled() || !this.model.hasPrevPage() );
this.dirSelectWidget.getItemFromData( 'next' )
.setDisabled( this.isDisabled() || !this.model.hasNextPage() );
this.startButton.toggle(
!this.isDisabled() &&
this.model.getCurrPageIndex() >= this.showFirstButtonAfter
);
// Only show pagination buttons if there's anywhere to go
this.dirSelectWidget.toggle( this.model.hasPrevPage() || this.model.hasNextPage() );
// Update label text and visibility
this.updateLabel();
this.labelWidget.toggle( !this.isDisabled() );
};
// eslint-disable-next-line valid-jsdoc
/**
* Set the 'disabled' state of the widget.
*
* @param {boolean} disabled Disable widget
* @chainable
*/
mw.echo.ui.PaginationWidget.prototype.setDisabled = function ( disabled ) {
// Parent
mw.echo.ui.PaginationWidget.parent.prototype.setDisabled.call( this, disabled );
if (
this.dirSelectWidget &&
this.startButton &&
this.labelWidget
) {
this.updateWidgetState();
}
return this;
};
/**
* Update the pagination label according to the page number, the amount of notifications
* per page, and the number of notifications on the current page.
*/
mw.echo.ui.PaginationWidget.prototype.updateLabel = function () {
var label,
Relate read-state filter and mark read/unread action When we are viewing a certain read state filter ('read' or 'unread') the visibility of items should correspond to that state even when the user marks a specific item as read/unread. That means that the system should remove these items from view when the action is taken. In this commit: * The controller makes the judgment of whether to remove items when read/unread action is taken, based on whether a filter is set. * We clean up the terminology of discard - no more 'remove' - to make sure we have consistency in the code. * Related: The 'discard' event is now scoped within the hierarchy; meaning, lists emit 'discard' when an item is removed, grouplist emits 'discard' when a group is removed, and the manager emits 'discard' when an entire notification model is removed. This means we can actually have proper hierarchy and organization with a single event, and not worry about clashing between the intentional 'discard' action and the event 'remove' that is also used while resorting happens. * The model manager emits a discard event when a model is removed so that the general list can listen to the manager and remove an entire batch of items if needed. * The pagination model now updates the count for the current page rather than some vague notion of the last page. This is also updated when the controller removes items, so we can get an accurate count in the page for the number of notifications that are displayed. Bug: T136891 Change-Id: I247c618042ef256fadf09922f7b83bd1ad361f64
2016-07-14 00:03:57 +00:00
itemsInPage = this.model.getCurrentPageItemCount(),
firstNotifNum = this.model.getCurrPageIndex() * this.itemsPerPage,
lastNotifNum = firstNotifNum + itemsInPage;
if ( itemsInPage === 0 ) {
label = '';
} else if ( !this.model.hasPrevPage() && !this.model.hasNextPage() ) {
label = mw.msg(
'echo-specialpage-pagination-numnotifications',
mw.language.convertNumber( itemsInPage )
);
} else {
label = mw.msg(
'echo-specialpage-pagination-range',
mw.language.convertNumber( firstNotifNum + 1 ),
mw.language.convertNumber( lastNotifNum )
);
}
this.labelWidget.setLabel( label );
};
}( jQuery, mediaWiki ) );