Merge "maintenance: Script to rename titles for Unicode uppercasing changes"
[lhc/web/wiklou.git] / resources / src / mediawiki.special.watchlist / watchlist.js
1 /*!
2 * JavaScript for Special:Watchlist
3 */
4 ( function () {
5 $( function () {
6 var api = new mw.Api(), $progressBar, $resetForm = $( '#mw-watchlist-resetbutton' );
7
8 // If the user wants to reset their watchlist, use an API call to do so (no reload required)
9 // Adapted from a user script by User:NQ of English Wikipedia
10 // (User:NQ/WatchlistResetConfirm.js)
11 $resetForm.on( 'submit', function ( event ) {
12 var $button = $resetForm.find( 'input[name=mw-watchlist-reset-submit]' );
13
14 event.preventDefault();
15
16 // Disable reset button to prevent multiple concurrent requests
17 $button.prop( 'disabled', true );
18
19 if ( !$progressBar ) {
20 $progressBar = new OO.ui.ProgressBarWidget( { progress: false } ).$element;
21 $progressBar.css( {
22 position: 'absolute', width: '100%'
23 } );
24 }
25 // Show progress bar
26 $resetForm.append( $progressBar );
27
28 // Use action=setnotificationtimestamp to mark all as visited,
29 // then set all watchlist lines accordingly
30 api.postWithToken( 'csrf', {
31 formatversion: 2, action: 'setnotificationtimestamp', entirewatchlist: true
32 } ).done( function () {
33 // Enable button again
34 $button.prop( 'disabled', false );
35 // Hide the button because further clicks can not generate any visual changes
36 $button.css( 'visibility', 'hidden' );
37 $progressBar.detach();
38 $( '.mw-changeslist-line-watched' )
39 .removeClass( 'mw-changeslist-line-watched' )
40 .addClass( 'mw-changeslist-line-not-watched' );
41 } ).fail( function () {
42 // On error, fall back to server-side reset
43 // First remove this submit listener and then re-submit the form
44 $resetForm.off( 'submit' ).trigger( 'submit' );
45 } );
46 } );
47
48 // if the user wishes to reload the watchlist whenever a filter changes
49 if ( mw.user.options.get( 'watchlistreloadautomatically' ) ) {
50 // add a listener on all form elements in the header form
51 $( '#mw-watchlist-form input, #mw-watchlist-form select' ).on( 'change', function () {
52 // submit the form when one of the input fields is modified
53 $( '#mw-watchlist-form' ).trigger( 'submit' );
54 } );
55 }
56
57 if ( mw.user.options.get( 'watchlistunwatchlinks' ) ) {
58 // Watch/unwatch toggle link:
59 // If a page is on the watchlist, a '×' is shown which, when clicked, removes the page from the watchlist.
60 // After unwatching a page, the '×' becomes a '+', which if clicked re-watches the page.
61 // Unwatched page entries are struck through and have lowered opacity.
62 $( '.mw-changeslist' ).on( 'click', '.mw-unwatch-link, .mw-watch-link', function ( event ) {
63 var $unwatchLink = $( this ), // EnhancedChangesList uses <table> for each row, while OldChangesList uses <li> for each row
64 $watchlistLine = $unwatchLink.closest( 'li, table' )
65 .find( '[data-target-page]' ),
66 pageTitle = $watchlistLine.data( 'targetPage' ),
67 isTalk = mw.Title.newFromText( pageTitle ).isTalkPage();
68
69 // Utility function for looping through each watchlist line that matches
70 // a certain page or its associated page (e.g. Talk)
71 function forEachMatchingTitle( title, callback ) {
72
73 var titleObj = mw.Title.newFromText( title ),
74 associatedTitleObj = titleObj.isTalkPage() ? titleObj.getSubjectPage() : titleObj.getTalkPage(),
75 associatedTitle = associatedTitleObj.getPrefixedText();
76 $( '.mw-changeslist-line' ).each( function () {
77 var $this = $( this ), $row, $unwatchLink;
78
79 $this.find( '[data-target-page]' ).each( function () {
80 var $this = $( this ), rowTitle = $this.data( 'targetPage' );
81 if ( rowTitle === title || rowTitle === associatedTitle ) {
82
83 // EnhancedChangesList groups log entries by performer rather than target page. Therefore...
84 // * If using OldChangesList, use the <li>
85 // * If using EnhancedChangesList and $this is part of a grouped log entry, use the <td> sub-entry
86 // * If using EnhancedChangesList and $this is not part of a grouped log entry, use the <table> grouped entry
87 $row =
88 $this.closest(
89 'li, table.mw-collapsible.mw-changeslist-log td[data-target-page], table' );
90 $unwatchLink = $row.find( '.mw-unwatch-link, .mw-watch-link' );
91
92 callback( rowTitle, $row, $unwatchLink );
93 }
94 } );
95 } );
96 }
97
98 // Preload the notification module for mw.notify
99 mw.loader.load( 'mediawiki.notification' );
100
101 // Depending on whether we are watching or unwatching, for each entry of the page (and its associated page i.e. Talk),
102 // change the text, tooltip, and non-JS href of the (un)watch button, and update the styling of the watchlist entry.
103 // eslint-disable-next-line no-jquery/no-class-state
104 if ( $unwatchLink.hasClass( 'mw-unwatch-link' ) ) {
105 api.unwatch( pageTitle )
106 .done( function () {
107 forEachMatchingTitle( pageTitle,
108 function ( rowPageTitle, $row, $rowUnwatchLink ) {
109 $rowUnwatchLink
110 .text( mw.msg( 'watchlist-unwatch-undo' ) )
111 .attr( 'title', mw.msg( 'tooltip-ca-watch' ) )
112 .attr( 'href',
113 mw.util.getUrl( rowPageTitle, { action: 'watch' } ) )
114 .removeClass( 'mw-unwatch-link loading' )
115 .addClass( 'mw-watch-link' );
116 $row.find(
117 '.mw-changeslist-line-inner, .mw-enhanced-rc-nested' )
118 .addBack( '.mw-enhanced-rc-nested' ) // For matching log sub-entry
119 .addClass( 'mw-changelist-line-inner-unwatched' );
120 } );
121
122 mw.notify(
123 mw.message( isTalk ? 'removedwatchtext-talk' : 'removedwatchtext',
124 pageTitle ), { tag: 'watch-self' } );
125 } );
126 } else {
127 api.watch( pageTitle )
128 .then( function () {
129 forEachMatchingTitle( pageTitle,
130 function ( rowPageTitle, $row, $rowUnwatchLink ) {
131 $rowUnwatchLink
132 .text( mw.msg( 'watchlist-unwatch' ) )
133 .attr( 'title', mw.msg( 'tooltip-ca-unwatch' ) )
134 .attr( 'href',
135 mw.util.getUrl( rowPageTitle, { action: 'unwatch' } ) )
136 .removeClass( 'mw-watch-link loading' )
137 .addClass( 'mw-unwatch-link' );
138 $row.find( '.mw-changelist-line-inner-unwatched' )
139 .addBack( '.mw-enhanced-rc-nested' )
140 .removeClass( 'mw-changelist-line-inner-unwatched' );
141 } );
142
143 mw.notify(
144 mw.message( isTalk ? 'addedwatchtext-talk' : 'addedwatchtext',
145 pageTitle ), { tag: 'watch-self' } );
146 } );
147 }
148
149 event.preventDefault();
150 event.stopPropagation();
151 $unwatchLink.trigger( 'blur' );
152 } );
153 }
154 } );
155
156 }() );