090e4c3d1e32e0b2d46f4494e524ee8014df8839
[lhc/web/wiklou.git] / resources / mediawiki.action / mediawiki.action.watch.ajax.js
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, undefined ) {
6
7 /**
8 * The name of the page to watch or unwatch.
9 */
10 var title = mw.config.get( 'wgRelevantPageName', mw.config.get( 'wgPageName' ) );
11
12 /**
13 * Update the link text, link href attribute and (if applicable)
14 * "loading" class.
15 *
16 * @param $link {jQuery} Anchor tag of (un)watch link.
17 * @param action {String} One of 'watch', 'unwatch'.
18 * @param state {String} [optional] 'idle' or 'loading'. Default is 'idle'.
19 */
20 function updateWatchLink( $link, action, state ) {
21 var accesskeyTip, msgKey, $li;
22
23 // message keys 'watch', 'watching', 'unwatch' or 'unwatching'.
24 msgKey = state === 'loading' ? action + 'ing' : action;
25 accesskeyTip = $link.attr( 'title' ).match( mw.util.tooltipAccessKeyRegexp );
26 $li = $link.closest( 'li' );
27
28 $link
29 .text( mw.msg( msgKey ) )
30 .attr( 'title', mw.msg( 'tooltip-ca-' + action ) +
31 ( accesskeyTip ? ' ' + accesskeyTip[0] : '' )
32 )
33 .attr( 'href', mw.util.wikiScript() + '?' + $.param({
34 title: title,
35 action: action
36 })
37 );
38
39 // Special case for vector icon
40 if ( $li.hasClass( 'icon' ) ) {
41 if ( state === 'loading' ) {
42 $link.addClass( 'loading' );
43 } else {
44 $link.removeClass( 'loading' );
45 }
46 }
47 }
48
49 /**
50 * @todo This should be moved somewhere more accessible.
51 * @param url {String}
52 * @return {String} The extracted action, defaults to 'view'.
53 */
54 function mwUriGetAction( url ) {
55 var action, actionPaths, key, i, m, parts;
56
57 actionPaths = mw.config.get( 'wgActionPaths' );
58
59 // @todo: Does MediaWiki give action path or query param
60 // precedence ? If the former, move this to the bottom
61 action = mw.util.getParamValue( 'action', url );
62 if ( action !== null ) {
63 return action;
64 }
65
66 for ( key in actionPaths ) {
67 if ( actionPaths.hasOwnProperty( key ) ) {
68 parts = actionPaths[key].split( '$1' );
69 for ( i = 0; i < parts.length; i += 1 ) {
70 parts[i] = $.escapeRE( parts[i] );
71 }
72 m = new RegExp( parts.join( '(.+)' ) ).exec( url );
73 if ( m && m[1] ) {
74 return key;
75 }
76
77 }
78 }
79
80 return 'view';
81 }
82
83 $( document ).ready( function () {
84 var $links = $( '.mw-watchlink a, a.mw-watchlink, ' +
85 '#ca-watch a, #ca-unwatch a, #mw-unwatch-link1, ' +
86 '#mw-unwatch-link2, #mw-watch-link2, #mw-watch-link1' );
87
88 // Allowing people to add inline animated links is a little scary
89 $links = $links.filter( ':not( #bodyContent *, #content * )' );
90
91 $links.click( function ( e ) {
92 var action, api, $link;
93
94 action = mwUriGetAction( this.href );
95
96 if ( action !== 'watch' && action !== 'unwatch' ) {
97 // Could not extract target action from link url,
98 // let native browsing handle it further
99 return true;
100 }
101 e.preventDefault();
102 e.stopPropagation();
103
104 $link = $( this );
105
106 updateWatchLink( $link, action, 'loading' );
107
108 api = new mw.Api();
109 api[action](
110 title,
111 // Success
112 function ( watchResponse ) {
113 var $li, otherAction;
114
115 otherAction = action === 'watch' ? 'unwatch' : 'watch';
116 $li = $link.closest( 'li' );
117
118 mw.util.jsMessage( watchResponse.message, 'ajaxwatch' );
119
120 // Set link to opposite
121 updateWatchLink( $link, otherAction );
122
123 // Most common ID style
124 if ( $li.prop( 'id' ) === 'ca-' + otherAction || $li.prop( 'id' ) === 'ca-' + action ) {
125 $li.prop( 'id', 'ca-' + otherAction );
126 }
127
128 // Bug 12395 - update the watch checkbox on edit pages when the
129 // page is watched or unwatched via the tab.
130 if ( watchResponse.watched !== undefined ) {
131 $( '#wpWatchthis' ).prop( 'checked', true );
132 } else {
133 $( '#wpWatchthis' ).removeProp( 'checked' );
134 }
135 },
136 // Error
137 function () {
138 var cleanTitle, html, link;
139
140 // Reset link to non-loading mode
141 updateWatchLink( $link, action );
142
143 // Format error message
144 cleanTitle = title.replace( /_/g, ' ' );
145 link = mw.html.element(
146 'a', {
147 href: mw.util.wikiGetlink( title ),
148 title: cleanTitle
149 }, cleanTitle
150 );
151 html = mw.msg( 'watcherrortext', link );
152
153 // Report to user about the error
154 mw.util.jsMessage( html, 'ajaxwatch' );
155
156 }
157 );
158 });
159 });
160
161 }( jQuery, mediaWiki ) );