Index: trunk/extensions/ArticleFeedbackv5/modules/jquery.articleFeedbackv5/jquery.articleFeedbackv5.special.js |
— | — | @@ -24,7 +24,7 @@ |
25 | 25 | |
26 | 26 | ( function ( $ ) { |
27 | 27 | |
28 | | -// {{{ articleFeedbackv5 definition |
| 28 | +// {{{ articleFeedbackv5special definition |
29 | 29 | |
30 | 30 | // TODO: jam sort/filter options into URL anchors, and use them as defaults if present. |
31 | 31 | |
— | — | @@ -38,40 +38,37 @@ |
39 | 39 | $.articleFeedbackv5special.page = undefined; |
40 | 40 | |
41 | 41 | /** |
42 | | - * The name of the filter used to select feedback |
| 42 | + * The url to which to send the pull request |
43 | 43 | */ |
44 | | - $.articleFeedbackv5special.filter = 'comment'; |
| 44 | + $.articleFeedbackv5special.apiUrl = undefined; |
45 | 45 | |
46 | 46 | /** |
47 | | - * Some fitlers have values they need tobe passed (eg, permalinks) |
| 47 | + * Controls for the list: sort, filter, continue flag, etc |
48 | 48 | */ |
49 | | - $.articleFeedbackv5special.filterValue = undefined; |
| 49 | + $.articleFeedbackv5special.listControls = { |
| 50 | + filter: 'comment', |
| 51 | + filterValue: undefined, // Permalinks require a feedback ID |
| 52 | + sort: 'age', |
| 53 | + sortDirection: 'desc', |
| 54 | + limit: 25, |
| 55 | + continue: null |
| 56 | + }; |
50 | 57 | |
51 | 58 | /** |
52 | | - * The name of the sorting method used |
| 59 | + * User activity: for each feedback record on this page, anything the user |
| 60 | + * has done (flagged as abuse, marked as helpful/unhelpful) |
| 61 | + * |
| 62 | + * @var object |
53 | 63 | */ |
54 | | - $.articleFeedbackv5special.sort = 'age'; |
| 64 | + $.articleFeedbackv5special.activity = {}; |
55 | 65 | |
56 | 66 | /** |
57 | | - * The dorection of the sorting method used |
| 67 | + * User activity cookie name (page id is appended on init) |
| 68 | + * |
| 69 | + * @var string |
58 | 70 | */ |
59 | | - $.articleFeedbackv5special.sortDirection = 'desc'; |
| 71 | + $.articleFeedbackv5special.activityCookieName = 'activity-'; |
60 | 72 | |
61 | | - /** |
62 | | - * The number of responses to display per data pull |
63 | | - */ |
64 | | - $.articleFeedbackv5special.limit = 25; |
65 | | - |
66 | | - /** |
67 | | - * The index at which to start the pull |
68 | | - */ |
69 | | - $.articleFeedbackv5special.continue = null; |
70 | | - |
71 | | - /** |
72 | | - * The url to which to send the request |
73 | | - */ |
74 | | - $.articleFeedbackv5special.apiUrl = undefined; |
75 | | - |
76 | 73 | // }}} |
77 | 74 | // {{{ Init methods |
78 | 75 | |
— | — | @@ -82,8 +79,6 @@ |
83 | 80 | */ |
84 | 81 | $.articleFeedbackv5special.setup = function() { |
85 | 82 | // Set up config vars, event binds, and do initial fetch. |
86 | | - aft5_debug( mw ); |
87 | | - aft5_debug( mw.util ); |
88 | 83 | $.articleFeedbackv5special.apiUrl = mw.util.wikiScript( 'api' ); |
89 | 84 | $.articleFeedbackv5special.page = mw.config.get( 'afPageId' ); |
90 | 85 | $.articleFeedbackv5special.setBinds(); |
— | — | @@ -92,10 +87,14 @@ |
93 | 88 | // Permalinks. |
94 | 89 | var id = window.location.hash.match(/id=(\d+)/) |
95 | 90 | if( id ) { |
96 | | - $.articleFeedbackv5special.filter = 'id'; |
97 | | - $.articleFeedbackv5special.filterValue = id[1]; |
| 91 | + $.articleFeedbackv5special.listControls.filter = 'id'; |
| 92 | + $.articleFeedbackv5special.listControls.filterValue = id[1]; |
98 | 93 | } |
99 | 94 | |
| 95 | + // Grab the user's activity out of the cookie |
| 96 | + $.articleFeedbackv5special.activityCookieName += $.articleFeedbackv5special.page; |
| 97 | + $.articleFeedbackv5special.loadActivity(); |
| 98 | + |
100 | 99 | // Initial load |
101 | 100 | $.articleFeedbackv5special.loadFeedback( true ); |
102 | 101 | }; |
— | — | @@ -108,25 +107,25 @@ |
109 | 108 | */ |
110 | 109 | $.articleFeedbackv5special.setBinds = function() { |
111 | 110 | $( '#articleFeedbackv5-filter-select' ).bind( 'change', function( e ) { |
112 | | - $.articleFeedbackv5special.filter = $(this).val(); |
113 | | - $.articleFeedbackv5special.continue = null; |
| 111 | + $.articleFeedbackv5special.listControls.filter = $(this).val(); |
| 112 | + $.articleFeedbackv5special.listControls.continue = null; |
114 | 113 | $.articleFeedbackv5special.loadFeedback( true ); |
115 | 114 | return false; |
116 | 115 | } ); |
117 | 116 | |
118 | 117 | $( '.articleFeedbackv5-sort-link' ).bind( 'click', function( e ) { |
119 | 118 | id = $.articleFeedbackv5special.stripID( this, 'articleFeedbackv5-special-sort-' ); |
120 | | - oldId = $.articleFeedbackv5special.sort; |
| 119 | + oldId = $.articleFeedbackv5special.listControls.sort; |
121 | 120 | |
122 | 121 | // set direction = desc... |
123 | | - $.articleFeedbackv5special.sort = id; |
124 | | - $.articleFeedbackv5special.continue = null; |
| 122 | + $.articleFeedbackv5special.listControls.sort = id; |
| 123 | + $.articleFeedbackv5special.listControls.continue = null; |
125 | 124 | |
126 | 125 | // unless we're flipping the direction on the current sort. |
127 | | - if( id == oldId && $.articleFeedbackv5special.sortDirection == 'desc' ) { |
128 | | - $.articleFeedbackv5special.sortDirection = 'asc'; |
| 126 | + if( id == oldId && $.articleFeedbackv5special.listControls.sortDirection == 'desc' ) { |
| 127 | + $.articleFeedbackv5special.listControls.sortDirection = 'asc'; |
129 | 128 | } else { |
130 | | - $.articleFeedbackv5special.sortDirection = 'desc'; |
| 129 | + $.articleFeedbackv5special.listControls.sortDirection = 'desc'; |
131 | 130 | } |
132 | 131 | |
133 | 132 | $.articleFeedbackv5special.loadFeedback( true ); |
— | — | @@ -143,9 +142,9 @@ |
144 | 143 | |
145 | 144 | $( '.articleFeedbackv5-permalink' ).live( 'click', function( e ) { |
146 | 145 | id = $.articleFeedbackv5special.stripID( this, 'articleFeedbackv5-permalink-' ); |
147 | | - $.articleFeedbackv5special.filter = 'id'; |
148 | | - $.articleFeedbackv5special.filterValue = id; |
149 | | - $.articleFeedbackv5special.continue = null; |
| 146 | + $.articleFeedbackv5special.listControls.filter = 'id'; |
| 147 | + $.articleFeedbackv5special.listControls.filterValue = id; |
| 148 | + $.articleFeedbackv5special.listControls.continue = null; |
150 | 149 | $.articleFeedbackv5special.loadFeedback( true ); |
151 | 150 | } ); |
152 | 151 | |
— | — | @@ -176,8 +175,6 @@ |
177 | 176 | // }}} |
178 | 177 | // {{{ Utility methods |
179 | 178 | |
180 | | - |
181 | | - |
182 | 179 | // {{{ toggleComment |
183 | 180 | $.articleFeedbackv5special.toggleComment = function( id ) { |
184 | 181 | if( $( '#articleFeedbackv5-comment-toggle-' + id ).text() |
— | — | @@ -194,14 +191,14 @@ |
195 | 192 | mw.msg( 'articlefeedbackv5-comment-more' ) |
196 | 193 | ); |
197 | 194 | } |
198 | | - } |
| 195 | + }; |
| 196 | + |
199 | 197 | // }}} |
200 | | - |
201 | 198 | // {{{ drawSortArrow |
202 | 199 | |
203 | 200 | $.articleFeedbackv5special.drawSortArrow = function() { |
204 | | - id = $.articleFeedbackv5special.sort; |
205 | | - dir = $.articleFeedbackv5special.sortDirection; |
| 201 | + id = $.articleFeedbackv5special.listControls.sort; |
| 202 | + dir = $.articleFeedbackv5special.listControls.sortDirection; |
206 | 203 | |
207 | 204 | $( '.articleFeedbackv5-sort-arrow' ).hide(); |
208 | 205 | $( '.articleFeedbackv5-sort-link' ).removeClass( 'sort-active' ); |
— | — | @@ -211,7 +208,7 @@ |
212 | 209 | 'src', '/extensions/ArticleFeedbackv5/modules/jquery.articleFeedbackv5/images/sort-' + dir + 'ending.png' |
213 | 210 | ); |
214 | 211 | $( '#articleFeedbackv5-special-sort-' + id).addClass( 'sort-active' ); |
215 | | - } |
| 212 | + }; |
216 | 213 | |
217 | 214 | // }}} |
218 | 215 | // {{{ stripID |
— | — | @@ -219,11 +216,101 @@ |
220 | 217 | // Utility method for stripping long IDs down to the specific bits we care about. |
221 | 218 | $.articleFeedbackv5special.stripID = function( object, toRemove ) { |
222 | 219 | return $( object ).attr( 'id' ).replace( toRemove, '' ); |
223 | | - } |
| 220 | + }; |
224 | 221 | |
225 | 222 | // }}} |
| 223 | + // {{{ prefix |
226 | 224 | |
| 225 | + /** |
| 226 | + * Utility method: Prefixes a key for cookies or events with extension and |
| 227 | + * version information |
| 228 | + * |
| 229 | + * @param key string name of event to prefix |
| 230 | + * @return string prefixed event name |
| 231 | + */ |
| 232 | + $.articleFeedbackv5special.prefix = function ( key ) { |
| 233 | + var version = mw.config.get( 'wgArticleFeedbackv5Tracking' ).version || 0; |
| 234 | + return 'ext.articleFeedbackv5@' + version + '-' + key; |
| 235 | + }; |
| 236 | + |
227 | 237 | // }}} |
| 238 | + // {{{ encodeActivity |
| 239 | + |
| 240 | + /** |
| 241 | + * Utility method: Turns the user activity object into an encoded string |
| 242 | + * |
| 243 | + * @param activity object the activity object |
| 244 | + * @return string the encoded string |
| 245 | + */ |
| 246 | + $.articleFeedbackv5special.encodeActivity = function ( activity ) { |
| 247 | + var encoded = ''; |
| 248 | + for ( var fb in activity ) { |
| 249 | + var info = activity[fb]; |
| 250 | + var buffer = fb + ':'; |
| 251 | + if ( info.helpful ) { |
| 252 | + buffer += 'H'; |
| 253 | + } else if ( info.unhelpful ) { |
| 254 | + buffer += 'U'; |
| 255 | + } |
| 256 | + if ( info.abuse ) { |
| 257 | + buffer += 'A'; |
| 258 | + } |
| 259 | + if ( info.hide ) { |
| 260 | + buffer += 'I'; |
| 261 | + } |
| 262 | + if ( info.delete ) { |
| 263 | + buffer += 'D'; |
| 264 | + } |
| 265 | + encoded += encoded == '' ? buffer : ';' + buffer; |
| 266 | + } |
| 267 | + return encoded; |
| 268 | + }; |
| 269 | + |
| 270 | + // }}} |
| 271 | + // {{{ decodeActivity |
| 272 | + |
| 273 | + /** |
| 274 | + * Utility method: Turns the encoded string into a user activity object |
| 275 | + * |
| 276 | + * @param encoded string the encoded string |
| 277 | + * @return object the activity object |
| 278 | + */ |
| 279 | + $.articleFeedbackv5special.decodeActivity = function ( encoded ) { |
| 280 | + var entries = encoded.split( ';' ); |
| 281 | + var activity = {}; |
| 282 | + for ( var i = 0; i < entries.length; ++i ) { |
| 283 | + var parts = entries[i].split( ':' ); |
| 284 | + if ( parts.length != 2 ) { |
| 285 | + continue; |
| 286 | + } |
| 287 | + var fb = parts[0]; |
| 288 | + var info = parts[1]; |
| 289 | + var obj = { helpful: false, unhelpful: false, abuse: false, hide: false, delete: false }; |
| 290 | + if ( fb.length > 0 && info.length > 0 ) { |
| 291 | + if ( info.search( /H/ ) != -1 ) { |
| 292 | + obj.helpful = true; |
| 293 | + } |
| 294 | + if ( info.search( /U/ ) != -1 ) { |
| 295 | + obj.unhelpful = true; |
| 296 | + } |
| 297 | + if ( info.search( /A/ ) != -1 ) { |
| 298 | + obj.abuse = true; |
| 299 | + } |
| 300 | + if ( info.search( /I/ ) != -1 ) { |
| 301 | + obj.hide = true; |
| 302 | + } |
| 303 | + if ( info.search( /D/ ) != -1 ) { |
| 304 | + obj.delete = true; |
| 305 | + } |
| 306 | + activity[fb] = obj; |
| 307 | + } |
| 308 | + } |
| 309 | + return activity; |
| 310 | + }; |
| 311 | + |
| 312 | + // }}} |
| 313 | + |
| 314 | + // }}} |
228 | 315 | // {{{ Process methods |
229 | 316 | |
230 | 317 | // {{{ flagFeedback |
— | — | @@ -232,7 +319,7 @@ |
233 | 320 | * Sends the request to mark a response |
234 | 321 | * |
235 | 322 | * @param id int the feedback id |
236 | | - * @param type string the type of mark (valid values: hide, abuse, delete, helpful, unhelpful |
| 323 | + * @param type string the type of mark (valid values: hide, abuse, delete, helpful, unhelpful) |
237 | 324 | */ |
238 | 325 | $.articleFeedbackv5special.flagFeedback = function ( id, type ) { |
239 | 326 | $.ajax( { |
— | — | @@ -250,14 +337,18 @@ |
251 | 338 | var msg = 'articlefeedbackv5-error-flagging'; |
252 | 339 | if ( 'articlefeedbackv5-flag-feedback' in data ) { |
253 | 340 | if ( 'result' in data['articlefeedbackv5-flag-feedback'] ) { |
254 | | - if( data['articlefeedbackv5-flag-feedback'].result == 'Success' ) { |
| 341 | + if ( data['articlefeedbackv5-flag-feedback'].result == 'Success' ) { |
255 | 342 | msg = 'articlefeedbackv5-' + type + '-saved'; |
256 | | - if( 'helpful' in data['articlefeedbackv5-flag-feedback'] ) { |
257 | | - |
| 343 | + if ( 'helpful' in data['articlefeedbackv5-flag-feedback'] ) { |
258 | 344 | $( '#articleFeedbackv5-helpful-votes-' + id ).text( data['articlefeedbackv5-flag-feedback'].helpful ); |
259 | | - |
260 | 345 | } |
261 | | - } else if (data['articlefeedbackv5-flag-feedback'].result == 'Error' ) { |
| 346 | + // Save activity |
| 347 | + if ( !( id in $.articleFeedbackv5special.activity ) ) { |
| 348 | + $.articleFeedbackv5special.activity[id] = { helpful: false, unhelpful: false, abuse: false, hide: false, delete: false }; |
| 349 | + } |
| 350 | + $.articleFeedbackv5special.activity[id][type] = true; |
| 351 | + $.articleFeedbackv5special.storeActivity(); |
| 352 | + } else if ( data['articlefeedbackv5-flag-feedback'].result == 'Error' ) { |
262 | 353 | msg = data['articlefeedbackv5-flag-feedback'].reason; |
263 | 354 | } |
264 | 355 | } |
— | — | @@ -290,12 +381,12 @@ |
291 | 382 | 'dataType': 'json', |
292 | 383 | 'data' : { |
293 | 384 | 'afvfpageid' : $.articleFeedbackv5special.page, |
294 | | - 'afvffilter' : $.articleFeedbackv5special.filter, |
295 | | - 'afvffiltervalue' : $.articleFeedbackv5special.filterValue, |
296 | | - 'afvfsort' : $.articleFeedbackv5special.sort, |
297 | | - 'afvfsortdirection' : $.articleFeedbackv5special.sortDirection, |
298 | | - 'afvflimit' : $.articleFeedbackv5special.limit, |
299 | | - 'afvfcontinue' : $.articleFeedbackv5special.continue, |
| 385 | + 'afvffilter' : $.articleFeedbackv5special.listControls.filter, |
| 386 | + 'afvffiltervalue' : $.articleFeedbackv5special.listControls.filterValue, |
| 387 | + 'afvfsort' : $.articleFeedbackv5special.listControls.sort, |
| 388 | + 'afvfsortdirection' : $.articleFeedbackv5special.listControls.sortDirection, |
| 389 | + 'afvflimit' : $.articleFeedbackv5special.listControls.limit, |
| 390 | + 'afvfcontinue' : $.articleFeedbackv5special.listControls.continue, |
300 | 391 | 'action' : 'query', |
301 | 392 | 'format' : 'json', |
302 | 393 | 'list' : 'articlefeedbackv5-view-feedback', |
— | — | @@ -309,7 +400,7 @@ |
310 | 401 | $( '#articleFeedbackv5-show-feedback' ).append( data['articlefeedbackv5-view-feedback'].feedback); |
311 | 402 | } |
312 | 403 | $( '#articleFeedbackv5-feedback-count-total' ).text( data['articlefeedbackv5-view-feedback'].count ); |
313 | | - $.articleFeedbackv5special.continue = data['articlefeedbackv5-view-feedback'].continue; |
| 404 | + $.articleFeedbackv5special.listControls.continue = data['articlefeedbackv5-view-feedback'].continue; |
314 | 405 | // set effects on toolboxes |
315 | 406 | $( '.articleFeedbackv5-feedback-tools > ul' ).hide(); |
316 | 407 | $( '.articleFeedbackv5-feedback-tools' ).hover( |
— | — | @@ -336,9 +427,37 @@ |
337 | 428 | } |
338 | 429 | |
339 | 430 | // }}} |
| 431 | + // {{{ loadActivity |
340 | 432 | |
| 433 | + /** |
| 434 | + * Loads the user activity from the cookie |
| 435 | + */ |
| 436 | + $.articleFeedbackv5special.loadActivity = function () { |
| 437 | + var flatActivity = $.cookie( $.articleFeedbackv5special.prefix( $.articleFeedbackv5special.activityCookieName ) ); |
| 438 | + if ( flatActivity ) { |
| 439 | + $.articleFeedbackv5special.activity = $.articleFeedbackv5special.decodeActivity( flatActivity ); |
| 440 | + } |
| 441 | + } |
| 442 | + |
341 | 443 | // }}} |
| 444 | + // {{{ storeActivity |
342 | 445 | |
| 446 | + /** |
| 447 | + * Stores the user activity to the cookie |
| 448 | + */ |
| 449 | + $.articleFeedbackv5special.storeActivity = function () { |
| 450 | + var flatActivity = $.articleFeedbackv5special.encodeActivity( $.articleFeedbackv5special.activity ); |
| 451 | + $.cookie( |
| 452 | + $.articleFeedbackv5special.prefix( $.articleFeedbackv5special.activityCookieName ), |
| 453 | + flatActivity, |
| 454 | + { 'expires': 365, 'path': '/' } |
| 455 | + ); |
| 456 | + } |
| 457 | + |
| 458 | + // }}} |
| 459 | + |
| 460 | + // }}} |
| 461 | + |
343 | 462 | // }}} |
344 | 463 | |
345 | 464 | } )( jQuery ); |