jenkins-bot has submitted this change and it was merged. Change subject: DesktopArticleTarget: Rebuild the category links when they're edited ......................................................................
DesktopArticleTarget: Rebuild the category links when they're edited This has to go to the API, because it's skinnable. Also, separates out a few of the initial page setup functions so they can be re-applied to the new content inserted. Bug: T151651 Change-Id: I8d5a6504edc2e0486a0b4f016d8ee6d9a6228de9 --- M modules/ve-mw/init/targets/ve.init.mw.DesktopArticleTarget.js 1 file changed, 124 insertions(+), 49 deletions(-) Approvals: Esanders: Looks good to me, approved jenkins-bot: Verified diff --git a/modules/ve-mw/init/targets/ve.init.mw.DesktopArticleTarget.js b/modules/ve-mw/init/targets/ve.init.mw.DesktopArticleTarget.js index 7860bba..783ba95 100644 --- a/modules/ve-mw/init/targets/ve.init.mw.DesktopArticleTarget.js +++ b/modules/ve-mw/init/targets/ve.init.mw.DesktopArticleTarget.js @@ -597,6 +597,7 @@ // Move original content back out of the target target.$element.parent().append( target.$originalContent.children() ); + $( '#catlinks' ).replaceWith( target.$originalCategories ); $( '.ve-init-mw-desktopArticleTarget-uneditableContent' ) .off( '.ve-target' ) .removeClass( 've-init-mw-desktopArticleTarget-uneditableContent' ); @@ -742,45 +743,51 @@ * @param {boolean} [loading=false] Whether VE is loading. */ ve.init.mw.DesktopArticleTarget.prototype.onMetaItemInserted = function ( metaItem, loading ) { - var title, target, $link; - if ( metaItem.getType() === 'mwRedirect' ) { - target = this; - title = metaItem.getAttribute( 'title' ); - $link = $( '<a>' ) - .attr( 'title', mw.msg( 'visualeditor-redirect-description', title ) ) - .text( title ); - ve.init.platform.linkCache.styleElement( title, $link ); + var title, target, $link, + metaList = this.surface.getModel().getMetaList(); + switch ( metaItem.getType() ) { + case 'mwRedirect': + target = this; + title = metaItem.getAttribute( 'title' ); + $link = $( '<a>' ) + .attr( 'title', mw.msg( 'visualeditor-redirect-description', title ) ) + .text( title ); + ve.init.platform.linkCache.styleElement( title, $link ); - if ( loading ) { - this.$originalRedirectMsg = $( '.redirectMsg' ).clone(); - this.$originalRedirectSub = $( '#redirectsub, #redirectsub + br' ).clone(); - } - // Add redirect target header - if ( !$( '#redirectsub' ).length ) { - $( '#contentSub' ).append( - $( '<span>' ) - .text( mw.msg( 'redirectpagesub' ) ) - .attr( 'id', 'redirectsub' ), - $( '<br>' ) - ); - } - $( '<div>' ) - // Bit of a hack: Make sure any redirect note is styled - .addClass( 'redirectMsg mw-content-' + $( 'html' ).attr( 'dir' ) ) + if ( loading ) { + this.$originalRedirectMsg = $( '.redirectMsg' ).clone(); + this.$originalRedirectSub = $( '#redirectsub, #redirectsub + br' ).clone(); + } + // Add redirect target header + if ( !$( '#redirectsub' ).length ) { + $( '#contentSub' ).append( + $( '<span>' ) + .text( mw.msg( 'redirectpagesub' ) ) + .attr( 'id', 'redirectsub' ), + $( '<br>' ) + ); + } + $( '<div>' ) + // Bit of a hack: Make sure any redirect note is styled + .addClass( 'redirectMsg mw-content-' + $( 'html' ).attr( 'dir' ) ) - .addClass( 've-redirect-header' ) - .append( - $( '<p>' ).text( mw.msg( 'redirectto' ) ), - $( '<ul>' ) - .addClass( 'redirectText' ) - .append( $( '<li>' ).append( $link ) ) - ) - .click( function ( e ) { - var windowAction = ve.ui.actionFactory.create( 'window', target.getSurface() ); - windowAction.open( 'meta', { page: 'settings' } ); - e.preventDefault(); - } ) - .insertAfter( $( '.mw-jump' ) ); + .addClass( 've-redirect-header' ) + .append( + $( '<p>' ).text( mw.msg( 'redirectto' ) ), + $( '<ul>' ) + .addClass( 'redirectText' ) + .append( $( '<li>' ).append( $link ) ) + ) + .click( function ( e ) { + var windowAction = ve.ui.actionFactory.create( 'window', target.getSurface() ); + windowAction.open( 'meta', { page: 'settings' } ); + e.preventDefault(); + } ) + .insertAfter( $( '.mw-jump' ) ); + break; + case 'mwCategory': + this.rebuildCategories( metaList.getItemsInGroup( 'mwCategory' ) ); + break; } }; @@ -792,10 +799,53 @@ * @param {number} index Index within that offset the item was at */ ve.init.mw.DesktopArticleTarget.prototype.onMetaItemRemoved = function ( metaItem ) { - if ( metaItem.getType() === 'mwRedirect' ) { - this.$originalContent.find( '.redirectMsg' ).remove(); - $( '#contentSub #redirectsub, #contentSub #redirectsub + br' ).remove(); + var metaList = this.surface.getModel().getMetaList(); + switch ( metaItem.getType() ) { + case 'mwRedirect': + this.$originalContent.find( '.redirectMsg' ).remove(); + $( '#contentSub #redirectsub, #contentSub #redirectsub + br' ).remove(); + break; + case 'mwCategory': + this.rebuildCategories( metaList.getItemsInGroup( 'mwCategory' ) ); + break; } +}; + +/** + * Redisplay the category list on the page + * + * @param {ve.dm.MetaItem[]} categoryItems Array of category metaitems to display + */ +ve.init.mw.DesktopArticleTarget.prototype.rebuildCategories = function ( categoryItems ) { + var target = this; + // We need to fetch this from the API because the category list is skin- + // dependent, so the HTML output could be absolutely anything. + new mw.Api().post( { + formatversion: 2, + action: 'parse', + contentmodel: 'wikitext', + text: categoryItems.map( function ( categoryItem ) { + // TODO: wikitext-building is a bad smell here, but is done + // because there's no other API call that will get the category + // markup. Adding such an API, if other use cases for it emerge, + // might make sense. + if ( categoryItem.getAttribute( 'sortkey' ) ) { + return '[[' + categoryItem.getAttribute( 'category' ) + '|' + categoryItem.getAttribute( 'sortkey' ) + ']]'; + } + return '[[' + categoryItem.getAttribute( 'category' ) + ']]'; + } ).join( '\n' ), + prop: 'categorieshtml' + } ).then( function ( response ) { + var $categories; + if ( !response || !response.parse || !response.parse.categorieshtml ) { + return; + } + $categories = $( $.parseHTML( response.parse.categorieshtml ) ); + target.transformCategoryLinks( $categories ); + target.disableUneditableContent( $categories ); + mw.hook( 'wikipage.categories' ).fire( $categories ); + $( '#catlinks' ).replaceWith( $categories ); + } ); }; /** @@ -1126,8 +1176,7 @@ * Page modifications for switching to edit mode. */ ve.init.mw.DesktopArticleTarget.prototype.transformPage = function () { - var target = this, - $content; + var $content; this.updateTabs( true ); this.emit( 'transformPage' ); @@ -1136,6 +1185,7 @@ // Move all native content inside the target this.$originalContent.append( this.$element.siblings() ); + this.$originalCategories = $( '#catlinks' ).clone( true ); // Mark every non-direct ancestor between editableContent and the container as uneditable $content = this.$editableContent; @@ -1145,22 +1195,41 @@ $content = $content.parent(); } + this.transformCategoryLinks( $( '.catlinks' ) ); + + this.disableUneditableContent(); + + this.updateHistoryState(); +}; + +/** + * Category link section transformations for switching to edit mode. Broken out + * so it can be re-applied when displaying changes to the categories. + * + * @param {jQuery} $catlinks Category links container element + */ +ve.init.mw.DesktopArticleTarget.prototype.transformCategoryLinks = function ( $catlinks ) { + var target = this; // Un-disable the catlinks wrapper, but not the links - $( '.catlinks' ) - .removeClass( 've-init-mw-desktopArticleTarget-uneditableContent' ) + $catlinks.removeClass( 've-init-mw-desktopArticleTarget-uneditableContent' ) .on( 'click.ve-target', function () { var windowAction = ve.ui.actionFactory.create( 'window', target.getSurface() ); windowAction.open( 'meta', { page: 'categories' } ); return false; } ) .find( 'a' ).addClass( 've-init-mw-desktopArticleTarget-uneditableContent' ); +}; - $( '.ve-init-mw-desktopArticleTarget-uneditableContent' ).on( 'click.ve-target', function ( e ) { +/** + * Disabling of non-editable content, in a given context + * + * @param {jQuery|string} [context] Context to disable in + */ +ve.init.mw.DesktopArticleTarget.prototype.disableUneditableContent = function ( context ) { + $( '.ve-init-mw-desktopArticleTarget-uneditableContent', context ).on( 'click.ve-target', function ( e ) { // Support IE9: Prevent default, but don't stop propagation e.preventDefault(); } ); - - this.updateHistoryState(); }; /** @@ -1221,6 +1290,10 @@ this.$originalRedirectSub.prependTo( $( '#contentSub' ) ); this.$originalRedirectMsg = undefined; this.$originalRedirectSub = undefined; + } + + if ( this.$originalCategories ) { + $( '#catlinks' ).replaceWith( this.$originalCategories ); } mw.hook( 've.deactivate' ).fire(); @@ -1306,7 +1379,7 @@ html, categoriesHtml, displayTitle, lastModified, contentSub, isRedirect ) { var $content = $( $.parseHTML( html ) ), - $veSectionLinks; + $veSectionLinks, $categories; if ( lastModified ) { // If we were not viewing the most recent revision before (a requirement @@ -1346,7 +1419,9 @@ if ( displayTitle ) { $( '#content #firstHeading' ).html( displayTitle ); } - $( '#catlinks' ).replaceWith( categoriesHtml ); + $categories = $( $.parseHTML( categoriesHtml ) ); + mw.hook( 'wikipage.categories' ).fire( $categories ); + $( '#catlinks' ).replaceWith( $categories ); $( '#contentSub' ).html( contentSub ); if ( isRedirect ) { -- To view, visit https://gerrit.wikimedia.org/r/324786 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: merged Gerrit-Change-Id: I8d5a6504edc2e0486a0b4f016d8ee6d9a6228de9 Gerrit-PatchSet: 8 Gerrit-Project: mediawiki/extensions/VisualEditor Gerrit-Branch: master Gerrit-Owner: DLynch <dly...@wikimedia.org> Gerrit-Reviewer: Alex Monk <a...@wikimedia.org> Gerrit-Reviewer: DLynch <dly...@wikimedia.org> Gerrit-Reviewer: Esanders <esand...@wikimedia.org> Gerrit-Reviewer: jenkins-bot <> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits