Localisation updates from https://translatewiki.net.
[mediawiki.git] / resources / src / mediawiki.diff / inlineFormatToggle.js
blobc760d086a40dbebbbbb152a84e297cbf6446003c
1 /*!
2  * JavaScript for diff inline toggle
3  */
4 module.exports = function ( $inlineToggleSwitchLayout ) {
5         const url = new URL( location.href ),
6                 api = new mw.Api(),
7                 $inlineLegendContainer = $( '.mw-diff-inline-legend' ),
8                 inlineToggleSwitchLayout = OO.ui.FieldLayout.static.infuse( $inlineToggleSwitchLayout ),
9                 inlineToggleSwitch = inlineToggleSwitchLayout.getField();
11         inlineToggleSwitch.on( 'change', ( e ) => {
12                 onDiffTypeInlineChange( e, true );
13         } );
14         inlineToggleSwitch.on( 'disable', onDiffTypeInlineDisabled );
16         const $wikitextDiffContainer = $( 'table.diff[data-mw="interface"]' );
17         const $wikitextDiffHeader = $wikitextDiffContainer.find( 'tr.diff-title' )
18                 .add( $wikitextDiffContainer.find( 'td.diff-multi, td.diff-notice' ).parent() );
19         let $wikitextDiffBody = $wikitextDiffContainer.find( 'tr' ).not( $wikitextDiffHeader );
21         let $wikitextDiffBodyInline, $wikitextDiffBodyTable;
22         if ( inlineToggleSwitch.getValue() ) {
23                 $wikitextDiffBodyInline = $wikitextDiffBody;
24         } else {
25                 $wikitextDiffBodyTable = $wikitextDiffBody;
26         }
28         /**
29          * Handler for inlineToggleSwitch onChange event
30          *
31          * @param {boolean} isInline
32          * @param {boolean} saveDiffTypeOption
33          */
34         function onDiffTypeInlineChange( isInline, saveDiffTypeOption ) {
35                 if ( ( isInline && typeof $wikitextDiffBodyInline === 'undefined' ) ||
36                         ( !isInline && typeof $wikitextDiffBodyTable === 'undefined' ) ) {
37                         fetchDiff( isInline );
38                 } else {
39                         toggleDiffTypeVisibility( isInline );
40                 }
42                 if ( saveDiffTypeOption ) {
43                         api.saveOption( 'diff-type', isInline ? 'inline' : 'table' )
44                                 .fail( ( error ) => {
45                                         if ( error === 'notloggedin' ) {
46                                                 // Can't save preference, so use query parameter stickiness
47                                                 switchQueryParams( isInline );
48                                         }
49                                 } );
50                 }
51         }
53         /**
54          * Toggle legend and the DOM containers according to the format selected.
55          *
56          * @param {boolean} isInline
57          */
58         function toggleDiffTypeVisibility( isInline ) {
59                 $inlineLegendContainer.toggleClass( 'oo-ui-element-hidden', !isInline );
60                 if ( typeof $wikitextDiffBodyInline !== 'undefined' ) {
61                         $wikitextDiffBodyInline.toggleClass( 'oo-ui-element-hidden', !isInline );
62                 }
64                 if ( typeof $wikitextDiffBodyTable !== 'undefined' ) {
65                         $wikitextDiffBodyTable.toggleClass( 'oo-ui-element-hidden', isInline );
66                 }
67         }
69         /**
70          * Change the query parameters to maintain the new diff type.
71          * This is used for anonymous users.
72          *
73          * @param {boolean} isInline
74          */
75         function switchQueryParams( isInline ) {
76                 $( '#differences-prevlink, #differences-nextlink' )
77                         .each( function () {
78                                 let linkUrl;
79                                 try {
80                                         linkUrl = new URL( this.href );
81                                 } catch ( e ) {
82                                         return;
83                                 }
84                                 if ( isInline ) {
85                                         linkUrl.searchParams.set( 'diff-type', 'inline' );
86                                 } else {
87                                         linkUrl.searchParams.delete( 'diff-type' );
88                                 }
89                                 this.href = linkUrl.toString();
90                         } );
91         }
93         /**
94          * Toggle the legend when the toggle switch disabled state changes.
95          *
96          * @param {boolean} disabled
97          */
98         function onDiffTypeInlineDisabled( disabled ) {
99                 if ( disabled ) {
100                         $inlineLegendContainer.addClass( 'oo-ui-element-hidden' );
101                 } else {
102                         $inlineLegendContainer.toggleClass( 'oo-ui-element-hidden', !inlineToggleSwitch.getValue() );
103                         // When Inline Switch is enabled, toggle wikitext according to its value.
104                         // Do not save user 'diff-type' preference
105                         onDiffTypeInlineChange( inlineToggleSwitch.getValue(), false );
106                 }
107         }
109         /**
110          * Fetch the diff through mw.API in the given format.
111          *
112          * @param {boolean} isInline
113          */
114         function fetchDiff( isInline ) {
115                 const diffType = isInline ? 'inline' : 'table',
116                         oldRevId = mw.config.get( 'wgDiffOldId' ),
117                         newRevId = mw.config.get( 'wgDiffNewId' );
119                 let oldPageName, newPageName;
120                 if ( mw.config.get( 'wgCanonicalSpecialPageName' ) !== 'ComparePages' ) {
121                         oldPageName = newPageName = mw.config.get( 'wgRelevantPageName' );
122                 } else {
123                         oldPageName = url.searchParams.get( 'page1' );
124                         newPageName = url.searchParams.get( 'page2' );
125                 }
127                 const apiParams = {
128                         action: 'compare',
129                         fromtitle: oldPageName,
130                         totitle: newPageName,
131                         fromrev: oldRevId,
132                         torev: newRevId,
133                         difftype: diffType
134                 };
136                 api.get( apiParams ).done( ( diffData ) => {
137                         if ( isInline ) {
138                                 $wikitextDiffBodyInline = $( diffData.compare[ '*' ] );
139                         } else {
140                                 $wikitextDiffBodyTable = $( diffData.compare[ '*' ] );
141                         }
143                         toggleDiffTypeVisibility( inlineToggleSwitch.getValue() );
145                         $wikitextDiffBody.last().after( isInline ? $wikitextDiffBodyInline : $wikitextDiffBodyTable );
146                         $wikitextDiffBody = $wikitextDiffContainer.find( 'tr' ).not( $wikitextDiffHeader );
147                         /**
148                          * Fired when the wikitext DOM is updated so others can react accordingly.
149                          *
150                          * @event ~'wikipage.diff.wikitextDiffBody'
151                          * @memberof Hooks
152                          * @param {jQuery} $wikitextDiffBody
153                          */
154                         mw.hook( 'wikipage.diff.wikitextBodyUpdate' ).fire( $wikitextDiffBody );
155                 } );
156         }
158         /**
159          * Fired when the diff type switch is present so others can decide
160          * how to manipulate the DOM.
161          *
162          * @event ~'wikipage.diff.diffTypeSwitch'
163          * @memberof Hooks
164          * @param {OO.ui.ToggleSwitchWidget} inlineToggleSwitch
165          */
166         mw.hook( 'wikipage.diff.diffTypeSwitch' ).fire( inlineToggleSwitch );