diff options
Diffstat (limited to 'skins/common/ajaxwatch.js')
-rw-r--r-- | skins/common/ajaxwatch.js | 262 |
1 files changed, 101 insertions, 161 deletions
diff --git a/skins/common/ajaxwatch.js b/skins/common/ajaxwatch.js index 7f546014..aaf6360c 100644 --- a/skins/common/ajaxwatch.js +++ b/skins/common/ajaxwatch.js @@ -1,180 +1,120 @@ -// dependencies: -// * ajax.js: - /*extern sajax_init_object, sajax_do_call */ -// * wikibits.js: - /*extern changeText, hookEvent, jsMsg */ +/** + * Animate watch/unwatch links to use asynchronous API requests to + * watch pages, rather than clicking on links. Requires jQuery. + * Uses jsMsg() from wikibits.js. + */ -// These should have been initialized in the generated js -/*extern wgAjaxWatch, wgPageName */ - -if(typeof wgAjaxWatch === "undefined" || !wgAjaxWatch) { - var wgAjaxWatch = { - watchMsg: "Watch", - unwatchMsg: "Unwatch", - watchingMsg: "Watching...", - unwatchingMsg: "Unwatching...", - 'tooltip-ca-watchMsg': "Add this page to your watchlist", - 'tooltip-ca-unwatchMsg': "Remove this page from your watchlist" - }; +if ( typeof wgAjaxWatch === 'undefined' || !wgAjaxWatch ) { + window.wgAjaxWatch = { }; } -wgAjaxWatch.supported = true; // supported on current page and by browser -wgAjaxWatch.watching = false; // currently watching page -wgAjaxWatch.inprogress = false; // ajax request in progress -wgAjaxWatch.timeoutID = null; // see wgAjaxWatch.ajaxCall -wgAjaxWatch.watchLinks = []; // "watch"/"unwatch" links -wgAjaxWatch.iconMode = false; // new icon driven functionality -wgAjaxWatch.imgBasePath = ""; // base img path derived from icons on load - -wgAjaxWatch.setLinkText = function( newText ) { - if( wgAjaxWatch.iconMode ) { - for ( i = 0; i < wgAjaxWatch.watchLinks.length; i++ ) { - wgAjaxWatch.watchLinks[i].firstChild.alt = newText; - if ( newText == wgAjaxWatch.watchingMsg || newText == wgAjaxWatch.unwatchingMsg ) { - wgAjaxWatch.watchLinks[i].className += ' loading'; - } else if ( newText == wgAjaxWatch.watchMsg || newText == wgAjaxWatch.unwatchMsg ) { - wgAjaxWatch.watchLinks[i].className = - wgAjaxWatch.watchLinks[i].className.replace( /loading/i, '' ); - // update the title text on the link - var keyCommand = wgAjaxWatch.watchLinks[i].title.match( /\[.*?\]$/ ) ? - wgAjaxWatch.watchLinks[i].title.match( /\[.*?\]$/ )[0] : ""; - wgAjaxWatch.watchLinks[i].title = ( newText == wgAjaxWatch.watchMsg ? - wgAjaxWatch['tooltip-ca-watchMsg'] : wgAjaxWatch['tooltip-ca-unwatchMsg'] ) - + " " + keyCommand; - } +wgAjaxWatch.setLinkText = function( $link, action ) { + if ( action == 'watch' || action == 'unwatch' ) { + // save the accesskey from the title + var keyCommand = $link.attr( 'title' ).match( /\[.*?\]$/ ) ? $link.attr( 'title' ).match( /\[.*?\]$/ )[0] : ''; + $link.attr( 'title', mediaWiki.msg( 'tooltip-ca-' + action ) + ' ' + keyCommand ); + } + if ( $link.data( 'icon' ) ) { + $link.attr( 'alt', mediaWiki.msg( action ) ); + if ( action == 'watching' || action == 'unwatching' ) { + $link.addClass( 'loading' ); + } else { + $link.removeClass( 'loading' ); } } else { - for ( i = 0; i < wgAjaxWatch.watchLinks.length; i++ ) { - changeText( wgAjaxWatch.watchLinks[i], newText ); - } + $link.html( mediaWiki.msg( action ) ); } }; -wgAjaxWatch.setLinkID = function( newId ) { - // We can only set the first one - wgAjaxWatch.watchLinks[0].parentNode.setAttribute( 'id', newId ); -}; - -wgAjaxWatch.setHref = function( string ) { - for( i = 0; i < wgAjaxWatch.watchLinks.length; i++ ) { - if( string == 'watch' ) { - wgAjaxWatch.watchLinks[i].href = wgAjaxWatch.watchLinks[i].href - .replace( /&action=unwatch/, '&action=watch' ); - } else if( string == 'unwatch' ) { - wgAjaxWatch.watchLinks[i].href = wgAjaxWatch.watchLinks[i].href - .replace( /&action=watch/, '&action=unwatch' ); - } - } -} - -wgAjaxWatch.ajaxCall = function() { - if(!wgAjaxWatch.supported) { - return true; - } else if (wgAjaxWatch.inprogress) { - return false; - } - if(!wfSupportsAjax()) { - // Lazy initialization so we don't toss up - // ActiveX warnings on initial page load - // for IE 6 users with security settings. - wgAjaxWatch.supported = false; - return true; +wgAjaxWatch.processResult = function( response ) { + response = response.watch; + var $link = $( this ); + // To ensure we set the same status for all watch links with the + // same target we trigger a custom event on *all* watch links. + if( response.watched !== undefined ) { + wgAjaxWatch.$links.trigger( 'mw-ajaxwatch', [response.title, 'watch'] ); + } else if ( response.unwatched !== undefined ) { + wgAjaxWatch.$links.trigger( 'mw-ajaxwatch', [response.title, 'unwatch'] ); + } else { + // Either we got an error code or it just plain broke. + window.location.href = $link.attr( 'href' ); + return; } - wgAjaxWatch.inprogress = true; - wgAjaxWatch.setLinkText( wgAjaxWatch.watching - ? wgAjaxWatch.unwatchingMsg : wgAjaxWatch.watchingMsg); - sajax_do_call( - "wfAjaxWatch", - [wgPageName, (wgAjaxWatch.watching ? "u" : "w")], - wgAjaxWatch.processResult - ); - // if the request isn't done in 10 seconds, allow user to try again - wgAjaxWatch.timeoutID = window.setTimeout( - function() { wgAjaxWatch.inprogress = false; }, - 10000 - ); - return false; -}; + jsMsg( response.message, 'watch' ); -wgAjaxWatch.processResult = function(request) { - if(!wgAjaxWatch.supported) { - return; - } - var response = request.responseText; - if( response.match(/^<w#>/) ) { - wgAjaxWatch.watching = true; - wgAjaxWatch.setLinkText(wgAjaxWatch.unwatchMsg); - wgAjaxWatch.setLinkID("ca-unwatch"); - wgAjaxWatch.setHref( 'unwatch' ); - } else if( response.match(/^<u#>/) ) { - wgAjaxWatch.watching = false; - wgAjaxWatch.setLinkText(wgAjaxWatch.watchMsg); - wgAjaxWatch.setLinkID("ca-watch"); - wgAjaxWatch.setHref( 'watch' ); + // Bug 12395 - update the watch checkbox on edit pages when the + // page is watched or unwatched via the tab. + if( response.watched !== undefined ) { + $( '#wpWatchthis' ).attr( 'checked', '1' ); } else { - // Either we got a <err#> error code or it just plain broke. - window.location.href = wgAjaxWatch.watchLinks[0].href; - return; + $( '#wpWatchthis' ).removeAttr( 'checked' ); } - jsMsg( response.substr(4), 'watch' ); - wgAjaxWatch.inprogress = false; - if(wgAjaxWatch.timeoutID) { - window.clearTimeout(wgAjaxWatch.timeoutID); - } - // Bug 12395 - avoid some watch link confusion on edit - var watchthis = document.getElementById("wpWatchthis"); - if( watchthis && response.match(/^<[uw]#>/) ) { - watchthis.checked = response.match(/^<w#>/) ? "checked" : ""; - } - return; }; -wgAjaxWatch.onLoad = function() { - // This document structure hardcoding sucks. We should make a class and - // toss all this out the window. - - var el1 = document.getElementById("ca-unwatch"); - var el2 = null; - if ( !el1 ) { - el1 = document.getElementById("mw-unwatch-link1"); - el2 = document.getElementById("mw-unwatch-link2"); - } - if( el1 ) { - wgAjaxWatch.watching = true; - } else { - wgAjaxWatch.watching = false; - el1 = document.getElementById("ca-watch"); - if ( !el1 ) { - el1 = document.getElementById("mw-watch-link1"); - el2 = document.getElementById("mw-watch-link2"); - } - if( !el1 ) { - wgAjaxWatch.supported = false; - return; +$( document ).ready( function() { + var $links = $( '.mw-watchlink a, a.mw-watchlink' ); + // BC with older skins + $links = $links + .add( $( '#ca-watch a, #ca-unwatch a, a#mw-unwatch-link1' ) ) + .add( $( 'a#mw-unwatch-link2, a#mw-watch-link2, a#mw-watch-link1' ) ); + // allowing people to add inline animated links is a little scary + $links = $links.filter( ':not( #bodyContent *, #content * )' ); + + $links.each( function() { + var $link = $( this ); + $link + .data( 'icon', $link.parents( 'li' ).hasClass( 'icon' ) ) + .data( 'action', $link.attr( 'href' ).match( /[\?&]action=unwatch/i ) ? 'unwatch' : 'watch' ); + var title = $link.attr( 'href' ).match( /[\?&]title=(.*?)&/i )[1]; + $link.data( 'target', decodeURIComponent( title ).replace( /_/g, ' ' ) ); + }); + + $links.click( function( event ) { + var $link = $( this ); + + if( wgAjaxWatch.supported === false || !wgEnableWriteAPI || !wfSupportsAjax() ) { + // Lazy initialization so we don't toss up + // ActiveX warnings on initial page load + // for IE 6 users with security settings. + wgAjaxWatch.$links.unbind( 'click' ); + return true; } - } - - // Detect if the watch/unwatch feature is in icon mode - if ( el1.className.match( /icon/i ) ) { - wgAjaxWatch.iconMode = true; - } - - // The id can be either for the parent (Monobook-based) or the element - // itself (non-Monobook) - wgAjaxWatch.watchLinks.push( el1.tagName.toLowerCase() == "a" - ? el1 : el1.firstChild ); - if( el2 ) { - wgAjaxWatch.watchLinks.push( el2 ); - } + wgAjaxWatch.setLinkText( $link, $link.data( 'action' ) + 'ing' ); + $.get( wgScriptPath + + '/api' + wgScriptExtension + '?action=watch&format=json&title=' + + encodeURIComponent( $link.data( 'target' ) ) + + ( $link.data( 'action' ) == 'unwatch' ? '&unwatch' : '' ), + {}, + wgAjaxWatch.processResult, + 'json' + ); - // I couldn't get for (watchLink in wgAjaxWatch.watchLinks) to work, if - // you can be my guest. - for( i = 0; i < wgAjaxWatch.watchLinks.length; i++ ) { - wgAjaxWatch.watchLinks[i].onclick = wgAjaxWatch.ajaxCall; - } - return; -}; + return false; + }); + + // When a request returns, a custom event 'mw-ajaxwatch' is triggered + // on *all* watch links, so they can be updated if necessary + $links.bind( 'mw-ajaxwatch', function( event, target, action ) { + var $link = $( this ); + var foo = $link.data( 'target' ); + if( $link.data( 'target' ) == target ) { + var otheraction = action == 'watch' + ? 'unwatch' + : 'watch'; + + $link.data( 'action', otheraction ); + wgAjaxWatch.setLinkText( $link, otheraction ); + $link.attr( 'href', $link.attr( 'href' ).replace( '/&action=' + action + '/', '&action=' + otheraction ) ); + if( $link.parents( 'li' ).attr( 'id' ) == 'ca-' + action ) { + $link.parents( 'li' ).attr( 'id', 'ca-' + otheraction ); + // update the link text with the new message + $link.text( mediaWiki.msg( otheraction ) ); + } + }; + return false; + }); -hookEvent("load", wgAjaxWatch.onLoad); + wgAjaxWatch.$links = $links; +}); |