jenkins-bot has submitted this change and it was merged. Change subject: Implemented "move" functionality in listview widget ......................................................................
Implemented "move" functionality in listview widget Change-Id: Ia5f0b684274d83fd285de7ee3fbbd736480a8af1 --- M lib/resources/jquery.wikibase/jquery.wikibase.listview.js M lib/tests/qunit/jquery.wikibase/jquery.wikibase.listview.tests.js 2 files changed, 225 insertions(+), 0 deletions(-) Approvals: Tobias Gritschacher: Looks good to me, approved jenkins-bot: Verified diff --git a/lib/resources/jquery.wikibase/jquery.wikibase.listview.js b/lib/resources/jquery.wikibase/jquery.wikibase.listview.js index c1bbbdd..743cf18 100644 --- a/lib/resources/jquery.wikibase/jquery.wikibase.listview.js +++ b/lib/resources/jquery.wikibase/jquery.wikibase.listview.js @@ -49,6 +49,11 @@ * (1) {jQuery.Event} * (2) {jQuery} The DOM node pending to be added permanently to the list. * + * @event afteritemmove: Triggered when an item node is moved within the list. + * (1) {jQuery.Event} + * (2) {number} The item node's new index. + * (3) {number} Number of items in the list. + * * @event destroy: Triggered when the widget has been destroyed. * (1) {jQuery.Event} */ @@ -190,6 +195,85 @@ }, /** + * Returns the index of a given item node within the list managed by the listview. Returns -1 if + * the node could not be found. + * @since 0.4 + * + * @param {jQuery} $itemNode + * @return {number} + */ + indexOf: function( $itemNode ) { + var $items = this.items(), + itemNode = $itemNode.get( 0 ); + + for( var i = 0; i < $items.length; i++ ) { + if( $items.get( i ) === itemNode ) { + return i; + } + } + + return -1; + }, + + /** + * Moves a list item to a new index. + * @since 0.4 + * + * @param {jQuery} $itemNode + * @param {number} toIndex + * + * @triggers afteritemmove + */ + move: function( $itemNode, toIndex ) { + var currIndex = this.indexOf( $itemNode ), + items = this.items(); + + // No need to move if the item has the index already or if it should be moved to after the + // last item although it is at the end already: + if( + currIndex < 0 + || currIndex === toIndex + || currIndex === items.length - 1 && toIndex >= items.length + ) { + return; + } + + if( toIndex >= items.length ) { + $itemNode.insertAfter( items.last() ); + } else if( items.eq( toIndex ).prev().get( 0 ) === $itemNode.get( 0 ) ) { + // Item already is at the position it shall be moved to. + return; + } else { + $itemNode.insertBefore( items.eq( toIndex ) ); + } + + this._trigger( 'afteritemmove', null, [ this.indexOf( $itemNode ), items.length ] ); + }, + + /** + * Moves an item node one index towards the top of the list. + * @since 0.4 + * + * @param {jQuery} $itemNode + */ + moveUp: function( $itemNode ) { + if( this.indexOf( $itemNode ) !== 0 ) { + this.move( $itemNode, this.indexOf( $itemNode ) - 1 ); + } + }, + + /** + * Moves an item node one index towards the bottom of the list. + * @since 0.4 + * + * @param {jQuery} $itemNode + */ + moveDown: function( $itemNode ) { + // Adding 2 to the index to move the element to before the element after the next element: + this.move( $itemNode, this.indexOf( $itemNode ) + 2 ); + }, + + /** * Returns the list item adapter object to deal with this list's list items. * @return {jQuery.wikibase.listview.ListItemAdapter} */ diff --git a/lib/tests/qunit/jquery.wikibase/jquery.wikibase.listview.tests.js b/lib/tests/qunit/jquery.wikibase/jquery.wikibase.listview.tests.js index 390d719..3f63916 100644 --- a/lib/tests/qunit/jquery.wikibase/jquery.wikibase.listview.tests.js +++ b/lib/tests/qunit/jquery.wikibase/jquery.wikibase.listview.tests.js @@ -31,6 +31,22 @@ return $node; } + /** + * Returns the joined string values of all the generic value widgets within a listview. + * + * @param {jquery.wikibase.listview} listview + * @return {string} + */ + function getListItemStrings( listview ) { + var value = ''; + + $.each( listview.value(), function( i, valueWidget ) { + value += valueWidget.value(); + } ); + + return value; + } + QUnit.module( 'jquery.wikibase.listview', window.QUnit.newWbEnvironment( { setup: function() { /** @@ -283,4 +299,129 @@ ); } ); + QUnit.test( 'indexOf()', function( assert ) { + var $node = createListview( ['a', 'b', 'c'] ), + listview = $node.data( 'listview' ); + + for( var i = 0; i < listview.items().length; i++ ) { + assert.strictEqual( + listview.indexOf( listview.items().eq( i ) ), + i, + 'Validated index of list item #' + i + '.' + ); + } + } ); + + QUnit.test( 'move()', 56, function( assert ) { + var values = ['a', 'b', 'c', 'd'], + $node, + listview; + + /** + * 0 => Index of item to move + * 1 => Index to move item to + * 2 => Expected resulting order + * @type {*[][]} + */ + var testCases = [ + [0, 0, 'abcd'], // no event + [0, 1, 'abcd'], // no event + [0, 2, 'bacd'], + [0, 3, 'bcad'], + [0, 4, 'bcda'], + [1, 0, 'bacd'], + [1, 1, 'abcd'], // no event + [1, 2, 'abcd'], // no event + [1, 3, 'acbd'], + [1, 4, 'acdb'], + [2, 0, 'cabd'], + [2, 1, 'acbd'], + [2, 2, 'abcd'], // no event + [2, 3, 'abcd'], // no event + [2, 4, 'abdc'], + [3, 0, 'dabc'], + [3, 1, 'adbc'], + [3, 2, 'abdc'], + [3, 3, 'abcd'], // no event + [3, 4, 'abcd'] // no event + ]; + + $.each( testCases, function( i, testCase ) { + $node = createListview( values ); + listview = $node.data( 'listview' ); + + $node.one( 'listviewafteritemmove', function( event, newIndex, listLength ) { + assert.ok( + true, + 'Triggered "afteritemmove" event.' + ); + + assert.equal( + newIndex, + testCase[2].indexOf( values[testCase[0]]), + 'Verified new item index.' + ); + + assert.equal( + listLength, + testCase[2].length, + 'Verified list length.' + ); + } ); + + listview.move( listview.items().eq( testCase[0] ), testCase[1] ); + + $node.off( 'listviewafteritemmove' ); + + assert.equal( + getListItemStrings( listview ), + testCase[2], + 'Moving item #' + testCase[0] + ' to index #' + testCase[1] + ' results in order "' + + testCase[2] + '".' + ); + } ); + } ); + + QUnit.test( 'moveUp() and moveDown()', function( assert ) { + var values = ['a', 'b', 'c', 'd']; + + /** + * The key specifies the objects method to call. The value represents the expected resulting + * order when issuing the method on the item that has the same index than the result. + * @type {Object} + */ + var testCases = { + 'moveUp': [ + 'abcd', + 'bacd', + 'acbd', + 'abdc' + ], + 'moveDown': [ + 'bacd', + 'acbd', + 'abdc', + 'abcd' + ] + }; + + var $node, listview; + + $.each( testCases, function( methodName, expectedResults ) { + $.each( expectedResults, function( i, expected ) { + $node = createListview( values ); + listview = $node.data( 'listview' ); + + listview[methodName]( listview.items().eq( i ) ); + + assert.equal( + getListItemStrings( listview ), + expected, + 'Issuing ' + methodName + '() on item #' + i + ' results in order "' + expected + + '".' + ); + } ); + } ); + } ); + } )( jQuery, mediaWiki, wikibase ); -- To view, visit https://gerrit.wikimedia.org/r/80200 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: merged Gerrit-Change-Id: Ia5f0b684274d83fd285de7ee3fbbd736480a8af1 Gerrit-PatchSet: 9 Gerrit-Project: mediawiki/extensions/Wikibase Gerrit-Branch: master Gerrit-Owner: Henning Snater <henning.sna...@wikimedia.de> Gerrit-Reviewer: Daniel Werner <daniel.wer...@wikimedia.de> Gerrit-Reviewer: Tobias Gritschacher <tobias.gritschac...@wikimedia.de> Gerrit-Reviewer: jenkins-bot _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits