Index: trunk/extensions/ArticleAssessmentPilot/ArticleAssessmentPilot.php |
— | — | @@ -11,6 +11,9 @@ |
12 | 12 | // Extension is "disabled" if this field is an empty string (as per default configuration) |
13 | 13 | $wgArticleAssessmentCategory = ''; |
14 | 14 | |
| 15 | +// Set to 'combined' or 'raw' if you need to debug this extension's JS |
| 16 | +$wgArticleAssessmentResourceMode = 'minified'; |
| 17 | + |
15 | 18 | // Path to jQuery UI |
16 | 19 | $wgArticleAssessmentJUIPath = null; // Defaults to "$wgExtensionAssetsPath/ArticleAssessmentPilot/js/jui.combined.min.js" |
17 | 20 | |
Index: trunk/extensions/ArticleAssessmentPilot/ArticleAssessmentPilot.hooks.php |
— | — | @@ -8,14 +8,30 @@ |
9 | 9 | */ |
10 | 10 | class ArticleAssessmentPilotHooks { |
11 | 11 | private static $styleFiles = array( |
12 | | - array( 'src' => 'css/ArticleAssessment.css', 'version' => 1 ), |
| 12 | + 'raw' => array( |
| 13 | + array( 'src' => 'css/ArticleAssessment.css', 'version' => 1 ), |
| 14 | + ), |
| 15 | + 'combined' => array( |
| 16 | + array( 'src' => 'css/ArticleAssessment.css', 'version' => 1 ), |
| 17 | + ), |
| 18 | + 'minified' => array( |
| 19 | + array( 'src' => 'css/ArticleAssessment.css', 'version' => 1 ), |
| 20 | + ), |
13 | 21 | ); |
14 | 22 | |
15 | 23 | private static $scriptFiles = array( |
16 | | - array( 'src' => 'js/ArticleAssessment.js', 'version' => 2 ), |
17 | | - array( 'src' => 'js/jquery.cookie.js', 'version' => 1 ), |
18 | | - array( 'src' => 'js/jquery.tipsy.js', 'version' => 1 ), |
19 | | - array( 'src' => 'js/jquery.stars.js', 'version' => 1 ), |
| 24 | + 'raw' => array( |
| 25 | + array( 'src' => 'js/ArticleAssessment.js', 'version' => 2 ), |
| 26 | + array( 'src' => 'js/jquery.cookie.js', 'version' => 1 ), |
| 27 | + array( 'src' => 'js/jquery.tipsy.js', 'version' => 1 ), |
| 28 | + array( 'src' => 'js/jquery.stars.js', 'version' => 1 ), |
| 29 | + ), |
| 30 | + 'combined' => array( |
| 31 | + array( 'src' => 'js/ArticleAssessment.combined.js', 'version' => 1 ) |
| 32 | + ), |
| 33 | + 'minified' => array( |
| 34 | + array( 'src' => 'js/ArticleAssessment.combined.min.js', 'version' => 1 ) |
| 35 | + ), |
20 | 36 | ); |
21 | 37 | |
22 | 38 | private static $messages = array(); |
— | — | @@ -78,9 +94,9 @@ |
79 | 95 | return true; |
80 | 96 | } |
81 | 97 | |
82 | | - global $wgExtensionAssetsPath; |
83 | | - |
84 | | - foreach ( self::$scriptFiles as $script ) { |
| 98 | + global $wgExtensionAssetsPath, $wgArticleAssessmentResourceMode; |
| 99 | + $mode = isset( self::$scriptFiles[$wgArticleAssessmentResourceMode] ) ? $wgArticleAssessmentResourceMode : 'minified'; |
| 100 | + foreach ( self::$scriptFiles[$mode] as $script ) { |
85 | 101 | $out->addScriptFile( $wgExtensionAssetsPath . |
86 | 102 | "/ArticleAssessmentPilot/{$script['src']}", $script['version'] |
87 | 103 | ); |
— | — | @@ -88,9 +104,9 @@ |
89 | 105 | |
90 | 106 | global $wgArticleAssessmentNeedJUICSS; |
91 | 107 | if ( $wgArticleAssessmentNeedJUICSS ) { |
92 | | - self::$styleFiles[] = array( 'src' => 'css/jquery-ui-1.7.2.css', 'version' => '1.7.2y' ); |
| 108 | + self::$styleFiles[$mode][] = array( 'src' => 'css/jquery-ui-1.7.2.css', 'version' => '1.7.2y' ); |
93 | 109 | } |
94 | | - foreach ( self::$styleFiles as $style ) { |
| 110 | + foreach ( self::$styleFiles[$mode] as $style ) { |
95 | 111 | $out->addExtensionStyle( $wgExtensionAssetsPath . |
96 | 112 | "/ArticleAssessmentPilot/{$style['src']}?{$style['version']}" |
97 | 113 | ); |
Index: trunk/extensions/ArticleAssessmentPilot/js/ArticleAssessment.combined.js |
— | — | @@ -0,0 +1,1125 @@ |
| 2 | +( function( $ ) { |
| 3 | + $.ArticleAssessment = { |
| 4 | + 'config': { |
| 5 | + 'authtoken': '', |
| 6 | + 'userID': '', |
| 7 | + 'pageID': wgArticleId, |
| 8 | + 'revID': wgCurRevisionId |
| 9 | + }, |
| 10 | + 'messages': {}, |
| 11 | + 'settings': { |
| 12 | + 'endpoint': wgScriptPath + '/api.php?', |
| 13 | + 'fieldMessages' : [ |
| 14 | + 'wellsourced', |
| 15 | + 'neutrality', |
| 16 | + 'completeness', |
| 17 | + 'readability' |
| 18 | + ], |
| 19 | + 'fieldHintSuffix': '-tooltip', |
| 20 | + 'fieldPrefix': 'articleassessment-rating-', |
| 21 | + 'fieldHTML': '<div class="field-wrapper"> \ |
| 22 | + <label class="rating-field-label"></label> \ |
| 23 | + <select class="rating-field"> \ |
| 24 | + <option value="1">1</option> \ |
| 25 | + <option value="2">2</option> \ |
| 26 | + <option value="3">3</option> \ |
| 27 | + <option value="4">4</option> \ |
| 28 | + <option value="5">5</option> \ |
| 29 | + </select> \ |
| 30 | + </div>', |
| 31 | + 'structureHTML': '<div class="article-assessment-wrapper"> \ |
| 32 | + <form action="rate" method="post" id="article-assessment"> \ |
| 33 | + <fieldset id="article-assessment-rate"> \ |
| 34 | + <legend></legend> \ |
| 35 | + <div class="article-assessment-information"> \ |
| 36 | + <span class="article-assessment-rate-instructions"></span> \ |
| 37 | + <span class="article-assessment-rate-feedback"></span> \ |
| 38 | + </div> \ |
| 39 | + <div class="article-assessment-rating-fields"></div> \ |
| 40 | + <div class="article-assessment-submit"> \ |
| 41 | + <input type="submit" value="Submit" /> \ |
| 42 | + </div> \ |
| 43 | + </fieldset> \ |
| 44 | + <fieldset id="article-assessment-ratings"> \ |
| 45 | + <legend></legend> \ |
| 46 | + <div class="article-assessment-information"> \ |
| 47 | + <span class="article-assessment-show-ratings"></span> \ |
| 48 | + <span class="article-assessment-hide-ratings"></span> \ |
| 49 | + </div> \ |
| 50 | + </fieldset> \ |
| 51 | + </form> \ |
| 52 | + </div>', |
| 53 | + 'ratingHTML': '<div class="article-assessment-rating"> \ |
| 54 | + <span class="article-assessment-rating-field-name"></span> \ |
| 55 | + <span class="article-assessment-rating-field-value-wrapper"> \ |
| 56 | + <span class="article-assessment-rating-field-value">0%</span> \ |
| 57 | + </span> \ |
| 58 | + <span class="article-assessment-rating-count"></span> \ |
| 59 | + </div>' |
| 60 | + }, |
| 61 | + |
| 62 | + 'fn' : { |
| 63 | + 'init': function( $$options ) { |
| 64 | + // merge options with the config |
| 65 | + var settings = $.extend( {}, $.ArticleAssessment.settings, $$options ); |
| 66 | + var config = $.ArticleAssessment.config; |
| 67 | + // if this is an anon user, get a unique identifier for them |
| 68 | + // load up the stored ratings and update the markup if the cookie exists |
| 69 | + var userToken = $.cookie( 'mwArticleAssessmentUserToken' ); |
| 70 | + if ( typeof userToken == 'undefined' || userToken == null ) { |
| 71 | + function randomString( string_length ) { |
| 72 | + var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz"; |
| 73 | + var randomstring = ''; |
| 74 | + for ( var i = 0; i < string_length; i++ ) { |
| 75 | + var rnum = Math.floor( Math.random() * chars.length ); |
| 76 | + randomstring += chars.substring( rnum, rnum + 1 ); |
| 77 | + } |
| 78 | + return randomstring; |
| 79 | + } |
| 80 | + userToken = randomString( 32 ); |
| 81 | + $.cookie( 'mwArticleAssessmentUserToken', userToken, { 'expires': 30, 'path': '/' } ); |
| 82 | + } |
| 83 | + if ( !wgUserName ) { |
| 84 | + config.userID = userToken; |
| 85 | + } |
| 86 | + // setup our markup using the template variables in settings |
| 87 | + var $structure = $( settings.structureHTML ), |
| 88 | + instructions = $.ArticleAssessment.fn.getMsg( 'articleassessment-pleaserate' ), |
| 89 | + feedback = $.ArticleAssessment.fn.getMsg( 'articleassessment-featurefeedback' ), |
| 90 | + yourfeedback = $.ArticleAssessment.fn.getMsg( 'articleassessment-yourfeedback'), |
| 91 | + articlerating = $.ArticleAssessment.fn.getMsg( 'articleassessment-articlerating' ), |
| 92 | + resultshide = $.ArticleAssessment.fn.getMsg( 'articleassessment-results-hide' ), |
| 93 | + resultsshow = $.ArticleAssessment.fn.getMsg( 'articleassessment-results-show' ); |
| 94 | + submitbutton = $.ArticleAssessment.fn.getMsg( 'articleassessment-submit' ); |
| 95 | + $structure |
| 96 | + .find( '#article-assessment-rate legend' ) |
| 97 | + .text( yourfeedback ) |
| 98 | + .end() |
| 99 | + .find( '.article-assessment-rate-instructions' ) |
| 100 | + .text( instructions ) |
| 101 | + .end() |
| 102 | + .find( '.article-assessment-rate-feedback' ) |
| 103 | + .html( feedback ) |
| 104 | + .find( '.feedbacklink' ) |
| 105 | + .wrap( '<a href="#"></a>' ) |
| 106 | + .parent() |
| 107 | + .click( $.ArticleAssessment.fn.showFeedback ) |
| 108 | + .end() |
| 109 | + .end() |
| 110 | + .end() |
| 111 | + .find( '#article-assessment-ratings legend' ) |
| 112 | + .text( articlerating ) |
| 113 | + .end() |
| 114 | + .find( '.article-assessment-show-ratings' ) |
| 115 | + .html( resultsshow ) |
| 116 | + .find( '.showlink' ) |
| 117 | + .wrap( '<a href="#"></a>' ) |
| 118 | + .parent() |
| 119 | + .click( $.ArticleAssessment.fn.showRatings ) |
| 120 | + .end() |
| 121 | + .end() |
| 122 | + .end() |
| 123 | + .find( '.article-assessment-hide-ratings' ) |
| 124 | + .html( resultshide ) |
| 125 | + .find ( '.hidelink' ) |
| 126 | + .wrap( '<a href="#"></a>' ) |
| 127 | + .parent() |
| 128 | + .click( $.ArticleAssessment.fn.hideRatings ) |
| 129 | + .end() |
| 130 | + .end() |
| 131 | + .end() |
| 132 | + .find( '.article-assessment-submit input' ) |
| 133 | + .attr( "value", submitbutton ) |
| 134 | + .end(); |
| 135 | + // hide the feedback link if we need to |
| 136 | + if( $.cookie( 'mwArticleAssessmentHideFeedback' ) ) { |
| 137 | + $structure |
| 138 | + .find( '.article-assessment-rate-feedback' ) |
| 139 | + .hide(); |
| 140 | + } |
| 141 | + for ( var i = 0; i < settings.fieldMessages.length; i++ ) { |
| 142 | + var $field = $( settings.fieldHTML ), |
| 143 | + $rating = $( settings.ratingHTML ), |
| 144 | + label = $.ArticleAssessment.fn.getMsg( settings.fieldPrefix + settings.fieldMessages[i] ), |
| 145 | + field = settings.fieldMessages[i], |
| 146 | + hint = $.ArticleAssessment.fn.getMsg( settings.fieldPrefix + settings.fieldMessages[i] + settings.fieldHintSuffix ), |
| 147 | + count = $.ArticleAssessment.fn.getMsg( 'articleassessment-noratings', [0, 0] ); |
| 148 | + // initialize the field html |
| 149 | + $field |
| 150 | + .attr( 'id', 'articleassessment-rate-' + field ) |
| 151 | + .find( 'label' ) |
| 152 | + .attr( 'for', 'rating_' + field ) |
| 153 | + .attr( 'original-title', hint ) |
| 154 | + .text( label ) |
| 155 | + .end() |
| 156 | + .find( 'select' ) |
| 157 | + .attr( 'id', 'rating_' + field ) |
| 158 | + .attr( 'name', 'rating[' + field + ']' ); |
| 159 | + // initialize the rating html |
| 160 | + $rating |
| 161 | + .attr( 'id', 'articleassessment-rating-' + field ) |
| 162 | + .find( '.article-assessment-rating-field-name' ) |
| 163 | + .text( label ) |
| 164 | + .end() |
| 165 | + .find( '.article-assessment-rating-count' ) |
| 166 | + .text( count ); |
| 167 | + // append the field and rating html |
| 168 | + $structure |
| 169 | + .find( '.article-assessment-rating-fields' ) |
| 170 | + .append( $field ) |
| 171 | + .end() |
| 172 | + .find( '#article-assessment-ratings' ) |
| 173 | + .append( $rating ); |
| 174 | + } |
| 175 | + // store our settings and configuration for later |
| 176 | + $structure.find( '#article-assessment' ).data( 'articleAssessment-context', { 'settings': settings, 'config': config } ); |
| 177 | + $( '#catlinks' ).before( $structure ); |
| 178 | + // Hide the ratings initially |
| 179 | + $.ArticleAssessment.fn.hideRatings(); |
| 180 | + |
| 181 | + |
| 182 | + // set the height of our smaller fieldset to match the taller |
| 183 | + if ( $( '#article-assessment-rate' ).height() > $( '#article-assessment-ratings' ).height() ) { |
| 184 | + $( '#article-assessment-ratings' ).css( 'minHeight', $( '#article-assessment-rate' ).height() ); |
| 185 | + } else { |
| 186 | + $( '#article-assessment-rate' ).css( 'minHeight', $( '#article-assessment-ratings' ).height() ); |
| 187 | + } |
| 188 | + // attempt to fetch the ratings |
| 189 | + $.ArticleAssessment.fn.getRatingData(); |
| 190 | + |
| 191 | + // initialize the star plugin |
| 192 | + $( '.rating-field' ).each( function() { |
| 193 | + $( this ) |
| 194 | + .wrapAll( '<div class="rating-field"></div>' ) |
| 195 | + .parent() |
| 196 | + .stars( { |
| 197 | + inputType: 'select', |
| 198 | + callback: function( value, link ) { |
| 199 | + // remove any stale or rated classes |
| 200 | + value.$stars.each( function() { |
| 201 | + $( this ) |
| 202 | + .removeClass( 'ui-stars-star-stale' ) |
| 203 | + .removeClass( 'ui-stars-star-rated' ); |
| 204 | + // enable our submit button if it's still disabled |
| 205 | + $( '#article-assessment input:disabled' ).removeAttr( 'disabled' ); |
| 206 | + } ); |
| 207 | + } |
| 208 | + } ); |
| 209 | + }); |
| 210 | + // intialize the tooltips |
| 211 | + $( '.field-wrapper label[original-title]' ).each( function() { |
| 212 | + $( this ) |
| 213 | + .after( $( '<span class="rating-field-hint" />' ) |
| 214 | + .attr( 'original-title', $( this ).attr( 'original-title' ) ) |
| 215 | + .tipsy( { gravity : 'se', opacity: '0.9' } ) ); |
| 216 | + } ); |
| 217 | + // bind submit event to the form |
| 218 | + $( '#article-assessment' ) |
| 219 | + .submit( function() { $.ArticleAssessment.fn.submitRating(); return false; } ); |
| 220 | + // prevent the submit button for being active until all ratings are filled out |
| 221 | + $( '#article-assessment input[type=submit]' ) |
| 222 | + .attr( 'disabled', 'disabled' ); |
| 223 | + }, |
| 224 | + 'showRatings': function() { |
| 225 | + $( '#article-assessment-ratings' ) |
| 226 | + .removeClass( 'article-assessment-ratings-disabled' ) |
| 227 | + .find( '.article-assessment-show-ratings' ) |
| 228 | + .hide() |
| 229 | + .end() |
| 230 | + .find( '.article-assessment-hide-ratings' ) |
| 231 | + .show(); |
| 232 | + return false; |
| 233 | + }, |
| 234 | + 'hideRatings': function() { |
| 235 | + $( '#article-assessment-ratings' ) |
| 236 | + .addClass( 'article-assessment-ratings-disabled' ) |
| 237 | + .find( '.article-assessment-hide-ratings' ) |
| 238 | + .hide() |
| 239 | + .end() |
| 240 | + .find( '.article-assessment-show-ratings' ) |
| 241 | + .show(); |
| 242 | + return false; |
| 243 | + |
| 244 | + }, |
| 245 | + |
| 246 | + // Request the ratings data for the current article |
| 247 | + 'getRatingData': function() { |
| 248 | + var config = $( '#article-assessment' ).data( 'articleAssessment-context' ).config; |
| 249 | + var requestData = { |
| 250 | + 'action': 'query', |
| 251 | + 'list': 'articleassessment', |
| 252 | + 'aapageid': config.pageID, |
| 253 | + 'aauserrating': 1, |
| 254 | + 'format': 'json' |
| 255 | + } |
| 256 | + if ( config.userID.length == 32 ) { |
| 257 | + requestData.aaanontoken = config.userID; |
| 258 | + } |
| 259 | + |
| 260 | + var request = $.ajax( { |
| 261 | + url: wgScriptPath + '/api.php', |
| 262 | + data: requestData, |
| 263 | + dataType: 'json', |
| 264 | + success: $.ArticleAssessment.fn.afterGetRatingData, |
| 265 | + error: function( XMLHttpRequest, textStatus, errorThrown ) { |
| 266 | + $.ArticleAssessment.fn.flashNotice( $.ArticleAssessment.fn.getMsg( 'articleassessment-error' ), |
| 267 | + { 'class': 'article-assessment-error-msg' } ); |
| 268 | + } |
| 269 | + } ); |
| 270 | + }, |
| 271 | + 'afterGetRatingData' : function( data ) { |
| 272 | + var settings = $( '#article-assessment' ).data( 'articleAssessment-context' ).settings; |
| 273 | + // add the correct data to the markup |
| 274 | + if ( data.query && data.query.articleassessment && data.query.articleassessment.length > 0 ) { |
| 275 | + for ( var r in data.query.articleassessment[0].ratings ) { |
| 276 | + var rating = data.query.articleassessment[0].ratings[r], |
| 277 | + $rating = $( '#' + rating.ratingdesc ), |
| 278 | + count = rating.count, |
| 279 | + total = ( rating.total / count ).toFixed( 1 ), |
| 280 | + label = $.ArticleAssessment.fn.getMsg( 'articleassessment-noratings', [total, count] ); |
| 281 | + $rating |
| 282 | + .find( '.article-assessment-rating-field-value' ) |
| 283 | + .text( total ) |
| 284 | + .end() |
| 285 | + .find( '.article-assessment-rating-count' ) |
| 286 | + .text( label ); |
| 287 | + if( rating.userrating ) { |
| 288 | + // this user rated. Word. Show them their ratings |
| 289 | + var $rateControl = $( '#' + rating.ratingdesc.replace( 'rating', 'rate' ) + ' .rating-field' ); |
| 290 | + $rateControl.stars( 'select', rating.userrating ); |
| 291 | + // oh let's show them the overall ratings too |
| 292 | + $.ArticleAssessment.fn.showRatings(); |
| 293 | + } |
| 294 | + } |
| 295 | + // if the rating is more than 5 revisions old, mark it as stale |
| 296 | + if ( typeof data.query.articleassessment[0].stale != 'undefined' ) { |
| 297 | + // add the stale star class to each on star |
| 298 | + $( '.ui-stars-star-on' ) |
| 299 | + .addClass( 'ui-stars-star-stale' ); |
| 300 | + // add the stale message |
| 301 | + var msg = $.ArticleAssessment.fn.getMsg( 'articleassessment-stalemessage-norevisioncount' ); |
| 302 | + $.ArticleAssessment.fn.flashNotice( msg, { 'class': 'article-assessment-stale-msg' } ); |
| 303 | + } else { |
| 304 | + // if it's not a stale rating, we want to make the stars blue |
| 305 | + $( '.ui-stars-star-on' ).addClass( 'ui-stars-star-rated' ); |
| 306 | + } |
| 307 | + } |
| 308 | + // initialize the ratings |
| 309 | + $( '.article-assessment-rating-field-value' ).each( function() { |
| 310 | + $( this ) |
| 311 | + .css( { |
| 312 | + 'width': 120 - ( 120 * ( parseFloat( $( this ).text() ) / 5 ) ) + 'px' |
| 313 | + } ) |
| 314 | + } ); |
| 315 | + }, |
| 316 | + 'submitRating': function() { |
| 317 | + var config = $( '#article-assessment' ).data( 'articleAssessment-context' ).config; |
| 318 | + // clear out the stale message |
| 319 | + $.ArticleAssessment.fn.flashNotice( ); |
| 320 | + |
| 321 | + // lock the star inputs & submit |
| 322 | + $( '.rating-field' ).stars( 'disable' ); |
| 323 | + $( '#article-assessment input' ).attr( 'disabled', 'disabled' ); |
| 324 | + // get our results for submitting |
| 325 | + var results = {}; |
| 326 | + $( '.rating-field input' ).each( function() { |
| 327 | + // expects the hidden inputs to have names like 'rating[field-name]' which we use to |
| 328 | + // be transparent about what values we're sending to the server |
| 329 | + var fieldName = $( this ).attr( 'name' ).match( /\[([a-zA-Z0-9\-]*)\]/ )[1]; |
| 330 | + results[ fieldName ] = $( this ).val(); |
| 331 | + } ); |
| 332 | + var request = $.ajax( { |
| 333 | + url: wgScriptPath + '/api.php', |
| 334 | + type: 'POST', |
| 335 | + data: { |
| 336 | + 'action': 'articleassessment', |
| 337 | + 'revid': config.revID, |
| 338 | + 'pageid': config.pageID, |
| 339 | + 'r1' : results['wellsourced'], |
| 340 | + 'r2' : results['neutrality'], |
| 341 | + 'r3' : results['completeness'], |
| 342 | + 'r4' : results['readability'], |
| 343 | + 'anontoken': config.userID, |
| 344 | + 'format': 'json' |
| 345 | + }, |
| 346 | + dataType: 'json', |
| 347 | + success: $.ArticleAssessment.fn.afterSubmitRating, |
| 348 | + error: function( XMLHttpRequest, textStatus, errorThrown ) { |
| 349 | + $.ArticleAssessment.fn.flashNotice( $.ArticleAssessment.fn.getMsg( 'articleassessment-error' ), |
| 350 | + { 'class': 'article-assessment-error-msg' } ); |
| 351 | + } |
| 352 | + } ); |
| 353 | + }, |
| 354 | + 'afterSubmitRating': function ( data ) { |
| 355 | + // update the ratings |
| 356 | + $.ArticleAssessment.fn.getRatingData(); |
| 357 | + // set the stars to rated status |
| 358 | + $( '.ui-stars-star-on' ).addClass( 'ui-stars-star-rated' ); |
| 359 | + // unlock the stars & submit |
| 360 | + $( '.rating-field' ).stars( 'enable' ); |
| 361 | + $( '#article-assessment input:disabled' ).removeAttr( 'disabled' ); |
| 362 | + // update the results |
| 363 | + |
| 364 | + // show the results |
| 365 | + $.ArticleAssessment.fn.showRatings(); |
| 366 | + // say thank you |
| 367 | + $.ArticleAssessment.fn.flashNotice( $.ArticleAssessment.fn.getMsg( 'articleassessment-thanks' ), |
| 368 | + { 'class': 'article-assessment-success-msg' } ); |
| 369 | + }, |
| 370 | + // places a message on the interface |
| 371 | + 'flashNotice': function( text, options ) { |
| 372 | + if ( arguments.length == 0 ) { |
| 373 | + // clear existing messages, but don't add a new one |
| 374 | + $( '#article-assessment .article-assessment-flash' ).remove(); |
| 375 | + } else { |
| 376 | + // clear and add a new message |
| 377 | + $( '#article-assessment .article-assessment-flash' ).remove(); |
| 378 | + var className = options['class']; |
| 379 | + // create our new message |
| 380 | + $msg = $( '<div />' ) |
| 381 | + .addClass( 'article-assessment-flash' ) |
| 382 | + .html( text ); |
| 383 | + // if the class option was passed, add it |
| 384 | + if( options['class'] ) { |
| 385 | + $msg.addClass( options['class'] ); |
| 386 | + } |
| 387 | + // place our new message on the page |
| 388 | + $( '#article-assessment .article-assessment-submit' ) |
| 389 | + .append( $msg ); |
| 390 | + } |
| 391 | + }, |
| 392 | + 'showFeedback': function() { |
| 393 | + $.ArticleAssessment.fn.withJUI( function() { |
| 394 | + var $dialogDiv = $( '#article-assessment-dialog' ); |
| 395 | + if ( $dialogDiv.size() == 0 ) { |
| 396 | + $dialogDiv = $( '<div id="article-assessment-dialog" class="loading" />' ) |
| 397 | + .dialog( { |
| 398 | + width: 600, |
| 399 | + height: 400, |
| 400 | + bgiframe: true, |
| 401 | + autoOpen: true, |
| 402 | + modal: true, |
| 403 | + title: $.ArticleAssessment.fn.getMsg( 'articleassessment-survey-title' ), |
| 404 | + close: function() { |
| 405 | + $( this ) |
| 406 | + .dialog( 'option', 'height', 400 ) |
| 407 | + .find( '.article-assessment-success-msg, .article-assessment-error-msg' ) |
| 408 | + .remove() |
| 409 | + .end() |
| 410 | + .find( 'form' ) |
| 411 | + .show(); |
| 412 | + } |
| 413 | + } ); |
| 414 | + $dialogDiv.load( |
| 415 | + wgScript + '?title=Special:SimpleSurvey&survey=articlerating&raw=1', |
| 416 | + function() { |
| 417 | + $( this ).find( 'form' ).bind( 'submit', $.ArticleAssessment.fn.submitFeedback ); |
| 418 | + $( this ).removeClass( 'loading' ); |
| 419 | + } |
| 420 | + ); |
| 421 | + } |
| 422 | + $dialogDiv.dialog( 'open' ); |
| 423 | + } ); |
| 424 | + return false; |
| 425 | + }, |
| 426 | + 'submitFeedback': function() { |
| 427 | + var $dialogDiv = $( '#article-assessment-dialog' ); |
| 428 | + $dialogDiv |
| 429 | + .find( 'form' ) |
| 430 | + .hide() |
| 431 | + .end() |
| 432 | + .addClass( 'loading' ); |
| 433 | + // Submit straight to the special page. Yes, this is a dirty dirty hack |
| 434 | + // Build request from form data |
| 435 | + var formData = {}; |
| 436 | + $dialogDiv.find( 'input' ).each( function() { |
| 437 | + var name = $( this ).attr( 'name' ); |
| 438 | + if ( name !== '' ) { |
| 439 | + if ( name.substr( -2 ) == '[]' ) { |
| 440 | + var trimmedName = name.substr( 0, name.length - 2 ); |
| 441 | + if ( typeof formData[trimmedName] == 'undefined' ) { |
| 442 | + formData[trimmedName] = []; |
| 443 | + } |
| 444 | + formData[trimmedName].push( $( this ).val() ); |
| 445 | + } else { |
| 446 | + formData[name] = $( this ).val(); |
| 447 | + } |
| 448 | + } |
| 449 | + } ); |
| 450 | + formData.title = 'Special:SimpleSurvey'; |
| 451 | + |
| 452 | + $.ajax( { |
| 453 | + url: wgScript, |
| 454 | + type: 'POST', |
| 455 | + data: formData, |
| 456 | + dataType: 'html', |
| 457 | + success: function( data ) { |
| 458 | + // This is an evil screenscraping method to determine whether |
| 459 | + // the submission was successful |
| 460 | + var success = $( data ).find( '.simplesurvey-success' ).size() > 0; |
| 461 | + // TODO: Style success-msg, error-msg |
| 462 | + var $msgDiv = $( '<div />' ) |
| 463 | + .addClass( success ? 'article-assessment-success-msg' : 'article-assessment-error-msg' ) |
| 464 | + .text( $.ArticleAssessment.fn.getMsg( success? 'articleassessment-survey-thanks' : 'articleassessment-error' ) ) |
| 465 | + .appendTo( $dialogDiv ); |
| 466 | + $dialogDiv |
| 467 | + .dialog( 'option', 'height', $msgDiv.height() + 100 ) |
| 468 | + .removeClass( 'loading' ); |
| 469 | + if ( success ) { |
| 470 | + // Hide the dialog link |
| 471 | + $( '#article-assessment .article-assessment-rate-feedback' ).hide(); |
| 472 | + // set a cookie to keep the dialog link hidden |
| 473 | + $.cookie( 'mwArticleAssessmentHideFeedback', true, { 'expires': 30, 'path': '/' } ); |
| 474 | + |
| 475 | + } |
| 476 | + }, |
| 477 | + error: function( XMLHttpRequest, textStatus, errorThrown ) { |
| 478 | + // TODO: Duplicates code, factor out, maybe |
| 479 | + var $msgDiv = $( '<div />' ) |
| 480 | + .addClass( 'article-assessment-error-msg' ) |
| 481 | + .text( $.ArticleAssessment.fn.getMsg( 'articleassessment-error' ) ) |
| 482 | + .appendTo( $dialogDiv ); |
| 483 | + $dialogDiv |
| 484 | + .dialog( 'option', 'height', $msgDiv.height() + 100 ) |
| 485 | + .removeClass( 'loading' ); |
| 486 | + } |
| 487 | + } ); |
| 488 | + return false; |
| 489 | + }, |
| 490 | + 'addMessages': function( messages ) { |
| 491 | + for ( var key in messages ) { |
| 492 | + $.ArticleAssessment.messages[key] = messages[key]; |
| 493 | + } |
| 494 | + }, |
| 495 | + /** |
| 496 | + * Get a message |
| 497 | + * FIXME: Parameter expansion is broken in all sorts of edge cases |
| 498 | + */ |
| 499 | + 'getMsg': function( key, args ) { |
| 500 | + if ( !( key in $.ArticleAssessment.messages ) ) { |
| 501 | + return '[' + key + ']'; |
| 502 | + } |
| 503 | + var msg = $.ArticleAssessment.messages[key]; |
| 504 | + if ( typeof args == 'object' || typeof args == 'array' ) { |
| 505 | + for ( var i = 0; i < args.length; i++ ) { |
| 506 | + msg = msg.replace( new RegExp( '\\$' + ( parseInt( i ) + 1 ), 'g' ), args[i] ); |
| 507 | + } |
| 508 | + } else if ( typeof args == 'string' || typeof args == 'number' ) { |
| 509 | + msg = msg.replace( /\$1/g, args ); |
| 510 | + } |
| 511 | + return msg; |
| 512 | + }, |
| 513 | + 'withJUI': function( callback ) { |
| 514 | + if ( typeof $.ui == 'undefined' ) { |
| 515 | + $.getScript( wgArticleAssessmentJUIPath, callback ); |
| 516 | + } else { |
| 517 | + callback(); |
| 518 | + } |
| 519 | + } |
| 520 | + } |
| 521 | + }; |
| 522 | + $( document ).ready( function () { |
| 523 | + $.ArticleAssessment.fn.init( ); |
| 524 | + } ); //document ready |
| 525 | +} )( jQuery ); |
| 526 | +/** |
| 527 | + * Cookie plugin |
| 528 | + * |
| 529 | + * Copyright (c) 2006 Klaus Hartl (stilbuero.de) |
| 530 | + * Dual licensed under the MIT and GPL licenses: |
| 531 | + * http://www.opensource.org/licenses/mit-license.php |
| 532 | + * http://www.gnu.org/licenses/gpl.html |
| 533 | + * |
| 534 | + */ |
| 535 | + |
| 536 | +/** |
| 537 | + * Create a cookie with the given name and value and other optional parameters. |
| 538 | + * |
| 539 | + * @example $.cookie('the_cookie', 'the_value'); |
| 540 | + * @desc Set the value of a cookie. |
| 541 | + * @example $.cookie('the_cookie', 'the_value', { expires: 7, path: '/', domain: 'jquery.com', secure: true }); |
| 542 | + * @desc Create a cookie with all available options. |
| 543 | + * @example $.cookie('the_cookie', 'the_value'); |
| 544 | + * @desc Create a session cookie. |
| 545 | + * @example $.cookie('the_cookie', null); |
| 546 | + * @desc Delete a cookie by passing null as value. Keep in mind that you have to use the same path and domain |
| 547 | + * used when the cookie was set. |
| 548 | + * |
| 549 | + * @param String name The name of the cookie. |
| 550 | + * @param String value The value of the cookie. |
| 551 | + * @param Object options An object literal containing key/value pairs to provide optional cookie attributes. |
| 552 | + * @option Number|Date expires Either an integer specifying the expiration date from now on in days or a Date object. |
| 553 | + * If a negative value is specified (e.g. a date in the past), the cookie will be deleted. |
| 554 | + * If set to null or omitted, the cookie will be a session cookie and will not be retained |
| 555 | + * when the the browser exits. |
| 556 | + * @option String path The value of the path atribute of the cookie (default: path of page that created the cookie). |
| 557 | + * @option String domain The value of the domain attribute of the cookie (default: domain of page that created the cookie). |
| 558 | + * @option Boolean secure If true, the secure attribute of the cookie will be set and the cookie transmission will |
| 559 | + * require a secure protocol (like HTTPS). |
| 560 | + * @type undefined |
| 561 | + * |
| 562 | + * @name $.cookie |
| 563 | + * @cat Plugins/Cookie |
| 564 | + * @author Klaus Hartl/klaus.hartl@stilbuero.de |
| 565 | + */ |
| 566 | + |
| 567 | +/** |
| 568 | + * Get the value of a cookie with the given name. |
| 569 | + * |
| 570 | + * @example $.cookie('the_cookie'); |
| 571 | + * @desc Get the value of a cookie. |
| 572 | + * |
| 573 | + * @param String name The name of the cookie. |
| 574 | + * @return The value of the cookie. |
| 575 | + * @type String |
| 576 | + * |
| 577 | + * @name $.cookie |
| 578 | + * @cat Plugins/Cookie |
| 579 | + * @author Klaus Hartl/klaus.hartl@stilbuero.de |
| 580 | + */ |
| 581 | +jQuery.cookie = function(name, value, options) { |
| 582 | + if (typeof value != 'undefined') { // name and value given, set cookie |
| 583 | + options = options || {}; |
| 584 | + if (value === null) { |
| 585 | + value = ''; |
| 586 | + options.expires = -1; |
| 587 | + } |
| 588 | + var expires = ''; |
| 589 | + if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) { |
| 590 | + var date; |
| 591 | + if (typeof options.expires == 'number') { |
| 592 | + date = new Date(); |
| 593 | + date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000)); |
| 594 | + } else { |
| 595 | + date = options.expires; |
| 596 | + } |
| 597 | + expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE |
| 598 | + } |
| 599 | + // CAUTION: Needed to parenthesize options.path and options.domain |
| 600 | + // in the following expressions, otherwise they evaluate to undefined |
| 601 | + // in the packed version for some reason... |
| 602 | + var path = options.path ? '; path=' + (options.path) : ''; |
| 603 | + var domain = options.domain ? '; domain=' + (options.domain) : ''; |
| 604 | + var secure = options.secure ? '; secure' : ''; |
| 605 | + document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join(''); |
| 606 | + } else { // only name given, get cookie |
| 607 | + var cookieValue = null; |
| 608 | + if (document.cookie && document.cookie != '') { |
| 609 | + var cookies = document.cookie.split(';'); |
| 610 | + for (var i = 0; i < cookies.length; i++) { |
| 611 | + var cookie = jQuery.trim(cookies[i]); |
| 612 | + // Does this cookie string begin with the name we want? |
| 613 | + if (cookie.substring(0, name.length + 1) == (name + '=')) { |
| 614 | + cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); |
| 615 | + break; |
| 616 | + } |
| 617 | + } |
| 618 | + } |
| 619 | + return cookieValue; |
| 620 | + } |
| 621 | +}; |
| 622 | + |
| 623 | +/*! |
| 624 | + * jQuery Stars v1 |
| 625 | + * adapted by Adam Miller (acm6603@gmail.com) |
| 626 | + * |
| 627 | + * Adapted from jQuery UI Stars v3.0.1 |
| 628 | + * Marek "Orkan" Zajac (orkans@gmail.com) |
| 629 | + * http://plugins.jquery.com/project/Star_Rating_widget |
| 630 | + * |
| 631 | + */ |
| 632 | +(function($) { |
| 633 | +$.stars = { |
| 634 | + defaults : { |
| 635 | + inputType: 'radio', // [radio|select] |
| 636 | + split: 0, // decrease number of stars by splitting each star into pieces [2|3|4|...] |
| 637 | + disabled: false, // set to [true] to make the stars initially disabled |
| 638 | + cancelTitle: 'Cancel Rating', |
| 639 | + cancelValue: 0, // default value of Cancel btn. |
| 640 | + cancelShow: true, |
| 641 | + disableValue: true, // set to [false] to not disable the hidden input when Cancel btn is clicked, so the value will present in POST data. |
| 642 | + oneVoteOnly: false, |
| 643 | + showTitles: false, |
| 644 | + captionEl: null, // jQuery object - target for text captions |
| 645 | + callback: null, // function(ui, type, value, event) |
| 646 | + /* |
| 647 | + * CSS classes |
| 648 | + */ |
| 649 | + starWidth: 16, // width of the star image |
| 650 | + cancelClass: 'ui-stars-cancel', |
| 651 | + starClass: 'ui-stars-star', |
| 652 | + starOnClass: 'ui-stars-star-on', |
| 653 | + starHoverClass: 'ui-stars-star-hover', |
| 654 | + starDisabledClass: 'ui-stars-star-disabled', |
| 655 | + cancelHoverClass: 'ui-stars-cancel-hover', |
| 656 | + cancelDisabledClass: 'ui-stars-cancel-disabled' |
| 657 | + }, |
| 658 | + create: function( ) { |
| 659 | + var self = this, o = this.options, starId = 0; |
| 660 | + this.element.data('former.stars', this.element.html()); |
| 661 | + o.isSelect = o.inputType == 'select'; |
| 662 | + this.$form = $(this.element).closest('form'); |
| 663 | + this.$selec = o.isSelect ? $('select', this.element) : null; |
| 664 | + this.$rboxs = o.isSelect ? $('option', this.$selec) : $(':radio', this.element); |
| 665 | + /* |
| 666 | + * Map all inputs from $rboxs array to Stars elements |
| 667 | + */ |
| 668 | + this.$stars = this.$rboxs.map(function(i) |
| 669 | + { |
| 670 | + var el = { |
| 671 | + value: this.value, |
| 672 | + title: (o.isSelect ? this.text : this.title) || this.value, |
| 673 | + isDefault: (o.isSelect && this.defaultSelected) || this.defaultChecked |
| 674 | + }; |
| 675 | + if(i==0) { |
| 676 | + o.split = typeof o.split != 'number' ? 0 : o.split; |
| 677 | + o.val2id = []; |
| 678 | + o.id2val = []; |
| 679 | + o.id2title = []; |
| 680 | + o.name = o.isSelect ? self.$selec.get(0).name : this.name; |
| 681 | + o.disabled = o.disabled || (o.isSelect ? $(self.$selec).attr('disabled') : $(this).attr('disabled')); |
| 682 | + } |
| 683 | + /* |
| 684 | + * Consider it as a Cancel button? |
| 685 | + */ |
| 686 | + if(el.value == o.cancelValue) { |
| 687 | + o.cancelTitle = el.title; |
| 688 | + return null; |
| 689 | + } |
| 690 | + o.val2id[el.value] = starId; |
| 691 | + o.id2val[starId] = el.value; |
| 692 | + o.id2title[starId] = el.title; |
| 693 | + if(el.isDefault) { |
| 694 | + o.checked = starId; |
| 695 | + o.value = o.defaultValue = el.value; |
| 696 | + o.title = el.title; |
| 697 | + } |
| 698 | + var $s = $('<div/>').addClass(o.starClass); |
| 699 | + var $a = $('<a/>').attr('title', o.showTitles ? el.title : '').text(el.value); |
| 700 | + /* |
| 701 | + * Prepare division settings |
| 702 | + */ |
| 703 | + if(o.split) { |
| 704 | + var oddeven = (starId % o.split); |
| 705 | + var stwidth = Math.floor(o.starWidth / o.split); |
| 706 | + $s.width(stwidth); |
| 707 | + $a.css('margin-left', '-' + (oddeven * stwidth) + 'px'); |
| 708 | + } |
| 709 | + starId++; |
| 710 | + return $s.append($a).get(0); |
| 711 | + }); |
| 712 | + /* |
| 713 | + * How many Stars? |
| 714 | + */ |
| 715 | + o.items = starId; |
| 716 | + /* |
| 717 | + * Remove old content |
| 718 | + */ |
| 719 | + o.isSelect ? this.$selec.remove() : this.$rboxs.remove(); |
| 720 | + /* |
| 721 | + * Append Stars interface |
| 722 | + */ |
| 723 | + this.$cancel = $('<div/>').addClass(o.cancelClass).append( $('<a/>').attr('title', o.showTitles ? o.cancelTitle : '').text(o.cancelValue) ); |
| 724 | + o.cancelShow &= !o.disabled && !o.oneVoteOnly; |
| 725 | + o.cancelShow && this.element.append(this.$cancel); |
| 726 | + this.element.append(this.$stars); |
| 727 | + /* |
| 728 | + * Initial selection |
| 729 | + */ |
| 730 | + if(o.checked === undefined) { |
| 731 | + o.checked = -1; |
| 732 | + o.value = o.defaultValue = o.cancelValue; |
| 733 | + o.title = ''; |
| 734 | + } |
| 735 | + /* |
| 736 | + * The only FORM element, that has been linked to the stars control. The value field is updated on each Star click event |
| 737 | + */ |
| 738 | + this.$value = $("<input type='hidden' name='"+o.name+"' value='"+o.value+"' />"); |
| 739 | + this.element.append(this.$value); |
| 740 | + /* |
| 741 | + * Attach stars event handler |
| 742 | + */ |
| 743 | + this.$stars.bind('click.stars', function(e) { |
| 744 | + if(!o.forceSelect && o.disabled) return false; |
| 745 | + var i = self.$stars.index(this); |
| 746 | + o.checked = i; |
| 747 | + o.value = o.id2val[i]; |
| 748 | + o.title = o.id2title[i]; |
| 749 | + self.$value.attr({disabled: o.disabled ? 'disabled' : '', value: o.value}); |
| 750 | + fillTo(i, false); |
| 751 | + self.disableCancel(); |
| 752 | + !o.forceSelect && self.callback(e, 'star'); |
| 753 | + }) |
| 754 | + .bind('mouseover.stars', function() { |
| 755 | + if(o.disabled) return false; |
| 756 | + var i = self.$stars.index(this); |
| 757 | + fillTo(i, true); |
| 758 | + }) |
| 759 | + .bind('mouseout.stars', function() { |
| 760 | + if(o.disabled) return false; |
| 761 | + fillTo(self.options.checked, false); |
| 762 | + }); |
| 763 | + /* |
| 764 | + * Attach cancel event handler |
| 765 | + */ |
| 766 | + this.$cancel.bind('click.stars', function(e) { |
| 767 | + if(!o.forceSelect && (o.disabled || o.value == o.cancelValue)) return false; |
| 768 | + o.checked = -1; |
| 769 | + o.value = o.cancelValue; |
| 770 | + o.title = ''; |
| 771 | + self.$value.val(o.value); |
| 772 | + o.disableValue && self.$value.attr({disabled: 'disabled'}); |
| 773 | + fillNone(); |
| 774 | + self.disableCancel(); |
| 775 | + !o.forceSelect && self.callback(e, 'cancel'); |
| 776 | + }) |
| 777 | + .bind('mouseover.stars', function() { |
| 778 | + if(self.disableCancel()) return false; |
| 779 | + self.$cancel.addClass(o.cancelHoverClass); |
| 780 | + fillNone(); |
| 781 | + self.showCap(o.cancelTitle); |
| 782 | + }) |
| 783 | + .bind('mouseout.stars', function() { |
| 784 | + if(self.disableCancel()) return false; |
| 785 | + self.$cancel.removeClass(o.cancelHoverClass); |
| 786 | + self.$stars.triggerHandler('mouseout.stars'); |
| 787 | + }); |
| 788 | + /* |
| 789 | + * Attach onReset event handler to the parent FORM |
| 790 | + */ |
| 791 | + this.$form.bind('reset.stars', function(){ |
| 792 | + !o.disabled && self.select(o.defaultValue); |
| 793 | + }); |
| 794 | + /* |
| 795 | + * Clean up to avoid memory leaks in certain versions of IE 6 |
| 796 | + */ |
| 797 | + $(window).unload(function(){ |
| 798 | + self.$cancel.unbind('.stars'); |
| 799 | + self.$stars.unbind('.stars'); |
| 800 | + self.$form.unbind('.stars'); |
| 801 | + self.$selec = self.$rboxs = self.$stars = self.$value = self.$cancel = self.$form = null; |
| 802 | + }); |
| 803 | + /* |
| 804 | + * Star selection helpers |
| 805 | + */ |
| 806 | + function fillTo(index, hover) { |
| 807 | + if(index != -1) { |
| 808 | + var addClass = hover ? o.starHoverClass : o.starOnClass; |
| 809 | + var remClass = hover ? o.starOnClass : o.starHoverClass; |
| 810 | + self.$stars.eq(index).prevAll('.' + o.starClass).andSelf().removeClass(remClass).addClass(addClass); |
| 811 | + self.$stars.eq(index).nextAll('.' + o.starClass).removeClass(o.starHoverClass + ' ' + o.starOnClass); |
| 812 | + self.showCap(o.id2title[index]); |
| 813 | + } |
| 814 | + else fillNone(); |
| 815 | + }; |
| 816 | + function fillNone() { |
| 817 | + self.$stars.removeClass(o.starOnClass + ' ' + o.starHoverClass); |
| 818 | + self.showCap(''); |
| 819 | + }; |
| 820 | + /* |
| 821 | + * Finally, set up the Stars |
| 822 | + */ |
| 823 | + this.select( o.value ); |
| 824 | + o.disabled && this.disable(); |
| 825 | + }, |
| 826 | + /* |
| 827 | + * Private functions |
| 828 | + */ |
| 829 | + disableCancel: function() { |
| 830 | + var o = this.options, disabled = o.disabled || o.oneVoteOnly || (o.value == o.cancelValue); |
| 831 | + if(disabled) this.$cancel.removeClass(o.cancelHoverClass).addClass(o.cancelDisabledClass); |
| 832 | + else this.$cancel.removeClass(o.cancelDisabledClass); |
| 833 | + this.$cancel.css('opacity', disabled ? 0.5 : 1); |
| 834 | + return disabled; |
| 835 | + }, |
| 836 | + disableAll: function() { |
| 837 | + var o = this.options; |
| 838 | + this.disableCancel(); |
| 839 | + if(o.disabled) this.$stars.filter('div').addClass(o.starDisabledClass); |
| 840 | + else this.$stars.filter('div').removeClass(o.starDisabledClass); |
| 841 | + }, |
| 842 | + showCap: function(s) { |
| 843 | + var o = this.options; |
| 844 | + if(o.captionEl) o.captionEl.text(s); |
| 845 | + }, |
| 846 | + /* |
| 847 | + * Public functions |
| 848 | + */ |
| 849 | + value: function() { |
| 850 | + return this.options.value; |
| 851 | + }, |
| 852 | + select: function( val ) { |
| 853 | + var o = this.options, e = (val == o.cancelValue) ? this.$cancel : this.$stars.eq(o.val2id[val]); |
| 854 | + o.forceSelect = true; |
| 855 | + e.triggerHandler('click.stars'); |
| 856 | + o.forceSelect = false; |
| 857 | + }, |
| 858 | + selectID: function(id) { |
| 859 | + var o = this.options, e = (id == -1) ? this.$cancel : this.$stars.eq(id); |
| 860 | + o.forceSelect = true; |
| 861 | + e.triggerHandler('click.stars'); |
| 862 | + o.forceSelect = false; |
| 863 | + }, |
| 864 | + enable: function() { |
| 865 | + this.options.disabled = false; |
| 866 | + this.disableAll(); |
| 867 | + }, |
| 868 | + disable: function() { |
| 869 | + this.options.disabled = true; |
| 870 | + this.disableAll(); |
| 871 | + }, |
| 872 | + destroy: function() { |
| 873 | + this.$form.unbind('.stars'); |
| 874 | + this.$cancel.unbind('.stars').remove(); |
| 875 | + this.$stars.unbind('.stars').remove(); |
| 876 | + this.$value.remove(); |
| 877 | + this.element.unbind('.stars').html(this.element.data('former.stars')).removeData('stars'); |
| 878 | + return this; |
| 879 | + }, |
| 880 | + callback: function(e, type) { |
| 881 | + var o = this.options; |
| 882 | + o.callback && o.callback(this, type, o.value, e); |
| 883 | + o.oneVoteOnly && !o.disabled && this.disable(); |
| 884 | + } |
| 885 | +} |
| 886 | +$.fn.stars = function ( ) { |
| 887 | + // convert the arguments to an array |
| 888 | + var args = Array.prototype.slice.call(arguments); |
| 889 | + // default value to return -- overwritten by api calls |
| 890 | + var out = $( this ); |
| 891 | + $( this ).each( function() { |
| 892 | + // get the context if it's already been initialized |
| 893 | + var context = $( this ).data( 'stars-context' ); |
| 894 | + if ( typeof context == 'undefined' || context == null ) { |
| 895 | + // setup the context if it hasn't been yet |
| 896 | + context = $.extend( {}, { |
| 897 | + element: $( this ), |
| 898 | + options: $.stars.defaults |
| 899 | + }, $.stars ); |
| 900 | + } |
| 901 | + // Handle various calling styles |
| 902 | + if ( args.length > 0 ) { |
| 903 | + if ( typeof args[0] == 'object' ) { |
| 904 | + // merge the passed options into defaults |
| 905 | + context.options = $.extend( {}, context.options, args[0] ); |
| 906 | + // initialize |
| 907 | + $.stars.create.call( context ); |
| 908 | + } else if ( typeof args[0] == 'string' ) { |
| 909 | + // API call |
| 910 | + var funcName = args[0]; |
| 911 | + // call the function, and if it returns something, store the output in our return var |
| 912 | + out = $.stars[funcName].call( context, args.slice(1) ) || out; |
| 913 | + } |
| 914 | + } else { |
| 915 | + // initialize with the defaults |
| 916 | + $.stars.create.call( context ); |
| 917 | + } |
| 918 | + // save our context, bay-bee |
| 919 | + $( this ).data( 'stars-context', context ); |
| 920 | + } ); |
| 921 | + |
| 922 | + return out; |
| 923 | +}; |
| 924 | +} )( jQuery ); |
| 925 | +// tipsy, facebook style tooltips for jquery |
| 926 | +// version 1.0.0a |
| 927 | +// (c) 2008-2010 jason frame [jason@onehackoranother.com] |
| 928 | +// released under the MIT license |
| 929 | + |
| 930 | +(function($) { |
| 931 | + |
| 932 | + function Tipsy(element, options) { |
| 933 | + this.$element = $(element); |
| 934 | + this.options = options; |
| 935 | + this.enabled = true; |
| 936 | + this.fixTitle(); |
| 937 | + } |
| 938 | + |
| 939 | + Tipsy.prototype = { |
| 940 | + show: function() { |
| 941 | + var title = this.getTitle(); |
| 942 | + if (title && this.enabled) { |
| 943 | + var $tip = this.tip(); |
| 944 | + |
| 945 | + $tip.find('.tipsy-inner')[this.options.html ? 'html' : 'text'](title); |
| 946 | + $tip[0].className = 'tipsy'; // reset classname in case of dynamic gravity |
| 947 | + $tip.remove().css({top: 0, left: 0, visibility: 'hidden', display: 'block'}).appendTo(document.body); |
| 948 | + |
| 949 | + var pos = $.extend({}, this.$element.offset(), { |
| 950 | + width: this.$element[0].offsetWidth, |
| 951 | + height: this.$element[0].offsetHeight |
| 952 | + }); |
| 953 | + |
| 954 | + var actualWidth = $tip[0].offsetWidth, actualHeight = $tip[0].offsetHeight; |
| 955 | + var gravity = (typeof this.options.gravity == 'function') |
| 956 | + ? this.options.gravity.call(this.$element[0]) |
| 957 | + : this.options.gravity; |
| 958 | + |
| 959 | + var tp; |
| 960 | + switch (gravity.charAt(0)) { |
| 961 | + case 'n': |
| 962 | + tp = {top: pos.top + pos.height + this.options.offset, left: pos.left + pos.width / 2 - actualWidth / 2}; |
| 963 | + break; |
| 964 | + case 's': |
| 965 | + tp = {top: pos.top - actualHeight - this.options.offset, left: pos.left + pos.width / 2 - actualWidth / 2}; |
| 966 | + break; |
| 967 | + case 'e': |
| 968 | + tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth - this.options.offset}; |
| 969 | + break; |
| 970 | + case 'w': |
| 971 | + tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width + this.options.offset}; |
| 972 | + break; |
| 973 | + } |
| 974 | + |
| 975 | + if (gravity.length == 2) { |
| 976 | + if (gravity.charAt(1) == 'w') { |
| 977 | + tp.left = pos.left + pos.width / 2 - 15; |
| 978 | + } else { |
| 979 | + tp.left = pos.left + pos.width / 2 - actualWidth + 15; |
| 980 | + } |
| 981 | + } |
| 982 | + |
| 983 | + $tip.css(tp).addClass('tipsy-' + gravity); |
| 984 | + |
| 985 | + if (this.options.fade) { |
| 986 | + $tip.stop().css({opacity: 0, display: 'block', visibility: 'visible'}).animate({opacity: this.options.opacity}); |
| 987 | + } else { |
| 988 | + $tip.css({visibility: 'visible', opacity: this.options.opacity}); |
| 989 | + } |
| 990 | + } |
| 991 | + }, |
| 992 | + |
| 993 | + hide: function() { |
| 994 | + if (this.options.fade) { |
| 995 | + this.tip().stop().fadeOut(function() { $(this).remove(); }); |
| 996 | + } else { |
| 997 | + this.tip().remove(); |
| 998 | + } |
| 999 | + }, |
| 1000 | + |
| 1001 | + fixTitle: function() { |
| 1002 | + var $e = this.$element; |
| 1003 | + if ($e.attr('title') || typeof($e.attr('original-title')) != 'string') { |
| 1004 | + $e.attr('original-title', $e.attr('title') || '').removeAttr('title'); |
| 1005 | + } |
| 1006 | + }, |
| 1007 | + |
| 1008 | + getTitle: function() { |
| 1009 | + var title, $e = this.$element, o = this.options; |
| 1010 | + this.fixTitle(); |
| 1011 | + var title, o = this.options; |
| 1012 | + if (typeof o.title == 'string') { |
| 1013 | + title = $e.attr(o.title == 'title' ? 'original-title' : o.title); |
| 1014 | + } else if (typeof o.title == 'function') { |
| 1015 | + title = o.title.call($e[0]); |
| 1016 | + } |
| 1017 | + title = ('' + title).replace(/(^\s*|\s*$)/, ""); |
| 1018 | + return title || o.fallback; |
| 1019 | + }, |
| 1020 | + |
| 1021 | + tip: function() { |
| 1022 | + if (!this.$tip) { |
| 1023 | + this.$tip = $('<div class="tipsy"></div>').html('<div class="tipsy-arrow"></div><div class="tipsy-inner"></div>'); |
| 1024 | + } |
| 1025 | + return this.$tip; |
| 1026 | + }, |
| 1027 | + |
| 1028 | + validate: function() { |
| 1029 | + if (!this.$element[0].parentNode) { |
| 1030 | + this.hide(); |
| 1031 | + this.$element = null; |
| 1032 | + this.options = null; |
| 1033 | + } |
| 1034 | + }, |
| 1035 | + |
| 1036 | + enable: function() { this.enabled = true; }, |
| 1037 | + disable: function() { this.enabled = false; }, |
| 1038 | + toggleEnabled: function() { this.enabled = !this.enabled; } |
| 1039 | + }; |
| 1040 | + |
| 1041 | + $.fn.tipsy = function(options) { |
| 1042 | + |
| 1043 | + if (options === true) { |
| 1044 | + return this.data('tipsy'); |
| 1045 | + } else if (typeof options == 'string') { |
| 1046 | + var tipsy = this.data('tipsy'); |
| 1047 | + if (tipsy) tipsy[options](); |
| 1048 | + return this; |
| 1049 | + } |
| 1050 | + |
| 1051 | + options = $.extend({}, $.fn.tipsy.defaults, options); |
| 1052 | + |
| 1053 | + function get(ele) { |
| 1054 | + var tipsy = $.data(ele, 'tipsy'); |
| 1055 | + if (!tipsy) { |
| 1056 | + tipsy = new Tipsy(ele, $.fn.tipsy.elementOptions(ele, options)); |
| 1057 | + $.data(ele, 'tipsy', tipsy); |
| 1058 | + } |
| 1059 | + return tipsy; |
| 1060 | + } |
| 1061 | + |
| 1062 | + function enter() { |
| 1063 | + var tipsy = get(this); |
| 1064 | + tipsy.hoverState = 'in'; |
| 1065 | + if (options.delayIn == 0) { |
| 1066 | + tipsy.show(); |
| 1067 | + } else { |
| 1068 | + tipsy.fixTitle(); |
| 1069 | + setTimeout(function() { if (tipsy.hoverState == 'in') tipsy.show(); }, options.delayIn); |
| 1070 | + } |
| 1071 | + }; |
| 1072 | + |
| 1073 | + function leave() { |
| 1074 | + var tipsy = get(this); |
| 1075 | + tipsy.hoverState = 'out'; |
| 1076 | + if (options.delayOut == 0) { |
| 1077 | + tipsy.hide(); |
| 1078 | + } else { |
| 1079 | + setTimeout(function() { if (tipsy.hoverState == 'out') tipsy.hide(); }, options.delayOut); |
| 1080 | + } |
| 1081 | + }; |
| 1082 | + |
| 1083 | + if (!options.live) this.each(function() { get(this); }); |
| 1084 | + |
| 1085 | + if (options.trigger != 'manual') { |
| 1086 | + var binder = options.live ? 'live' : 'bind', |
| 1087 | + eventIn = options.trigger == 'hover' ? 'mouseenter' : 'focus', |
| 1088 | + eventOut = options.trigger == 'hover' ? 'mouseleave' : 'blur'; |
| 1089 | + this[binder](eventIn, enter)[binder](eventOut, leave); |
| 1090 | + } |
| 1091 | + |
| 1092 | + return this; |
| 1093 | + |
| 1094 | + }; |
| 1095 | + |
| 1096 | + $.fn.tipsy.defaults = { |
| 1097 | + delayIn: 0, |
| 1098 | + delayOut: 0, |
| 1099 | + fade: false, |
| 1100 | + fallback: '', |
| 1101 | + gravity: 'n', |
| 1102 | + html: false, |
| 1103 | + live: false, |
| 1104 | + offset: 0, |
| 1105 | + opacity: 0.8, |
| 1106 | + title: 'title', |
| 1107 | + trigger: 'hover' |
| 1108 | + }; |
| 1109 | + |
| 1110 | + // Overwrite this method to provide options on a per-element basis. |
| 1111 | + // For example, you could store the gravity in a 'tipsy-gravity' attribute: |
| 1112 | + // return $.extend({}, options, {gravity: $(ele).attr('tipsy-gravity') || 'n' }); |
| 1113 | + // (remember - do not modify 'options' in place!) |
| 1114 | + $.fn.tipsy.elementOptions = function(ele, options) { |
| 1115 | + return $.metadata ? $.extend({}, options, $(ele).metadata()) : options; |
| 1116 | + }; |
| 1117 | + |
| 1118 | + $.fn.tipsy.autoNS = function() { |
| 1119 | + return $(this).offset().top > ($(document).scrollTop() + $(window).height() / 2) ? 's' : 'n'; |
| 1120 | + }; |
| 1121 | + |
| 1122 | + $.fn.tipsy.autoWE = function() { |
| 1123 | + return $(this).offset().left > ($(document).scrollLeft() + $(window).width() / 2) ? 'e' : 'w'; |
| 1124 | + }; |
| 1125 | + |
| 1126 | +})(jQuery); |
Index: trunk/extensions/ArticleAssessmentPilot/js/ArticleAssessment.combined.min.js |
— | — | @@ -0,0 +1,77 @@ |
| 2 | + |
| 3 | +(function($){$.ArticleAssessment={'config':{'authtoken':'','userID':'','pageID':wgArticleId,'revID':wgCurRevisionId},'messages':{},'settings':{'endpoint':wgScriptPath+'/api.php?','fieldMessages':['wellsourced','neutrality','completeness','readability'],'fieldHintSuffix':'-tooltip','fieldPrefix':'articleassessment-rating-','fieldHTML':'<div class="field-wrapper"> \ |
| 4 | + <label class="rating-field-label"></label> \ |
| 5 | + <select class="rating-field"> \ |
| 6 | + <option value="1">1</option> \ |
| 7 | + <option value="2">2</option> \ |
| 8 | + <option value="3">3</option> \ |
| 9 | + <option value="4">4</option> \ |
| 10 | + <option value="5">5</option> \ |
| 11 | + </select> \ |
| 12 | + </div>','structureHTML':'<div class="article-assessment-wrapper"> \ |
| 13 | + <form action="rate" method="post" id="article-assessment"> \ |
| 14 | + <fieldset id="article-assessment-rate"> \ |
| 15 | + <legend></legend> \ |
| 16 | + <div class="article-assessment-information"> \ |
| 17 | + <span class="article-assessment-rate-instructions"></span> \ |
| 18 | + <span class="article-assessment-rate-feedback"></span> \ |
| 19 | + </div> \ |
| 20 | + <div class="article-assessment-rating-fields"></div> \ |
| 21 | + <div class="article-assessment-submit"> \ |
| 22 | + <input type="submit" value="Submit" /> \ |
| 23 | + </div> \ |
| 24 | + </fieldset> \ |
| 25 | + <fieldset id="article-assessment-ratings"> \ |
| 26 | + <legend></legend> \ |
| 27 | + <div class="article-assessment-information"> \ |
| 28 | + <span class="article-assessment-show-ratings"></span> \ |
| 29 | + <span class="article-assessment-hide-ratings"></span> \ |
| 30 | + </div> \ |
| 31 | + </fieldset> \ |
| 32 | + </form> \ |
| 33 | + </div>','ratingHTML':'<div class="article-assessment-rating"> \ |
| 34 | + <span class="article-assessment-rating-field-name"></span> \ |
| 35 | + <span class="article-assessment-rating-field-value-wrapper"> \ |
| 36 | + <span class="article-assessment-rating-field-value">0%</span> \ |
| 37 | + </span> \ |
| 38 | + <span class="article-assessment-rating-count"></span> \ |
| 39 | + </div>'},'fn':{'init':function($$options){var settings=$.extend({},$.ArticleAssessment.settings,$$options);var config=$.ArticleAssessment.config;var userToken=$.cookie('mwArticleAssessmentUserToken');if(typeof userToken=='undefined'||userToken==null){function randomString(string_length){var chars="0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz";var randomstring='';for(var i=0;i<string_length;i++){var rnum=Math.floor(Math.random()*chars.length);randomstring+=chars.substring(rnum,rnum+1);} |
| 40 | +return randomstring;} |
| 41 | +userToken=randomString(32);$.cookie('mwArticleAssessmentUserToken',userToken,{'expires':30,'path':'/'});} |
| 42 | +if(!wgUserName){config.userID=userToken;} |
| 43 | +var $structure=$(settings.structureHTML),instructions=$.ArticleAssessment.fn.getMsg('articleassessment-pleaserate'),feedback=$.ArticleAssessment.fn.getMsg('articleassessment-featurefeedback'),yourfeedback=$.ArticleAssessment.fn.getMsg('articleassessment-yourfeedback'),articlerating=$.ArticleAssessment.fn.getMsg('articleassessment-articlerating'),resultshide=$.ArticleAssessment.fn.getMsg('articleassessment-results-hide'),resultsshow=$.ArticleAssessment.fn.getMsg('articleassessment-results-show');submitbutton=$.ArticleAssessment.fn.getMsg('articleassessment-submit');$structure.find('#article-assessment-rate legend').text(yourfeedback).end().find('.article-assessment-rate-instructions').text(instructions).end().find('.article-assessment-rate-feedback').html(feedback).find('.feedbacklink').wrap('<a href="#"></a>').parent().click($.ArticleAssessment.fn.showFeedback).end().end().end().find('#article-assessment-ratings legend').text(articlerating).end().find('.article-assessment-show-ratings').html(resultsshow).find('.showlink').wrap('<a href="#"></a>').parent().click($.ArticleAssessment.fn.showRatings).end().end().end().find('.article-assessment-hide-ratings').html(resultshide).find('.hidelink').wrap('<a href="#"></a>').parent().click($.ArticleAssessment.fn.hideRatings).end().end().end().find('.article-assessment-submit input').attr("value",submitbutton).end();if($.cookie('mwArticleAssessmentHideFeedback')){$structure.find('.article-assessment-rate-feedback').hide();} |
| 44 | +for(var i=0;i<settings.fieldMessages.length;i++){var $field=$(settings.fieldHTML),$rating=$(settings.ratingHTML),label=$.ArticleAssessment.fn.getMsg(settings.fieldPrefix+settings.fieldMessages[i]),field=settings.fieldMessages[i],hint=$.ArticleAssessment.fn.getMsg(settings.fieldPrefix+settings.fieldMessages[i]+settings.fieldHintSuffix),count=$.ArticleAssessment.fn.getMsg('articleassessment-noratings',[0,0]);$field.attr('id','articleassessment-rate-'+field).find('label').attr('for','rating_'+field).attr('original-title',hint).text(label).end().find('select').attr('id','rating_'+field).attr('name','rating['+field+']');$rating.attr('id','articleassessment-rating-'+field).find('.article-assessment-rating-field-name').text(label).end().find('.article-assessment-rating-count').text(count);$structure.find('.article-assessment-rating-fields').append($field).end().find('#article-assessment-ratings').append($rating);} |
| 45 | +$structure.find('#article-assessment').data('articleAssessment-context',{'settings':settings,'config':config});$('#catlinks').before($structure);$.ArticleAssessment.fn.hideRatings();if($('#article-assessment-rate').height()>$('#article-assessment-ratings').height()){$('#article-assessment-ratings').css('minHeight',$('#article-assessment-rate').height());}else{$('#article-assessment-rate').css('minHeight',$('#article-assessment-ratings').height());} |
| 46 | +$.ArticleAssessment.fn.getRatingData();$('.rating-field').each(function(){$(this).wrapAll('<div class="rating-field"></div>').parent().stars({inputType:'select',callback:function(value,link){value.$stars.each(function(){$(this).removeClass('ui-stars-star-stale').removeClass('ui-stars-star-rated');$('#article-assessment input:disabled').removeAttr('disabled');});}});});$('.field-wrapper label[original-title]').each(function(){$(this).after($('<span class="rating-field-hint" />').attr('original-title',$(this).attr('original-title')).tipsy({gravity:'se',opacity:'0.9'}));});$('#article-assessment').submit(function(){$.ArticleAssessment.fn.submitRating();return false;});$('#article-assessment input[type=submit]').attr('disabled','disabled');},'showRatings':function(){$('#article-assessment-ratings').removeClass('article-assessment-ratings-disabled').find('.article-assessment-show-ratings').hide().end().find('.article-assessment-hide-ratings').show();return false;},'hideRatings':function(){$('#article-assessment-ratings').addClass('article-assessment-ratings-disabled').find('.article-assessment-hide-ratings').hide().end().find('.article-assessment-show-ratings').show();return false;},'getRatingData':function(){var config=$('#article-assessment').data('articleAssessment-context').config;var requestData={'action':'query','list':'articleassessment','aapageid':config.pageID,'aauserrating':1,'format':'json'} |
| 47 | +if(config.userID.length==32){requestData.aaanontoken=config.userID;} |
| 48 | +var request=$.ajax({url:wgScriptPath+'/api.php',data:requestData,dataType:'json',success:$.ArticleAssessment.fn.afterGetRatingData,error:function(XMLHttpRequest,textStatus,errorThrown){$.ArticleAssessment.fn.flashNotice($.ArticleAssessment.fn.getMsg('articleassessment-error'),{'class':'article-assessment-error-msg'});}});},'afterGetRatingData':function(data){var settings=$('#article-assessment').data('articleAssessment-context').settings;if(data.query&&data.query.articleassessment&&data.query.articleassessment.length>0){for(var r in data.query.articleassessment[0].ratings){var rating=data.query.articleassessment[0].ratings[r],$rating=$('#'+rating.ratingdesc),count=rating.count,total=(rating.total/count).toFixed(1),label=$.ArticleAssessment.fn.getMsg('articleassessment-noratings',[total,count]);$rating.find('.article-assessment-rating-field-value').text(total).end().find('.article-assessment-rating-count').text(label);if(rating.userrating){var $rateControl=$('#'+rating.ratingdesc.replace('rating','rate')+' .rating-field');$rateControl.stars('select',rating.userrating);$.ArticleAssessment.fn.showRatings();}} |
| 49 | +if(typeof data.query.articleassessment[0].stale!='undefined'){$('.ui-stars-star-on').addClass('ui-stars-star-stale');var msg=$.ArticleAssessment.fn.getMsg('articleassessment-stalemessage-norevisioncount');$.ArticleAssessment.fn.flashNotice(msg,{'class':'article-assessment-stale-msg'});}else{$('.ui-stars-star-on').addClass('ui-stars-star-rated');}} |
| 50 | +$('.article-assessment-rating-field-value').each(function(){$(this).css({'width':120-(120*(parseFloat($(this).text())/5))+'px'})});},'submitRating':function(){var config=$('#article-assessment').data('articleAssessment-context').config;$.ArticleAssessment.fn.flashNotice();$('.rating-field').stars('disable');$('#article-assessment input').attr('disabled','disabled');var results={};$('.rating-field input').each(function(){var fieldName=$(this).attr('name').match(/\[([a-zA-Z0-9\-]*)\]/)[1];results[fieldName]=$(this).val();});var request=$.ajax({url:wgScriptPath+'/api.php',type:'POST',data:{'action':'articleassessment','revid':config.revID,'pageid':config.pageID,'r1':results['wellsourced'],'r2':results['neutrality'],'r3':results['completeness'],'r4':results['readability'],'anontoken':config.userID,'format':'json'},dataType:'json',success:$.ArticleAssessment.fn.afterSubmitRating,error:function(XMLHttpRequest,textStatus,errorThrown){$.ArticleAssessment.fn.flashNotice($.ArticleAssessment.fn.getMsg('articleassessment-error'),{'class':'article-assessment-error-msg'});}});},'afterSubmitRating':function(data){$.ArticleAssessment.fn.getRatingData();$('.ui-stars-star-on').addClass('ui-stars-star-rated');$('.rating-field').stars('enable');$('#article-assessment input:disabled').removeAttr('disabled');$.ArticleAssessment.fn.showRatings();$.ArticleAssessment.fn.flashNotice($.ArticleAssessment.fn.getMsg('articleassessment-thanks'),{'class':'article-assessment-success-msg'});},'flashNotice':function(text,options){if(arguments.length==0){$('#article-assessment .article-assessment-flash').remove();}else{$('#article-assessment .article-assessment-flash').remove();var className=options['class'];$msg=$('<div />').addClass('article-assessment-flash').html(text);if(options['class']){$msg.addClass(options['class']);} |
| 51 | +$('#article-assessment .article-assessment-submit').append($msg);}},'showFeedback':function(){$.ArticleAssessment.fn.withJUI(function(){var $dialogDiv=$('#article-assessment-dialog');if($dialogDiv.size()==0){$dialogDiv=$('<div id="article-assessment-dialog" class="loading" />').dialog({width:600,height:400,bgiframe:true,autoOpen:true,modal:true,title:$.ArticleAssessment.fn.getMsg('articleassessment-survey-title'),close:function(){$(this).dialog('option','height',400).find('.article-assessment-success-msg, .article-assessment-error-msg').remove().end().find('form').show();}});$dialogDiv.load(wgScript+'?title=Special:SimpleSurvey&survey=articlerating&raw=1',function(){$(this).find('form').bind('submit',$.ArticleAssessment.fn.submitFeedback);$(this).removeClass('loading');});} |
| 52 | +$dialogDiv.dialog('open');});return false;},'submitFeedback':function(){var $dialogDiv=$('#article-assessment-dialog');$dialogDiv.find('form').hide().end().addClass('loading');var formData={};$dialogDiv.find('input').each(function(){var name=$(this).attr('name');if(name!==''){if(name.substr(-2)=='[]'){var trimmedName=name.substr(0,name.length-2);if(typeof formData[trimmedName]=='undefined'){formData[trimmedName]=[];} |
| 53 | +formData[trimmedName].push($(this).val());}else{formData[name]=$(this).val();}}});formData.title='Special:SimpleSurvey';$.ajax({url:wgScript,type:'POST',data:formData,dataType:'html',success:function(data){var success=$(data).find('.simplesurvey-success').size()>0;var $msgDiv=$('<div />').addClass(success?'article-assessment-success-msg':'article-assessment-error-msg').text($.ArticleAssessment.fn.getMsg(success?'articleassessment-survey-thanks':'articleassessment-error')).appendTo($dialogDiv);$dialogDiv.dialog('option','height',$msgDiv.height()+100).removeClass('loading');if(success){$('#article-assessment .article-assessment-rate-feedback').hide();$.cookie('mwArticleAssessmentHideFeedback',true,{'expires':30,'path':'/'});}},error:function(XMLHttpRequest,textStatus,errorThrown){var $msgDiv=$('<div />').addClass('article-assessment-error-msg').text($.ArticleAssessment.fn.getMsg('articleassessment-error')).appendTo($dialogDiv);$dialogDiv.dialog('option','height',$msgDiv.height()+100).removeClass('loading');}});return false;},'addMessages':function(messages){for(var key in messages){$.ArticleAssessment.messages[key]=messages[key];}},'getMsg':function(key,args){if(!(key in $.ArticleAssessment.messages)){return'['+key+']';} |
| 54 | +var msg=$.ArticleAssessment.messages[key];if(typeof args=='object'||typeof args=='array'){for(var i=0;i<args.length;i++){msg=msg.replace(new RegExp('\\$'+(parseInt(i)+1),'g'),args[i]);}}else if(typeof args=='string'||typeof args=='number'){msg=msg.replace(/\$1/g,args);} |
| 55 | +return msg;},'withJUI':function(callback){if(typeof $.ui=='undefined'){$.getScript(wgArticleAssessmentJUIPath,callback);}else{callback();}}}};$(document).ready(function(){$.ArticleAssessment.fn.init();});})(jQuery);jQuery.cookie=function(name,value,options){if(typeof value!='undefined'){options=options||{};if(value===null){value='';options.expires=-1;} |
| 56 | +var expires='';if(options.expires&&(typeof options.expires=='number'||options.expires.toUTCString)){var date;if(typeof options.expires=='number'){date=new Date();date.setTime(date.getTime()+(options.expires*24*60*60*1000));}else{date=options.expires;} |
| 57 | +expires='; expires='+date.toUTCString();} |
| 58 | +var path=options.path?'; path='+(options.path):'';var domain=options.domain?'; domain='+(options.domain):'';var secure=options.secure?'; secure':'';document.cookie=[name,'=',encodeURIComponent(value),expires,path,domain,secure].join('');}else{var cookieValue=null;if(document.cookie&&document.cookie!=''){var cookies=document.cookie.split(';');for(var i=0;i<cookies.length;i++){var cookie=jQuery.trim(cookies[i]);if(cookie.substring(0,name.length+1)==(name+'=')){cookieValue=decodeURIComponent(cookie.substring(name.length+1));break;}}} |
| 59 | +return cookieValue;}};(function($){$.stars={defaults:{inputType:'radio',split:0,disabled:false,cancelTitle:'Cancel Rating',cancelValue:0,cancelShow:true,disableValue:true,oneVoteOnly:false,showTitles:false,captionEl:null,callback:null,starWidth:16,cancelClass:'ui-stars-cancel',starClass:'ui-stars-star',starOnClass:'ui-stars-star-on',starHoverClass:'ui-stars-star-hover',starDisabledClass:'ui-stars-star-disabled',cancelHoverClass:'ui-stars-cancel-hover',cancelDisabledClass:'ui-stars-cancel-disabled'},create:function(){var self=this,o=this.options,starId=0;this.element.data('former.stars',this.element.html());o.isSelect=o.inputType=='select';this.$form=$(this.element).closest('form');this.$selec=o.isSelect?$('select',this.element):null;this.$rboxs=o.isSelect?$('option',this.$selec):$(':radio',this.element);this.$stars=this.$rboxs.map(function(i) |
| 60 | +{var el={value:this.value,title:(o.isSelect?this.text:this.title)||this.value,isDefault:(o.isSelect&&this.defaultSelected)||this.defaultChecked};if(i==0){o.split=typeof o.split!='number'?0:o.split;o.val2id=[];o.id2val=[];o.id2title=[];o.name=o.isSelect?self.$selec.get(0).name:this.name;o.disabled=o.disabled||(o.isSelect?$(self.$selec).attr('disabled'):$(this).attr('disabled'));} |
| 61 | +if(el.value==o.cancelValue){o.cancelTitle=el.title;return null;} |
| 62 | +o.val2id[el.value]=starId;o.id2val[starId]=el.value;o.id2title[starId]=el.title;if(el.isDefault){o.checked=starId;o.value=o.defaultValue=el.value;o.title=el.title;} |
| 63 | +var $s=$('<div/>').addClass(o.starClass);var $a=$('<a/>').attr('title',o.showTitles?el.title:'').text(el.value);if(o.split){var oddeven=(starId%o.split);var stwidth=Math.floor(o.starWidth/o.split);$s.width(stwidth);$a.css('margin-left','-'+(oddeven*stwidth)+'px');} |
| 64 | +starId++;return $s.append($a).get(0);});o.items=starId;o.isSelect?this.$selec.remove():this.$rboxs.remove();this.$cancel=$('<div/>').addClass(o.cancelClass).append($('<a/>').attr('title',o.showTitles?o.cancelTitle:'').text(o.cancelValue));o.cancelShow&=!o.disabled&&!o.oneVoteOnly;o.cancelShow&&this.element.append(this.$cancel);this.element.append(this.$stars);if(o.checked===undefined){o.checked=-1;o.value=o.defaultValue=o.cancelValue;o.title='';} |
| 65 | +this.$value=$("<input type='hidden' name='"+o.name+"' value='"+o.value+"' />");this.element.append(this.$value);this.$stars.bind('click.stars',function(e){if(!o.forceSelect&&o.disabled)return false;var i=self.$stars.index(this);o.checked=i;o.value=o.id2val[i];o.title=o.id2title[i];self.$value.attr({disabled:o.disabled?'disabled':'',value:o.value});fillTo(i,false);self.disableCancel();!o.forceSelect&&self.callback(e,'star');}).bind('mouseover.stars',function(){if(o.disabled)return false;var i=self.$stars.index(this);fillTo(i,true);}).bind('mouseout.stars',function(){if(o.disabled)return false;fillTo(self.options.checked,false);});this.$cancel.bind('click.stars',function(e){if(!o.forceSelect&&(o.disabled||o.value==o.cancelValue))return false;o.checked=-1;o.value=o.cancelValue;o.title='';self.$value.val(o.value);o.disableValue&&self.$value.attr({disabled:'disabled'});fillNone();self.disableCancel();!o.forceSelect&&self.callback(e,'cancel');}).bind('mouseover.stars',function(){if(self.disableCancel())return false;self.$cancel.addClass(o.cancelHoverClass);fillNone();self.showCap(o.cancelTitle);}).bind('mouseout.stars',function(){if(self.disableCancel())return false;self.$cancel.removeClass(o.cancelHoverClass);self.$stars.triggerHandler('mouseout.stars');});this.$form.bind('reset.stars',function(){!o.disabled&&self.select(o.defaultValue);});$(window).unload(function(){self.$cancel.unbind('.stars');self.$stars.unbind('.stars');self.$form.unbind('.stars');self.$selec=self.$rboxs=self.$stars=self.$value=self.$cancel=self.$form=null;});function fillTo(index,hover){if(index!=-1){var addClass=hover?o.starHoverClass:o.starOnClass;var remClass=hover?o.starOnClass:o.starHoverClass;self.$stars.eq(index).prevAll('.'+o.starClass).andSelf().removeClass(remClass).addClass(addClass);self.$stars.eq(index).nextAll('.'+o.starClass).removeClass(o.starHoverClass+' '+o.starOnClass);self.showCap(o.id2title[index]);} |
| 66 | +else fillNone();};function fillNone(){self.$stars.removeClass(o.starOnClass+' '+o.starHoverClass);self.showCap('');};this.select(o.value);o.disabled&&this.disable();},disableCancel:function(){var o=this.options,disabled=o.disabled||o.oneVoteOnly||(o.value==o.cancelValue);if(disabled)this.$cancel.removeClass(o.cancelHoverClass).addClass(o.cancelDisabledClass);else this.$cancel.removeClass(o.cancelDisabledClass);this.$cancel.css('opacity',disabled?0.5:1);return disabled;},disableAll:function(){var o=this.options;this.disableCancel();if(o.disabled)this.$stars.filter('div').addClass(o.starDisabledClass);else this.$stars.filter('div').removeClass(o.starDisabledClass);},showCap:function(s){var o=this.options;if(o.captionEl)o.captionEl.text(s);},value:function(){return this.options.value;},select:function(val){var o=this.options,e=(val==o.cancelValue)?this.$cancel:this.$stars.eq(o.val2id[val]);o.forceSelect=true;e.triggerHandler('click.stars');o.forceSelect=false;},selectID:function(id){var o=this.options,e=(id==-1)?this.$cancel:this.$stars.eq(id);o.forceSelect=true;e.triggerHandler('click.stars');o.forceSelect=false;},enable:function(){this.options.disabled=false;this.disableAll();},disable:function(){this.options.disabled=true;this.disableAll();},destroy:function(){this.$form.unbind('.stars');this.$cancel.unbind('.stars').remove();this.$stars.unbind('.stars').remove();this.$value.remove();this.element.unbind('.stars').html(this.element.data('former.stars')).removeData('stars');return this;},callback:function(e,type){var o=this.options;o.callback&&o.callback(this,type,o.value,e);o.oneVoteOnly&&!o.disabled&&this.disable();}} |
| 67 | +$.fn.stars=function(){var args=Array.prototype.slice.call(arguments);var out=$(this);$(this).each(function(){var context=$(this).data('stars-context');if(typeof context=='undefined'||context==null){context=$.extend({},{element:$(this),options:$.stars.defaults},$.stars);} |
| 68 | +if(args.length>0){if(typeof args[0]=='object'){context.options=$.extend({},context.options,args[0]);$.stars.create.call(context);}else if(typeof args[0]=='string'){var funcName=args[0];out=$.stars[funcName].call(context,args.slice(1))||out;}}else{$.stars.create.call(context);} |
| 69 | +$(this).data('stars-context',context);});return out;};})(jQuery);(function($){function Tipsy(element,options){this.$element=$(element);this.options=options;this.enabled=true;this.fixTitle();} |
| 70 | +Tipsy.prototype={show:function(){var title=this.getTitle();if(title&&this.enabled){var $tip=this.tip();$tip.find('.tipsy-inner')[this.options.html?'html':'text'](title);$tip[0].className='tipsy';$tip.remove().css({top:0,left:0,visibility:'hidden',display:'block'}).appendTo(document.body);var pos=$.extend({},this.$element.offset(),{width:this.$element[0].offsetWidth,height:this.$element[0].offsetHeight});var actualWidth=$tip[0].offsetWidth,actualHeight=$tip[0].offsetHeight;var gravity=(typeof this.options.gravity=='function')?this.options.gravity.call(this.$element[0]):this.options.gravity;var tp;switch(gravity.charAt(0)){case'n':tp={top:pos.top+pos.height+this.options.offset,left:pos.left+pos.width/2-actualWidth/2};break;case's':tp={top:pos.top-actualHeight-this.options.offset,left:pos.left+pos.width/2-actualWidth/2};break;case'e':tp={top:pos.top+pos.height/2-actualHeight/2,left:pos.left-actualWidth-this.options.offset};break;case'w':tp={top:pos.top+pos.height/2-actualHeight/2,left:pos.left+pos.width+this.options.offset};break;} |
| 71 | +if(gravity.length==2){if(gravity.charAt(1)=='w'){tp.left=pos.left+pos.width/2-15;}else{tp.left=pos.left+pos.width/2-actualWidth+15;}} |
| 72 | +$tip.css(tp).addClass('tipsy-'+gravity);if(this.options.fade){$tip.stop().css({opacity:0,display:'block',visibility:'visible'}).animate({opacity:this.options.opacity});}else{$tip.css({visibility:'visible',opacity:this.options.opacity});}}},hide:function(){if(this.options.fade){this.tip().stop().fadeOut(function(){$(this).remove();});}else{this.tip().remove();}},fixTitle:function(){var $e=this.$element;if($e.attr('title')||typeof($e.attr('original-title'))!='string'){$e.attr('original-title',$e.attr('title')||'').removeAttr('title');}},getTitle:function(){var title,$e=this.$element,o=this.options;this.fixTitle();var title,o=this.options;if(typeof o.title=='string'){title=$e.attr(o.title=='title'?'original-title':o.title);}else if(typeof o.title=='function'){title=o.title.call($e[0]);} |
| 73 | +title=(''+title).replace(/(^\s*|\s*$)/,"");return title||o.fallback;},tip:function(){if(!this.$tip){this.$tip=$('<div class="tipsy"></div>').html('<div class="tipsy-arrow"></div><div class="tipsy-inner"></div>');} |
| 74 | +return this.$tip;},validate:function(){if(!this.$element[0].parentNode){this.hide();this.$element=null;this.options=null;}},enable:function(){this.enabled=true;},disable:function(){this.enabled=false;},toggleEnabled:function(){this.enabled=!this.enabled;}};$.fn.tipsy=function(options){if(options===true){return this.data('tipsy');}else if(typeof options=='string'){var tipsy=this.data('tipsy');if(tipsy)tipsy[options]();return this;} |
| 75 | +options=$.extend({},$.fn.tipsy.defaults,options);function get(ele){var tipsy=$.data(ele,'tipsy');if(!tipsy){tipsy=new Tipsy(ele,$.fn.tipsy.elementOptions(ele,options));$.data(ele,'tipsy',tipsy);} |
| 76 | +return tipsy;} |
| 77 | +function enter(){var tipsy=get(this);tipsy.hoverState='in';if(options.delayIn==0){tipsy.show();}else{tipsy.fixTitle();setTimeout(function(){if(tipsy.hoverState=='in')tipsy.show();},options.delayIn);}};function leave(){var tipsy=get(this);tipsy.hoverState='out';if(options.delayOut==0){tipsy.hide();}else{setTimeout(function(){if(tipsy.hoverState=='out')tipsy.hide();},options.delayOut);}};if(!options.live)this.each(function(){get(this);});if(options.trigger!='manual'){var binder=options.live?'live':'bind',eventIn=options.trigger=='hover'?'mouseenter':'focus',eventOut=options.trigger=='hover'?'mouseleave':'blur';this[binder](eventIn,enter)[binder](eventOut,leave);} |
| 78 | +return this;};$.fn.tipsy.defaults={delayIn:0,delayOut:0,fade:false,fallback:'',gravity:'n',html:false,live:false,offset:0,opacity:0.8,title:'title',trigger:'hover'};$.fn.tipsy.elementOptions=function(ele,options){return $.metadata?$.extend({},options,$(ele).metadata()):options;};$.fn.tipsy.autoNS=function(){return $(this).offset().top>($(document).scrollTop()+$(window).height()/2)?'s':'n';};$.fn.tipsy.autoWE=function(){return $(this).offset().left>($(document).scrollLeft()+$(window).width()/2)?'e':'w';};})(jQuery); |
\ No newline at end of file |
Index: trunk/extensions/ArticleAssessmentPilot/Makefile |
— | — | @@ -0,0 +1,39 @@ |
| 2 | +# |
| 3 | +# Handy makefile to combine and minify css and javascript files |
| 4 | +# |
| 5 | +SHELL := /bin/bash |
| 6 | + |
| 7 | +JS := \ |
| 8 | + js/ArticleAssessment.js\ |
| 9 | + js/jquery.cookie.js\ |
| 10 | + js/jquery.stars.js\ |
| 11 | + js/jquery.tipsy.js |
| 12 | + |
| 13 | +all: \ |
| 14 | + js/ArticleAssessment.combined.min.js |
| 15 | + |
| 16 | + |
| 17 | +# JavaScript Combination |
| 18 | +js/ArticleAssessment.combined.js: $(JS) |
| 19 | + cat $(JS) > js/ArticleAssessment.combined.js |
| 20 | + |
| 21 | +# JavaScript Minification |
| 22 | + |
| 23 | +js/ArticleAssessment.combined.min.js: js/ArticleAssessment.combined.js jsmin |
| 24 | + if [ -e ./jsmin ]; then ./jsmin < js/ArticleAssessment.combined.js > js/ArticleAssessment.combined.min.js;\ |
| 25 | + else jsmin < js/ArticleAssessment.combined.js > js/ArticleAssessment.combined.min.js; fi |
| 26 | + |
| 27 | +# JSMin - For more info on JSMin, see: http://www.crockford.com/javascript/jsmin.html |
| 28 | + |
| 29 | +jsmin: |
| 30 | + type -P jsmin &>/dev/null || ( wget http://www.crockford.com/javascript/jsmin.c; gcc jsmin.c -o jsmin ) |
| 31 | + |
| 32 | +# Actions |
| 33 | + |
| 34 | +distclean: clean |
| 35 | + rm -rf jsmin |
| 36 | + rm -rf jsmin.c |
| 37 | + |
| 38 | +clean: |
| 39 | + rm -f js/ArticleAssessment.combined.* |
| 40 | + |