Localisation updates from https://translatewiki.net.
[mediawiki.git] / resources / src / mediawiki.diff / diff.js
blob500e0a5bd5f2cc125501d9ee67e2c162ad84577a
1 /*!
2  * JavaScript for diff views
3  */
4 const inlineFormatToggle = require( './inlineFormatToggle.js' );
6 ( function () {
7         $( () => {
8                 /**
9                  * @param {Node} node
10                  * @return {string|undefined}
11                  * @ignore
12                  */
13                 function getNodeSide( node ) {
14                         if ( $( node ).closest( '.diff-side-deleted' ).length !== 0 ) {
15                                 return 'deleted';
16                         } else if ( $( node ).closest( '.diff-side-added' ).length !== 0 ) {
17                                 return 'added';
18                         } else {
19                                 // Not inside the diff.
20                                 return undefined;
21                         }
22                 }
24                 /**
25                  * @return {string|undefined}
26                  * @ignore
27                  */
28                 function getCurrentlyLockedSide() {
29                         return $( '.diff' ).attr( 'data-selected-side' );
30                 }
32                 /**
33                  * @param {string|undefined} side Either "added" or "deleted", or undefined to unset.
34                  * @ignore
35                  */
36                 function setSideLock( side ) {
37                         $( '.diff' ).attr( 'data-selected-side', side );
38                 }
40                 /**
41                  * @param {MouseEvent} e
42                  * @ignore
43                  */
44                 function maybeClearSelectProtection( e ) {
45                         if ( e.button === 2 ) {
46                                 // Right click.
47                                 return;
48                         }
49                         const clickSide = getNodeSide( e.target );
50                         if ( getCurrentlyLockedSide() !== clickSide ) {
51                                 document.getSelection().removeAllRanges();
52                         }
53                         setSideLock( clickSide );
54                 }
56                 function selectionHandler() {
57                         const textNode = document.getSelection().anchorNode;
59                         if ( !textNode ) {
60                                 return;
61                         }
63                         setSideLock( getNodeSide( textNode ) );
64                 }
66                 $( document ).on( 'selectionchange', selectionHandler );
67                 $( document ).on( 'mousedown', maybeClearSelectProtection );
69                 $( document ).on(
70                         'click',
71                         [
72                                 '.mw-diff-inline-moved del',
73                                 '.mw-diff-inline-moved ins',
74                                 '.mw-diff-inline-changed del',
75                                 '.mw-diff-inline-changed ins',
76                                 '.mw-diff-inline-added ins',
77                                 '.mw-diff-inline-deleted del'
78                         ].join( ',' ),
79                         /**
80                          * Shows a tooltip when added/deleted text is clicked on a tablet or mobile resolution.
81                          *
82                          * @param {Event} ev
83                          */
84                         ( ev ) => {
85                                 // Limit this behaviour to mobile.
86                                 const widthBreakpointTablet = 720;
87                                 const isTabletOrMobile = window.matchMedia( `(max-width: ${ widthBreakpointTablet }px)` );
88                                 if ( !isTabletOrMobile.matches ) {
89                                         return;
90                                 }
91                                 const contentAdded = ev.target && ev.target.matches( 'ins' );
92                                 const text = contentAdded ?
93                                         mw.msg( 'diff-inline-tooltip-ins' ) :
94                                         mw.msg( 'diff-inline-tooltip-del' );
95                                 mw.loader.using( 'oojs-ui-core' ).then( () => {
96                                         const popup = new OO.ui.PopupWidget( {
97                                                 $content: $( '<p>' ).text( text ),
98                                                 padded: true,
99                                                 autoClose: true,
100                                                 anchor: true,
101                                                 align: 'center',
102                                                 $floatableContainer: $( ev.target ),
103                                                 position: 'below',
104                                                 classes: [ 'mw-diff-popup' ],
105                                                 width: 'auto'
106                                         } );
107                                         $( OO.ui.getTeleportTarget() ).append( popup.$element );
108                                         popup.toggle( true );
109                                         popup.toggleClipping( true );
110                                 } );
111                         }
112                 );
113         } );
115         // If there is a diff present on page, load the toggle.
116         const $inlineToggleSwitchLayout = $( '#mw-diffPage-inline-toggle-switch-layout' );
117         // Return if inline switch is not displaying.
118         if ( $inlineToggleSwitchLayout.length ) {
119                 mw.loader.using( 'oojs-ui' ).then( () => {
120                         inlineFormatToggle( $inlineToggleSwitchLayout );
121                 } );
122         }
123 }() );