2 * Animate watch/unwatch links to use asynchronous API requests to
3 * watch pages, rather than navigating to a different URI.
5 * @class mw.page.watch.ajax
8 // The name of the page to watch or unwatch
9 var title
= mw
.config
.get( 'wgRelevantPageName' );
12 * Update the link text, link href attribute and (if applicable)
15 * @param {jQuery} $link Anchor tag of (un)watch link
16 * @param {string} action One of 'watch', 'unwatch'
17 * @param {string} [state="idle"] 'idle' or 'loading'. Default is 'idle'
19 function updateWatchLink( $link
, action
, state
) {
20 var msgKey
, $li
, otherAction
;
22 // A valid but empty jQuery object shouldn't throw a TypeError
23 if ( !$link
.length
) {
27 // Invalid actions shouldn't silently turn the page in an unrecoverable state
28 if ( action
!== 'watch' && action
!== 'unwatch' ) {
29 throw new Error( 'Invalid action' );
32 // message keys 'watch', 'watching', 'unwatch' or 'unwatching'.
33 msgKey
= state
=== 'loading' ? action
+ 'ing' : action
;
34 otherAction
= action
=== 'watch' ? 'unwatch' : 'watch';
35 $li
= $link
.closest( 'li' );
37 // Trigger a 'watchpage' event for this List item.
38 // Announce the otherAction value as the first param.
39 // Used to monitor the state of watch link.
40 // TODO: Revise when system wide hooks are implemented
41 if ( state
=== undefined ) {
42 $li
.trigger( 'watchpage.mw', otherAction
);
46 .text( mw
.msg( msgKey
) )
47 .attr( 'title', mw
.msg( 'tooltip-ca-' + action
) )
48 .updateTooltipAccessKeys()
49 .attr( 'href', mw
.util
.wikiScript() + '?' + $.param( {
55 // Most common ID style
56 if ( $li
.prop( 'id' ) === 'ca-' + otherAction
) {
57 $li
.prop( 'id', 'ca-' + action
);
60 if ( state
=== 'loading' ) {
61 $link
.addClass( 'loading' );
63 $link
.removeClass( 'loading' );
68 * TODO: This should be moved somewhere more accessible.
72 * @return {string} The extracted action, defaults to 'view'
74 function mwUriGetAction( url
) {
75 var action
, actionPaths
, key
, i
, m
, parts
;
77 // TODO: Does MediaWiki give action path or query param
78 // precedence? If the former, move this to the bottom
79 action
= mw
.util
.getParamValue( 'action', url
);
80 if ( action
!== null ) {
84 actionPaths
= mw
.config
.get( 'wgActionPaths' );
85 for ( key
in actionPaths
) {
86 if ( actionPaths
.hasOwnProperty( key
) ) {
87 parts
= actionPaths
[key
].split( '$1' );
88 for ( i
= 0; i
< parts
.length
; i
++ ) {
89 parts
[i
] = $.escapeRE( parts
[i
] );
91 m
= new RegExp( parts
.join( '(.+)' ) ).exec( url
);
102 // Expose public methods
104 updateWatchLink
: updateWatchLink
108 var $links
= $( '.mw-watchlink a, a.mw-watchlink, ' +
109 '#ca-watch a, #ca-unwatch a, #mw-unwatch-link1, ' +
110 '#mw-unwatch-link2, #mw-watch-link2, #mw-watch-link1' );
112 // Allowing people to add inline animated links is a little scary
113 $links
= $links
.filter( ':not( #bodyContent *, #content * )' );
115 $links
.click( function ( e
) {
116 var action
, api
, $link
;
118 // Start preloading the notification module (normally loaded by mw.notify())
119 mw
.loader
.load( ['mediawiki.notification'], null, true );
121 action
= mwUriGetAction( this.href
);
123 if ( action
!== 'watch' && action
!== 'unwatch' ) {
124 // Could not extract target action from link url,
125 // let native browsing handle it further
133 if ( $link
.hasClass( 'loading' ) ) {
137 updateWatchLink( $link
, action
, 'loading' );
142 .done( function ( watchResponse
) {
143 var otherAction
= action
=== 'watch' ? 'unwatch' : 'watch';
145 mw
.notify( $.parseHTML( watchResponse
.message
), {
149 // Set link to opposite
150 updateWatchLink( $link
, otherAction
);
152 // Update the "Watch this page" checkbox on action=edit when the
153 // page is watched or unwatched via the tab (bug 12395).
154 $( '#wpWatchthis' ).prop( 'checked', watchResponse
.watched
!== undefined );
157 var cleanTitle
, msg
, link
;
159 // Reset link to non-loading mode
160 updateWatchLink( $link
, action
);
162 // Format error message
163 cleanTitle
= title
.replace( /_
/g
, ' ' );
164 link
= mw
.html
.element(
166 href
: mw
.util
.getUrl( title
),
170 msg
= mw
.message( 'watcherrortext', link
);
172 // Report to user about the error
173 mw
.notify( msg
, { tag
: 'watch-self' } );
178 }( mediaWiki
, jQuery
) );