Index: trunk/phase3/js2/mwEmbed/libMwApi/mwProxy.js |
— | — | @@ -0,0 +1,17 @@ |
| 2 | + |
| 3 | +var mwApiClientProxy = function(iObj){ |
| 4 | + return this.init( iObj ); |
| 5 | +} |
| 6 | +mwApiClientProxy.prototype = { |
| 7 | + init:function( iObj ){ |
| 8 | + |
| 9 | + }, |
| 10 | + //Gets the apiResult callback |
| 11 | + mwApiProxy:resultCb( apiResult ){ |
| 12 | + |
| 13 | + } |
| 14 | +} |
| 15 | + |
| 16 | +var mwApiServerProxy = function(iObj){ |
| 17 | + return this.init( |
| 18 | +} |
\ No newline at end of file |
Index: trunk/phase3/js2/mwEmbed/libMwApi/NestedCallbackIframe.html |
— | — | @@ -0,0 +1,16 @@ |
| 2 | +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> |
| 3 | +<html> |
| 4 | +<head> |
| 5 | +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> |
| 6 | +<title>Simple nested iframe callback page</title> |
| 7 | +<script type="text/javascript"> |
| 8 | +window.onload = function (){ |
| 9 | + //call the nested callback in top most frame: |
| 10 | + top.$mw.proxy.nested( window.location.href.split("#")[1] || false ); |
| 11 | +} |
| 12 | +</script> |
| 13 | +</head> |
| 14 | +<body> |
| 15 | +Nested Iframe callback |
| 16 | +</body> |
| 17 | +</html> |
\ No newline at end of file |
Index: trunk/phase3/js2/mwEmbed/libMwApi/json2.js |
— | — | @@ -0,0 +1,479 @@ |
| 2 | +/* |
| 3 | + http://www.JSON.org/json2.js |
| 4 | + 2009-09-29 |
| 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 | + This file creates a global JSON object containing two methods: stringify |
| 13 | + and parse. |
| 14 | + |
| 15 | + JSON.stringify(value, replacer, space) |
| 16 | + value any JavaScript value, usually an object or array. |
| 17 | + |
| 18 | + replacer an optional parameter that determines how object |
| 19 | + values are stringified for objects. It can be a |
| 20 | + function or an array of strings. |
| 21 | + |
| 22 | + space an optional parameter that specifies the indentation |
| 23 | + of nested structures. If it is omitted, the text will |
| 24 | + be packed without extra whitespace. If it is a number, |
| 25 | + it will specify the number of spaces to indent at each |
| 26 | + level. If it is a string (such as '\t' or ' '), |
| 27 | + it contains the characters used to indent at each level. |
| 28 | + |
| 29 | + This method produces a JSON text from a JavaScript value. |
| 30 | + |
| 31 | + When an object value is found, if the object contains a toJSON |
| 32 | + method, its toJSON method will be called and the result will be |
| 33 | + stringified. A toJSON method does not serialize: it returns the |
| 34 | + value represented by the name/value pair that should be serialized, |
| 35 | + or undefined if nothing should be serialized. The toJSON method |
| 36 | + will be passed the key associated with the value, and this will be |
| 37 | + bound to the value |
| 38 | + |
| 39 | + For example, this would serialize Dates as ISO strings. |
| 40 | + |
| 41 | + Date.prototype.toJSON = function (key) { |
| 42 | + function f(n) { |
| 43 | + // Format integers to have at least two digits. |
| 44 | + return n < 10 ? '0' + n : n; |
| 45 | + } |
| 46 | + |
| 47 | + return this.getUTCFullYear() + '-' + |
| 48 | + f(this.getUTCMonth() + 1) + '-' + |
| 49 | + f(this.getUTCDate()) + 'T' + |
| 50 | + f(this.getUTCHours()) + ':' + |
| 51 | + f(this.getUTCMinutes()) + ':' + |
| 52 | + f(this.getUTCSeconds()) + 'Z'; |
| 53 | + }; |
| 54 | + |
| 55 | + You can provide an optional replacer method. It will be passed the |
| 56 | + key and value of each member, with this bound to the containing |
| 57 | + object. The value that is returned from your method will be |
| 58 | + serialized. If your method returns undefined, then the member will |
| 59 | + be excluded from the serialization. |
| 60 | + |
| 61 | + If the replacer parameter is an array of strings, then it will be |
| 62 | + used to select the members to be serialized. It filters the results |
| 63 | + such that only members with keys listed in the replacer array are |
| 64 | + stringified. |
| 65 | + |
| 66 | + Values that do not have JSON representations, such as undefined or |
| 67 | + functions, will not be serialized. Such values in objects will be |
| 68 | + dropped; in arrays they will be replaced with null. You can use |
| 69 | + a replacer function to replace those with JSON values. |
| 70 | + JSON.stringify(undefined) returns undefined. |
| 71 | + |
| 72 | + The optional space parameter produces a stringification of the |
| 73 | + value that is filled with line breaks and indentation to make it |
| 74 | + easier to read. |
| 75 | + |
| 76 | + If the space parameter is a non-empty string, then that string will |
| 77 | + be used for indentation. If the space parameter is a number, then |
| 78 | + the indentation will be that many spaces. |
| 79 | + |
| 80 | + Example: |
| 81 | + |
| 82 | + text = JSON.stringify(['e', {pluribus: 'unum'}]); |
| 83 | + // text is '["e",{"pluribus":"unum"}]' |
| 84 | + |
| 85 | + |
| 86 | + text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t'); |
| 87 | + // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]' |
| 88 | + |
| 89 | + text = JSON.stringify([new Date()], function (key, value) { |
| 90 | + return this[key] instanceof Date ? |
| 91 | + 'Date(' + this[key] + ')' : value; |
| 92 | + }); |
| 93 | + // text is '["Date(---current time---)"]' |
| 94 | + |
| 95 | + |
| 96 | + JSON.parse(text, reviver) |
| 97 | + This method parses a JSON text to produce an object or array. |
| 98 | + It can throw a SyntaxError exception. |
| 99 | + |
| 100 | + The optional reviver parameter is a function that can filter and |
| 101 | + transform the results. It receives each of the keys and values, |
| 102 | + and its return value is used instead of the original value. |
| 103 | + If it returns what it received, then the structure is not modified. |
| 104 | + If it returns undefined then the member is deleted. |
| 105 | + |
| 106 | + Example: |
| 107 | + |
| 108 | + // Parse the text. Values that look like ISO date strings will |
| 109 | + // be converted to Date objects. |
| 110 | + |
| 111 | + myData = JSON.parse(text, function (key, value) { |
| 112 | + var a; |
| 113 | + if (typeof value === 'string') { |
| 114 | + a = |
| 115 | +/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value); |
| 116 | + if (a) { |
| 117 | + return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4], |
| 118 | + +a[5], +a[6])); |
| 119 | + } |
| 120 | + } |
| 121 | + return value; |
| 122 | + }); |
| 123 | + |
| 124 | + myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) { |
| 125 | + var d; |
| 126 | + if (typeof value === 'string' && |
| 127 | + value.slice(0, 5) === 'Date(' && |
| 128 | + value.slice(-1) === ')') { |
| 129 | + d = new Date(value.slice(5, -1)); |
| 130 | + if (d) { |
| 131 | + return d; |
| 132 | + } |
| 133 | + } |
| 134 | + return value; |
| 135 | + }); |
| 136 | + |
| 137 | + |
| 138 | + This is a reference implementation. You are free to copy, modify, or |
| 139 | + redistribute. |
| 140 | + |
| 141 | + This code should be minified before deployment. |
| 142 | + See http://javascript.crockford.com/jsmin.html |
| 143 | + |
| 144 | + USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO |
| 145 | + NOT CONTROL. |
| 146 | +*/ |
| 147 | + |
| 148 | +/*jslint evil: true, strict: false */ |
| 149 | + |
| 150 | +/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply, |
| 151 | + call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours, |
| 152 | + getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join, |
| 153 | + lastIndex, length, parse, prototype, push, replace, slice, stringify, |
| 154 | + test, toJSON, toString, valueOf |
| 155 | +*/ |
| 156 | + |
| 157 | + |
| 158 | +// Create a JSON object only if one does not already exist. We create the |
| 159 | +// methods in a closure to avoid creating global variables. |
| 160 | + |
| 161 | +if (!this.JSON) { |
| 162 | + this.JSON = {}; |
| 163 | +} |
| 164 | + |
| 165 | +(function () { |
| 166 | + |
| 167 | + function f(n) { |
| 168 | + // Format integers to have at least two digits. |
| 169 | + return n < 10 ? '0' + n : n; |
| 170 | + } |
| 171 | + |
| 172 | + if (typeof Date.prototype.toJSON !== 'function') { |
| 173 | + |
| 174 | + Date.prototype.toJSON = function (key) { |
| 175 | + |
| 176 | + return isFinite(this.valueOf()) ? |
| 177 | + this.getUTCFullYear() + '-' + |
| 178 | + f(this.getUTCMonth() + 1) + '-' + |
| 179 | + f(this.getUTCDate()) + 'T' + |
| 180 | + f(this.getUTCHours()) + ':' + |
| 181 | + f(this.getUTCMinutes()) + ':' + |
| 182 | + f(this.getUTCSeconds()) + 'Z' : null; |
| 183 | + }; |
| 184 | + |
| 185 | + String.prototype.toJSON = |
| 186 | + Number.prototype.toJSON = |
| 187 | + Boolean.prototype.toJSON = function (key) { |
| 188 | + return this.valueOf(); |
| 189 | + }; |
| 190 | + } |
| 191 | + |
| 192 | + var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, |
| 193 | + escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, |
| 194 | + gap, |
| 195 | + indent, |
| 196 | + meta = { // table of character substitutions |
| 197 | + '\b': '\\b', |
| 198 | + '\t': '\\t', |
| 199 | + '\n': '\\n', |
| 200 | + '\f': '\\f', |
| 201 | + '\r': '\\r', |
| 202 | + '"' : '\\"', |
| 203 | + '\\': '\\\\' |
| 204 | + }, |
| 205 | + rep; |
| 206 | + |
| 207 | + |
| 208 | + function quote(string) { |
| 209 | + |
| 210 | +// If the string contains no control characters, no quote characters, and no |
| 211 | +// backslash characters, then we can safely slap some quotes around it. |
| 212 | +// Otherwise we must also replace the offending characters with safe escape |
| 213 | +// sequences. |
| 214 | + |
| 215 | + escapable.lastIndex = 0; |
| 216 | + return escapable.test(string) ? |
| 217 | + '"' + string.replace(escapable, function (a) { |
| 218 | + var c = meta[a]; |
| 219 | + return typeof c === 'string' ? c : |
| 220 | + '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); |
| 221 | + }) + '"' : |
| 222 | + '"' + string + '"'; |
| 223 | + } |
| 224 | + |
| 225 | + |
| 226 | + function str(key, holder) { |
| 227 | + |
| 228 | +// Produce a string from holder[key]. |
| 229 | + |
| 230 | + var i, // The loop counter. |
| 231 | + k, // The member key. |
| 232 | + v, // The member value. |
| 233 | + length, |
| 234 | + mind = gap, |
| 235 | + partial, |
| 236 | + value = holder[key]; |
| 237 | + |
| 238 | +// If the value has a toJSON method, call it to obtain a replacement value. |
| 239 | + |
| 240 | + if (value && typeof value === 'object' && |
| 241 | + typeof value.toJSON === 'function') { |
| 242 | + value = value.toJSON(key); |
| 243 | + } |
| 244 | + |
| 245 | +// If we were called with a replacer function, then call the replacer to |
| 246 | +// obtain a replacement value. |
| 247 | + |
| 248 | + if (typeof rep === 'function') { |
| 249 | + value = rep.call(holder, key, value); |
| 250 | + } |
| 251 | + |
| 252 | +// What happens next depends on the value's type. |
| 253 | + |
| 254 | + switch (typeof value) { |
| 255 | + case 'string': |
| 256 | + return quote(value); |
| 257 | + |
| 258 | + case 'number': |
| 259 | + |
| 260 | +// JSON numbers must be finite. Encode non-finite numbers as null. |
| 261 | + |
| 262 | + return isFinite(value) ? String(value) : 'null'; |
| 263 | + |
| 264 | + case 'boolean': |
| 265 | + case 'null': |
| 266 | + |
| 267 | +// If the value is a boolean or null, convert it to a string. Note: |
| 268 | +// typeof null does not produce 'null'. The case is included here in |
| 269 | +// the remote chance that this gets fixed someday. |
| 270 | + |
| 271 | + return String(value); |
| 272 | + |
| 273 | +// If the type is 'object', we might be dealing with an object or an array or |
| 274 | +// null. |
| 275 | + |
| 276 | + case 'object': |
| 277 | + |
| 278 | +// Due to a specification blunder in ECMAScript, typeof null is 'object', |
| 279 | +// so watch out for that case. |
| 280 | + |
| 281 | + if (!value) { |
| 282 | + return 'null'; |
| 283 | + } |
| 284 | + |
| 285 | +// Make an array to hold the partial results of stringifying this object value. |
| 286 | + |
| 287 | + gap += indent; |
| 288 | + partial = []; |
| 289 | + |
| 290 | +// Is the value an array? |
| 291 | + |
| 292 | + if (Object.prototype.toString.apply(value) === '[object Array]') { |
| 293 | + |
| 294 | +// The value is an array. Stringify every element. Use null as a placeholder |
| 295 | +// for non-JSON values. |
| 296 | + |
| 297 | + length = value.length; |
| 298 | + for (i = 0; i < length; i += 1) { |
| 299 | + partial[i] = str(i, value) || 'null'; |
| 300 | + } |
| 301 | + |
| 302 | +// Join all of the elements together, separated with commas, and wrap them in |
| 303 | +// brackets. |
| 304 | + |
| 305 | + v = partial.length === 0 ? '[]' : |
| 306 | + gap ? '[\n' + gap + |
| 307 | + partial.join(',\n' + gap) + '\n' + |
| 308 | + 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 | + k = rep[i]; |
| 320 | + if (typeof k === 'string') { |
| 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.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 ? '{}' : |
| 345 | + gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + |
| 346 | + mind + '}' : '{' + 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.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 | + cx.lastIndex = 0; |
| 436 | + if (cx.test(text)) { |
| 437 | + text = text.replace(cx, function (a) { |
| 438 | + return '\\u' + |
| 439 | + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); |
| 440 | + }); |
| 441 | + } |
| 442 | + |
| 443 | +// In the second stage, we run the text against regular expressions that look |
| 444 | +// for non-JSON patterns. We are especially concerned with '()' and 'new' |
| 445 | +// because they can cause invocation, and '=' because it can cause mutation. |
| 446 | +// But just to be safe, we want to reject all unexpected forms. |
| 447 | + |
| 448 | +// We split the second stage into 4 regexp operations in order to work around |
| 449 | +// crippling inefficiencies in IE's and Safari's regexp engines. First we |
| 450 | +// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we |
| 451 | +// replace all simple value tokens with ']' characters. Third, we delete all |
| 452 | +// open brackets that follow a colon or comma or that begin the text. Finally, |
| 453 | +// we look to see that the remaining characters are only whitespace or ']' or |
| 454 | +// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval. |
| 455 | + |
| 456 | + if (/^[\],:{}\s]*$/. |
| 457 | +test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@'). |
| 458 | +replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']'). |
| 459 | +replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) { |
| 460 | + |
| 461 | +// In the third stage we use the eval function to compile the text into a |
| 462 | +// JavaScript structure. The '{' operator is subject to a syntactic ambiguity |
| 463 | +// in JavaScript: it can begin a block or an object literal. We wrap the text |
| 464 | +// in parens to eliminate the ambiguity. |
| 465 | + |
| 466 | + j = eval('(' + text + ')'); |
| 467 | + |
| 468 | +// In the optional fourth stage, we recursively walk the new structure, passing |
| 469 | +// each name/value pair to a reviver function for possible transformation. |
| 470 | + |
| 471 | + return typeof reviver === 'function' ? |
| 472 | + walk({'': j}, '') : j; |
| 473 | + } |
| 474 | + |
| 475 | +// If the text is not JSON parseable, then a SyntaxError is thrown. |
| 476 | + |
| 477 | + throw new SyntaxError('JSON.parse'); |
| 478 | + }; |
| 479 | + } |
| 480 | +}()); |
Index: trunk/phase3/js2/mwEmbed/libMwApi/mw.proxy.js |
— | — | @@ -0,0 +1,210 @@ |
| 2 | +/* |
| 3 | +* |
| 4 | +* Api proxy system |
| 5 | +* |
| 6 | +* Built to support cross domain uploading, and api actions for a approved set of domains. |
| 7 | +* mwProxy enables a system for fluid contributions across wikis domains for which your logged in. |
| 8 | +* |
| 9 | +* The framework support a request approval system for per-user domain approval |
| 10 | +* and a central blacklisting of domains controlled by site or system administrators. |
| 11 | +* |
| 12 | +* Flow outline below: |
| 13 | +* |
| 14 | +* Domain A (lets say en.wiki) |
| 15 | +* invokes add-media-wizard and wants to upload to domain B ( commons.wiki ) |
| 16 | +* |
| 17 | +* Domain A loads iframe to domain B ? with request param to to insert from Domain A |
| 18 | +* Domain B checks list of approved domains for (Domain A) & checks the user is logged in ( and if the same account name ) |
| 19 | +* if user is not logged in |
| 20 | +* a _link_ to Domain B to new window login page is given |
| 21 | +* if user has not approved domain and (Domain A) is not pre-approved |
| 22 | +* a new page link is generated with a approve domain request |
| 23 | +* if user approves domain it goes into their User:{username}/apiProxyDomains.js config |
| 24 | +* If Domain A is approved we then: |
| 25 | +* loads a "push" and "pull" iframe back to Domain A |
| 26 | + (Domain B can change the #hash values of these children thereby proxy the data) |
| 27 | +* Domain A now gets the iframe "loaded" callback a does a initial echo to confirm cross domain proxy |
| 28 | +* echo sends "echo" to push and (Domain A) js passes the echo onto the "pull" |
| 29 | +* Domain A now sends api requests to the iframe "push" child and gets results from the iframe "pull" |
| 30 | +* api actions happen with status updates and everything and we can reuse existing api interface code |
| 31 | +* |
| 32 | +* if the browser supports it we can pass msgs with the postMessage API |
| 33 | +* http://ejohn.org/blog/cross-window-messaging/ |
| 34 | +* |
| 35 | +* @@todo it would be nice if this supported multiple proxy targets (ie to a bright widgets future) |
| 36 | +* |
| 37 | +*/ |
| 38 | + |
| 39 | +loadGM({ |
| 40 | + "mwe-setting-up-proxy": "Setting up proxy" |
| 41 | +}); |
| 42 | + |
| 43 | +(function( $ ) { |
| 44 | + /** |
| 45 | + * Base API Proxy object |
| 46 | + * |
| 47 | + */ |
| 48 | + $.proxy = {}; |
| 49 | + |
| 50 | + /** |
| 51 | + * The clientApiProxy handles a request to external server |
| 52 | + * |
| 53 | + * This is (Domain A) in the above described setup |
| 54 | + */ |
| 55 | + $.proxy.client = function( pConf, callback ){ |
| 56 | + var _this = this; |
| 57 | + //do setup: |
| 58 | + if( pConf.server_frame ) |
| 59 | + $.proxy.server_frame = pConf.server_frame; |
| 60 | + |
| 61 | + if( pConf.client_frame_path ) |
| 62 | + $.proxy.client_frame_path = pConf.client_frame_path; |
| 63 | + |
| 64 | + //setup a dialog to manage proxy setup: |
| 65 | + $j.addLoaderDialog( gM('mwe-setting-up-proxy') ); |
| 66 | + |
| 67 | + if( parseUri( $.proxy.server_frame).host == parseUri( document.URL ).host ){ |
| 68 | + js_log("Error: why are you trying to proxy yourself? " ); |
| 69 | + return false; |
| 70 | + } |
| 71 | + //add an iframe to domain B with request for proxy just do the setup |
| 72 | + $.proxy.doFrameProxy( { 'init' : 'echo' } ); |
| 73 | + |
| 74 | + //if we have a setup callback |
| 75 | + $.proxy.callback = callback; |
| 76 | + } |
| 77 | + /* setup a iframe request hash */ |
| 78 | + $.proxy.doFrameProxy = function( reqObj ){ |
| 79 | + var hashPack = { |
| 80 | + 'cd': parseUri( document.URL ).host, |
| 81 | + 'cfp': $.proxy.client_frame_path, |
| 82 | + 'req': reqObj |
| 83 | + } |
| 84 | + js_log( "Do frame proxy request on src: \n" + $.proxy.server_frame + "\n" + |
| 85 | + JSON.stringify( reqObj ) ); |
| 86 | + //we can't update src's so we have to remove and add all the time :( |
| 87 | + //@@todo we should support frame msg system |
| 88 | + $j('#frame_proxy').remove(); |
| 89 | + $j('body').append('<iframe id="frame_proxy" name="frame_proxy" ' + |
| 90 | + 'src="' + $.proxy.server_frame + |
| 91 | + '#' + escape( JSON.stringify( hashPack ) ) + |
| 92 | + '"></iframe>' ); |
| 93 | + } |
| 94 | + |
| 95 | + /* the do_api_request with callback: */ |
| 96 | + $.proxy.doRequest = function( reqObj, callback){ |
| 97 | + js_log("doRequest:: " + JSON.stringify( reqObj ) ); |
| 98 | + //setup the callback: |
| 99 | + $.proxy.callback = callback; |
| 100 | + //do the proxy req: |
| 101 | + $.proxy.doFrameProxy( reqObj ); |
| 102 | + } |
| 103 | + /** |
| 104 | + * The nested iframe action that passes its msg back up to the top instance |
| 105 | + */ |
| 106 | + $.proxy.nested = function( hashResult ){ |
| 107 | + js_log( 'got $.proxy.nested callback!! :: ' + hashResult ); |
| 108 | + //try to parse the hash result: |
| 109 | + try{ |
| 110 | + var rObj = JSON.parse( unescape( hashResult ) ); |
| 111 | + }catch (e) { |
| 112 | + js_log("Error could not parse hashResult"); |
| 113 | + } |
| 114 | + //hide the loader if the initial state = ready msg is fired: |
| 115 | + if( rObj && rObj.state == 'ready') |
| 116 | + $j.closeLoaderDialog(); |
| 117 | + //if all good pass it to the callback: |
| 118 | + $.proxy.callback( rObj ); |
| 119 | + } |
| 120 | + /** |
| 121 | + * The serverApiProxy handles the actual proxy |
| 122 | + * and child frames pointing to the parent "blank" frames |
| 123 | + * |
| 124 | + * This is (Domain B) in the above described setup |
| 125 | + */ |
| 126 | + $.proxy.server = function( pConf, callback){ |
| 127 | + /* clear the body of any html */ |
| 128 | + $j('body').html( 'proxy setup' ); |
| 129 | + |
| 130 | + //read the anchor action from the requesting url |
| 131 | + var jmsg = unescape( parseUri( document.URL ).anchor ); |
| 132 | + try{ |
| 133 | + var aObj = JSON.parse( jmsg ); |
| 134 | + }catch ( e ){ |
| 135 | + js_log("ProxyServer:: could not parse anchor"); |
| 136 | + } |
| 137 | + if( !aObj.cd ){ |
| 138 | + js_log("Error: no client domain provided "); |
| 139 | + return false; |
| 140 | + } |
| 141 | + |
| 142 | + js_log("Setup server on: " + parseUri( document.URL ).host + |
| 143 | + ' client from: ' + aObj.cd + |
| 144 | + ' to nested target: ' + aObj.cfp ); |
| 145 | + |
| 146 | + // make sure we are logged in |
| 147 | + // (its a normal mediaWiki page so all site vars should be defined) |
| 148 | + if( !wgUserName ){ |
| 149 | + js_log('error Not logged in'); |
| 150 | + return false; |
| 151 | + } |
| 152 | + |
| 153 | + var domain = parseUri( document.URL ).host; |
| 154 | + var nested_frame_src = 'http://' + aObj.cd + aObj.cfp; |
| 155 | + //check the master whitelist |
| 156 | + for(var i in pConf.master_whitelist){ |
| 157 | + if( domain == pConf.master_whitelist[ i ] ){ |
| 158 | + //do the request: |
| 159 | + return doNestedProxy( aObj.req ); |
| 160 | + } |
| 161 | + } |
| 162 | + //check master blacklist |
| 163 | + for(var i in pConf.master_blacklist ){ |
| 164 | + if( domain == pConf.master_blacklist ){ |
| 165 | + js_log('domain: ' + domain + ' is blacklisted'); |
| 166 | + return false; |
| 167 | + } |
| 168 | + } |
| 169 | + //@@todo grab the users whitelist for our current domain |
| 170 | + /*var local_api = wgScriptPath + '/index' + wgScriptExtension + '?title=' + |
| 171 | + 'User:' + wgUserName + '/apiProxyDomainList.js' + |
| 172 | + '&action=raw&smaxage=0&gen=js'; |
| 173 | + $j.get( local_api, function( data ){ |
| 174 | + debugger; |
| 175 | + });*/ |
| 176 | + |
| 177 | + //if still not found: |
| 178 | + js_log("domain " + domain + " not approved"); |
| 179 | + |
| 180 | + function doNestedProxy( reqObj ){ |
| 181 | + js_log("doNestedProxy to: " + nested_frame_src); |
| 182 | + var outputhash = escape( JSON.stringify( reqObj ) ); |
| 183 | + //check if its just a "echo" request (no need to hit the api) |
| 184 | + if( reqObj.init && reqObj.init == 'echo'){ |
| 185 | + doNestedFrame( {'state': 'ready', "echo": true } ); |
| 186 | + }else{ |
| 187 | + //add some api stuff: |
| 188 | + reqObj['format'] = 'json'; |
| 189 | + //process the api request |
| 190 | + $j.get(wgScriptPath + '/api' + wgScriptExtension, |
| 191 | + reqObj, |
| 192 | + function( data ){ |
| 193 | + js_log("Proxy GOT Res: " + data ); |
| 194 | + //put it into the nested frame hash string: |
| 195 | + doNestedFrame( JSON.parse( data ) ); |
| 196 | + } |
| 197 | + ); |
| 198 | + } |
| 199 | + } |
| 200 | + //add the doNestedFrame iframe: |
| 201 | + function doNestedFrame( resultObj ){ |
| 202 | + $j('#nested_push').remove(); |
| 203 | + //setup the nested proxy that points back to top domain: |
| 204 | + $j('body').append( '<iframe id="nested_push" name="nested_push" ' + |
| 205 | + 'src="'+ nested_frame_src + |
| 206 | + '#' + escape( JSON.stringify( resultObj ) ) + |
| 207 | + '"></iframe>' ); |
| 208 | + } |
| 209 | + } |
| 210 | + |
| 211 | +})(window.$mw); |
Index: trunk/phase3/js2/mwEmbed/php/languages/mwEmbed.i18n.php |
— | — | @@ -104,6 +104,7 @@ |
105 | 105 | 'mwe-size-bytes' => '$1 B', |
106 | 106 | 'mwe-error_load_lib' => 'Error: JavaScript $1 was not retrievable or does not define $2', |
107 | 107 | 'mwe-loading-add-media-wiz' => "Loading add media wizard", |
| 108 | + 'mwe-apiproxy-setup' => " Setting up API proxy", |
108 | 109 | |
109 | 110 | /* |
110 | 111 | * js file: /libAddMedia/mvFirefogg.js |
Index: trunk/phase3/js2/mwEmbed/mv_embed.js |
— | — | @@ -91,7 +91,7 @@ |
92 | 92 | var mv_embed_path = getMvEmbedPath(); |
93 | 93 | } |
94 | 94 | /** |
95 | | -* wrap the global $mw object here: |
| 95 | +* The global $mw object: |
96 | 96 | * |
97 | 97 | * Any global functions/classes that are not jQuery plugins should make |
98 | 98 | * there way into the $mw namespace |
— | — | @@ -382,8 +382,9 @@ |
383 | 383 | //@@todo we need a formatNum and we need to request some special packaged info to deal with that case. |
384 | 384 | return gM( msg , size ); |
385 | 385 | }; |
386 | | - |
387 | | - |
| 386 | + |
| 387 | + |
| 388 | + |
388 | 389 | /** |
389 | 390 | * MediaWiki wikitext "Parser" |
390 | 391 | * |
— | — | @@ -429,36 +430,15 @@ |
430 | 431 | this.pOut = ''; |
431 | 432 | }, |
432 | 433 | parse : function(){ |
433 | | - this.pObj = {}; |
434 | | - this.pObj.tmpl = new Array(); |
435 | | - |
436 | | - //refrences for swap key |
437 | | - this.pObj.tmpl_text = new Array(); |
438 | | - this.pObj.tmpl_key = new Array(); |
439 | | - this.pObj.tmpl_ns = '' ; // wikiText with place-holder |
440 | | - |
441 | | - //get templates losly based on Magnus_Manske/tmpl.js code: |
442 | | - var tcnt = 0 ; |
443 | | - var ts = '' ; |
444 | | - var curt = 0 ; |
445 | | - var schar = 0; |
446 | | - |
447 | | - |
448 | | - //build out nested template holders: |
449 | | - var depth = 0; |
450 | | - var tKey = 0; |
451 | | - var ns = ''; |
452 | | - |
453 | 434 | /* |
454 | | - * quickly recursive / parse out templates with top down recurse decent |
| 435 | + * quickly recursive / parse out templates: |
455 | 436 | */ |
456 | 437 | |
457 | 438 | // ~ probably a better algorithm out there / should mirror php parser flow ~ |
458 | 439 | // ... but I am having fun with recursion so here it is... |
459 | | - function rdpp ( txt ){ |
| 440 | + // or at least mirror: http://www.mediawiki.org/wiki/Extension:Page_Object_Model |
| 441 | + function rdpp ( txt , cn){ |
460 | 442 | var node = {}; |
461 | | - //if we should output node text |
462 | | - var ont = true; |
463 | 443 | //inspect each char |
464 | 444 | for(var a=0; a < txt.length; a++){ |
465 | 445 | if( txt[a] == '{' && txt[a+1] == '{' ){ |
— | — | @@ -467,21 +447,20 @@ |
468 | 448 | if(!node['c']) |
469 | 449 | node['c'] = new Array(); |
470 | 450 | |
471 | | - node['c'].push( rdpp( txt.substr( a ) ) ); |
472 | | - ont=true; |
| 451 | + node['c'].push( rdpp( txt.substr( a ), true ) ); |
473 | 452 | }else if( txt[a] == '}' && txt[a+1] == '}'){ |
474 | 453 | if( !node['p'] ){ |
475 | 454 | return node; |
476 | 455 | } |
477 | 456 | node = node['p']; |
478 | | - ont=false; |
479 | 457 | a=a+2; |
480 | 458 | } |
481 | 459 | if(!node['t']) |
482 | 460 | node['t']=''; |
483 | | - |
| 461 | + |
484 | 462 | if( txt[a] ) |
485 | 463 | node['t']+=txt[a]; |
| 464 | + |
486 | 465 | } |
487 | 466 | return node; |
488 | 467 | } |
— | — | @@ -503,8 +482,8 @@ |
504 | 483 | tObj["arg"] = tname.split(':').pop(); |
505 | 484 | } |
506 | 485 | |
507 | | - js_log("TNAME::" + tObj["arg"] + ' from:: ' + ts); |
508 | | - |
| 486 | + js_log("TNAME::" + tObj["name"] + ' from:: ' + ts); |
| 487 | + |
509 | 488 | var pSet = ts.split('\|'); |
510 | 489 | pSet.splice(0,1); |
511 | 490 | if( pSet.length ){ |
— | — | @@ -566,25 +545,57 @@ |
567 | 546 | return getMagicTxtFromTempNode( node ); |
568 | 547 | } |
569 | 548 | } |
570 | | - //get text node system: |
571 | | - var node = rdpp ( this.wikiText ); |
572 | | - //debugger; |
573 | | - //parse out stuff: |
| 549 | + //parse out the template node structure: |
| 550 | + this.pNode = rdpp ( this.wikiText ); |
| 551 | + //strip out the parent from the root |
| 552 | + this.pNode['p'] = null; |
| 553 | + |
| 554 | + //do the recusrive magic swap text: |
| 555 | + this.pOut = recurse_magic_swap( this.pNode ); |
574 | 556 | |
575 | | - this.pOut = recurse_magic_swap( node); |
576 | | - |
577 | 557 | }, |
| 558 | + |
| 559 | + /* |
| 560 | + * parsed template api ~losely based off of ~POM~ |
| 561 | + * http://www.mediawiki.org/wiki/Extension:Page_Object_Model |
| 562 | + */ |
| 563 | + |
578 | 564 | /** |
| 565 | + * templates |
| 566 | + * |
| 567 | + * gets a requested template from the wikitext (if available) |
| 568 | + * |
| 569 | + */ |
| 570 | + templates: function( tname ){ |
| 571 | + this.parse(); |
| 572 | + var tmplSet = new Array(); |
| 573 | + function getMatchingTmpl( node ){ |
| 574 | + if( node['c'] ){ |
| 575 | + for(var i in node['c']){ |
| 576 | + getMatchingTmpl( node['c'] ); |
| 577 | + } |
| 578 | + } |
| 579 | + if( tname && node.tObj){ |
| 580 | + if( node.tObj['name'] == tname ) |
| 581 | + tmplSet.push( node.tObj ); |
| 582 | + }else if( node.tObj ){ |
| 583 | + tmplSet.push( node.tObj ); |
| 584 | + } |
| 585 | + } |
| 586 | + getMatchingTmpl( this.pNode ); |
| 587 | + return tmplSet; |
| 588 | + }, |
| 589 | + /** |
579 | 590 | * Returns the transformed wikitext |
580 | | - * |
581 | | - * Build output from swapable index |
582 | | - * (all transforms must be expanded in parse stage and linerarly rebuilt) |
583 | | - * Alternativly we could build output using a placeholder & replace system |
| 591 | + * |
| 592 | + * Build output from swapable index |
| 593 | + * (all transforms must be expanded in parse stage and linerarly rebuilt) |
| 594 | + * Alternativly we could build output using a placeholder & replace system |
584 | 595 | * (this lets us be slightly more slopty with ordering and indexes, but probably slower) |
585 | | - * |
586 | | - * Ideal: we build a 'wiki DOM' |
| 596 | + * |
| 597 | + * Ideal: we build a 'wiki DOM' |
587 | 598 | * When editing you update the data structure directly |
588 | | - * Then in output time you just go DOM->html-ish output without re-parsing anything |
| 599 | + * Then in output time you just go DOM->html-ish output without re-parsing anything |
589 | 600 | */ |
590 | 601 | getHTML : function(){ |
591 | 602 | //wikiText updates should invalidate pOut |
— | — | @@ -597,8 +608,9 @@ |
598 | 609 | //return the parserObj |
599 | 610 | return new parseObj( wikiText, opt) ; |
600 | 611 | } |
| 612 | + |
| 613 | +})(window.$mw); |
601 | 614 | |
602 | | -})(window.$mw); |
603 | 615 | //setup legacy global shortcuts: |
604 | 616 | var loadGM = $mw.lang.loadGM; |
605 | 617 | var loadRS = $mw.lang.loadRS; |
— | — | @@ -618,7 +630,8 @@ |
619 | 631 | "mwe-size-kilobytes" : "$1 K", |
620 | 632 | "mwe-size-bytes" : "$1 B", |
621 | 633 | "mwe-error_load_lib" : "Error: JavaScript $1 was not retrievable or does not define $2", |
622 | | - "mwe-loading-add-media-wiz": "Loading add media wizard" |
| 634 | + "mwe-loading-add-media-wiz": "Loading add media wizard", |
| 635 | + "mwe-apiproxy-setup" : " Setting up API proxy" |
623 | 636 | }); |
624 | 637 | |
625 | 638 | |
— | — | @@ -666,10 +679,6 @@ |
667 | 680 | * This is used by the script loader to auto-load classes (so we only define |
668 | 681 | * this once for PHP & JavaScript) |
669 | 682 | * |
670 | | - * This is more verbose than the earlier version that compressed paths |
671 | | - * but it's all good, gzipping helps compress path strings |
672 | | - * grouped by directory. |
673 | | - * |
674 | 683 | * Right now the PHP AutoLoader only reads this mv_embed.js file. |
675 | 684 | * In the future we could have multiple lcPath calls that PHP reads |
676 | 685 | * (if our autoloading class list becomes too long) just have to add those |
— | — | @@ -685,13 +694,15 @@ |
686 | 695 | "$j.ui" : "jquery/jquery.ui/ui/ui.core.js", |
687 | 696 | "$j.fn.ColorPicker" : "libClipEdit/colorpicker/js/colorpicker.js", |
688 | 697 | "$j.Jcrop" : "libClipEdit/Jcrop/js/jquery.Jcrop.js", |
689 | | - "$j.fn.simpleUploadForm": "libAddMedia/simpleUploadForm.js", |
690 | | - |
| 698 | + "$j.fn.simpleUploadForm" : "libAddMedia/simpleUploadForm.js", |
| 699 | + |
| 700 | + "$mw.proxy" : "libMwApi/mw.proxy.js", |
| 701 | + |
691 | 702 | "ctrlBuilder" : "skins/ctrlBuilder.js", |
692 | 703 | "kskinConfig" : "skins/kskin/kskin.js", |
693 | 704 | "mvpcfConfig" : "skins/mvpcf/mvpcf.js", |
694 | 705 | |
695 | | - "$j.secureEvalJSON" : "jquery/plugins/jquery.secureEvalJSON.js", |
| 706 | + "JSON" : "libMwApi/json2.js", |
696 | 707 | "$j.cookie" : "jquery/plugins/jquery.cookie.js", |
697 | 708 | "$j.contextMenu" : "jquery/plugins/jquery.contextMenu.js", |
698 | 709 | "$j.fn.suggestions" : "jquery/plugins/jquery.suggestions.js", |
— | — | @@ -725,12 +736,13 @@ |
726 | 737 | "mvAdvFirefogg" : "libAddMedia/mvAdvFirefogg.js", |
727 | 738 | "mvBaseUploadInterface" : "libAddMedia/mvBaseUploadInterface.js", |
728 | 739 | "remoteSearchDriver" : "libAddMedia/remoteSearchDriver.js", |
729 | | - "seqRemoteSearchDriver" : "libAddMedia/seqRemoteSearchDriver.js", |
| 740 | + "seqRemoteSearchDriver" : "libSequencer/seqRemoteSearchDriver.js", |
730 | 741 | |
731 | 742 | "baseRemoteSearch" : "libAddMedia/searchLibs/baseRemoteSearch.js", |
732 | 743 | "mediaWikiSearch" : "libAddMedia/searchLibs/mediaWikiSearch.js", |
733 | 744 | "metavidSearch" : "libAddMedia/searchLibs/metavidSearch.js", |
734 | 745 | "archiveOrgSearch" : "libAddMedia/searchLibs/archiveOrgSearch.js", |
| 746 | + "flickrSearch" : "libAddMedia/searchLibs/flickrSearch.js", |
735 | 747 | "baseRemoteSearch" : "libAddMedia/searchLibs/baseRemoteSearch.js", |
736 | 748 | |
737 | 749 | "mvClipEdit" : "libClipEdit/mvClipEdit.js", |
— | — | @@ -778,10 +790,6 @@ |
779 | 791 | * mvJsLoader class handles initialization and js file loads |
780 | 792 | */ |
781 | 793 | |
782 | | -// Shortcut |
783 | | -function mwLoad( loadSet, callback ) { |
784 | | - mvJsLoader.doLoad( loadSet, callback ); |
785 | | -} |
786 | 794 | var mvJsLoader = { |
787 | 795 | libreq : {}, |
788 | 796 | libs : {}, |
— | — | @@ -1066,6 +1074,13 @@ |
1067 | 1075 | } |
1068 | 1076 | } |
1069 | 1077 | |
| 1078 | +// Shortcut ( @@todo consolidate shortcuts & re-factor mvJsLoader ) |
| 1079 | +function mwLoad( loadSet, callback ) { |
| 1080 | + mvJsLoader.doLoad( loadSet, callback ); |
| 1081 | +} |
| 1082 | +//$mw.shortcut |
| 1083 | +$mw.load = mwLoad; |
| 1084 | + |
1070 | 1085 | // Load an external JS file. Similar to jquery .require plugin, |
1071 | 1086 | // but checks for object availability rather than load state. |
1072 | 1087 | |
— | — | @@ -1172,15 +1187,30 @@ |
1173 | 1188 | /* |
1174 | 1189 | * Store all the mwEmbed jQuery-specific bindings |
1175 | 1190 | * (set up after jQuery is available). |
1176 | | - * This lets you call rewrites in a jQuery way |
1177 | 1191 | * |
1178 | | - * @@ eventually we should refactor mwCode over to jQuery style plugins |
1179 | | - * and mv_embed.js will just handle dependency mapping and loading. |
| 1192 | + * These functions are genneraly are loaders that do the dynamic mapping of |
| 1193 | + * dependencies for a given compoent |
| 1194 | + * |
1180 | 1195 | * |
1181 | 1196 | */ |
1182 | 1197 | function mv_jqueryBindings() { |
1183 | 1198 | js_log( 'mv_jqueryBindings' ); |
1184 | 1199 | (function( $ ) { |
| 1200 | + /* |
| 1201 | + * apiProxy Loader loader: |
| 1202 | + * |
| 1203 | + * @param mode is either 'server' or 'client' |
| 1204 | + */ |
| 1205 | + $.apiProxy = function( mode, pConf, callback ){ |
| 1206 | + js_log('do apiProxy setup'); |
| 1207 | + $.addLoaderDialog( gM('mwe-apiproxy-setup') ); |
| 1208 | + mvJsLoader.doLoad( [ |
| 1209 | + '$mw.proxy', |
| 1210 | + 'JSON' |
| 1211 | + ], function(){ |
| 1212 | + $mw.proxy[mode]( pConf, callback ); |
| 1213 | + }); |
| 1214 | + } |
1185 | 1215 | //non selector based add-media-wizard direct invocation with loader |
1186 | 1216 | $.addMediaWiz = function( iObj, callback ){ |
1187 | 1217 | js_log(".addMediaWiz call"); |
— | — | @@ -1253,7 +1283,7 @@ |
1254 | 1284 | 'mvPlayList', |
1255 | 1285 | '$j.ui', |
1256 | 1286 | '$j.contextMenu', |
1257 | | - '$j.secureEvalJSON', |
| 1287 | + 'JSON', |
1258 | 1288 | 'mvSequencer' |
1259 | 1289 | ], |
1260 | 1290 | [ |
— | — | @@ -1421,14 +1451,15 @@ |
1422 | 1452 | * |
1423 | 1453 | * @param msg text text of the loader msg |
1424 | 1454 | */ |
1425 | | - $.addLoaderDialog = function( msg_txt ){ |
1426 | | - if( $('#mwe_tmp_loader').length != 0 ) |
1427 | | - $('#mwe_tmp_loader').remove(); |
1428 | | - |
| 1455 | + $.addLoaderDialog = function( msg_txt ){ |
| 1456 | + $.addDialog( msg_txt, msg_txt + '<br>' + mv_get_loading_img() ); |
| 1457 | + } |
| 1458 | + |
| 1459 | + $.addDialog = function ( title, msg_txt, btn ){ |
| 1460 | + $('#mwe_tmp_loader').remove(); |
1429 | 1461 | //append the style free loader ontop: |
1430 | | - $('body').append('<div id="mwe_tmp_loader" title="' + msg_txt + '" >' + |
1431 | | - msg_txt + '<br>' + |
1432 | | - mv_get_loading_img() + |
| 1462 | + $('body').append('<div id="mwe_tmp_loader" title="' + title + '" >' + |
| 1463 | + msg_txt + |
1433 | 1464 | '</div>'); |
1434 | 1465 | //turn the loader into a real dialog loader: |
1435 | 1466 | mvJsLoader.doLoadDepMode([ |
— | — | @@ -1444,14 +1475,21 @@ |
1445 | 1476 | draggable: false, |
1446 | 1477 | resizable: false, |
1447 | 1478 | height: 140, |
1448 | | - modal: true |
| 1479 | + modal: true, |
| 1480 | + buttons: btn |
1449 | 1481 | }); |
1450 | 1482 | }); |
1451 | 1483 | } |
1452 | | - $.closeLoaderDialog = function(){ |
| 1484 | + $.closeLoaderDialog = function(){ |
1453 | 1485 | $('#mwe_tmp_loader').dialog('close'); |
1454 | 1486 | } |
1455 | | - |
| 1487 | + |
| 1488 | + $.mwProxy = function( apiConf ){ |
| 1489 | + mvJsLoader.doLoad( ['$mw.apiProxy'], |
| 1490 | + function(){ |
| 1491 | + $mw.apiProxy( apiConf ); |
| 1492 | + }); |
| 1493 | + } |
1456 | 1494 | })(jQuery); |
1457 | 1495 | } |
1458 | 1496 | /* |
— | — | @@ -1876,7 +1914,11 @@ |
1877 | 1915 | * Utility functions |
1878 | 1916 | */ |
1879 | 1917 | function js_log( string ) { |
1880 | | - if( window.console ) { |
| 1918 | + ///add any prepend debug strings if nessesary |
| 1919 | + if( mwConfig['debug_pre'] ) |
| 1920 | + string = mwConfig['debug_pre']+ string; |
| 1921 | + |
| 1922 | + if( window.console ) { |
1881 | 1923 | window.console.log( string ); |
1882 | 1924 | } else { |
1883 | 1925 | /* |
Index: trunk/phase3/js2/mwEmbed/libEmbedVideo/nativeEmbed.js |
— | — | @@ -37,13 +37,12 @@ |
38 | 38 | |
39 | 39 | //continue with the other attr: |
40 | 40 | eb+= 'oncanplaythrough="$j(\'#'+this.id+'\').get(0).oncanplaythrough();return false;" ' + |
41 | | - 'onloadedmetadata="$j(\'#'+this.id+'\').get(0).onloadedmetadata();return false;" ' + |
42 | | - 'loadedmetadata="$j(\'#'+this.id+'\').get(0).onloadedmetadata();return false;" ' + |
43 | | - 'onprogress="$j(\'#'+this.id+'\').get(0).onprogress( event );return false;" '+ |
44 | | - 'onended="$j(\'#'+this.id+'\').get(0).onended();return false;" '+ |
45 | | - 'onseeking="$j(\'#'+this.id+'\').get(0).onseeking();" ' + |
46 | | - 'onseeked="$j(\'#'+this.id+'\').get(0).onseeked();" ' + |
47 | | - '>' + |
| 41 | + 'onloadedmetadata="$j(\'#'+this.id+'\').get(0).onloadedmetadata();return false;" ' + |
| 42 | + 'loadedmetadata="$j(\'#'+this.id+'\').get(0).onloadedmetadata();return false;" ' + |
| 43 | + 'onprogress="$j(\'#'+this.id+'\').get(0).onprogress( event );return false;" '+ |
| 44 | + 'onended="$j(\'#'+this.id+'\').get(0).onended();return false;" '+ |
| 45 | + 'onseeking="$j(\'#'+this.id+'\').get(0).onseeking();" ' + |
| 46 | + 'onseeked="$j(\'#'+this.id+'\').get(0).onseeked();" >' + |
48 | 47 | '</video>'; |
49 | 48 | return eb; |
50 | 49 | }, |
Index: trunk/phase3/js2/mwEmbed/jquery/plugins/jquery.secureEvalJSON.js |
— | — | @@ -1,156 +0,0 @@ |
2 | | -/* |
3 | | - * jQuery JSON Plugin |
4 | | - * version: 1.0 (2008-04-17) |
5 | | - * |
6 | | - * This document is licensed as free software under the terms of the |
7 | | - * MIT License: http://www.opensource.org/licenses/mit-license.php |
8 | | - * |
9 | | - * Brantley Harris technically wrote this plugin, but it is based somewhat |
10 | | - * on the JSON.org website's http://www.json.org/json2.js, which proclaims: |
11 | | - * "NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.", a sentiment that |
12 | | - * I uphold. I really just cleaned it up. |
13 | | - * |
14 | | - * It is also based heavily on MochiKit's serializeJSON, which is |
15 | | - * copywrited 2005 by Bob Ippolito. |
16 | | - */ |
17 | | - |
18 | | -(function($) { |
19 | | - function toIntegersAtLease(n) |
20 | | - // Format integers to have at least two digits. |
21 | | - { |
22 | | - return n < 10 ? '0' + n : n; |
23 | | - } |
24 | | - |
25 | | - Date.prototype.toJSON = function(date) |
26 | | - // Yes, it polutes the Date namespace, but we'll allow it here, as |
27 | | - // it's damned usefull. |
28 | | - { |
29 | | - return this.getUTCFullYear() + '-' + |
30 | | - toIntegersAtLease(this.getUTCMonth()) + '-' + |
31 | | - toIntegersAtLease(this.getUTCDate()); |
32 | | - }; |
33 | | - |
34 | | - var escapeable = /["\\\x00-\x1f\x7f-\x9f]/g; |
35 | | - var meta = { // table of character substitutions |
36 | | - '\b': '\\b', |
37 | | - '\t': '\\t', |
38 | | - '\n': '\\n', |
39 | | - '\f': '\\f', |
40 | | - '\r': '\\r', |
41 | | - '"' : '\\"', |
42 | | - '\\': '\\\\' |
43 | | - }; |
44 | | - |
45 | | - $.quoteString = function(string) |
46 | | - // Places quotes around a string, inteligently. |
47 | | - // If the string contains no control characters, no quote characters, and no |
48 | | - // backslash characters, then we can safely slap some quotes around it. |
49 | | - // Otherwise we must also replace the offending characters with safe escape |
50 | | - // sequences. |
51 | | - { |
52 | | - if (escapeable.test(string)) |
53 | | - { |
54 | | - return '"' + string.replace(escapeable, function (a) |
55 | | - { |
56 | | - var c = meta[a]; |
57 | | - if (typeof c === 'string') { |
58 | | - return c; |
59 | | - } |
60 | | - c = a.charCodeAt(); |
61 | | - return '\\u00' + Math.floor(c / 16).toString(16) + (c % 16).toString(16); |
62 | | - }) + '"'; |
63 | | - } |
64 | | - return '"' + string + '"'; |
65 | | - }; |
66 | | - |
67 | | - $.toJSON = function(o, compact) |
68 | | - { |
69 | | - var type = typeof(o); |
70 | | - |
71 | | - if (type == "undefined") |
72 | | - return "undefined"; |
73 | | - else if (type == "number" || type == "boolean") |
74 | | - return o + ""; |
75 | | - else if (o === null) |
76 | | - return "null"; |
77 | | - |
78 | | - // Is it a string? |
79 | | - if (type == "string") |
80 | | - { |
81 | | - return $.quoteString(o); |
82 | | - } |
83 | | - |
84 | | - // Does it have a .toJSON function? |
85 | | - if (type == "object" && typeof o.toJSON == "function") |
86 | | - return o.toJSON(compact); |
87 | | - |
88 | | - // Is it an array? |
89 | | - if (type != "function" && typeof(o.length) == "number") |
90 | | - { |
91 | | - var ret = []; |
92 | | - for (var i = 0; i < o.length; i++) { |
93 | | - ret.push( $.toJSON(o[i], compact) ); |
94 | | - } |
95 | | - if (compact) |
96 | | - return "[" + ret.join(",") + "]"; |
97 | | - else |
98 | | - return "[" + ret.join(", ") + "]"; |
99 | | - } |
100 | | - |
101 | | - // If it's a function, we have to warn somebody! |
102 | | - if (type == "function") { |
103 | | - throw new TypeError("Unable to convert object of type 'function' to json."); |
104 | | - } |
105 | | - |
106 | | - // It's probably an object, then. |
107 | | - var ret = []; |
108 | | - for (var k in o) { |
109 | | - var name; |
110 | | - type = typeof(k); |
111 | | - |
112 | | - if (type == "number") |
113 | | - name = '"' + k + '"'; |
114 | | - else if (type == "string") |
115 | | - name = $.quoteString(k); |
116 | | - else |
117 | | - continue; //skip non-string or number keys |
118 | | - |
119 | | - var val = $.toJSON(o[k], compact); |
120 | | - if (typeof(val) != "string") { |
121 | | - // skip non-serializable values |
122 | | - continue; |
123 | | - } |
124 | | - |
125 | | - if (compact) |
126 | | - ret.push(name + ":" + val); |
127 | | - else |
128 | | - ret.push(name + ": " + val); |
129 | | - } |
130 | | - return "{" + ret.join(", ") + "}"; |
131 | | - }; |
132 | | - |
133 | | - $.compactJSON = function(o) |
134 | | - { |
135 | | - return $.toJSON(o, true); |
136 | | - }; |
137 | | - |
138 | | - $.evalJSON = function(src) |
139 | | - // Evals JSON that we know to be safe. |
140 | | - { |
141 | | - return eval("(" + src + ")"); |
142 | | - }; |
143 | | - |
144 | | - $.secureEvalJSON = function(src) |
145 | | - // Evals JSON in a way that is *more* secure. |
146 | | - { |
147 | | - var filtered = src; |
148 | | - filtered = filtered.replace(/\\["\\\/bfnrtu]/g, '@'); |
149 | | - filtered = filtered.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']'); |
150 | | - filtered = filtered.replace(/(?:^|:|,)(?:\s*\[)+/g, ''); |
151 | | - |
152 | | - if (/^[\],:{}\s]*$/.test(filtered)) |
153 | | - return eval("(" + src + ")"); |
154 | | - else |
155 | | - throw new SyntaxError("Error parsing JSON, source is not valid."); |
156 | | - }; |
157 | | -})(jQuery); |
Index: trunk/phase3/js2/mwEmbed/jquery/plugins/jquery.json-1.3.js |
— | — | @@ -1,156 +0,0 @@ |
2 | | -/* |
3 | | - * jQuery JSON Plugin |
4 | | - * version: 1.0 (2008-04-17) |
5 | | - * |
6 | | - * This document is licensed as free software under the terms of the |
7 | | - * MIT License: http://www.opensource.org/licenses/mit-license.php |
8 | | - * |
9 | | - * Brantley Harris technically wrote this plugin, but it is based somewhat |
10 | | - * on the JSON.org website's http://www.json.org/json2.js, which proclaims: |
11 | | - * "NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.", a sentiment that |
12 | | - * I uphold. I really just cleaned it up. |
13 | | - * |
14 | | - * It is also based heavily on MochiKit's serializeJSON, which is |
15 | | - * copywrited 2005 by Bob Ippolito. |
16 | | - */ |
17 | | - |
18 | | -(function($) { |
19 | | - function toIntegersAtLease(n) |
20 | | - // Format integers to have at least two digits. |
21 | | - { |
22 | | - return n < 10 ? '0' + n : n; |
23 | | - } |
24 | | - |
25 | | - Date.prototype.toJSON = function(date) |
26 | | - // Yes, it polutes the Date namespace, but we'll allow it here, as |
27 | | - // it's damned usefull. |
28 | | - { |
29 | | - return this.getUTCFullYear() + '-' + |
30 | | - toIntegersAtLease(this.getUTCMonth()) + '-' + |
31 | | - toIntegersAtLease(this.getUTCDate()); |
32 | | - }; |
33 | | - |
34 | | - var escapeable = /["\\\x00-\x1f\x7f-\x9f]/g; |
35 | | - var meta = { // table of character substitutions |
36 | | - '\b': '\\b', |
37 | | - '\t': '\\t', |
38 | | - '\n': '\\n', |
39 | | - '\f': '\\f', |
40 | | - '\r': '\\r', |
41 | | - '"' : '\\"', |
42 | | - '\\': '\\\\' |
43 | | - }; |
44 | | - |
45 | | - $.quoteString = function(string) |
46 | | - // Places quotes around a string, inteligently. |
47 | | - // If the string contains no control characters, no quote characters, and no |
48 | | - // backslash characters, then we can safely slap some quotes around it. |
49 | | - // Otherwise we must also replace the offending characters with safe escape |
50 | | - // sequences. |
51 | | - { |
52 | | - if (escapeable.test(string)) |
53 | | - { |
54 | | - return '"' + string.replace(escapeable, function (a) |
55 | | - { |
56 | | - var c = meta[a]; |
57 | | - if (typeof c === 'string') { |
58 | | - return c; |
59 | | - } |
60 | | - c = a.charCodeAt(); |
61 | | - return '\\u00' + Math.floor(c / 16).toString(16) + (c % 16).toString(16); |
62 | | - }) + '"'; |
63 | | - } |
64 | | - return '"' + string + '"'; |
65 | | - }; |
66 | | - |
67 | | - $.toJSON = function(o, compact) |
68 | | - { |
69 | | - var type = typeof(o); |
70 | | - |
71 | | - if (type == "undefined") |
72 | | - return "undefined"; |
73 | | - else if (type == "number" || type == "boolean") |
74 | | - return o + ""; |
75 | | - else if (o === null) |
76 | | - return "null"; |
77 | | - |
78 | | - // Is it a string? |
79 | | - if (type == "string") |
80 | | - { |
81 | | - return $.quoteString(o); |
82 | | - } |
83 | | - |
84 | | - // Does it have a .toJSON function? |
85 | | - if (type == "object" && typeof o.toJSON == "function") |
86 | | - return o.toJSON(compact); |
87 | | - |
88 | | - // Is it an array? |
89 | | - if (type != "function" && typeof(o.length) == "number") |
90 | | - { |
91 | | - var ret = []; |
92 | | - for (var i = 0; i < o.length; i++) { |
93 | | - ret.push( $.toJSON(o[i], compact) ); |
94 | | - } |
95 | | - if (compact) |
96 | | - return "[" + ret.join(",") + "]"; |
97 | | - else |
98 | | - return "[" + ret.join(", ") + "]"; |
99 | | - } |
100 | | - |
101 | | - // If it's a function, we have to warn somebody! |
102 | | - if (type == "function") { |
103 | | - throw new TypeError("Unable to convert object of type 'function' to json."); |
104 | | - } |
105 | | - |
106 | | - // It's probably an object, then. |
107 | | - var ret = []; |
108 | | - for (var k in o) { |
109 | | - var name; |
110 | | - type = typeof(k); |
111 | | - |
112 | | - if (type == "number") |
113 | | - name = '"' + k + '"'; |
114 | | - else if (type == "string") |
115 | | - name = $.quoteString(k); |
116 | | - else |
117 | | - continue; //skip non-string or number keys |
118 | | - |
119 | | - var val = $.toJSON(o[k], compact); |
120 | | - if (typeof(val) != "string") { |
121 | | - // skip non-serializable values |
122 | | - continue; |
123 | | - } |
124 | | - |
125 | | - if (compact) |
126 | | - ret.push(name + ":" + val); |
127 | | - else |
128 | | - ret.push(name + ": " + val); |
129 | | - } |
130 | | - return "{" + ret.join(", ") + "}"; |
131 | | - }; |
132 | | - |
133 | | - $.compactJSON = function(o) |
134 | | - { |
135 | | - return $.toJSON(o, true); |
136 | | - }; |
137 | | - |
138 | | - $.evalJSON = function(src) |
139 | | - // Evals JSON that we know to be safe. |
140 | | - { |
141 | | - return eval("(" + src + ")"); |
142 | | - }; |
143 | | - |
144 | | - $.secureEvalJSON = function(src) |
145 | | - // Evals JSON in a way that is *more* secure. |
146 | | - { |
147 | | - var filtered = src; |
148 | | - filtered = filtered.replace(/\\["\\\/bfnrtu]/g, '@'); |
149 | | - filtered = filtered.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']'); |
150 | | - filtered = filtered.replace(/(?:^|:|,)(?:\s*\[)+/g, ''); |
151 | | - |
152 | | - if (/^[\],:{}\s]*$/.test(filtered)) |
153 | | - return eval("(" + src + ")"); |
154 | | - else |
155 | | - throw new SyntaxError("Error parsing JSON, source is not valid."); |
156 | | - }; |
157 | | -})(jQuery); |
Index: trunk/phase3/js2/mwEmbed/libAddMedia/seqRemoteSearchDriver.js |
— | — | @@ -1,181 +0,0 @@ |
2 | | -/*the sequence remote search driver |
3 | | - extends the base remote search driver with sequence specific stuff |
4 | | -*/ |
5 | | - |
6 | | -var seqRemoteSearchDriver = function(iObj){ |
7 | | - return this.init( iObj ) |
8 | | -} |
9 | | -seqRemoteSearchDriver.prototype = { |
10 | | - sequence_add_target:false, |
11 | | - init:function( this_seq ){ |
12 | | - var _this = this; |
13 | | - js_log("init:seqRemoteSearchDriver"); |
14 | | - //setup remote search driver with a seq parent: |
15 | | - this.pSeq = this_seq; |
16 | | - var iObj = { |
17 | | - 'target_container' : '#cliplib_ic', |
18 | | - 'local_wiki_api_url': this_seq.getLocalApiUrl(), |
19 | | - 'instance_name' : this_seq.instance_name + '.mySearch', |
20 | | - 'default_query' : this.pSeq.plObj.title |
21 | | - } |
22 | | - if(typeof this_seq.amw_conf != 'undefined') |
23 | | - $j.extend(iObj, this_seq.amw_conf); |
24 | | - //inherit the remoteSearchDriver properties:n |
25 | | - var tmpRSD = new remoteSearchDriver( iObj ); |
26 | | - for(var i in tmpRSD){ |
27 | | - if(this[i]){ |
28 | | - this['parent_'+i] = tmpRSD[i]; |
29 | | - }else{ |
30 | | - this[i] = tmpRSD[i]; |
31 | | - } |
32 | | - } |
33 | | - //extend parent_do_refresh_timeline actions: |
34 | | - if(!this.pSeq.parent_do_refresh_timeline){ |
35 | | - this.pSeq.parent_do_refresh_timeline = this.pSeq.do_refresh_timeline; |
36 | | - this.pSeq.do_refresh_timeline = function(){ |
37 | | - js_log("seqRemoteSearchDriver::" + _this.pSeq.disp_menu_item); |
38 | | - //call the parent |
39 | | - _this.pSeq.parent_do_refresh_timeline(); |
40 | | - //add our local bindings |
41 | | - _this.addResultBindings(); |
42 | | - return true; |
43 | | - } |
44 | | - } |
45 | | - }, |
46 | | - resourceEdit:function(){ |
47 | | - var _this = this; |
48 | | - |
49 | | - }, |
50 | | - addResultBindings:function(){ |
51 | | - //set up seq: |
52 | | - var _this = this; |
53 | | - //setup parent bindings: |
54 | | - this.parent_addResultBindings(); |
55 | | - |
56 | | - //add an aditional click binding |
57 | | - $j('.rsd_res_item').click(function(){ |
58 | | - js_log('SeqRemoteSearch: rsd_res_item: click (remove sequence_add_target)'); |
59 | | - _this.sequence_add_target =false; |
60 | | - }); |
61 | | - |
62 | | - //add an additional drag binding |
63 | | - $j( '.rsd_res_item' ).draggable('destroy').draggable({ |
64 | | - helper:function(){ |
65 | | - return $j( this ).clone().appendTo('body').css({'z-index':9999}).get(0); |
66 | | - }, |
67 | | - revert:'invalid', |
68 | | - start:function(){ |
69 | | - js_log('start drag'); |
70 | | - } |
71 | | - }); |
72 | | - $j(".mv_clip_drag").droppable( 'destroy' ).droppable({ |
73 | | - accept: '.rsd_res_item', |
74 | | - over:function(event, ui){ |
75 | | - //js_log("over : mv_clip_drag: " + $j(this).attr('id') ); |
76 | | - $j(this).css('border-right', 'solid thick red'); |
77 | | - }, |
78 | | - out:function(event, ui){ |
79 | | - $j(this).css('border-right', 'solid thin white'); |
80 | | - }, |
81 | | - drop: function(event, ui) { |
82 | | - $j(this).css('border-right', 'solid thin white'); |
83 | | - js_log("Droped: "+ $j(ui.draggable).attr('id') +' on ' + $j(this).attr('id') ); |
84 | | - _this.sequence_add_target = $j(this).attr('id'); |
85 | | - //load the orginal draged item |
86 | | - var rObj = _this.getResourceFromId( $j(ui.draggable).attr('id') ); |
87 | | - _this.resourceEdit(rObj, ui.draggable); |
88 | | - } |
89 | | - }); |
90 | | - |
91 | | - }, |
92 | | - insertResource:function(rObj){ |
93 | | - var _this = this; |
94 | | - js_log("SEQ insert resource after:" + _this.sequence_add_target + ' of type: ' + rObj.mime); |
95 | | - if(_this.sequence_add_target ){ |
96 | | - var tClip = _this.pSeq.getClipFromSeqID( _this.sequence_add_target ); |
97 | | - var target_order = false; |
98 | | - if(tClip) |
99 | | - var target_order = tClip.order; |
100 | | - } |
101 | | - //@@todo show wating of sorts. |
102 | | - |
103 | | - //get target order: |
104 | | - var cat = rObj; |
105 | | - //check for target insert path |
106 | | - this.checkImportResource( rObj, function(){ |
107 | | - |
108 | | - var clipConfig = { |
109 | | - 'type' : rObj.mime, |
110 | | - 'uri' : _this.cFileNS + ':' + rObj.target_resource_title, |
111 | | - 'title' : rObj.title |
112 | | - }; |
113 | | - //set via local properites if avaliable |
114 | | - clipConfig['src'] = (rObj.local_src) ? rObj.local_src : rObj.src; |
115 | | - clipConfig['poster'] = ( rObj.local_poster ) ? rObj.local_poster : rObj.poster; |
116 | | - |
117 | | - if(rObj.start_time && rObj.end_time){ |
118 | | - clipConfig['dur'] = npt2seconds( rObj.end_time ) - npt2seconds( rObj.start_time ); |
119 | | - }else{ |
120 | | - //provide a default duration if none set |
121 | | - clipConfig['dur'] = 4; |
122 | | - } |
123 | | - |
124 | | - //create the media element (target order+1 (since we insert (after) |
125 | | - _this.pSeq.plObj.tryAddMediaObj( clipConfig, (parseInt(target_order) + 1) ); |
126 | | - //refresh the timeline: |
127 | | - _this.pSeq.do_refresh_timeline(); |
128 | | - js_log("run close all: "); |
129 | | - _this.closeAll(); |
130 | | - }); |
131 | | - }, |
132 | | - getClipEditControlActions:function(){ |
133 | | - var _this = this; |
134 | | - return { |
135 | | - 'insert_seq':function(rObj){ |
136 | | - _this.insertResource( rObj ) |
137 | | - }, |
138 | | - 'cancel':function(rObj){ |
139 | | - _this.cancelClipEditCB( rObj ) |
140 | | - } |
141 | | - }; |
142 | | - }, |
143 | | - resourceEdit:function(rObj, rsdElement){ |
144 | | - var _this = this; |
145 | | - //don't resize to default (full screen behavior) |
146 | | - _this.dmodalCss = {}; |
147 | | - //open up a new target_contaienr: |
148 | | - if($j('#seq_resource_import').length == 0) |
149 | | - $j('body').append('<div id="seq_resource_import" style="position:relative"></div>'); |
150 | | - |
151 | | - $j('#seq_resource_import').dialog('destroy').dialog({ |
152 | | - bgiframe: true, |
153 | | - width:750, |
154 | | - height:480, |
155 | | - modal: true, |
156 | | - buttons: { |
157 | | - "Cancel": function() { |
158 | | - $j(this).dialog("close"); |
159 | | - } |
160 | | - } |
161 | | - }); |
162 | | - _this.target_container = '#seq_resource_import'; |
163 | | - //do parent resource edit (with updated target) |
164 | | - this.parent_resourceEdit(rObj, rsdElement); |
165 | | - }, |
166 | | - closeAll:function(){ |
167 | | - js_log( 'should close: seq_resource_import'); |
168 | | - $j('#seq_resource_import').dialog('close').dialog('destroy').remove(); |
169 | | - this.parent_closeAll(); |
170 | | - }, |
171 | | - getEditToken:function(callback){ |
172 | | - if(this.pSeq.sequenceEditToken){ |
173 | | - callback( this.pSeq.sequenceEditToken ) |
174 | | - }else{ |
175 | | - this.parent_getEditToken(callback); |
176 | | - } |
177 | | - }, |
178 | | - cancelClipEditCB:function(){ |
179 | | - js_log('seqRSD:cancelClipEditCB'); |
180 | | - $j('#seq_resource_import').dialog('close').dialog('destroy').remove(); |
181 | | - } |
182 | | -}; |
Index: trunk/phase3/js2/mwEmbed/libAddMedia/mvBaseUploadInterface.js |
— | — | @@ -359,16 +359,11 @@ |
360 | 360 | //@@check if we are done |
361 | 361 | if( data.upload['apiUploadResult'] ){ |
362 | 362 | //update status to 100% |
363 | | - _this.updateProgress( 1 ); |
364 | | - if(typeof JSON == 'undefined'){ |
365 | | - //we need to load the jQuery json parser: (older browsers don't have JSON.parse |
366 | | - mvJsLoader.doLoad([ |
367 | | - '$j.secureEvalJSON' |
368 | | - ],function(){ |
369 | | - var apiResult = $j.secureEvalJSON( data.upload['apiUploadResult'] ); |
370 | | - _this.processApiResult( apiResult ); |
371 | | - }); |
372 | | - }else{ |
| 363 | + _this.updateProgress( 1 ); |
| 364 | + //see if we need to load JSON substitue: |
| 365 | + mvJsLoader.doLoad( [ |
| 366 | + 'JSON' |
| 367 | + ],function(){ |
373 | 368 | var apiResult = {}; |
374 | 369 | try{ |
375 | 370 | apiResult = JSON.parse ( data.upload['apiUploadResult'] ) ; |
— | — | @@ -377,7 +372,7 @@ |
378 | 373 | js_log('errro: could not parse apiUploadResult ') |
379 | 374 | } |
380 | 375 | _this.processApiResult( apiResult ); |
381 | | - } |
| 376 | + }); |
382 | 377 | return ; |
383 | 378 | } |
384 | 379 | |
Index: trunk/phase3/js2/mwEmbed/libAddMedia/searchLibs/baseRemoteSearch.js |
— | — | @@ -35,9 +35,9 @@ |
36 | 36 | |
37 | 37 | //default search result values for paging: |
38 | 38 | offset :0, |
39 | | - limit :20, |
40 | | - more_results :false, |
41 | | - num_results :0, |
| 39 | + limit : 30, |
| 40 | + more_results : false, |
| 41 | + num_results : 0, |
42 | 42 | |
43 | 43 | //init the object: |
44 | 44 | init: function( iObj ){ |
— | — | @@ -53,8 +53,9 @@ |
54 | 54 | //do global getSearchResults bindings |
55 | 55 | this.last_query = $j('#rsd_q').val(); |
56 | 56 | this.last_offset = this.cp.offset; |
57 | | - //@@todo its possible that video rss is the "default" format we could put that logic here: |
58 | | - }, |
| 57 | + //set the loading flag: |
| 58 | + this.loading=true; |
| 59 | + }, |
59 | 60 | /* |
60 | 61 | * Parses and adds video rss based input format |
61 | 62 | * @param $data XML data to parse |
— | — | @@ -146,6 +147,37 @@ |
147 | 148 | _this.num_results++; |
148 | 149 | }); |
149 | 150 | }, |
| 151 | + getEmbedHTML: function( rObj , options) { |
| 152 | + if(!options) |
| 153 | + options = {}; |
| 154 | + //set up the output var with the default values: |
| 155 | + var outOpt = { 'width': rObj.width, 'height': rObj.height}; |
| 156 | + if( options['max_height'] ){ |
| 157 | + outOpt.height = (options.max_height > rObj.height) ? rObj.height : options.max_height; |
| 158 | + outOpt.width = (rObj.width / rObj.height) *outOpt.height; |
| 159 | + } |
| 160 | + options.style_attr = 'style="width:' + outOpt.width + 'px;height:' + outOpt.height +'px"'; |
| 161 | + options.id_attr = (options['id'])?' id = "' + options['id'] +'" ': ''; |
| 162 | + |
| 163 | + if( rObj.mime.indexOf('image') != -1 ){ |
| 164 | + return this.getImageEmbedHTML( rObj, options ); |
| 165 | + }else{ |
| 166 | + js_log("ERROR:: no embed code for mime type: " + rObj.mime); |
| 167 | + return ' Error missing embed code '; |
| 168 | + } |
| 169 | + }, |
| 170 | + getImageEmbedHTML:function( rObj, options ) { |
| 171 | + //if crop is null do base output: |
| 172 | + var imgHtml = '<img ' + options.id_attr + ' src="' + rObj.edit_url + '"' + options.style_attr + ' >'; |
| 173 | + if( rObj.crop == null) |
| 174 | + return imgHtml |
| 175 | + //else do crop output: |
| 176 | + return '<div style="width:'+rObj.crop.w +'px;height: ' + rObj.crop.h +'px;overflow:hidden;position:relative">' + |
| 177 | + '<div style="position:relative;top:-' + rObj.crop.y +'px;left:-' + rObj.crop.x +'px">'+ |
| 178 | + imgHtml + |
| 179 | + '</div>'+ |
| 180 | + '</div>'; |
| 181 | + }, |
150 | 182 | //by default just return the existing image with callback |
151 | 183 | getImageObj:function( rObj, size, callback){ |
152 | 184 | callback( {'url':rObj.poster} ); |
Index: trunk/phase3/js2/mwEmbed/libAddMedia/searchLibs/archiveOrgSearch.js |
— | — | @@ -23,23 +23,21 @@ |
24 | 24 | }, |
25 | 25 | getSearchResults:function(){ |
26 | 26 | //call parent: |
27 | | - this.parent_getSearchResults(); |
28 | | - |
29 | | - var _this = this; |
30 | | - this.loading=true; |
| 27 | + this.parent_getSearchResults(); |
| 28 | + var _this = this; |
31 | 29 | js_log('f:getSearchResults for:' + $j('#rsd_q').val() ); |
32 | 30 | //build the query var |
33 | 31 | var q = $j('#rsd_q').val(); |
34 | 32 | //@@todo check advanced options: include audio and images media types |
35 | | - //for now force (Ogg video) & a creativecommons license |
| 33 | + //for now force (Ogg video) & url based license |
36 | 34 | q+=' format:(Ogg video)'; |
37 | 35 | q+=' licenseurl:(http\\:\\/\\/*)'; |
38 | 36 | var reqObj = { |
39 | 37 | 'q': q, //just search for video atm |
40 | 38 | 'fl':"description,title,identifier,licenseurl,format,license,thumbnail", |
41 | 39 | 'wt':'json', |
42 | | - 'rows':'30', |
43 | | - 'indent':'yes' |
| 40 | + 'rows' : this.cp.limit, |
| 41 | + 'start' : this.cp.offset |
44 | 42 | } |
45 | 43 | do_api_req( { |
46 | 44 | 'data':reqObj, |
— | — | @@ -77,15 +75,7 @@ |
78 | 76 | 'pSobj' :_this |
79 | 77 | |
80 | 78 | }; |
81 | | - this.resultsObj[ resource_id ] = rObj; |
82 | | - |
83 | | - //likely a audio clip if no poster and type application/ogg |
84 | | - //@@todo we should return audio/ogg for the mime type or some other way to specify its "audio" |
85 | | - |
86 | | - //this.num_results++; |
87 | | - //for(var i in this.resultsObj[page_id]){ |
88 | | - // js_log('added: '+ i +' '+ this.resultsObj[page_id][i]); |
89 | | - //} |
| 79 | + this.resultsObj[ resource_id ] = rObj; |
90 | 80 | } |
91 | 81 | } |
92 | 82 | }, |
Index: trunk/phase3/js2/mwEmbed/libAddMedia/searchLibs/metavidSearch.js |
— | — | @@ -26,10 +26,8 @@ |
27 | 27 | getSearchResults:function(){ |
28 | 28 | //call parent: |
29 | 29 | this.parent_getSearchResults(); |
30 | | - |
31 | | - var _this = this; |
32 | | - //start loading: |
33 | | - _this.loading= 1; |
| 30 | + //set local ref: |
| 31 | + var _this = this; |
34 | 32 | js_log('metavidSearch::getSearchResults()'); |
35 | 33 | //proccess all options |
36 | 34 | var url = this.cp.api_url; |
Index: trunk/phase3/js2/mwEmbed/libAddMedia/searchLibs/flickrSearch.js |
— | — | @@ -1,7 +1,36 @@ |
2 | | -var flickrOrgSearch = function ( iObj){ |
| 2 | +/* |
| 3 | +* basic flickr search uses flickr jsonp api |
| 4 | +* http://www.flickr.com/services/api/ |
| 5 | +* |
| 6 | +* uses the "example api_key" 519b66e3fd8d8080e27a64fe51101e2c |
| 7 | +* should update with a difrent "public" key sometime soon |
| 8 | +http://www.flickr.com/services/rest/?method=flickr.test.echo&format=json&api_key=519b66e3fd8d8080e27a64fe51101e2c |
| 9 | +* |
| 10 | +* we look for licenses from method=flickr.photos.licenses.getInfo |
| 11 | +* per http://commons.wikimedia.org/wiki/Special:Upload?uselang=fromflickr |
| 12 | +* we are interested in: |
| 13 | + (4) Attribution License |
| 14 | + (5) Attribution-ShareAlike License, |
| 15 | + (7) No known copyright restrictions, |
| 16 | + (8) United States Government Work |
| 17 | +*/ |
| 18 | + |
| 19 | +var flickrSearch = function ( iObj){ |
3 | 20 | return this.init( iObj ); |
4 | 21 | } |
5 | | -flickrOrgSearch.prototype = { |
| 22 | +flickrSearch.prototype = { |
| 23 | + dtUrl : 'http://www.flickr.com/photos/', |
| 24 | + //@@todo probably would be good to read the api-key from configuration |
| 25 | + apikey : '2867787a545cc66c0bce6f2e57aca1d1', |
| 26 | + //what licence we are interested in |
| 27 | + _licence_keys: '4,5,7,8', |
| 28 | + _srctypes: ['t','sq','s','m','o'], |
| 29 | + licenceMap:{ |
| 30 | + '4' : 'http://creativecommons.org/licenses+/by/3.0/', |
| 31 | + '5' : 'http://creativecommons.org/licenses/by-sa/3.0/', |
| 32 | + '7' : 'http://www.flickr.com/commons/usage/', |
| 33 | + '8' : 'http://www.usa.gov/copyright.shtml' |
| 34 | + }, |
6 | 35 | init:function( iObj ){ |
7 | 36 | //init base class and inherit: |
8 | 37 | var baseSearch = new baseRemoteSearch( iObj ); |
— | — | @@ -14,9 +43,111 @@ |
15 | 44 | } |
16 | 45 | //inherit the cp settings for |
17 | 46 | }, |
18 | | - getSearchResults:function(){ |
19 | | - //call parent: |
| 47 | + getSearchResults:function(){ |
| 48 | + var _this = this; |
| 49 | + js_log("flickr::getSearchResults"); |
| 50 | + //call parent (sets loading sate and other setup stuff) |
20 | 51 | this.parent_getSearchResults(); |
21 | 52 | //setup the flickr request: |
| 53 | + var reqObj = { |
| 54 | + 'method':'flickr.photos.search', |
| 55 | + 'format':'json', |
| 56 | + 'license':this._licence_keys, |
| 57 | + 'api_key':this.apikey, |
| 58 | + 'per_page': this.cp.limit, |
| 59 | + 'page' : this.cp.offset, |
| 60 | + 'text': $j('#rsd_q').val(), |
| 61 | + 'extras' : 'license, date_upload, date_taken, owner_name, icon_server, original_format, last_update, geo, tags, machine_tags, o_dims, views, media, path_alias, url_sq, url_t, url_s, url_m, url_o' |
| 62 | + } |
| 63 | + do_api_req( { |
| 64 | + 'data': reqObj, |
| 65 | + 'url':this.cp.api_url, |
| 66 | + 'jsonCB':'jsoncallback', |
| 67 | + }, function( data ){ |
| 68 | + _this.addResults( data); |
| 69 | + _this.loading = false; |
| 70 | + }); |
| 71 | + }, |
| 72 | + addResults:function( data ){ |
| 73 | + var _this = this; |
| 74 | + if(data.photos && data.photos.photo){ |
| 75 | + //set result info: |
| 76 | + this.num_results = data.photos.total; |
| 77 | + for(var resource_id in data.photos.photo){ |
| 78 | + var resource = data.photos.photo[resource_id]; |
| 79 | + |
| 80 | + var rObj = { |
| 81 | + 'titleKey' : resource.title + '.jpg', |
| 82 | + 'resourceKey': resource.id, |
| 83 | + 'link' : _this.dtUrl + resource.pathalias + '/'+ resource.id, |
| 84 | + 'title' : resource.title, |
| 85 | + 'thumbwidth' : resource.width_t, |
| 86 | + 'thumbheight': resource.height_t, |
| 87 | + 'desc' : resource.title, |
| 88 | + //set the license: (rsd is a pointer to the parent remoteSearchDriver ) |
| 89 | + 'license' : this.rsd.getLicenceFromUrl( _this.licenceMap[ resource.license ] ), |
| 90 | + 'pSobj' : _this, |
| 91 | + //assume image/jpeg for "photos" |
| 92 | + 'mime' : 'image/jpeg' |
| 93 | + }; |
| 94 | + //set all the provided srcs: |
| 95 | + rObj['srcSet'] = {}; |
| 96 | + for( var i in _this._srctypes){ |
| 97 | + var st = _this._srctypes[i]; |
| 98 | + //if resource has a url add it to the srcSet: |
| 99 | + if( resource['url_' + st] ){ |
| 100 | + rObj['srcSet'][st] = { |
| 101 | + 'h': resource['height_' + st], |
| 102 | + 'w': resource['width_' + st], |
| 103 | + 'src': resource['url_' + st] |
| 104 | + } |
| 105 | + //set src to the largest |
| 106 | + rObj['src'] = resource['url_' + st]; |
| 107 | + } |
| 108 | + } |
| 109 | + |
| 110 | + _this.resultsObj[ resource_id ] = rObj; |
| 111 | + } |
| 112 | + } |
| 113 | + }, |
| 114 | + //return image transform via callback |
| 115 | + getImageObj:function( rObj, size, callback){ |
| 116 | + if( size.width ){ |
| 117 | + var skey = this.getSrcTypeKey(rObj, size.width ) |
| 118 | + callback ({ |
| 119 | + 'url' : rObj.srcSet[ skey ].src, |
| 120 | + 'width' : rObj.srcSet[ skey ].w, |
| 121 | + 'height' : rObj.srcSet[ skey ].h |
| 122 | + }); |
| 123 | + } |
| 124 | + }, |
| 125 | + getImageTransform:function(rObj, opt){ |
| 126 | + if( opt.width ){ |
| 127 | + return rObj.srcSet[ this.getSrcTypeKey(rObj, opt.width) ].src; |
| 128 | + } |
| 129 | + }, |
| 130 | + getSrcTypeKey:function(rObj, width ){ |
| 131 | + if( width <= 75 ){ |
| 132 | + if( rObj.srcSet['sq'] ) |
| 133 | + return 'sq'; |
| 134 | + }else if( width <= 100 ){ |
| 135 | + if( rObj.srcSet['t'] ) |
| 136 | + return 't'; |
| 137 | + }else if( width <= 240 ){ |
| 138 | + if( rObj.srcSet['s'] ) |
| 139 | + return 's'; |
| 140 | + }else if( width <= 500 ){ |
| 141 | + if( rObj.srcSet['m'] ) |
| 142 | + return 'm'; |
| 143 | + }else{ |
| 144 | + if( rObj.srcSet['o'] ) |
| 145 | + return 'o'; |
| 146 | + } |
| 147 | + //original was missing return medium or small |
| 148 | + if( rObj.srcSet['m'] ) |
| 149 | + return 'm'; |
| 150 | + if( rObj.srcSet['s'] ) |
| 151 | + return 's'; |
| 152 | + |
22 | 153 | } |
23 | 154 | } |
\ No newline at end of file |
Index: trunk/phase3/js2/mwEmbed/libAddMedia/searchLibs/mediaWikiSearch.js |
— | — | @@ -88,9 +88,9 @@ |
89 | 89 | getSearchResults:function(){ |
90 | 90 | //call parent: |
91 | 91 | this.parent_getSearchResults(); |
92 | | - |
| 92 | + //set local ref: |
93 | 93 | var _this = this; |
94 | | - this.loading = true; |
| 94 | + |
95 | 95 | js_log('f:getSearchResults for:' + $j('#rsd_q').val() ); |
96 | 96 | //do two queries against the Image / File / MVD namespace: |
97 | 97 | |
— | — | @@ -207,7 +207,7 @@ |
208 | 208 | } |
209 | 209 | } |
210 | 210 | } |
211 | | - |
| 211 | + |
212 | 212 | //likely a audio clip if no poster and type application/ogg |
213 | 213 | //@@todo we should return audio/ogg for the mime type or some other way to specify its "audio" |
214 | 214 | if( ! rObj.poster && rObj.mime == 'application/ogg' ){ |
— | — | @@ -307,36 +307,20 @@ |
308 | 308 | if(!cEdit) |
309 | 309 | var cEdit = _this.cEdit; |
310 | 310 | }, |
311 | | - getEmbedHTML: function( rObj , options) { |
| 311 | + getEmbedHTML: function( rObj , options) { |
312 | 312 | if(!options) |
313 | | - options = {}; |
314 | | - //set up the output var with the default values: |
315 | | - var outOpt = { 'width': rObj.width, 'height': rObj.height}; |
316 | | - if( options['max_height'] ){ |
317 | | - outOpt.height = (options.max_height > rObj.height) ? rObj.height : options.max_height; |
318 | | - outOpt.width = (rObj.width / rObj.height) *outOpt.height; |
319 | | - } |
320 | | - var style_attr = 'style="width:' + outOpt.width + 'px;height:' + outOpt.height +'px"'; |
321 | | - var id_attr = (options['id'])?' id = "' + options['id'] +'" ': ''; |
322 | | - var cat = rObj; |
323 | | - //return the html type: |
324 | | - if(rObj.mime.indexOf('image')!=-1){ |
325 | | - //if crop is null do base output: |
326 | | - var imgHtml = '<img ' + id_attr + ' src="' + rObj.edit_url + '"' + style_attr + ' >'; |
327 | | - if( rObj.crop == null) |
328 | | - return imgHtml |
329 | | - //else do crop output: |
330 | | - return '<div style="width:'+rObj.crop.w +'px;height: ' + rObj.crop.h +'px;overflow:hidden;position:relative">' + |
331 | | - '<div style="position:relative;top:-' + rObj.crop.y +'px;left:-' + rObj.crop.x +'px">'+ |
332 | | - imgHtml + |
333 | | - '</div>'+ |
334 | | - '</div>'; |
| 313 | + options = {}; |
| 314 | + this.parent_getEmbedHTML( rObj, options); |
| 315 | + //check for image output: |
| 316 | + if( rObj.mime.indexOf('image') != -1 ){ |
| 317 | + return this.getImageEmbedHTML( rObj, options ); |
335 | 318 | } |
| 319 | + //for video and audio output: |
336 | 320 | var ahtml=''; |
337 | | - if(rObj.mime == 'application/ogg' || rObj.mime == 'audio/ogg'){ |
338 | | - ahtml = id_attr + |
| 321 | + if( rObj.mime == 'application/ogg' || rObj.mime == 'audio/ogg' ){ |
| 322 | + ahtml = options.id_attr + |
339 | 323 | ' src="' + rObj.src + '" ' + |
340 | | - style_attr + |
| 324 | + options.style_attr + |
341 | 325 | ' poster="'+ rObj.poster + '" ' |
342 | 326 | if(rObj.mime.indexOf('application/ogg')!=-1){ |
343 | 327 | return '<video ' + ahtml + '></video>'; |
— | — | @@ -346,13 +330,17 @@ |
347 | 331 | return '<audio ' + ahtml + '></audio>'; |
348 | 332 | } |
349 | 333 | } |
350 | | - js_log('ERROR:unsupored mime type: ' + rObj.mime); |
| 334 | + js_log( 'ERROR:unsupored mime type: ' + rObj.mime ); |
351 | 335 | }, |
352 | 336 | getInlineDescWiki:function( rObj ){ |
353 | 337 | var desc = this.parent_getInlineDescWiki( rObj ); |
| 338 | + |
| 339 | + //strip categories for inline Desc: (should strip license tags too but not as easy) |
| 340 | + desc = desc.replace(/\[\[Category\:[^\]]*\]\]/, ''); |
| 341 | + |
354 | 342 | //just grab the description tag for inline desc: |
355 | 343 | var descMatch = new RegExp(/Description=(\{\{en\|)?([^|]*|)/); |
356 | | - var dparts = desc.match(descMatch); |
| 344 | + var dparts = desc.match(descMatch); |
357 | 345 | |
358 | 346 | if( dparts && dparts.length > 1){ |
359 | 347 | desc = (dparts.length == 2) ? dparts[1] : dparts[2].replace('}}',''); |
— | — | @@ -363,9 +351,6 @@ |
364 | 352 | js_log('Error: No Description Tag, Using::' + desc ); |
365 | 353 | return desc; |
366 | 354 | }, |
367 | | - parseWikiTemplate: function( text ){ |
368 | | - //@@todo parse wiki Template return object with properties and values |
369 | | - }, |
370 | 355 | //returns the inline wikitext for insertion (template based crops for now) |
371 | 356 | getEmbedWikiCode: function( rObj ){ |
372 | 357 | //set default layout to right justified |
Index: trunk/phase3/js2/mwEmbed/libAddMedia/remoteSearchDriver.js |
— | — | @@ -35,8 +35,8 @@ |
36 | 36 | "mwe-results_from" : "Results from <a href=\"$1\" target=\"_new\" >$2<\/a>", |
37 | 37 | "mwe-missing_desc_see_source" : "This asset is missing a description. Please see the [$1 orginal source] and help describe it.", |
38 | 38 | "rsd_config_error" : "Add media wizard configuration error: $1", |
39 | | - "mwe-your_recent_uploads" : "Your recent uploads", |
40 | | - "mwe-upload_a_file" : "Upload a new file", |
| 39 | + "mwe-your_recent_uploads" : "Your recent uploads to $1", |
| 40 | + "mwe-upload_a_file" : "Upload a new file to $1", |
41 | 41 | "mwe-resource_page_desc" : "Resource page description:", |
42 | 42 | "mwe-edit_resource_desc" : "Edit wiki text resource description:", |
43 | 43 | "mwe-local_resource_title" : "Local resource title:", |
— | — | @@ -47,7 +47,7 @@ |
48 | 48 | "mwe-importing_asset" : "Importing asset", |
49 | 49 | "mwe-preview_insert_resource" : "Preview insert of resource: $1", |
50 | 50 | "mwe-checking-resource": "Checking for resource", |
51 | | - "mwe-resource-needs-import": "Resource $1 needs to be imported", |
| 51 | + "mwe-resource-needs-import": "Resource $1 needs to be imported to $2", |
52 | 52 | "mwe-ftype-svg" : "SVG vector file", |
53 | 53 | "mwe-ftype-jpg" : "JPEG image file", |
54 | 54 | "mwe-ftype-png" : "PNG image file", |
— | — | @@ -81,7 +81,9 @@ |
82 | 82 | 'cFileNS':'File', //What is the canonical namespace prefix for images |
83 | 83 | //@@todo (should get that from the api or in-page vars) |
84 | 84 | |
85 | | - 'upload_api_target': 'http://localhost/wiki_trunk/api.php', // can be local or the url of the upload api. |
| 85 | + 'upload_api_target': 'local', // can be local or the url or remote |
| 86 | + 'upload_api_name' : null, |
| 87 | + 'upload_api_proxy_frame': null, //a page that will request mw.proxy.server |
86 | 88 | |
87 | 89 | 'enabled_cps':'all', //can be keyword 'all' or an array of enabled content provider keys |
88 | 90 | |
— | — | @@ -173,9 +175,6 @@ |
174 | 176 | 'local_domains': ['wikimedia','wikipedia','wikibooks'], |
175 | 177 | //specific to wiki commons config: |
176 | 178 | 'search_title':false, //disable title search |
177 | | - //set up default range limit |
178 | | - 'offset' : 0, |
179 | | - 'limit' : 30, |
180 | 179 | 'tab_img':true |
181 | 180 | }, |
182 | 181 | 'archive_org':{ |
— | — | @@ -191,11 +190,24 @@ |
192 | 191 | 'resource_prefix': 'AO_', |
193 | 192 | 'tab_img':true |
194 | 193 | }, |
195 | | - 'metavid':{ |
| 194 | + 'flickr':{ |
196 | 195 | 'enabled':1, |
197 | 196 | 'checked':1, |
198 | | - 'title' :'Metavid.org', |
199 | | - 'homepage':'http://metavid.org', |
| 197 | + 'title' : 'flickr.com', |
| 198 | + 'desc' : 'flickr.com, a online photo sharing site', |
| 199 | + 'homepage':'http://www.flickr.com/about/', |
| 200 | + |
| 201 | + 'api_url':'http://www.flickr.com/services/rest/', |
| 202 | + 'lib' : 'flickr', |
| 203 | + 'local' : false, |
| 204 | + 'resource_prefix': '', |
| 205 | + 'tab_img':true |
| 206 | + }, |
| 207 | + 'metavid':{ |
| 208 | + 'enabled' : 1, |
| 209 | + 'checked' : 1, |
| 210 | + 'title' : 'Metavid.org', |
| 211 | + 'homepage':'http://metavid.org/wiki/Metavid_Overview', |
200 | 212 | 'desc' : 'Metavid hosts thousands of hours of US house and senate floor proceedings', |
201 | 213 | 'api_url':'http://metavid.org/w/index.php?title=Special:MvExportSearch', |
202 | 214 | 'lib' : 'metavid', |
— | — | @@ -216,7 +228,7 @@ |
217 | 229 | 'upload':{ |
218 | 230 | 'enabled':1, |
219 | 231 | 'checked':1, |
220 | | - 'title' :'Upload' |
| 232 | + 'title' :'Upload', |
221 | 233 | } |
222 | 234 | }, |
223 | 235 | //define the licenses |
— | — | @@ -309,6 +321,10 @@ |
310 | 322 | * @param licence_url the url of the license |
311 | 323 | */ |
312 | 324 | getLicenceFromUrl: function( license_url ){ |
| 325 | + //check for some pre-defined url types: |
| 326 | + if( license_url == 'http://www.usa.gov/copyright.shtml') |
| 327 | + return this.getLicenceFromKey('pd' , license_url); |
| 328 | + |
313 | 329 | //js_log("getLicenceFromUrl::" + license_url); |
314 | 330 | //first do a direct lookup check: |
315 | 331 | for(var j =0; j < this.licenses.cc.licenses.length; j++){ |
— | — | @@ -370,6 +386,7 @@ |
371 | 387 | |
372 | 388 | cUpLoader : null, |
373 | 389 | cEdit : null, |
| 390 | + proxySetupDone : null, |
374 | 391 | dmodalCss : {}, |
375 | 392 | |
376 | 393 | init: function( options ){ |
— | — | @@ -394,7 +411,11 @@ |
395 | 412 | } |
396 | 413 | } |
397 | 414 | } |
398 | | - |
| 415 | + //set the upload target name if unset |
| 416 | + if( _this.upload_api_target == 'local' && ! _this.upload_api_name && wgSiteName) |
| 417 | + _this.upload_api_name = wgSiteName; |
| 418 | + |
| 419 | + |
399 | 420 | //set up the target invocation: |
400 | 421 | if( $j( this.target_invocation ).length==0 ){ |
401 | 422 | js_log("RemoteSearchDriver:: no target invocation provided (will have to run your own doInitDisplay() )"); |
— | — | @@ -478,14 +499,13 @@ |
479 | 500 | init_modal:function(){ |
480 | 501 | js_log("init_modal"); |
481 | 502 | var _this = this; |
| 503 | + _this.target_container = '#rsd_modal_target'; |
482 | 504 | //add the parent target_container if not provided or missing |
483 | 505 | if(!_this.target_container || $j(_this.target_container).length==0){ |
484 | | - $j('body').append('<div id="rsd_modal_target" style="position:absolute;top:3em;left:0px;bottom:3em;right:0px;" title="' + gM('mwe-add_media_wizard') + '" ></div>'); |
485 | | - _this.target_container = '#rsd_modal_target'; |
| 506 | + $j('body').append('<div id="rsd_modal_target" style="position:absolute;top:3em;left:0px;bottom:3em;right:0px;" title="' + gM('mwe-add_media_wizard') + '" ></div>'); |
486 | 507 | //js_log('appended: #rsd_modal_target' + $j(_this.target_container).attr('id')); |
487 | 508 | //js_log('added target id:' + $j(_this.target_container).attr('id')); |
488 | 509 | //get layout |
489 | | - //layout = _this.getMaxModalLayout(); |
490 | 510 | js_log( 'width: ' + $j(window).width() + ' height: ' + $j(window).height()); |
491 | 511 | var cConf = {}; |
492 | 512 | cConf['cancel'] = function(){ |
— | — | @@ -508,9 +528,8 @@ |
509 | 529 | close: function() { |
510 | 530 | //if we are 'editing' a item close that |
511 | 531 | //@@todo maybe prompt the user? |
512 | | - _this.cancelClipEditCB(); |
513 | | - //$j(this).dialog('close'); |
514 | | - $j(this).parents('.ui-dialog').fadeOut('slow'); |
| 532 | + _this.cancelClipEditCB(); |
| 533 | + $j(this).parents('.ui-dialog').fadeOut('slow'); |
515 | 534 | } |
516 | 535 | }); |
517 | 536 | doResize(); |
— | — | @@ -528,27 +547,9 @@ |
529 | 548 | 'left':'0px', |
530 | 549 | 'right':'0px', |
531 | 550 | 'bottom':'0px' |
532 | | - }); |
533 | | - /* |
534 | | - |
535 | | - |
536 | | - js_log('done setup of target_container: ' + |
537 | | - $j(_this.target_container +'~ .ui-dialog-buttonpane').length); |
538 | | - */ |
539 | | - |
| 551 | + }); |
540 | 552 | } |
541 | 553 | }, |
542 | | - getMaxModalLayout:function(border){ |
543 | | - if(!border) |
544 | | - border = 50; |
545 | | - //js_log('setting h:' + (parseInt( $j(document).height() ) - parseInt(border*2)) + ' from:' + $j(document).height() ); |
546 | | - return { |
547 | | - 'h': parseInt( $j(document).height() ) - parseInt(border*4), |
548 | | - 'w': parseInt( $j(document).width() ) - parseInt(border*2), |
549 | | - 'r': border, |
550 | | - 't': border |
551 | | - } |
552 | | - }, |
553 | 554 | //sets up the initial html interface |
554 | 555 | init_interface_html:function(){ |
555 | 556 | js_log('init_interface_html'); |
— | — | @@ -623,82 +624,85 @@ |
624 | 625 | _this.upload_api_target = _this.local_wiki_api_url; |
625 | 626 | } |
626 | 627 | } |
| 628 | + |
627 | 629 | //make sure we have a url for the upload target: |
628 | 630 | if( parseUri( _this.upload_api_target ).host == _this.upload_api_target ){ |
629 | 631 | $j('#tab-upload').html( gM('rsd_config_error', 'bad_api_url') ); |
630 | 632 | return false; |
631 | 633 | } |
632 | | - //output the form |
633 | | - //set the form action based on domain: |
634 | | - if( parseUri( document.URL ).host == parseUri( _this.upload_api_target ).host ){ |
635 | | - mvJsLoader.doLoad(['$j.fn.simpleUploadForm'],function(){ |
636 | | - |
637 | | - //get extends info about the file |
638 | | - var cp = _this.content_providers['this_wiki']; |
639 | | - //check for "this_wiki" enabled |
640 | | - /*if(!cp.enabled){ |
641 | | - $j('#tab-upload').html('error this_wiki not enabled (can\'t get uploaded file info)'); |
642 | | - return false; |
643 | | - }*/ |
644 | | - |
645 | | - //load this_wiki search system to grab the rObj |
646 | | - _this.loadSearchLib(cp, function(){ |
647 | | - //do basic layout form on left upload "bin" on right |
648 | | - $j('#tab-upload').html('<table>' + |
649 | | - '<tr>' + |
650 | | - '<td valign="top" style="width:350px; padding-right: 12px;">' + |
651 | | - '<h4>' + gM('mwe-upload_a_file') + '</h4>' + |
652 | | - '<div id="upload_form">' + |
653 | | - mv_get_loading_img() + |
654 | | - '</div>' + |
655 | | - '</td>' + |
656 | | - '<td valign="top" id="upload_bin_cnt">' + |
657 | | - '<h4>' + gM('mwe-your_recent_uploads') + '</h4>' + |
658 | | - '<div id="upload_bin">' + |
659 | | - mv_get_loading_img() + |
660 | | - '</div>'+ |
661 | | - '</td>' + |
662 | | - '</tr>' + |
663 | | - '</table>'); |
664 | | - |
665 | | - |
666 | | - //fill in the user page: |
667 | | - if(typeof wgUserName != 'undefined' && wgUserName){ |
668 | | - //load the upload bin with anything the current user has uploaded |
669 | | - cp.sObj.getUserRecentUploads( wgUserName, function(){ |
670 | | - _this.drawOutputResults(); |
671 | | - }); |
672 | | - }else{ |
673 | | - $j('#upload_bin_cnt').empty(); |
674 | | - } |
675 | | - |
676 | | - //deal with the api form upload form directly: |
677 | | - $j('#upload_form').simpleUploadForm({ |
678 | | - "api_target" : _this.upload_api_target, |
679 | | - "ondone_cb" : function( resultData ){ |
680 | | - var wTitle = resultData['filename']; |
681 | | - //add a loading div |
682 | | - _this.addResourceEditLoader(); |
683 | | - //@@note: we have most of what we need in resultData imageinfo |
684 | | - cp.sObj.addByTitle( wTitle, function( rObj ){ |
685 | | - //redraw (with added result if new) |
686 | | - _this.drawOutputResults(); |
687 | | - //pull up resource editor: |
688 | | - _this.resourceEdit( rObj, $j('#res_upload__' + rObj.id).get(0) ); |
689 | | - }); |
690 | | - //return false to close progress window: |
691 | | - return false; |
692 | | - } |
693 | | - }) |
694 | | - }); |
695 | | - }); |
696 | | - }else{ |
697 | | - //setup the proxy |
698 | | - js_log('do proxy:: ' + parseUri( _this.upload_api_target ).host); |
699 | | - $j('#tab-upload').html('proxy upload not yet ready'); |
700 | | - } |
| 634 | + //check if we need to setup the proxy:: |
| 635 | + if( parseUri( document.URL ).host != parseUri( _this.upload_api_target ).host ){ |
| 636 | + //setup proxy |
| 637 | + $j('#tab-upload').html( 'do proxy setup'); |
| 638 | + }else{ |
| 639 | + _this.getUploadForm(); |
| 640 | + } |
701 | 641 | },1); |
702 | 642 | }, |
| 643 | + getUploadForm:function(){ |
| 644 | + var _this = this; |
| 645 | + mvJsLoader.doLoad(['$j.fn.simpleUploadForm'],function(){ |
| 646 | + //get extends info about the file |
| 647 | + var cp = _this.content_providers['this_wiki']; |
| 648 | + |
| 649 | + //check for "this_wiki" enabled |
| 650 | + /*if(!cp.enabled){ |
| 651 | + $j('#tab-upload').html('error this_wiki not enabled (can\'t get uploaded file info)'); |
| 652 | + return false; |
| 653 | + }*/ |
| 654 | + |
| 655 | + //load this_wiki search system to grab the rObj |
| 656 | + _this.loadSearchLib(cp, function(){ |
| 657 | + //do basic layout form on left upload "bin" on right |
| 658 | + $j('#tab-upload').html('<table>' + |
| 659 | + '<tr>' + |
| 660 | + '<td valign="top" style="width:350px; padding-right: 12px;">' + |
| 661 | + '<h4>' + gM('mwe-upload_a_file', _this.upload_api_name ) + '</h4>' + |
| 662 | + '<div id="upload_form">' + |
| 663 | + mv_get_loading_img() + |
| 664 | + '</div>' + |
| 665 | + '</td>' + |
| 666 | + '<td valign="top" id="upload_bin_cnt">' + |
| 667 | + '<h4>' + gM('mwe-your_recent_uploads', _this.upload_api_name) + '</h4>' + |
| 668 | + '<div id="upload_bin">' + |
| 669 | + mv_get_loading_img() + |
| 670 | + '</div>'+ |
| 671 | + '</td>' + |
| 672 | + '</tr>' + |
| 673 | + '</table>'); |
| 674 | + |
| 675 | + |
| 676 | + //fill in the user page: |
| 677 | + if(typeof wgUserName != 'undefined' && wgUserName){ |
| 678 | + //load the upload bin with anything the current user has uploaded |
| 679 | + cp.sObj.getUserRecentUploads( wgUserName, function(){ |
| 680 | + _this.drawOutputResults(); |
| 681 | + }); |
| 682 | + }else{ |
| 683 | + $j('#upload_bin_cnt').empty(); |
| 684 | + } |
| 685 | + |
| 686 | + //deal with the api form upload form directly: |
| 687 | + $j('#upload_form').simpleUploadForm({ |
| 688 | + "api_target" : _this.upload_api_target, |
| 689 | + "ondone_cb" : function( resultData ){ |
| 690 | + var wTitle = resultData['filename']; |
| 691 | + //add a loading div |
| 692 | + _this.addResourceEditLoader(); |
| 693 | + //@@note: we have most of what we need in resultData imageinfo |
| 694 | + cp.sObj.addByTitle( wTitle, function( rObj ){ |
| 695 | + //redraw (with added result if new) |
| 696 | + _this.drawOutputResults(); |
| 697 | + //pull up resource editor: |
| 698 | + _this.resourceEdit( rObj, $j('#res_upload__' + rObj.id).get(0) ); |
| 699 | + }); |
| 700 | + //return false to close progress window: |
| 701 | + return false; |
| 702 | + } |
| 703 | + }); |
| 704 | + }); //load searchLibs |
| 705 | + }); //load simpleUploadForm |
| 706 | + }, |
703 | 707 | runSearch: function(){ |
704 | 708 | js_log("f:runSearch::" + this.disp_item); |
705 | 709 | //draw_direct_flag |
— | — | @@ -709,9 +713,9 @@ |
710 | 714 | this.doUploadInteface(); |
711 | 715 | return true; |
712 | 716 | } |
713 | | - //else do runSearch |
714 | 717 | |
715 | | - cp = this.content_providers[this.disp_item]; |
| 718 | + //else do runSearch |
| 719 | + var cp = this.content_providers[this.disp_item]; |
716 | 720 | |
717 | 721 | //check if we need to update: |
718 | 722 | if( typeof cp.sObj != 'undefined' ){ |
— | — | @@ -737,6 +741,15 @@ |
738 | 742 | checkForCopyURLSupport:function ( callback ){ |
739 | 743 | var _this = this; |
740 | 744 | js_log('checkForCopyURLSupport:: '); |
| 745 | + //check if the import url is diffrent from |
| 746 | + //check if we need to setup the proxy:: |
| 747 | + /*if( parseUri( document.URL ).host != parseUri( _this.upload_api_target ).host ){ |
| 748 | + //setup proxy |
| 749 | + js_log(" doc.url:" + parseUri( document.URL ).host + ' != ' +parseUri( _this.upload_api_target ).host); |
| 750 | + $j('#tab-' + this.disp_item ).html( 'do proxy setup'); |
| 751 | + return false; |
| 752 | + }*/ |
| 753 | + |
741 | 754 | //see if we already have the import mode: |
742 | 755 | if( this.import_url_mode != 'autodetect'){ |
743 | 756 | js_log('import mode: ' + _this.import_url_mode); |
— | — | @@ -860,7 +873,7 @@ |
861 | 874 | var cp = this.content_providers[ cp_id ]; |
862 | 875 | if(typeof cp['sObj'] != 'undefined'){ |
863 | 876 | if( cp.sObj.loading ) |
864 | | - loading_done=false; |
| 877 | + loading_done = false; |
865 | 878 | } |
866 | 879 | } |
867 | 880 | if( loading_done ){ |
— | — | @@ -996,10 +1009,10 @@ |
997 | 1010 | _this.setResultBarControl(); |
998 | 1011 | } |
999 | 1012 | |
1000 | | - var drawResultCount =0; |
| 1013 | + var drawResultCount = 0; |
1001 | 1014 | |
1002 | 1015 | //output all the results for the current disp_item |
1003 | | - if( typeof cp['sObj'] != 'undefined' ){ |
| 1016 | + if( typeof cp['sObj'] != 'undefined' ){ |
1004 | 1017 | $j.each(cp.sObj.resultsObj, function(rInx, rItem){ |
1005 | 1018 | if( _this.result_display_mode == 'box' ){ |
1006 | 1019 | o+='<div id="mv_result_' + rInx + '" class="mv_clip_box_result" style="width:' + |
— | — | @@ -1051,7 +1064,7 @@ |
1052 | 1065 | $j(tab_target).append( o + '<div style="clear:both"/>'); |
1053 | 1066 | } |
1054 | 1067 | |
1055 | | - js_log( ' drawResultCount :: ' + drawResultCount + ' append: ' + $j('#rsd_q').val() ); |
| 1068 | + js_log( 'did drawResultCount :: ' + drawResultCount + ' append: ' + $j('#rsd_q').val() ); |
1056 | 1069 | |
1057 | 1070 | //remove any old search res |
1058 | 1071 | $j('#rsd_no_search_res').remove(); |
— | — | @@ -1206,7 +1219,7 @@ |
1207 | 1220 | }); |
1208 | 1221 | }, |
1209 | 1222 | cancelClipEditCB:function(){ |
1210 | | - var _this = this; |
| 1223 | + var _this = this; |
1211 | 1224 | js_log('cancelClipEditCB'); |
1212 | 1225 | var b_target = _this.target_container + '~ .ui-dialog-buttonpane'; |
1213 | 1226 | $j('#rsd_resource_edit').remove(); |
— | — | @@ -1218,12 +1231,12 @@ |
1219 | 1232 | //restore the title: |
1220 | 1233 | $j( _this.target_container ).dialog( 'option', 'title', gM('mwe-add_media_wizard')); |
1221 | 1234 | js_log("should update: " + b_target + ' with: cancel'); |
1222 | | - //restore the buttons: |
| 1235 | + //restore the buttons: |
1223 | 1236 | $j(b_target).html( $j.btnHtml( 'Cancel' , 'mv_cancel_rsd', 'close')) |
1224 | 1237 | .children('.mv_cancel_rsd') |
1225 | 1238 | .btnBind() |
1226 | 1239 | .click(function(){ |
1227 | | - $j( _this.target_container).dialog('close'); |
| 1240 | + $j( _this.target_container).dialog('close'); |
1228 | 1241 | }) |
1229 | 1242 | |
1230 | 1243 | }, |
— | — | @@ -1253,16 +1266,17 @@ |
1254 | 1267 | js_log('remoteSearchDriver::doMediaEdit: ' + mediaType); |
1255 | 1268 | |
1256 | 1269 | var mvClipInit = { |
1257 | | - 'rObj':rObj, //the resource object |
1258 | | - 'parent_ct' : 'rsd_modal_target', |
1259 | | - 'clip_disp_ct' : 'clip_edit_disp', |
1260 | | - 'control_ct' : 'clip_edit_ctrl', |
1261 | | - 'media_type' : mediaType, |
1262 | | - 'p_rsdObj' : _this, |
1263 | | - 'controlActionsCb' : _this.getClipEditControlActions( cp ) |
| 1270 | + 'rObj' : rObj, //the resource object |
| 1271 | + 'parent_ct' : 'rsd_modal_target', |
| 1272 | + 'clip_disp_ct' : 'clip_edit_disp', |
| 1273 | + 'control_ct' : 'clip_edit_ctrl', |
| 1274 | + 'media_type' : mediaType, |
| 1275 | + 'p_rsdObj' : _this, |
| 1276 | + 'controlActionsCb' : _this.getClipEditControlActions( cp ) |
1264 | 1277 | }; |
1265 | | - |
| 1278 | + //set the base clip edit lib class req set: |
1266 | 1279 | var clibs = ['mvClipEdit']; |
| 1280 | + |
1267 | 1281 | if( mediaType == 'image'){ |
1268 | 1282 | //display the mvClipEdit obj once we are done loading: |
1269 | 1283 | mvJsLoader.doLoad( clibs, function(){ |
— | — | @@ -1432,7 +1446,7 @@ |
1433 | 1447 | $j( _this.target_container ).append('<div id="rsd_resource_import" '+ |
1434 | 1448 | 'class="ui-state-highlight ui-widget-content ui-state-error" ' + |
1435 | 1449 | 'style="position:absolute;top:50px;left:50px;right:50px;bottom:50px;z-index:5">' + |
1436 | | - '<h3 style="color:red">' + gM('mwe-resource-needs-import', rObj.title) + '</h3>' + |
| 1450 | + '<h3 style="color:red">' + gM('mwe-resource-needs-import', [rObj.title, _this.upload_api_name] ) + '</h3>' + |
1437 | 1451 | '<div id="rsd_preview_import_container" style="position:absolute;width:50%;bottom:0px;left:0px;overflow:auto;top:30px;">' + |
1438 | 1452 | rObj.pSobj.getEmbedHTML( rObj, { |
1439 | 1453 | 'id': _this.target_container + '_rsd_pv_vid', |
— | — | @@ -1468,7 +1482,8 @@ |
1469 | 1483 | //add hover: |
1470 | 1484 | |
1471 | 1485 | //update video tag (if a video) |
1472 | | - rewrite_by_id( _this.target_container + '_rsd_pv_vid'); |
| 1486 | + if( rObj.mime.indexOf('video/') !== -1 ) |
| 1487 | + rewrite_by_id( $j(_this.target_container).attr('id') + '_rsd_pv_vid'); |
1473 | 1488 | |
1474 | 1489 | //load the preview text: |
1475 | 1490 | _this.getParsedWikiText( wt, _this.cFileNS +':'+ rObj.target_resource_title, function( o ){ |
— | — | @@ -1487,7 +1502,14 @@ |
1488 | 1503 | js_log("do import asset:" + _this.import_url_mode); |
1489 | 1504 | //check import mode: |
1490 | 1505 | if( _this.import_url_mode == 'api' ){ |
1491 | | - _this.doImportAPI( rObj , callback); |
| 1506 | + if( parseUri( document.URL ).host != parseUri( _this.upload_api_target ).host ){ |
| 1507 | + _this.setupProxy( function(){ |
| 1508 | + debugger; |
| 1509 | + //_this.doImportAPI( rObj , callback); |
| 1510 | + }); |
| 1511 | + }else{ |
| 1512 | + _this.doImportAPI( rObj , callback); |
| 1513 | + } |
1492 | 1514 | }else{ |
1493 | 1515 | js_log("Error: import mode is not form or API (can not copy asset)"); |
1494 | 1516 | } |
— | — | @@ -1497,7 +1519,33 @@ |
1498 | 1520 | $j(this).remove(); |
1499 | 1521 | }); |
1500 | 1522 | }); |
1501 | | - }, |
| 1523 | + }, |
| 1524 | + /** |
| 1525 | + * sets up the proxy for the remote inserts |
| 1526 | + */ |
| 1527 | + setupProxy:function(callback){ |
| 1528 | + var _this = this; |
| 1529 | + |
| 1530 | + if( _this.proxySetupDone ){ |
| 1531 | + if(callback) callback(); |
| 1532 | + return ; |
| 1533 | + } |
| 1534 | + //setup the the proxy via mv_embed $j.apiProxy loader: |
| 1535 | + if( ! _this.upload_api_proxy_frame ){ |
| 1536 | + js_log("Error:: remote api but no proxy frame target"); |
| 1537 | + return false; |
| 1538 | + }else{ |
| 1539 | + $j.apiProxy( |
| 1540 | + 'client', |
| 1541 | + { |
| 1542 | + 'server_frame' : _this.upload_api_proxy_frame, |
| 1543 | + },function(){ |
| 1544 | + //now that the api is setup call actual import |
| 1545 | + debugger; |
| 1546 | + } |
| 1547 | + ); |
| 1548 | + } |
| 1549 | + }, |
1502 | 1550 | checkForFile:function( fName, callback){ |
1503 | 1551 | js_log("checkForFile::"); |
1504 | 1552 | var _this = this; |
— | — | @@ -1559,7 +1607,7 @@ |
1560 | 1608 | |
1561 | 1609 | //close the loader now that we are ready to present the progress dialog:: |
1562 | 1610 | $j.closeLoaderDialog(); |
1563 | | - |
| 1611 | + |
1564 | 1612 | myUp.doHttpUpload({ |
1565 | 1613 | 'url' : rObj.src, |
1566 | 1614 | 'filename' : rObj.target_resource_title, |
— | — | @@ -1755,7 +1803,7 @@ |
1756 | 1804 | var cp = _this.content_providers['this_wiki']; |
1757 | 1805 | }else{ |
1758 | 1806 | var cp = this.content_providers[ this.disp_item ]; |
1759 | | - } |
| 1807 | + } |
1760 | 1808 | //js_log('getPaging:'+ cp_id + ' len: ' + cp.sObj.num_results); |
1761 | 1809 | var to_num = ( cp.limit > cp.sObj.num_results )? |
1762 | 1810 | (cp.offset + cp.sObj.num_results): |
Index: trunk/phase3/js2/mwEmbed/tests/testApiProxy.html |
— | — | @@ -0,0 +1,76 @@ |
| 2 | +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> |
| 3 | +<html> |
| 4 | +<head> |
| 5 | +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> |
| 6 | +<title>Api Proxy Test</title> |
| 7 | +<script type="text/javascript" src="../mv_embed.js"></script> |
| 8 | + |
| 9 | +<script type="text/javascript" > |
| 10 | +//HARD coded local test: |
| 11 | +var remote_wiki_host = 'http://127.1.1.100'; |
| 12 | +var remote_script_path = '/wiki_trunk'; |
| 13 | + |
| 14 | +js2AddOnloadHook( function(){ |
| 15 | + $j('#hostName').text( remote_wiki_host ); |
| 16 | + //run the api-proxy setup: |
| 17 | + $j.apiProxy( |
| 18 | + 'client', |
| 19 | + { |
| 20 | + 'server_frame': remote_wiki_host + remote_script_path + '/index.php/MediaWiki:ApiProxy', |
| 21 | + 'client_frame_path' : '/wiki_trunk/js2/mwEmbed/libMwApi/NestedCallbackIframe.html', |
| 22 | + }, |
| 23 | + function(){ |
| 24 | + //callback function here: |
| 25 | + $j('#setupDone').show('slow'); |
| 26 | + $j('#doAppendCat').click( doCatAppend ); |
| 27 | + } |
| 28 | + ); |
| 29 | +}); |
| 30 | +function doCatAppend(){ |
| 31 | + js_log('append cat to User page'); |
| 32 | + //first get our user name: |
| 33 | + var rObj = { |
| 34 | + 'action':'query', |
| 35 | + 'meta':'userinfo' |
| 36 | + } |
| 37 | + //we use normal do_api_req with keywork 'proxy' for the url |
| 38 | + $mw.proxy.doRequest( rObj, |
| 39 | + function(data){ |
| 40 | + //now we get the data back for that domain |
| 41 | + if( !data.query || !data.query.userinfo ){ |
| 42 | + js_log("Error no query.userinfo "); |
| 43 | + return false; |
| 44 | + } |
| 45 | + if( data.query.userinfo.id == 0 ){ |
| 46 | + var btn = {}; |
| 47 | + btn['try again'] = function(){ |
| 48 | + doCatAppend(); |
| 49 | + } |
| 50 | + btn['cancel'] = function(){ |
| 51 | + $j(this).close(); |
| 52 | + } |
| 53 | + $j.addDialog("Not logged in", |
| 54 | + "Are you logged in on" + remote_wiki_host + " ? Please loggin", |
| 55 | + btn |
| 56 | + ) |
| 57 | + }else{ |
| 58 | + $j('#helloTarget').hide().text( data.query.userinfo.name ).fadeIn('slow'); |
| 59 | + } |
| 60 | + } |
| 61 | + ); |
| 62 | + return false; |
| 63 | +} |
| 64 | +</script> |
| 65 | + |
| 66 | +</head> |
| 67 | +<body> |
| 68 | +<h3> Simple API proxy testing system </h3> |
| 69 | + |
| 70 | +<div id="setupProxy">Setting up Proxy ... ( <span id="hostName"></span> )</div> |
| 71 | +<div id="setupDone" style="display:none;"> |
| 72 | +<br> <a href="#" id="doAppendCat" >Hello User</a> <span id="helloTarget"><span> |
| 73 | +<br> Some other fun api stuff here... |
| 74 | +</div> |
| 75 | + |
| 76 | +</body> |
| 77 | +</html> |
\ No newline at end of file |
Index: trunk/phase3/js2/apiProxyPage.js |
— | — | @@ -0,0 +1,27 @@ |
| 2 | +/* |
| 3 | +* mwProxy js2 page system. |
| 4 | +* |
| 5 | +* invokes the apiProxy system |
| 6 | +*/ |
| 7 | + |
| 8 | +/* |
| 9 | + * since this is proxy server set a pre-append debug flag to know which debug msgs are coming from where |
| 10 | + */ |
| 11 | + |
| 12 | +if( !mwApiProxyConfig ) |
| 13 | + var mwApiProxyConfig = {}; |
| 14 | + |
| 15 | +//The default mwApiProxyConfig config |
| 16 | +//(presently hard coded but should read from user and site config) |
| 17 | +var mwApiProxyDefaultConfig = { |
| 18 | + 'master_whitelist' : [ 'en.wikipedia.org', 'localhost', '127.1.1.100' ], |
| 19 | + 'master_blacklist' : [] |
| 20 | +}; |
| 21 | +//user_white_list should also be checked and configured at runtime. |
| 22 | + |
| 23 | +js2AddOnloadHook( function() { |
| 24 | + //build our configuration from the default and mwApiProxyConfig vars |
| 25 | + mwApiProxyConfig = $j.extend(true, mwApiProxyDefaultConfig, mwApiProxyConfig); |
| 26 | + |
| 27 | + $j.apiProxy( 'server', mwApiProxyConfig ); |
| 28 | +}); |
Index: trunk/phase3/js2/remoteMwEmbed.js |
— | — | @@ -28,6 +28,15 @@ |
29 | 29 | importScriptURI( mwEmbedHostPath + '/uploadPage.js' + reqAguments ); |
30 | 30 | } ); |
31 | 31 | } |
| 32 | + |
| 33 | + // Special api proxy page |
| 34 | + if( wgPageName == 'MediaWiki:ApiProxy' ){ |
| 35 | + var wgEnableIframeApiProxy = true; |
| 36 | + load_mv_embed( function() { |
| 37 | + importScriptURI( mwEmbedHostPath + '/ApiProxyPage.js' + reqAguments ); |
| 38 | + }); |
| 39 | + } |
| 40 | + |
32 | 41 | |
33 | 42 | // OggHandler rewrite for view pages: |
34 | 43 | var vidIdList = []; |
Index: trunk/phase3/js2/editPage.js |
— | — | @@ -24,7 +24,7 @@ |
25 | 25 | js2AddOnloadHook( function() { |
26 | 26 | var amwConf = $j.extend( true, defaultAddMediaConfig, mwAddMediaConfig ); |
27 | 27 | // kind of tricky, it would be nice to use run on ready "loader" call here |
28 | | - if( typeof $j.wikiEditor != 'undefined' ) { |
| 28 | + if( typeof $j.wikiEditor != 'undefined' ) { |
29 | 29 | $j( 'textarea#wpTextbox1' ).bind( 'wikiEditor-toolbar-buildSection-main', |
30 | 30 | function( e, section ) { |
31 | 31 | if ( typeof section.groups.insert.tools.file !== 'undefined' ) { |
Index: trunk/phase3/includes/AutoLoader.php |
— | — | @@ -619,6 +619,7 @@ |
620 | 620 | 'uploadPage' => 'js2/uploadPage.js', |
621 | 621 | 'editPage' => 'js2/editPage.js', |
622 | 622 | 'ajaxCategories' => 'js2/ajaxcategories.js', |
| 623 | + 'apiProxyPage' => 'js2/apiProxyPage.js' |
623 | 624 | ); |
624 | 625 | |
625 | 626 | class AutoLoader { |
Index: trunk/phase3/includes/Skin.php |
— | — | @@ -363,6 +363,7 @@ |
364 | 364 | global $wgVersion, $wgEnableAPI, $wgEnableWriteAPI; |
365 | 365 | global $wgRestrictionTypes, $wgLivePreview; |
366 | 366 | global $wgMWSuggestTemplate, $wgDBname, $wgEnableMWSuggest; |
| 367 | + global $wgSitename, $wgEnableIframeApiProxy, $wgEnableJS2system; |
367 | 368 | |
368 | 369 | $ns = $wgTitle->getNamespace(); |
369 | 370 | $nsname = MWNamespace::exists( $ns ) ? MWNamespace::getCanonicalName( $ns ) : $wgTitle->getNsText(); |
— | — | @@ -413,6 +414,7 @@ |
414 | 415 | 'wgMainPageTitle' => $mainPage ? $mainPage->getPrefixedText() : null, |
415 | 416 | 'wgFormattedNamespaces' => $wgContLang->getFormattedNamespaces(), |
416 | 417 | 'wgNamespaceIds' => $wgContLang->getNamespaceIds(), |
| 418 | + 'wgSiteName' => $wgSitename, |
417 | 419 | ); |
418 | 420 | if ( $wgContLang->hasVariants() ) { |
419 | 421 | $vars['wgUserVariant'] = $wgContLang->getPreferredVariant(); |
— | — | @@ -442,6 +444,17 @@ |
443 | 445 | $vars['wgLivepreviewMessageError'] = wfMsg( 'livepreview-error' ); |
444 | 446 | } |
445 | 447 | |
| 448 | + //add api proxy var and script link if on the special proxy page: |
| 449 | + if( $wgEnableJS2system && |
| 450 | + $wgTitle->getNamespace() == NS_MEDIAWIKI && |
| 451 | + $wgTitle->getDBKey() == 'ApiProxy' ) |
| 452 | + { |
| 453 | + $vars['wgEnableIframeApiProxy'] = $wgEnableIframeApiProxy; |
| 454 | + //also add the apiProxy Page script if we are on that page |
| 455 | + if( $wgEnableIframeApiProxy ) |
| 456 | + $wgOut->addScriptClass( 'apiProxyPage' ); |
| 457 | + } |
| 458 | + |
446 | 459 | if ( $wgOut->isArticleRelated() && $wgUseAjax && $wgAjaxWatch && $wgUser->isLoggedIn() ) { |
447 | 460 | $msgs = (object)array(); |
448 | 461 | foreach ( array( 'watch', 'unwatch', 'watching', 'unwatching' ) as $msgName ) { |
— | — | @@ -864,7 +877,7 @@ |
865 | 878 | $catlinks = $this->getCategoryLinks(); |
866 | 879 | |
867 | 880 | $classes = 'catlinks'; |
868 | | - |
| 881 | + |
869 | 882 | // Check what we're showing |
870 | 883 | global $wgOut, $wgUser; |
871 | 884 | $allCats = $wgOut->getCategoryLinks(); |
— | — | @@ -960,7 +973,7 @@ |
961 | 974 | else |
962 | 975 | $ret .= str_repeat( "<ul><li>\n", $diff ); |
963 | 976 | $ret .= $display . "\n"; |
964 | | - |
| 977 | + |
965 | 978 | $curIdent = $ident; |
966 | 979 | } |
967 | 980 | $ret .= str_repeat( '</li></ul>', $curIdent ) . '</li>'; |
Index: trunk/phase3/includes/DefaultSettings.php |
— | — | @@ -213,9 +213,9 @@ |
214 | 214 | * thumbScriptUrl The URL for thumb.php (optional, not recommended) |
215 | 215 | * transformVia404 Whether to skip media file transformation on parse and rely on a 404 |
216 | 216 | * handler instead. |
217 | | - * initialCapital Equivalent to $wgCapitalLinks (or $wgCapitalLinkOverrides[NS_FILE], |
218 | | - * determines whether filenames implicitly start with a capital letter. |
219 | | - * The current implementation may give incorrect description page links |
| 217 | + * initialCapital Equivalent to $wgCapitalLinks (or $wgCapitalLinkOverrides[NS_FILE], |
| 218 | + * determines whether filenames implicitly start with a capital letter. |
| 219 | + * The current implementation may give incorrect description page links |
220 | 220 | * when the local $wgCapitalLinks and initialCapital are mismatched. |
221 | 221 | * pathDisclosureProtection |
222 | 222 | * May be 'paranoid' to remove all parameters from error messages, 'none' to |
— | — | @@ -462,7 +462,7 @@ |
463 | 463 | |
464 | 464 | |
465 | 465 | /** |
466 | | - * Enable Firefogg support. Adds support for in-browser transcoding to Ogg |
| 466 | + * Enable Firefogg support. Adds support for in-browser transcoding to Ogg |
467 | 467 | * Theora, chunked uploads for large image files and client side hash checks. |
468 | 468 | * |
469 | 469 | * Ignored unless $wgEnableJS2system is true. |
— | — | @@ -2438,11 +2438,11 @@ |
2439 | 2439 | |
2440 | 2440 | /** |
2441 | 2441 | * @since 1.16 - This can now be set per-namespace. Some special namespaces (such |
2442 | | - * as Special, see Namespace::$alwaysCapitalizedNamespaces for the full list) must be |
2443 | | - * true by default (and setting them has no effect), due to various things that |
2444 | | - * require them to be so. Also, since Talk namespaces need to directly mirror their |
2445 | | - * associated content namespaces, the values for those are ignored in favor of the |
2446 | | - * subject namespace's setting. Setting for NS_MEDIA is taken automatically from |
| 2442 | + * as Special, see Namespace::$alwaysCapitalizedNamespaces for the full list) must be |
| 2443 | + * true by default (and setting them has no effect), due to various things that |
| 2444 | + * require them to be so. Also, since Talk namespaces need to directly mirror their |
| 2445 | + * associated content namespaces, the values for those are ignored in favor of the |
| 2446 | + * subject namespace's setting. Setting for NS_MEDIA is taken automatically from |
2447 | 2447 | * NS_FILE. |
2448 | 2448 | * EX: $wgCapitalLinkOverrides[ NS_FILE ] = false; |
2449 | 2449 | */ |
— | — | @@ -2787,7 +2787,7 @@ |
2788 | 2788 | * |
2789 | 2789 | * note this will only check core scripts that are directly included on the page. |
2790 | 2790 | * (not scripts loaded after the initial page display since after initial page |
2791 | | - * display scripts inherit the unique request id) |
| 2791 | + * display scripts inherit the unique request id) |
2792 | 2792 | * |
2793 | 2793 | * and or you can update $wgStyleVersion |
2794 | 2794 | */ |
— | — | @@ -2800,13 +2800,18 @@ |
2801 | 2801 | $wgEnableJS2system = false; |
2802 | 2802 | |
2803 | 2803 | /* |
| 2804 | + * enable api iframe proxy |
| 2805 | + */ |
| 2806 | +$wgEnableIframeApiProxy = false; |
| 2807 | + |
| 2808 | +/* |
2804 | 2809 | * boolean; if we should minify the output. (note if you send ?debug=true in |
2805 | 2810 | * the page request it will automatically not group and not minify) |
2806 | 2811 | */ |
2807 | 2812 | $wgEnableScriptMinify = true; |
2808 | 2813 | |
2809 | 2814 | /* |
2810 | | - * boolean; if we should enable javascript localization (it loads loadGM json |
| 2815 | + * boolean; if we should enable javascript localization (it loads loadGM json |
2811 | 2816 | * call with mediaWiki msgs) |
2812 | 2817 | */ |
2813 | 2818 | $wgEnableScriptLocalization = true; |
— | — | @@ -2817,7 +2822,7 @@ |
2818 | 2823 | $wgMwEmbedDirectory = "js2/mwEmbed/"; |
2819 | 2824 | |
2820 | 2825 | /* |
2821 | | - * Turn on debugging for the javascript script-loader & forces fresh copies |
| 2826 | + * Turn on debugging for the javascript script-loader & forces fresh copies |
2822 | 2827 | * of javascript |
2823 | 2828 | */ |
2824 | 2829 | $wgDebugJavaScript = false; |
— | — | @@ -3729,7 +3734,7 @@ |
3730 | 3735 | $wgAjaxUploadDestCheck = true; |
3731 | 3736 | |
3732 | 3737 | /** |
3733 | | - * Enable the AJAX upload interface (needed for large http uploads & to display |
| 3738 | + * Enable the AJAX upload interface (needed for large http uploads & to display |
3734 | 3739 | * progress on uploads for browsers that support it) |
3735 | 3740 | */ |
3736 | 3741 | $wgAjaxUploadInterface = true; |
— | — | @@ -4010,7 +4015,7 @@ |
4011 | 4016 | * Page property link table invalidation lists. When a page property |
4012 | 4017 | * changes, this may require other link tables to be updated (eg |
4013 | 4018 | * adding __HIDDENCAT__ means the hiddencat tracking category will |
4014 | | - * have been added, so the categorylinks table needs to be rebuilt). |
| 4019 | + * have been added, so the categorylinks table needs to be rebuilt). |
4015 | 4020 | * This array can be added to by extensions. |
4016 | 4021 | */ |
4017 | 4022 | $wgPagePropLinkInvalidations = array( |