Index: trunk/extensions/Reviews/api/ApiSubmitReview.php |
— | — | @@ -71,7 +71,7 @@ |
72 | 72 | return array( |
73 | 73 | 'id' => 'The ID of the review being submitted.', |
74 | 74 | 'name' => 'The name of the review being submitted.', |
75 | | - 'token' => 'Edit token. You can get one of these through prop=info.', |
| 75 | + 'token' => 'Submission token.', |
76 | 76 | ); |
77 | 77 | } |
78 | 78 | |
Index: trunk/extensions/Reviews/Reviews.php |
— | — | @@ -109,12 +109,6 @@ |
110 | 110 | 'remoteExtPath' => 'Reviews/resources' |
111 | 111 | ); |
112 | 112 | |
113 | | -$wgResourceModules['reviews.JSON'] = $moduleTemplate + array( |
114 | | - 'scripts' => array( |
115 | | - 'JSON.js', |
116 | | - ), |
117 | | -); |
118 | | - |
119 | 113 | $wgResourceModules['ext.reviews'] = $moduleTemplate + array( |
120 | 114 | 'scripts' => array( |
121 | 115 | 'reviews.js', |
— | — | @@ -133,7 +127,7 @@ |
134 | 128 | 'messages' => array( |
135 | 129 | ), |
136 | 130 | 'dependencies' => array( |
137 | | - 'reviews.JSON', 'ext.reviews' |
| 131 | + 'jquery.json', 'ext.reviews' |
138 | 132 | ), |
139 | 133 | ); |
140 | 134 | |
Index: trunk/extensions/Reviews/resources/JSON.js |
— | — | @@ -1,480 +0,0 @@ |
2 | | -/* |
3 | | - http://www.JSON.org/json2.js |
4 | | - 2011-02-23 |
5 | | - |
6 | | - Public Domain. |
7 | | - |
8 | | - NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. |
9 | | - |
10 | | - See http://www.JSON.org/js.html |
11 | | - |
12 | | - |
13 | | - This code should be minified before deployment. |
14 | | - See http://javascript.crockford.com/jsmin.html |
15 | | - |
16 | | - USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO |
17 | | - NOT CONTROL. |
18 | | - |
19 | | - |
20 | | - This file creates a global JSON object containing two methods: stringify |
21 | | - and parse. |
22 | | - |
23 | | - JSON.stringify(value, replacer, space) |
24 | | - value any JavaScript value, usually an object or array. |
25 | | - |
26 | | - replacer an optional parameter that determines how object |
27 | | - values are stringified for objects. It can be a |
28 | | - function or an array of strings. |
29 | | - |
30 | | - space an optional parameter that specifies the indentation |
31 | | - of nested structures. If it is omitted, the text will |
32 | | - be packed without extra whitespace. If it is a number, |
33 | | - it will specify the number of spaces to indent at each |
34 | | - level. If it is a string (such as '\t' or ' '), |
35 | | - it contains the characters used to indent at each level. |
36 | | - |
37 | | - This method produces a JSON text from a JavaScript value. |
38 | | - |
39 | | - When an object value is found, if the object contains a toJSON |
40 | | - method, its toJSON method will be called and the result will be |
41 | | - stringified. A toJSON method does not serialize: it returns the |
42 | | - value represented by the name/value pair that should be serialized, |
43 | | - or undefined if nothing should be serialized. The toJSON method |
44 | | - will be passed the key associated with the value, and this will be |
45 | | - bound to the value |
46 | | - |
47 | | - For example, this would serialize Dates as ISO strings. |
48 | | - |
49 | | - Date.prototype.toJSON = function (key) { |
50 | | - function f(n) { |
51 | | - // Format integers to have at least two digits. |
52 | | - return n < 10 ? '0' + n : n; |
53 | | - } |
54 | | - |
55 | | - return this.getUTCFullYear() + '-' + |
56 | | - f(this.getUTCMonth() + 1) + '-' + |
57 | | - f(this.getUTCDate()) + 'T' + |
58 | | - f(this.getUTCHours()) + ':' + |
59 | | - f(this.getUTCMinutes()) + ':' + |
60 | | - f(this.getUTCSeconds()) + 'Z'; |
61 | | - }; |
62 | | - |
63 | | - You can provide an optional replacer method. It will be passed the |
64 | | - key and value of each member, with this bound to the containing |
65 | | - object. The value that is returned from your method will be |
66 | | - serialized. If your method returns undefined, then the member will |
67 | | - be excluded from the serialization. |
68 | | - |
69 | | - If the replacer parameter is an array of strings, then it will be |
70 | | - used to select the members to be serialized. It filters the results |
71 | | - such that only members with keys listed in the replacer array are |
72 | | - stringified. |
73 | | - |
74 | | - Values that do not have JSON representations, such as undefined or |
75 | | - functions, will not be serialized. Such values in objects will be |
76 | | - dropped; in arrays they will be replaced with null. You can use |
77 | | - a replacer function to replace those with JSON values. |
78 | | - JSON.stringify(undefined) returns undefined. |
79 | | - |
80 | | - The optional space parameter produces a stringification of the |
81 | | - value that is filled with line breaks and indentation to make it |
82 | | - easier to read. |
83 | | - |
84 | | - If the space parameter is a non-empty string, then that string will |
85 | | - be used for indentation. If the space parameter is a number, then |
86 | | - the indentation will be that many spaces. |
87 | | - |
88 | | - Example: |
89 | | - |
90 | | - text = JSON.stringify(['e', {pluribus: 'unum'}]); |
91 | | - // text is '["e",{"pluribus":"unum"}]' |
92 | | - |
93 | | - |
94 | | - text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t'); |
95 | | - // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]' |
96 | | - |
97 | | - text = JSON.stringify([new Date()], function (key, value) { |
98 | | - return this[key] instanceof Date ? |
99 | | - 'Date(' + this[key] + ')' : value; |
100 | | - }); |
101 | | - // text is '["Date(---current time---)"]' |
102 | | - |
103 | | - |
104 | | - JSON.parse(text, reviver) |
105 | | - This method parses a JSON text to produce an object or array. |
106 | | - It can throw a SyntaxError exception. |
107 | | - |
108 | | - The optional reviver parameter is a function that can filter and |
109 | | - transform the results. It receives each of the keys and values, |
110 | | - and its return value is used instead of the original value. |
111 | | - If it returns what it received, then the structure is not modified. |
112 | | - If it returns undefined then the member is deleted. |
113 | | - |
114 | | - Example: |
115 | | - |
116 | | - // Parse the text. Values that look like ISO date strings will |
117 | | - // be converted to Date objects. |
118 | | - |
119 | | - myData = JSON.parse(text, function (key, value) { |
120 | | - var a; |
121 | | - if (typeof value === 'string') { |
122 | | - a = |
123 | | -/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value); |
124 | | - if (a) { |
125 | | - return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4], |
126 | | - +a[5], +a[6])); |
127 | | - } |
128 | | - } |
129 | | - return value; |
130 | | - }); |
131 | | - |
132 | | - myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) { |
133 | | - var d; |
134 | | - if (typeof value === 'string' && |
135 | | - value.slice(0, 5) === 'Date(' && |
136 | | - value.slice(-1) === ')') { |
137 | | - d = new Date(value.slice(5, -1)); |
138 | | - if (d) { |
139 | | - return d; |
140 | | - } |
141 | | - } |
142 | | - return value; |
143 | | - }); |
144 | | - |
145 | | - |
146 | | - This is a reference implementation. You are free to copy, modify, or |
147 | | - redistribute. |
148 | | -*/ |
149 | | - |
150 | | -/*jslint evil: true, strict: false, regexp: false */ |
151 | | - |
152 | | -/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply, |
153 | | - call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours, |
154 | | - getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join, |
155 | | - lastIndex, length, parse, prototype, push, replace, slice, stringify, |
156 | | - test, toJSON, toString, valueOf |
157 | | -*/ |
158 | | - |
159 | | - |
160 | | -// Create a JSON object only if one does not already exist. We create the |
161 | | -// methods in a closure to avoid creating global variables. |
162 | | - |
163 | | -var JSON; |
164 | | -if (!JSON) { |
165 | | - JSON = {}; |
166 | | -} |
167 | | - |
168 | | -(function () { |
169 | | - "use strict"; |
170 | | - |
171 | | - function f(n) { |
172 | | - // Format integers to have at least two digits. |
173 | | - return n < 10 ? '0' + n : n; |
174 | | - } |
175 | | - |
176 | | - if (typeof Date.prototype.toJSON !== 'function') { |
177 | | - |
178 | | - Date.prototype.toJSON = function (key) { |
179 | | - |
180 | | - return isFinite(this.valueOf()) ? |
181 | | - this.getUTCFullYear() + '-' + |
182 | | - f(this.getUTCMonth() + 1) + '-' + |
183 | | - f(this.getUTCDate()) + 'T' + |
184 | | - f(this.getUTCHours()) + ':' + |
185 | | - f(this.getUTCMinutes()) + ':' + |
186 | | - f(this.getUTCSeconds()) + 'Z' : null; |
187 | | - }; |
188 | | - |
189 | | - String.prototype.toJSON = |
190 | | - Number.prototype.toJSON = |
191 | | - Boolean.prototype.toJSON = function (key) { |
192 | | - return this.valueOf(); |
193 | | - }; |
194 | | - } |
195 | | - |
196 | | - var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, |
197 | | - escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, |
198 | | - gap, |
199 | | - indent, |
200 | | - meta = { // table of character substitutions |
201 | | - '\b': '\\b', |
202 | | - '\t': '\\t', |
203 | | - '\n': '\\n', |
204 | | - '\f': '\\f', |
205 | | - '\r': '\\r', |
206 | | - '"' : '\\"', |
207 | | - '\\': '\\\\' |
208 | | - }, |
209 | | - rep; |
210 | | - |
211 | | - |
212 | | - function quote(string) { |
213 | | - |
214 | | -// If the string contains no control characters, no quote characters, and no |
215 | | -// backslash characters, then we can safely slap some quotes around it. |
216 | | -// Otherwise we must also replace the offending characters with safe escape |
217 | | -// sequences. |
218 | | - |
219 | | - escapable.lastIndex = 0; |
220 | | - return escapable.test(string) ? '"' + string.replace(escapable, function (a) { |
221 | | - var c = meta[a]; |
222 | | - return typeof c === 'string' ? c : |
223 | | - '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); |
224 | | - }) + '"' : '"' + string + '"'; |
225 | | - } |
226 | | - |
227 | | - |
228 | | - function str(key, holder) { |
229 | | - |
230 | | -// Produce a string from holder[key]. |
231 | | - |
232 | | - var i, // The loop counter. |
233 | | - k, // The member key. |
234 | | - v, // The member value. |
235 | | - length, |
236 | | - mind = gap, |
237 | | - partial, |
238 | | - value = holder[key]; |
239 | | - |
240 | | -// If the value has a toJSON method, call it to obtain a replacement value. |
241 | | - |
242 | | - if (value && typeof value === 'object' && |
243 | | - typeof value.toJSON === 'function') { |
244 | | - value = value.toJSON(key); |
245 | | - } |
246 | | - |
247 | | -// If we were called with a replacer function, then call the replacer to |
248 | | -// obtain a replacement value. |
249 | | - |
250 | | - if (typeof rep === 'function') { |
251 | | - value = rep.call(holder, key, value); |
252 | | - } |
253 | | - |
254 | | -// What happens next depends on the value's type. |
255 | | - |
256 | | - switch (typeof value) { |
257 | | - case 'string': |
258 | | - return quote(value); |
259 | | - |
260 | | - case 'number': |
261 | | - |
262 | | -// JSON numbers must be finite. Encode non-finite numbers as null. |
263 | | - |
264 | | - return isFinite(value) ? String(value) : 'null'; |
265 | | - |
266 | | - case 'boolean': |
267 | | - case 'null': |
268 | | - |
269 | | -// If the value is a boolean or null, convert it to a string. Note: |
270 | | -// typeof null does not produce 'null'. The case is included here in |
271 | | -// the remote chance that this gets fixed someday. |
272 | | - |
273 | | - return String(value); |
274 | | - |
275 | | -// If the type is 'object', we might be dealing with an object or an array or |
276 | | -// null. |
277 | | - |
278 | | - case 'object': |
279 | | - |
280 | | -// Due to a specification blunder in ECMAScript, typeof null is 'object', |
281 | | -// so watch out for that case. |
282 | | - |
283 | | - if (!value) { |
284 | | - return 'null'; |
285 | | - } |
286 | | - |
287 | | -// Make an array to hold the partial results of stringifying this object value. |
288 | | - |
289 | | - gap += indent; |
290 | | - partial = []; |
291 | | - |
292 | | -// Is the value an array? |
293 | | - |
294 | | - if (Object.prototype.toString.apply(value) === '[object Array]') { |
295 | | - |
296 | | -// The value is an array. Stringify every element. Use null as a placeholder |
297 | | -// for non-JSON values. |
298 | | - |
299 | | - length = value.length; |
300 | | - for (i = 0; i < length; i += 1) { |
301 | | - partial[i] = str(i, value) || 'null'; |
302 | | - } |
303 | | - |
304 | | -// Join all of the elements together, separated with commas, and wrap them in |
305 | | -// brackets. |
306 | | - |
307 | | - v = partial.length === 0 ? '[]' : gap ? |
308 | | - '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' : |
309 | | - '[' + partial.join(',') + ']'; |
310 | | - gap = mind; |
311 | | - return v; |
312 | | - } |
313 | | - |
314 | | -// If the replacer is an array, use it to select the members to be stringified. |
315 | | - |
316 | | - if (rep && typeof rep === 'object') { |
317 | | - length = rep.length; |
318 | | - for (i = 0; i < length; i += 1) { |
319 | | - if (typeof rep[i] === 'string') { |
320 | | - k = rep[i]; |
321 | | - v = str(k, value); |
322 | | - if (v) { |
323 | | - partial.push(quote(k) + (gap ? ': ' : ':') + v); |
324 | | - } |
325 | | - } |
326 | | - } |
327 | | - } else { |
328 | | - |
329 | | -// Otherwise, iterate through all of the keys in the object. |
330 | | - |
331 | | - for (k in value) { |
332 | | - if (Object.prototype.hasOwnProperty.call(value, k)) { |
333 | | - v = str(k, value); |
334 | | - if (v) { |
335 | | - partial.push(quote(k) + (gap ? ': ' : ':') + v); |
336 | | - } |
337 | | - } |
338 | | - } |
339 | | - } |
340 | | - |
341 | | -// Join all of the member texts together, separated with commas, |
342 | | -// and wrap them in braces. |
343 | | - |
344 | | - v = partial.length === 0 ? '{}' : gap ? |
345 | | - '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' : |
346 | | - '{' + partial.join(',') + '}'; |
347 | | - gap = mind; |
348 | | - return v; |
349 | | - } |
350 | | - } |
351 | | - |
352 | | -// If the JSON object does not yet have a stringify method, give it one. |
353 | | - |
354 | | - if (typeof JSON.stringify !== 'function') { |
355 | | - JSON.stringify = function (value, replacer, space) { |
356 | | - |
357 | | -// The stringify method takes a value and an optional replacer, and an optional |
358 | | -// space parameter, and returns a JSON text. The replacer can be a function |
359 | | -// that can replace values, or an array of strings that will select the keys. |
360 | | -// A default replacer method can be provided. Use of the space parameter can |
361 | | -// produce text that is more easily readable. |
362 | | - |
363 | | - var i; |
364 | | - gap = ''; |
365 | | - indent = ''; |
366 | | - |
367 | | -// If the space parameter is a number, make an indent string containing that |
368 | | -// many spaces. |
369 | | - |
370 | | - if (typeof space === 'number') { |
371 | | - for (i = 0; i < space; i += 1) { |
372 | | - indent += ' '; |
373 | | - } |
374 | | - |
375 | | -// If the space parameter is a string, it will be used as the indent string. |
376 | | - |
377 | | - } else if (typeof space === 'string') { |
378 | | - indent = space; |
379 | | - } |
380 | | - |
381 | | -// If there is a replacer, it must be a function or an array. |
382 | | -// Otherwise, throw an error. |
383 | | - |
384 | | - rep = replacer; |
385 | | - if (replacer && typeof replacer !== 'function' && |
386 | | - (typeof replacer !== 'object' || |
387 | | - typeof replacer.length !== 'number')) { |
388 | | - throw new Error('JSON.stringify'); |
389 | | - } |
390 | | - |
391 | | -// Make a fake root object containing our value under the key of ''. |
392 | | -// Return the result of stringifying the value. |
393 | | - |
394 | | - return str('', {'': value}); |
395 | | - }; |
396 | | - } |
397 | | - |
398 | | - |
399 | | -// If the JSON object does not yet have a parse method, give it one. |
400 | | - |
401 | | - if (typeof JSON.parse !== 'function') { |
402 | | - JSON.parse = function (text, reviver) { |
403 | | - |
404 | | -// The parse method takes a text and an optional reviver function, and returns |
405 | | -// a JavaScript value if the text is a valid JSON text. |
406 | | - |
407 | | - var j; |
408 | | - |
409 | | - function walk(holder, key) { |
410 | | - |
411 | | -// The walk method is used to recursively walk the resulting structure so |
412 | | -// that modifications can be made. |
413 | | - |
414 | | - var k, v, value = holder[key]; |
415 | | - if (value && typeof value === 'object') { |
416 | | - for (k in value) { |
417 | | - if (Object.prototype.hasOwnProperty.call(value, k)) { |
418 | | - v = walk(value, k); |
419 | | - if (v !== undefined) { |
420 | | - value[k] = v; |
421 | | - } else { |
422 | | - delete value[k]; |
423 | | - } |
424 | | - } |
425 | | - } |
426 | | - } |
427 | | - return reviver.call(holder, key, value); |
428 | | - } |
429 | | - |
430 | | - |
431 | | -// Parsing happens in four stages. In the first stage, we replace certain |
432 | | -// Unicode characters with escape sequences. JavaScript handles many characters |
433 | | -// incorrectly, either silently deleting them, or treating them as line endings. |
434 | | - |
435 | | - text = String(text); |
436 | | - cx.lastIndex = 0; |
437 | | - if (cx.test(text)) { |
438 | | - text = text.replace(cx, function (a) { |
439 | | - return '\\u' + |
440 | | - ('0000' + a.charCodeAt(0).toString(16)).slice(-4); |
441 | | - }); |
442 | | - } |
443 | | - |
444 | | -// In the second stage, we run the text against regular expressions that look |
445 | | -// for non-JSON patterns. We are especially concerned with '()' and 'new' |
446 | | -// because they can cause invocation, and '=' because it can cause mutation. |
447 | | -// But just to be safe, we want to reject all unexpected forms. |
448 | | - |
449 | | -// We split the second stage into 4 regexp operations in order to work around |
450 | | -// crippling inefficiencies in IE's and Safari's regexp engines. First we |
451 | | -// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we |
452 | | -// replace all simple value tokens with ']' characters. Third, we delete all |
453 | | -// open brackets that follow a colon or comma or that begin the text. Finally, |
454 | | -// we look to see that the remaining characters are only whitespace or ']' or |
455 | | -// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval. |
456 | | - |
457 | | - if (/^[\],:{}\s]*$/ |
458 | | - .test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@') |
459 | | - .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']') |
460 | | - .replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) { |
461 | | - |
462 | | -// In the third stage we use the eval function to compile the text into a |
463 | | -// JavaScript structure. The '{' operator is subject to a syntactic ambiguity |
464 | | -// in JavaScript: it can begin a block or an object literal. We wrap the text |
465 | | -// in parens to eliminate the ambiguity. |
466 | | - |
467 | | - j = eval('(' + text + ')'); |
468 | | - |
469 | | -// In the optional fourth stage, we recursively walk the new structure, passing |
470 | | -// each name/value pair to a reviver function for possible transformation. |
471 | | - |
472 | | - return typeof reviver === 'function' ? |
473 | | - walk({'': j}, '') : j; |
474 | | - } |
475 | | - |
476 | | -// If the text is not JSON parseable, then a SyntaxError is thrown. |
477 | | - |
478 | | - throw new SyntaxError('JSON.parse'); |
479 | | - }; |
480 | | - } |
481 | | -}()); |
Index: trunk/extensions/Reviews/resources/reviews.review.js |
— | — | @@ -9,7 +9,25 @@ |
10 | 10 | (function( $, mw, reviews ) { |
11 | 11 | |
12 | 12 | reviews.Review = function( data ) { |
| 13 | + var _this = this; |
13 | 14 | |
| 15 | + this.save = function() { |
| 16 | + requestArgs = { |
| 17 | + 'action': 'submitreview', |
| 18 | + 'format': 'json', |
| 19 | + 'token': $( this ).attr( 'survey-data-token' ), |
| 20 | + }; |
| 21 | + |
| 22 | + $.post( |
| 23 | + wgScriptPath + '/api.php', |
| 24 | + requestArgs, |
| 25 | + function( data ) { |
| 26 | + callback(); |
| 27 | + // TODO |
| 28 | + } |
| 29 | + ); |
| 30 | + }; |
| 31 | + |
14 | 32 | }; |
15 | 33 | |
16 | 34 | reviews.Review.prototype = { |
Index: trunk/extensions/Reviews/resources/jquery.reviewControl.js |
— | — | @@ -16,7 +16,7 @@ |
17 | 17 | |
18 | 18 | this.setup = function() { |
19 | 19 | var data = $this.attr( 'data-review' ); |
20 | | - this.review = new reviews.Review( data === undefined ? false : JSON.parse( data ) ); |
| 20 | + this.review = new reviews.Review( data === undefined ? false : $.parseJSON( data ) ); |
21 | 21 | |
22 | 22 | }; |
23 | 23 | |