Clean up: Consistently use "$" instead of "$( document ).ready"
[mediawiki.git] / resources / mediawiki.page / mediawiki.page.watch.ajax.js
blob545cd072d34bd64c5e26e9a5a965cc32b07bf4bb
1 /**
2  * Animate watch/unwatch links to use asynchronous API requests to
3  * watch pages, rather than navigating to a different URI.
4  */
5 ( function ( mw, $ ) {
6         /**
7          * The name of the page to watch or unwatch.
8          */
9         var title = mw.config.get( 'wgRelevantPageName', mw.config.get( 'wgPageName' ) );
11         /**
12          * Update the link text, link href attribute and (if applicable)
13          * "loading" class.
14          *
15          * @param $link {jQuery} Anchor tag of (un)watch link.
16          * @param action {String} One of 'watch', 'unwatch'.
17          * @param state {String} [optional] 'idle' or 'loading'. Default is 'idle'.
18          */
19         function updateWatchLink( $link, action, state ) {
20                 var accesskeyTip, msgKey, $li, otherAction;
22                 // message keys 'watch', 'watching', 'unwatch' or 'unwatching'.
23                 msgKey = state === 'loading' ? action + 'ing' : action;
24                 otherAction = action === 'watch' ? 'unwatch' : 'watch';
25                 accesskeyTip = $link.attr( 'title' ).match( mw.util.tooltipAccessKeyRegexp );
26                 $li = $link.closest( 'li' );
28                 /**
29                  * Trigger a 'watchpage' event for this List item.
30                  * Announce the otherAction value as the first param.
31                  * Used to monitor the state of watch link.
32                  * TODO: Revise when system wide hooks are implemented
33                  */
34                 if ( state === undefined ) {
35                         $li.trigger( 'watchpage.mw', otherAction );
36                 }
38                 $link
39                         .text( mw.msg( msgKey ) )
40                         .attr( 'title', mw.msg( 'tooltip-ca-' + action ) +
41                                 ( accesskeyTip ? ' ' + accesskeyTip[0] : '' )
42                         )
43                         .attr( 'href', mw.util.wikiScript() + '?' + $.param({
44                                         title: title,
45                                         action: action
46                                 })
47                         );
49                 // Most common ID style
50                 if ( $li.prop( 'id' ) === 'ca-' + otherAction ) {
51                         $li.prop( 'id', 'ca-' + action );
52                 }
54                 // Special case for vector icon
55                 if ( $li.hasClass( 'icon' ) ) {
56                         if ( state === 'loading' ) {
57                                 $link.addClass( 'loading' );
58                         } else {
59                                 $link.removeClass( 'loading' );
60                         }
61                 }
62         }
64         /**
65          * @todo This should be moved somewhere more accessible.
66          * @param url {String}
67          * @return {String} The extracted action, defaults to 'view'.
68          */
69         function mwUriGetAction( url ) {
70                 var action, actionPaths, key, i, m, parts;
72                 actionPaths = mw.config.get( 'wgActionPaths' );
74                 // @todo Does MediaWiki give action path or query param
75                 // precedence ? If the former, move this to the bottom
76                 action = mw.util.getParamValue( 'action', url );
77                 if ( action !== null ) {
78                         return action;
79                 }
81                 for ( key in actionPaths ) {
82                         if ( actionPaths.hasOwnProperty( key ) ) {
83                                 parts = actionPaths[key].split( '$1' );
84                                 for ( i = 0; i < parts.length; i += 1 ) {
85                                         parts[i] = $.escapeRE( parts[i] );
86                                 }
87                                 m = new RegExp( parts.join( '(.+)' ) ).exec( url );
88                                 if ( m && m[1] ) {
89                                         return key;
90                                 }
92                         }
93                 }
95                 return 'view';
96         }
98         // Expose local methods
99         mw.page.watch = {
100                 updateWatchLink: updateWatchLink
101         };
103         $( function () {
104                 var $links = $( '.mw-watchlink a, a.mw-watchlink, ' +
105                         '#ca-watch a, #ca-unwatch a, #mw-unwatch-link1, ' +
106                         '#mw-unwatch-link2, #mw-watch-link2, #mw-watch-link1' );
108                 // Allowing people to add inline animated links is a little scary
109                 $links = $links.filter( ':not( #bodyContent *, #content * )' );
111                 $links.click( function ( e ) {
112                         var action, api, $link;
114                         action = mwUriGetAction( this.href );
116                         if ( action !== 'watch' && action !== 'unwatch' ) {
117                                 // Could not extract target action from link url,
118                                 // let native browsing handle it further
119                                 return true;
120                         }
121                         e.preventDefault();
122                         e.stopPropagation();
124                         $link = $( this );
126                         updateWatchLink( $link, action, 'loading' );
128                         api = new mw.Api();
129                         api[action](
130                                 title,
131                                 // Success
132                                 function ( watchResponse ) {
133                                         var $li, otherAction;
135                                         otherAction = action === 'watch' ? 'unwatch' : 'watch';
136                                         $li = $link.closest( 'li' );
138                                         mw.notify( $.parseHTML( watchResponse.message ), {
139                                                 tag: 'watch-self'
140                                         } );
142                                         // Set link to opposite
143                                         updateWatchLink( $link, otherAction );
145                                         // Bug 12395 - update the watch checkbox on edit pages when the
146                                         // page is watched or unwatched via the tab.
147                                         if ( watchResponse.watched !== undefined ) {
148                                                 $( '#wpWatchthis' ).prop( 'checked', true );
149                                         } else {
150                                                 $( '#wpWatchthis' ).prop( 'checked', false );
151                                         }
152                                 },
153                                 // Error
154                                 function () {
155                                         var cleanTitle, msg, link;
157                                         // Reset link to non-loading mode
158                                         updateWatchLink( $link, action );
160                                         // Format error message
161                                         cleanTitle = title.replace( /_/g, ' ' );
162                                         link = mw.html.element(
163                                                 'a', {
164                                                         href: mw.util.wikiGetlink( title ),
165                                                         title: cleanTitle
166                                                 }, cleanTitle
167                                         );
168                                         msg = mw.message( 'watcherrortext', link );
170                                         // Report to user about the error
171                                         mw.notify( msg, { tag: 'watch-self' } );
173                                 }
174                         );
175                 } );
176         } );
178 }( mediaWiki, jQuery ) );