Mooeypoo has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/339800 )
Change subject: [wip] RCFilters UI: Scroll to filter when selected ...................................................................... [wip] RCFilters UI: Scroll to filter when selected Change-Id: I416c324eec4bc35ae9b1e0aeabd2897da0158d95 --- M resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterItemWidget.less M resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.CapsuleItemWidget.js M resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterCapsuleMultiselectWidget.js M resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterGroupWidget.js M resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterItemWidget.js M resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterWrapperWidget.js M resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FiltersListWidget.js 7 files changed, 150 insertions(+), 2 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/core refs/changes/00/339800/1 diff --git a/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterItemWidget.less b/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterItemWidget.less index 94da3ac..21953da 100644 --- a/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterItemWidget.less +++ b/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterItemWidget.less @@ -16,6 +16,10 @@ } } + &-selected { + background-color: #eaf3ff; // Accent90 AAA + } + &-label { &-title { font-weight: bold; diff --git a/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.CapsuleItemWidget.js b/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.CapsuleItemWidget.js index cf03932..fc05649 100644 --- a/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.CapsuleItemWidget.js +++ b/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.CapsuleItemWidget.js @@ -91,6 +91,14 @@ }; /** + * Emit a click event when the capsule is clicked so we can aggregate this + * in the parent (the capsule) + */ + mw.rcfilters.ui.CapsuleItemWidget.prototype.onClick = function () { + this.emit( 'click' ); + }; + + /** * Override the event listening to the item close button click */ mw.rcfilters.ui.CapsuleItemWidget.prototype.onCloseClick = function () { diff --git a/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterCapsuleMultiselectWidget.js b/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterCapsuleMultiselectWidget.js index 2bd2f0e..cd3191c 100644 --- a/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterCapsuleMultiselectWidget.js +++ b/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterCapsuleMultiselectWidget.js @@ -32,6 +32,7 @@ this.controller = controller; this.model = model; this.filterInput = filterInput; + this.isSelecting = false; this.topScrollOffset = config.topScrollOffset || 10; @@ -55,6 +56,7 @@ highlightChange: 'onModelHighlightChange' } ); this.popup.connect( this, { toggle: 'onPopupToggle' } ); + this.aggregate( { click: 'capsuleItemClick' } ); // Add the filterInput as trigger this.filterInput.$input diff --git a/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterGroupWidget.js b/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterGroupWidget.js index f858ab0..a750c44 100644 --- a/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterGroupWidget.js +++ b/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterGroupWidget.js @@ -19,6 +19,7 @@ this.controller = controller; this.model = model; + this.filters = {}; // Mixin constructors OO.ui.mixin.GroupWidget.call( this, config ); @@ -36,6 +37,7 @@ this.$element .addClass( 'mw-rcfilters-ui-filterGroupWidget' ) + .addClass( 'mw-rcfilters-ui-filterGroupWidget-name-' + this.model.getName() ) .append( this.$label, this.$group @@ -59,12 +61,28 @@ ); }; + /** + * Get an item widget from its filter name + * + * @param {string} filterName Filter name + * @return {mw.rcfilters.ui.FilterItemWidget} Item widget + */ + mw.rcfilters.ui.FilterGroupWidget.prototype.getItemWidget = function ( filterName ) { + return this.filters[ filterName ]; + }; + + /** + * Populate data from the model + */ mw.rcfilters.ui.FilterGroupWidget.prototype.populateFromModel = function () { var widget = this; + this.clearItems(); + this.filters = {}; + this.addItems( this.model.getItems().map( function ( filterItem ) { - return new mw.rcfilters.ui.FilterItemWidget( + var groupWidget = new mw.rcfilters.ui.FilterItemWidget( widget.controller, filterItem, { @@ -73,6 +91,10 @@ $overlay: widget.$overlay } ); + + widget.filters[ filterItem.getName() ] = groupWidget; + + return groupWidget; } ) ); }; diff --git a/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterItemWidget.js b/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterItemWidget.js index 63db2b0..eda4fe7 100644 --- a/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterItemWidget.js +++ b/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterItemWidget.js @@ -21,6 +21,7 @@ this.controller = controller; this.model = model; + this.selected = false; this.checkboxWidget = new mw.rcfilters.ui.CheckboxInputWidget( { value: this.model.getName(), @@ -113,6 +114,21 @@ }; /** + * Set selected state on this widget + * + * @param {boolean} [isSelected] Widget is selected + */ + mw.rcfilters.ui.FilterItemWidget.prototype.toggleSelected = function ( isSelected ) { + isSelected = isSelected !== undefined ? isSelected : !this.selected; + + if ( this.selected !== isSelected ) { + this.selected = isSelected; + + this.$element.toggleClass( 'mw-rcfilters-ui-filterItemWidget-selected', this.selected ); + } + }; + + /** * Set the current mute state for this item */ mw.rcfilters.ui.FilterItemWidget.prototype.setCurrentMuteState = function () { diff --git a/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterWrapperWidget.js b/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterWrapperWidget.js index d46bd4b..a6f1781 100644 --- a/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterWrapperWidget.js +++ b/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterWrapperWidget.js @@ -55,6 +55,10 @@ this.textInput.connect( this, { change: 'onTextInputChange' } ); + this.capsule.connect( this, { capsuleItemClick: 'onCapsuleItemClick' } ); + this.capsule.popup.connect( this, { toggle: 'onCapsulePopupToggle' } ); + + // Initialize this.$element .addClass( 'mw-rcfilters-ui-filterWrapperWidget' ) .append( this.capsule.$element, this.textInput.$element ); @@ -66,11 +70,44 @@ OO.mixinClass( mw.rcfilters.ui.FilterWrapperWidget, OO.ui.mixin.PendingElement ); /** + * Respond to capsule item click and make the popup scroll down to the requested item + * + * @param {mw.rcfilters.ui.CapsuleItemWidget} item Clicked item + */ + mw.rcfilters.ui.FilterWrapperWidget.prototype.onCapsuleItemClick = function ( item ) { + var filterName = item.getData(), + // Find the item in the popup + filterWidget = this.filterPopup.getItemWidget( filterName ), + container = OO.ui.Element.static.getClosestScrollableContainer( this.filterPopup.$element[ 0 ], 'y' ); + + // Highlight item + this.filterPopup.select( filterName ); + + // Scroll to item + $( container ).animate( { + scrollTop: filterWidget.$element.offset().top + } ); + }; + + /** + * Respond to popup toggle event. Reset selection in the list when the popup is closed. + * + * @param {boolean} isVisible Popup is visible + */ + mw.rcfilters.ui.FilterWrapperWidget.prototype.onCapsulePopupToggle = function ( isVisible ) { + if ( !isVisible ) { + this.filterPopup.resetSelection(); + } + }; + + /** * Respond to text input change * * @param {string} newValue Current value */ mw.rcfilters.ui.FilterWrapperWidget.prototype.onTextInputChange = function ( newValue ) { + this.filterPopup.resetSelection(); + // Filter the results this.filterPopup.filter( this.model.findMatches( newValue ) ); }; diff --git a/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FiltersListWidget.js b/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FiltersListWidget.js index ae9ee71..38679d7 100644 --- a/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FiltersListWidget.js +++ b/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FiltersListWidget.js @@ -26,6 +26,8 @@ this.controller = controller; this.model = model; this.$overlay = config.$overlay || this.$element; + this.groups = {}; + this.selected = null; this.highlightButton = new OO.ui.ButtonWidget( { label: mw.message( 'rcfilters-highlightbutton-title' ).text(), @@ -74,16 +76,20 @@ // Reset this.clearItems(); + this.groups = {}; this.addItems( Object.keys( this.model.getFilterGroups() ).map( function ( groupName ) { - return new mw.rcfilters.ui.FilterGroupWidget( + var groupWidget = new mw.rcfilters.ui.FilterGroupWidget( widget.controller, widget.model.getGroup( groupName ), { $overlay: widget.$overlay } ); + + widget.groups[ groupName ] = groupWidget; + return groupWidget; } ) ); }; @@ -100,6 +106,59 @@ }; /** + * Find the filter item widget that corresponds to the item name + * + * @param {string} itemName Filter name + * @return {mw.rcfilters.ui.FilterItemWidget} Filter widget + */ + mw.rcfilters.ui.FiltersListWidget.prototype.getItemWidget = function ( itemName ) { + var filterItem = this.model.getItemByName( itemName ), + // Find the group + groupWidget = this.groups[ filterItem.getGroupName() ]; + + // Find the item inside the group + return groupWidget.getItemWidget( itemName ); + }; + + /** + * Mark an item widget as selected + * + * @param {string} itemName Filter name + */ + mw.rcfilters.ui.FiltersListWidget.prototype.select = function ( itemName ) { + var filterWidget; + + if ( this.selected !== itemName ) { + // Unselect previous + if ( this.selected ) { + filterWidget = this.getItemWidget( this.selected ); + filterWidget.toggleSelected( false ); + } + + // Select new one + this.selected = itemName; + if ( this.selected ) { + filterWidget = this.getItemWidget( this.selected ); + filterWidget.toggleSelected( true ); + } + } + }; + + /** + * Reset selection and remove selected states from all items + */ + mw.rcfilters.ui.FiltersListWidget.prototype.resetSelection = function () { + if ( this.selected !== null ) { + this.selected = null; + this.getItems().forEach( function ( groupWidget ) { + groupWidget.getItems().forEach( function ( filterItemWidget ) { + filterItemWidget.toggleSelected( false ); + } ); + } ); + } + }; + + /** * Switch between showing the 'no results' message for filtering results or the result list. * * @param {boolean} showNoResults Show no results message -- To view, visit https://gerrit.wikimedia.org/r/339800 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I416c324eec4bc35ae9b1e0aeabd2897da0158d95 Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/core Gerrit-Branch: master Gerrit-Owner: Mooeypoo <mor...@gmail.com> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits