From: Aryeh Gregor Date: Fri, 22 Jun 2007 17:36:59 +0000 (+0000) Subject: Fix up AJAX watch and enable it by default. X-Git-Tag: 1.31.0-rc.0~52450 X-Git-Url: https://git.cyclocoop.org/%7B%24www_url%7Dadmin/compta/banques/ajouter.php?a=commitdiff_plain;h=faa7a6a8c80577947e8e2392ec401b0d63b9b909;p=lhc%2Fweb%2Fwiklou.git Fix up AJAX watch and enable it by default. * Allow it to work for nonexistent articles (pass title instead of ID) * Use event handlers, not javascript: URLs * Fix bug preventing akeytt from setting tooltips for a single element * Add jsMsg() function to wikibits to allow messages to be displayed dynamically at the top of the screen (could use dismiss button?) Some test-cases I've thrown at it worked fine (nonexistent pages, namespaced pages, pages with funny characters), but I haven't spent seven weeks in a cave meditating on what could possibly go wrong, so there may be some kind of omission somewhere. --- diff --git a/RELEASE-NOTES b/RELEASE-NOTES index a706f50f0b..aa78201289 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -97,6 +97,8 @@ it from source control: http://www.mediawiki.org/wiki/Download_from_SVN to cause hard-to-track-down interactions between extensions. * Use $wgJobClasses to determine the correct Job to instantiate for a particular queued task; allows extensions to introduce custom jobs +* (bug 10326) AJAX-based page watching and unwatching has been cleaned up and + enabled by default. == Bugfixes since 1.10 == diff --git a/includes/AjaxFunctions.php b/includes/AjaxFunctions.php index 86f853dbd7..7baac89d11 100644 --- a/includes/AjaxFunctions.php +++ b/includes/AjaxFunctions.php @@ -136,22 +136,29 @@ function wfSajaxSearch( $term ) { /** * Called for AJAX watch/unwatch requests. - * @param $pageID Integer ID of the page to be watched/unwatched + * @param $pagename Prefixed title string for page to watch/unwatch * @param $watch String 'w' to watch, 'u' to unwatch - * @return String '' or '' on successful watch or unwatch, respectively, or '' on error (invalid XML in case we want to add HTML sometime) + * @return String '' or '' on successful watch or unwatch, + * respectively, followed by an HTML message to display in the alert box; or + * '' on error */ -function wfAjaxWatch($pageID = "", $watch = "") { - if(wfReadOnly()) - return ''; // redirect to action=(un)watch, which will display the database lock message +function wfAjaxWatch($pagename = "", $watch = "") { + if(wfReadOnly()) { + // redirect to action=(un)watch, which will display the database lock + // message + return ''; + } - if(('w' !== $watch && 'u' !== $watch) || !is_numeric($pageID)) + if('w' !== $watch && 'u' !== $watch) { return ''; + } $watch = 'w' === $watch; - $pageID = intval($pageID); - $title = Title::newFromID($pageID); - if(!$title) + $title = Title::newFromText($pagename); + if(!$title) { + // Invalid title return ''; + } $article = new Article($title); $watching = $title->userIsWatching(); @@ -170,7 +177,10 @@ function wfAjaxWatch($pageID = "", $watch = "") { $dbw->commit(); } } - - return $watch ? '' : ''; + if( $watch ) { + return ''.wfMsgExt( 'addedwatchtext', array( 'parse' ), $title->getPrefixedText() ); + } else { + return ''.wfMsgExt( 'removedwatchtext', array( 'parse' ), $title->getPrefixedText() ); + } } ?> diff --git a/includes/DefaultSettings.php b/includes/DefaultSettings.php index a1cdd2a5b4..0c2513e342 100644 --- a/includes/DefaultSettings.php +++ b/includes/DefaultSettings.php @@ -2514,7 +2514,7 @@ $wgUpdateRowsPerQuery = 10; /** * Enable AJAX framework */ -$wgUseAjax = false; +$wgUseAjax = true; /** * Enable auto suggestion for the search bar @@ -2534,7 +2534,7 @@ $wgAjaxExportList = array( ); * Requires $wgUseAjax to be true too. * Causes wfAjaxWatch to be added to $wgAjaxExportList */ -$wgAjaxWatch = false; +$wgAjaxWatch = true; /** * Allow DISPLAYTITLE to change title display diff --git a/skins/common/ajaxwatch.js b/skins/common/ajaxwatch.js index 16e4fdc455..2187004943 100644 --- a/skins/common/ajaxwatch.js +++ b/skins/common/ajaxwatch.js @@ -2,17 +2,17 @@ // * ajax.js: /*extern sajax_init_object, sajax_do_call */ // * wikibits.js: - /*extern changeText, akeytt, hookEvent */ + /*extern changeText, akeytt, hookEvent, alertMsg */ // These should have been initialized in the generated js -/*extern wgAjaxWatch, wgArticleId */ +/*extern wgAjaxWatch, wgPageName */ if(typeof wgAjaxWatch === "undefined" || !wgAjaxWatch) { var wgAjaxWatch = { watchMsg: "Watch", unwatchMsg: "Unwatch", watchingMsg: "Watching...", - unwatchingMsg: "Unwatching..." + unwatchingMsg: "Unwatching...", }; } @@ -20,32 +20,52 @@ 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.watchLink1 = null; // "watch"/"unwatch" link -wgAjaxWatch.watchLink2 = null; // second one, for (some?) non-Monobook-based -wgAjaxWatch.oldHref = null; // url for action=watch/action=unwatch +wgAjaxWatch.watchLinks = []; // "watch"/"unwatch" links wgAjaxWatch.setLinkText = function(newText) { - changeText(wgAjaxWatch.watchLink1, newText); - if (wgAjaxWatch.watchLink2) { - changeText(wgAjaxWatch.watchLink2, newText); + for (i = 0; i < wgAjaxWatch.watchLinks.length; i++) { + changeText(wgAjaxWatch.watchLinks[i], newText); } }; wgAjaxWatch.setLinkID = function(newId) { - wgAjaxWatch.watchLink1.id = newId; + // We can only set the first one + wgAjaxWatch.watchLinks[0].setAttribute( 'id', newId ); akeytt(newId); // update tooltips for Monobook }; +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 || wgAjaxWatch.inprogress) { - return; + if(!wgAjaxWatch.supported) { + return true; + } else if (wgAjaxWatch.inprogress) { + return false; } wgAjaxWatch.inprogress = true; - wgAjaxWatch.setLinkText(wgAjaxWatch.watching ? wgAjaxWatch.unwatchingMsg : wgAjaxWatch.watchingMsg); - sajax_do_call("wfAjaxWatch", [wgArticleId, (wgAjaxWatch.watching ? "u" : "w")], wgAjaxWatch.processResult); + 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; + wgAjaxWatch.timeoutID = window.setTimeout( + function() { wgAjaxWatch.inprogress = false; }, + 10000 + ); + return false; }; wgAjaxWatch.processResult = function(request) { @@ -53,20 +73,21 @@ wgAjaxWatch.processResult = function(request) { return; } var response = request.responseText; - if(response == "") { - window.location.href = wgAjaxWatch.oldHref; + if( response.match(/^/) ) { + window.location.href = wgAjaxWatch.watchLink1.href; return; - } else if(response == "") { + } else if( response.match(/^/) ) { wgAjaxWatch.watching = true; wgAjaxWatch.setLinkText(wgAjaxWatch.unwatchMsg); wgAjaxWatch.setLinkID("ca-unwatch"); - wgAjaxWatch.oldHref = wgAjaxWatch.oldHref.replace(/action=watch/, "action=unwatch"); - } else if(response == "") { + wgAjaxWatch.setHref( 'unwatch' ); + } else if( response.match(/^/) ) { wgAjaxWatch.watching = false; wgAjaxWatch.setLinkText(wgAjaxWatch.watchMsg); wgAjaxWatch.setLinkID("ca-watch"); - wgAjaxWatch.oldHref = wgAjaxWatch.oldHref.replace(/action=unwatch/, "action=watch"); + wgAjaxWatch.setHref( 'watch' ); } + jsMsg( response.substr(4), 'watch' ); wgAjaxWatch.inprogress = false; if(wgAjaxWatch.timeoutID) { window.clearTimeout(wgAjaxWatch.timeoutID); @@ -75,6 +96,8 @@ wgAjaxWatch.processResult = function(request) { }; 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) { @@ -103,13 +126,17 @@ wgAjaxWatch.onLoad = function() { // The id can be either for the parent (Monobook-based) or the element // itself (non-Monobook) - wgAjaxWatch.watchLink1 = el1.tagName.toLowerCase() == "a" ? el1 : el1.firstChild; - wgAjaxWatch.watchLink2 = el2 ? el2 : null; + wgAjaxWatch.watchLinks.push( el1.tagName.toLowerCase() == "a" + ? el1 : el1.firstChild ); - wgAjaxWatch.oldHref = wgAjaxWatch.watchLink1.getAttribute("href"); - wgAjaxWatch.watchLink1.setAttribute("href", "javascript:wgAjaxWatch.ajaxCall()"); - if (wgAjaxWatch.watchLink2) { - wgAjaxWatch.watchLink2.setAttribute("href", "javascript:wgAjaxWatch.ajaxCall()"); + if( el2 ) { + wgAjaxWatch.watchLinks.push( el2 ); + } + + // 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; }; @@ -124,4 +151,4 @@ function wfSupportsAjax() { var supportsAjax = request ? true : false; delete request; return supportsAjax; -} \ No newline at end of file +} diff --git a/skins/common/shared.css b/skins/common/shared.css index f11893e78c..8c10c541dd 100644 --- a/skins/common/shared.css +++ b/skins/common/shared.css @@ -6,4 +6,5 @@ .mw-plusminus-null { color: #aaa; } .texvc { direction: ltr; unicode-bidi: embed; } /* Stop floats from intruding into edit area in previews */ -#toolbar, #wpTextbox1 { clear: both; } \ No newline at end of file +#toolbar, #wpTextbox1 { clear: both; } +div#mw-js-message { margin: 2em 5%; } diff --git a/skins/common/wikibits.js b/skins/common/wikibits.js index a139e7e444..a0603647a3 100644 --- a/skins/common/wikibits.js +++ b/skins/common/wikibits.js @@ -604,8 +604,7 @@ function akeytt( doId ) { // the original. var ta; if ( doId ) { - ta = new Array; - ta[doId] = window.ta[doId]; + ta = [doId]; } else { ta = window.ta; } @@ -1214,6 +1213,53 @@ function ts_alternate(table) { * End of table sorting code */ + +/** + * Add a cute little box at the top of the screen to inform the user of + * something, replacing any preexisting message. + * + * @param String message HTML to be put inside the right div + * @param String class Used in adding a class; should be different for each + * call to allow CSS/JS to hide different boxes. null = no class used. + * @return Boolean True on success, false on failure + */ +function jsMsg( message, class ) { + if ( !document.getElementById ) { + return false; + } + // We special-case skin structures provided by the software. Skins that + // choose to abandon or significantly modify our formatting can just define + // an mw-js-message div to start with. + var messageDiv = document.getElementById( 'mw-js-message' ); + if ( !messageDiv ) { + messageDiv = document.createElement( 'div' ); + if ( document.getElementById( 'column-content' ) + && document.getElementById( 'content' ) ) { + // MonoBook, presumably + document.getElementById( 'content' ).insertBefore( + messageDiv, + document.getElementById( 'content' ).firstChild + ); + } else if ( document.getElementById('content') + && document.getElementById( 'article' ) ) { + // Non-Monobook but still recognizable (old-style) + document.getElementById( 'article').insertBefore( + messageDiv, + document.getElementById( 'article' ).firstChild + ); + } else { + return false; + } + } + + messageDiv.setAttribute( 'id', 'mw-js-message' ); + if( class ) { + messageDiv.setAttribute( 'class', 'mw-js-message-'+class ); + } + messageDiv.innerHTML = message; + return true; +} + function runOnloadHook() { // don't run anything below this for non-dom browsers if (doneOnloadHook || !(document.getElementById && document.getElementsByTagName)) { @@ -1243,4 +1289,4 @@ function runOnloadHook() { // so the below should be redundant. It's there just in case. hookEvent("load", runOnloadHook); -hookEvent("load", mwSetupToolbar); \ No newline at end of file +hookEvent("load", mwSetupToolbar);