VoteNY: actually make this work under 1.18+, not just in ResourceLoader's debug mode.

Changelist:
*removed backwards-compatibility code
*used HTML5 data attributes to store various information that we access in the JS file
*incremented the extension's version number
*removed ancient vote key stuff (the "vote key" was being passed to the AJAX function but it wasn't used in any of the functions)
*updated Linker class, that class is now static
*killd $wgTitle

Some things are now a bit slower, i.e. if you click on the green voting box, then click again when the unvote link appears, it doesn't seem to change back to "vote" again...but at least it should work now.
This commit is contained in:
Jack Phoenix 2012-01-04 19:51:44 +00:00
parent 506e3ff4cc
commit a3c82a518b
6 changed files with 111 additions and 98 deletions

View file

@ -9,7 +9,7 @@
*
* @file
* @ingroup Extensions
* @date 21 August 2011
* @date 11 December 2011
* @license To the extent that it is possible, this code is in the public domain
*/
class SpecialTopRatings extends IncludableSpecialPage {
@ -27,7 +27,7 @@ class SpecialTopRatings extends IncludableSpecialPage {
* @param $par Mixed: parameter passed to the special page or null
*/
public function execute( $par ) {
global $wgOut, $wgScriptPath, $wgUser;
global $wgOut, $wgScriptPath;
// Set the page title, robot policies, etc.
$this->setHeaders();
@ -49,13 +49,12 @@ class SpecialTopRatings extends IncludableSpecialPage {
$limit = 50;
}
// Add JS -- needed so that users can vote on this page and so that
// their browsers' consoles won't be filled with JS errors ;-)
$wgOut->addScriptFile( $wgScriptPath . '/extensions/VoteNY/Vote.js' );
// Add JS (and CSS) -- needed so that users can vote on this page and
// so that their browsers' consoles won't be filled with JS errors ;-)
$wgOut->addModules( 'ext.voteNY' );
$ratings = array();
$output = '';
$sk = $wgUser->getSkin();
$dbr = wfGetDB( DB_SLAVE );
$tables = $where = $joinConds = array();
@ -124,7 +123,7 @@ class SpecialTopRatings extends IncludableSpecialPage {
$vote = new VoteStars( $pageId );
$output .= '<div class="user-list-rating">' .
$sk->link(
Linker::link(
$titleObj,
$titleObj->getPrefixedText() // prefixed, so that the namespace shows!
) . wfMsg( 'word-separator' ) . // i18n overkill? ya betcha...

100
Vote.js
View file

@ -4,11 +4,11 @@
* @file
* @ingroup Extensions
* @author Jack Phoenix <jack@countervandalism.net>
* @date 19 June 2011
* @date 4 January 2012
*/
var VoteNY = {
MaxRating: 5,
clearRatingTimer: '',
clearRatingTimer: null,
voted_new: [],
id: 0,
last_id: 0,
@ -16,57 +16,46 @@ var VoteNY = {
/**
* Called when voting through the green square voting box
*
* @param TheVote
* @param PageID Integer: internal ID number of the current article
* @param mk Mixed: random token
*/
clickVote: function( TheVote, PageID, mk ) {
clickVote: function( TheVote, PageID ) {
sajax_request_type = 'POST';
sajax_do_call( 'wfVoteClick', [ TheVote, PageID, mk ], function( request ) {
sajax_do_call( 'wfVoteClick', [ TheVote, PageID ], function( request ) {
document.getElementById( 'votebox' ).style.cursor = 'default';
document.getElementById( 'PollVotes' ).innerHTML = request.responseText;
var unvoteMessage;
if ( typeof( mediaWiki ) == 'undefined' ) {
unvoteMessage = _UNVOTE_LINK;
} else {
unvoteMessage = mediaWiki.msg( 'vote-unvote-link' );
}
document.getElementById( 'Answer' ).innerHTML =
"<a href=javascript:VoteNY.unVote(" + PageID + ",'" + mk +
"')>" + unvoteMessage + '</a>';
'<a href="javascript:void(0);" class="vote-unvote-link">' +
mediaWiki.msg( 'vote-unvote-link' ) + '</a>';
} );
},
/**
* Called when removing your vote through the green square voting box
*
* @param PageID Integer: internal ID number of the current article
* @param mk Mixed: random token
*/
unVote: function( PageID, mk ) {
unVote: function( PageID ) {
sajax_request_type = 'POST';
sajax_do_call( 'wfVoteDelete', [ PageID, mk ], function( request ) {
sajax_do_call( 'wfVoteDelete', [ PageID ], function( request ) {
document.getElementById( 'votebox' ).style.cursor = 'pointer';
document.getElementById( 'PollVotes' ).innerHTML = request.responseText;
var voteMessage;
if ( typeof( mediaWiki ) == 'undefined' ) {
voteMessage = _VOTE_LINK;
} else {
voteMessage = mediaWiki.msg( 'vote-link' );
}
document.getElementById( 'Answer' ).innerHTML =
'<a href=javascript:VoteNY.clickVote(1,' + PageID + ',"' + mk +
'")>' + voteMessage + '</a>';
'<a href="javascript:void(0);" class="vote-vote-link">' +
mediaWiki.msg( 'vote-link' ) + '</a>';
} );
},
/**
* Called when adding a vote after a user has clicked the yellow voting stars
*
* @param PageID Integer: internal ID number of the current article
* @param mk Mixed: random token
* @param id Integer: ID of the current rating star
* @param action Integer: controls which AJAX function will be called
*/
clickVoteStars: function( TheVote, PageID, mk, id, action ) {
clickVoteStars: function( TheVote, PageID, id, action ) {
VoteNY.voted_new[id] = TheVote;
var rsfun;
if( action == 3 ) {
@ -78,26 +67,25 @@ var VoteNY = {
var resultElement = document.getElementById( 'rating_' + id );
sajax_request_type = 'POST';
sajax_do_call( rsfun, [ TheVote, PageID, mk ], resultElement );
sajax_do_call( rsfun, [ TheVote, PageID ], resultElement );
},
/**
* Called when removing your vote through the yellow voting stars
*
* @param PageID Integer: internal ID number of the current article
* @param mk Mixed: random token
* @param id Integer: ID of the current rating star
*/
unVoteStars: function( PageID, mk, id ) {
unVoteStars: function( PageID, id ) {
var resultElement = document.getElementById( 'rating_' + id );
sajax_request_type = 'POST';
sajax_do_call( 'wfVoteStarsDelete', [ PageID, mk ], resultElement );
sajax_do_call( 'wfVoteStarsDelete', [ PageID ], resultElement );
},
startClearRating: function( id, rating, voted ) {
VoteNY.clearRatingTimer = setTimeout(
"VoteNY.clearRating('" + id + "',0," + rating + ',' + voted + ')',
200
);
VoteNY.clearRatingTimer = setTimeout( function() {
VoteNY.clearRating( id, 0, rating, voted );
}, 200 );
},
clearRating: function( id, num, prev_rating, voted ) {
@ -133,4 +121,48 @@ var VoteNY = {
}
VoteNY.last_id = id;
}
};
};
jQuery( document ).ready( function() {
// Green voting box
jQuery( '#votebox, a.vote-vote-link' ).click( function() {
VoteNY.clickVote( 1, mw.config.get( 'wgArticleId' ) );
} );
jQuery( 'a.vote-unvote-link' ).click( function() {
VoteNY.unVote( mw.config.get( 'wgArticleId' ) );
} );
// Rating stars
jQuery( 'img.vote-rating-star' ).click( function() {
var that = jQuery( this );
VoteNY.clickVoteStars(
that.data( 'vote-the-vote' ),
mw.config.get( 'wgArticleId' ),
that.data( 'vote-id' ),
that.data( 'vote-action' )
);
} ).mouseover( function() {
var that = jQuery( this );
VoteNY.updateRating(
that.data( 'vote-id' ),
that.data( 'vote-the-vote' ),
that.data( 'vote-rating' )
);
} ).mouseout( function() {
var that = jQuery( this );
VoteNY.startClearRating(
that.data( 'vote-id' ),
that.data( 'vote-rating' ),
that.data( 'vote-voted' )
);
} );
// Remove vote (rating stars)
jQuery( 'a.vote-remove-stars-link' ).click( function() {
VoteNY.unVoteStars(
mw.config.get( 'wgArticleId' ),
jQuery( this ).data( 'vote-id' )
);
} );
} );

View file

@ -4,7 +4,7 @@
*
* @file
* @ingroup Extensions
* @version 2.3.3
* @version 2.4
* @author Aaron Wright <aaron.wright@gmail.com>
* @author David Pean <david.pean@gmail.com>
* @author Jack Phoenix <jack@countervandalism.net>
@ -23,7 +23,7 @@ if ( !defined( 'MEDIAWIKI' ) ) {
// Extension credits that show up on Special:Version
$wgExtensionCredits['parserhook'][] = array(
'name' => 'Vote',
'version' => '2.3.3',
'version' => '2.4',
'author' => array( 'Aaron Wright', 'David Pean', 'Jack Phoenix' ),
'description' => 'JavaScript-based voting with the <tt>&lt;vote&gt;</tt> tag',
'url' => 'https://www.mediawiki.org/wiki/Extension:VoteNY'
@ -55,7 +55,6 @@ $wgSpecialPages['TopRatings'] = 'SpecialTopRatings';
$wgAutoloadClasses['VoteHooks'] = $dir . 'VoteHooks.php';
$wgHooks['ParserFirstCallInit'][] = 'VoteHooks::registerParserHook';
$wgHooks['MakeGlobalVariablesScript'][] = 'VoteHooks::addJSGlobalVariables';
$wgHooks['RenameUserSQL'][] = 'VoteHooks::onUserRename';
// Translations for {{NUMBEROFVOTES}}
//$wgExtensionMessagesFiles['NumberOfVotes'] = $dir . 'Vote.i18n.magic.php';

View file

@ -13,6 +13,7 @@ class Vote {
/**
* Constructor
*
* @param $pageID Integer: article ID number
*/
public function __construct( $pageID ) {
@ -26,10 +27,12 @@ class Vote {
/**
* Counts all votes, fetching the data from memcached if available
* or from the database if memcached isn't available
*
* @return Integer: amount of votes
*/
function count() {
global $wgMemc;
$key = wfMemcKey( 'vote', 'count', $this->PageID );
$data = $wgMemc->get( $key );
@ -52,6 +55,7 @@ class Vote {
}
$wgMemc->set( $key, $vote_count );
}
return $vote_count;
}
@ -82,6 +86,7 @@ class Vote {
}
$wgMemc->set( $key, $voteAvg );
}
return number_format( $voteAvg, 2 );
}
@ -96,21 +101,22 @@ class Vote {
$wgMemc->delete( wfMemcKey( 'vote', 'avg', $this->PageID ) );
// Purge squid
$page_title = Title::newFromID( $this->PageID );
if( is_object( $page_title ) ) {
$page_title->invalidateCache();
$page_title->purgeSquid();
$pageTitle = Title::newFromID( $this->PageID );
if( is_object( $pageTitle ) ) {
$pageTitle->invalidateCache();
$pageTitle->purgeSquid();
// Kill parser cache
$article = new Article( $page_title );
$article = new Article( $pageTitle );
$parserCache = ParserCache::singleton();
$parser_key = $parserCache->getKey( $article, $wgUser );
$wgMemc->delete( $parser_key );
$parserKey = $parserCache->getKey( $article, $wgUser );
$wgMemc->delete( $parserKey );
}
}
/**
* Delete the user's vote from the DB if s/he wants to remove his/her vote
* Delete the user's vote from the database, purges normal caches and
* updates SocialProfile's statistics, if SocialProfile is active.
*/
function delete() {
$dbw = wfGetDB( DB_MASTER );
@ -169,8 +175,9 @@ class Vote {
/**
* Checks if a user has already voted
* @return Boolean: false if s/he hasn't, otherwise returns the value of
* 'vote_value' column from Vote DB table
*
* @return Boolean|Integer: false if s/he hasn't, otherwise returns the
* value of 'vote_value' column from Vote DB table
*/
function UserAlreadyVoted() {
$dbr = wfGetDB( DB_SLAVE );
@ -197,7 +204,6 @@ class Vote {
function display() {
global $wgUser;
$this->votekey = md5( $this->PageID . 'pants' . $this->Username );
$voted = $this->UserAlreadyVoted();
$make_vote_box_clickable = '';
@ -205,7 +211,7 @@ class Vote {
$make_vote_box_clickable = ' vote-clickable';
}
$output = "<div class=\"vote-box{$make_vote_box_clickable}\" id=\"votebox\" onclick=\"VoteNY.clickVote(1,{$this->PageID},'{$this->votekey}')\">";
$output = "<div class=\"vote-box{$make_vote_box_clickable}\" id=\"votebox\">";
$output .= '<span id="PollVotes" class="vote-number">' . $this->count() . '</span>';
$output .= '</div>';
$output .= '<div id="Answer" class="vote-action">';
@ -221,10 +227,10 @@ class Vote {
} else {
if( !wfReadOnly() ) {
if( $voted == false ) {
$output .= "<a href=\"javascript:VoteNY.clickVote(1,{$this->PageID},'{$this->votekey}')\">" .
$output .= '<a href="javascript:void(0);" class="vote-vote-link">' .
wfMsg( 'vote-link' ) . '</a>';
} else {
$output .= "<a href=\"javascript:VoteNY.unVote('{$this->PageID}', '{$this->votekey}')\">" .
$output .= '<a href="javascript:void(0);" class="vote-unvote-link">' .
wfMsg( 'vote-unvote-link' ) . '</a>';
}
}
@ -244,7 +250,8 @@ class VoteStars extends Vote {
/**
* Displays voting stars
* @param $voted Boolean: false by default
*
* @param $voted Boolean: has the user already voted? False by default
* @return Mixed: HTML output
*/
function display( $voted = false ) {
@ -258,7 +265,6 @@ class VoteStars extends Vote {
$display_stars_rating = $this->getAverageVote();
}
$this->votekey = md5( $this->PageID . 'pants' . $this->Username );
$id = '';
// Should probably be $this->PageID or something?
@ -279,7 +285,7 @@ class VoteStars extends Vote {
$output .= '<div class="rating-voted">' .
wfMsgExt( 'vote-gave-this', 'parsemag', $already_voted ) .
" </div>
<a href=\"javascript:VoteNY.unVoteStars({$this->PageID},'{$this->votekey}','{$id}')\">("
<a href=\"javascript:void(0);\" class=\"vote-remove-stars-link\" data-vote-id=\"{$id}\">("
. wfMsg( 'vote-remove' ) .
')</a>';
}
@ -304,7 +310,6 @@ class VoteStars extends Vote {
if( !$rating ) {
$rating = 0;
}
$this->votekey = md5( $this->PageID . 'pants' . $this->Username );
if( !$voted ) {
$voted = 0;
}
@ -316,10 +321,10 @@ class VoteStars extends Vote {
} else {
$action = 5;
}
$onclick = "VoteNY.clickVoteStars({$x},{$this->PageID},'{$this->votekey}','{$id}',$action);";
$onmouseover = "VoteNY.updateRating('{$id}',{$x},{$rating});";
$onmouseout = "VoteNY.startClearRating('{$id}','{$rating}',{$voted});";
$output .= "<img onclick=\"javascript:{$onclick}\" onmouseover=\"javascript:{$onmouseover}\" onmouseout=\"javascript:{$onmouseout}\" id=\"rating_{$id}_{$x}\" src=\"{$wgScriptPath}/extensions/VoteNY/images/star_";
$output .= "<img class=\"vote-rating-star\" data-vote-the-vote=\"{$x}\"" .
" data-vote-id=\"{$id}\" data-vote-action=\"{$action}\" data-vote-rating=\"{$rating}\"" .
" data-vote-voted=\"{$voted}\" id=\"rating_{$id}_{$x}\"" .
" src=\"{$wgScriptPath}/extensions/VoteNY/images/star_";
switch( true ) {
case $rating >= $x:
if( $voted ) {

View file

@ -27,7 +27,7 @@ class VoteHooks {
* @return String: HTML
*/
public static function renderVote( $input, $args, $parser ) {
global $wgOut, $wgTitle, $wgScriptPath;
global $wgOut;
wfProfileIn( __METHOD__ );
@ -39,12 +39,7 @@ class VoteHooks {
// Add CSS & JS
// In order for us to do this *here* instead of having to do this in
// registerParserHook(), we must've disabled parser cache
if ( defined( 'MW_SUPPORTS_RESOURCE_MODULES' ) ) {
$wgOut->addModules( 'ext.voteNY' );
} else {
$wgOut->addScriptFile( $wgScriptPath . '/extensions/VoteNY/Vote.js' );
$wgOut->addExtensionStyle( $wgScriptPath . '/extensions/VoteNY/Vote.css' );
}
$wgOut->addModules( 'ext.voteNY' );
// Define variable - 0 means that we'll get that green voting box by default
$type = 0;
@ -56,7 +51,7 @@ class VoteHooks {
$type = intval( $args['type'] );
}
$articleID = $wgTitle->getArticleID();
$articleID = $wgOut->getTitle()->getArticleID();
switch( $type ) {
case 0:
$vote = new Vote( $articleID );
@ -75,18 +70,6 @@ class VoteHooks {
return $output;
}
/**
* Adds required JS variables to the HTML output.
*
* @param $vars Array: array of pre-existing JS globals
* @return Boolean: true
*/
public static function addJSGlobalVariables( $vars ) {
$vars['_VOTE_LINK'] = wfMsg( 'vote-link' );
$vars['_UNVOTE_LINK'] = wfMsg( 'vote-unvote-link' );
return true;
}
/**
* For the Renameuser extension.
*
@ -172,18 +155,13 @@ class VoteHooks {
* Creates the necessary database table when the user runs
* maintenance/update.php.
*
* @param $updater Object: instance of DatabaseUpdater
* @param $updater DatabaseUpdater
* @return Boolean: true
*/
public static function addTable( $updater = null ) {
public static function addTable( $updater ) {
$dir = dirname( __FILE__ );
$file = "$dir/vote.sql";
if ( $updater === null ) {
global $wgExtNewTables;
$wgExtNewTables[] = array( 'Vote', $file );
} else {
$updater->addExtensionUpdate( array( 'addTable', 'Vote', $file, true ) );
}
$updater->addExtensionUpdate( array( 'addTable', 'Vote', $file, true ) );
return true;
}
}

View file

@ -4,7 +4,7 @@
*/
$wgAjaxExportList[] = 'wfVoteClick';
function wfVoteClick( $voteValue, $pageId, $mk ) {
function wfVoteClick( $voteValue, $pageId ) {
global $wgUser;
if ( !$wgUser->isAllowed( 'vote' ) ) {
@ -22,7 +22,7 @@ function wfVoteClick( $voteValue, $pageId, $mk ) {
}
$wgAjaxExportList[] = 'wfVoteDelete';
function wfVoteDelete( $pageId, $mk ) {
function wfVoteDelete( $pageId ) {
global $wgUser;
if ( !$wgUser->isAllowed( 'vote' ) ) {
@ -40,7 +40,7 @@ function wfVoteDelete( $pageId, $mk ) {
}
$wgAjaxExportList[] = 'wfVoteStars';
function wfVoteStars( $voteValue, $pageId, $mk ) {
function wfVoteStars( $voteValue, $pageId ) {
global $wgUser;
if ( !$wgUser->isAllowed( 'vote' ) ) {
@ -57,7 +57,7 @@ function wfVoteStars( $voteValue, $pageId, $mk ) {
}
$wgAjaxExportList[] = 'wfVoteStarsMulti';
function wfVoteStarsMulti( $voteValue, $pageId, $mk ) {
function wfVoteStarsMulti( $voteValue, $pageId ) {
global $wgUser;
if ( !$wgUser->isAllowed( 'vote' ) ) {