r57858 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r57857‎ | r57858 | r57859 >
Date:10:35, 17 October 2009
Author:dale
Status:deferred (Comments)
Tags:
Comment:
* stubs for api iFrame Proxy system. Early summary in /js2/mwEmbed/apiProxy/
** testing page for proxy setup (hard coded to localhost)
** added basic support to skin.php for enabling of apiproxy (off by default)

* added flickrSearch as another remote repository
* other refactoring, cleanup of remoteSearchDriver (add-media-wizard)

* removed query.json.1-3.js
* removed jquery.secureEvalJSON.js
* replaced with official http://www.JSON.org/json2.js script which is only included if JSON is undefined
Modified paths:
  • /trunk/phase3/includes/AutoLoader.php (modified) (history)
  • /trunk/phase3/includes/DefaultSettings.php (modified) (history)
  • /trunk/phase3/includes/Skin.php (modified) (history)
  • /trunk/phase3/js2/apiProxyPage.js (added) (history)
  • /trunk/phase3/js2/editPage.js (modified) (history)
  • /trunk/phase3/js2/mwEmbed/jquery/plugins/jquery.json-1.3.js (deleted) (history)
  • /trunk/phase3/js2/mwEmbed/jquery/plugins/jquery.secureEvalJSON.js (deleted) (history)
  • /trunk/phase3/js2/mwEmbed/libAddMedia/mvBaseUploadInterface.js (modified) (history)
  • /trunk/phase3/js2/mwEmbed/libAddMedia/remoteSearchDriver.js (modified) (history)
  • /trunk/phase3/js2/mwEmbed/libAddMedia/searchLibs/archiveOrgSearch.js (modified) (history)
  • /trunk/phase3/js2/mwEmbed/libAddMedia/searchLibs/baseRemoteSearch.js (modified) (history)
  • /trunk/phase3/js2/mwEmbed/libAddMedia/searchLibs/flickrSearch.js (modified) (history)
  • /trunk/phase3/js2/mwEmbed/libAddMedia/searchLibs/mediaWikiSearch.js (modified) (history)
  • /trunk/phase3/js2/mwEmbed/libAddMedia/searchLibs/metavidSearch.js (modified) (history)
  • /trunk/phase3/js2/mwEmbed/libAddMedia/seqRemoteSearchDriver.js (deleted) (history)
  • /trunk/phase3/js2/mwEmbed/libEmbedVideo/nativeEmbed.js (modified) (history)
  • /trunk/phase3/js2/mwEmbed/libMwApi (added) (history)
  • /trunk/phase3/js2/mwEmbed/libMwApi/NestedCallbackIframe.html (added) (history)
  • /trunk/phase3/js2/mwEmbed/libMwApi/json2.js (added) (history)
  • /trunk/phase3/js2/mwEmbed/libMwApi/mw.proxy.js (added) (history)
  • /trunk/phase3/js2/mwEmbed/libMwApi/mwProxy.js (added) (history)
  • /trunk/phase3/js2/mwEmbed/mv_embed.js (modified) (history)
  • /trunk/phase3/js2/mwEmbed/php/languages/mwEmbed.i18n.php (modified) (history)
  • /trunk/phase3/js2/mwEmbed/tests/testApiProxy.html (added) (history)
  • /trunk/phase3/js2/remoteMwEmbed.js (modified) (history)

Diff [purge]

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 '&nbsp;'),
 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 @@
105105 'mwe-size-bytes' => '$1 B',
106106 'mwe-error_load_lib' => 'Error: JavaScript $1 was not retrievable or does not define $2',
107107 'mwe-loading-add-media-wiz' => "Loading add media wizard",
 108+ 'mwe-apiproxy-setup' => " Setting up API proxy",
108109
109110 /*
110111 * js file: /libAddMedia/mvFirefogg.js
Index: trunk/phase3/js2/mwEmbed/mv_embed.js
@@ -91,7 +91,7 @@
9292 var mv_embed_path = getMvEmbedPath();
9393 }
9494 /**
95 -* wrap the global $mw object here:
 95+* The global $mw object:
9696 *
9797 * Any global functions/classes that are not jQuery plugins should make
9898 * there way into the $mw namespace
@@ -382,8 +382,9 @@
383383 //@@todo we need a formatNum and we need to request some special packaged info to deal with that case.
384384 return gM( msg , size );
385385 };
386 -
387 -
 386+
 387+
 388+
388389 /**
389390 * MediaWiki wikitext "Parser"
390391 *
@@ -429,36 +430,15 @@
430431 this.pOut = '';
431432 },
432433 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 -
453434 /*
454 - * quickly recursive / parse out templates with top down recurse decent
 435+ * quickly recursive / parse out templates:
455436 */
456437
457438 // ~ probably a better algorithm out there / should mirror php parser flow ~
458439 // ... 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){
460442 var node = {};
461 - //if we should output node text
462 - var ont = true;
463443 //inspect each char
464444 for(var a=0; a < txt.length; a++){
465445 if( txt[a] == '{' && txt[a+1] == '{' ){
@@ -467,21 +447,20 @@
468448 if(!node['c'])
469449 node['c'] = new Array();
470450
471 - node['c'].push( rdpp( txt.substr( a ) ) );
472 - ont=true;
 451+ node['c'].push( rdpp( txt.substr( a ), true ) );
473452 }else if( txt[a] == '}' && txt[a+1] == '}'){
474453 if( !node['p'] ){
475454 return node;
476455 }
477456 node = node['p'];
478 - ont=false;
479457 a=a+2;
480458 }
481459 if(!node['t'])
482460 node['t']='';
483 -
 461+
484462 if( txt[a] )
485463 node['t']+=txt[a];
 464+
486465 }
487466 return node;
488467 }
@@ -503,8 +482,8 @@
504483 tObj["arg"] = tname.split(':').pop();
505484 }
506485
507 - js_log("TNAME::" + tObj["arg"] + ' from:: ' + ts);
508 -
 486+ js_log("TNAME::" + tObj["name"] + ' from:: ' + ts);
 487+
509488 var pSet = ts.split('\|');
510489 pSet.splice(0,1);
511490 if( pSet.length ){
@@ -566,25 +545,57 @@
567546 return getMagicTxtFromTempNode( node );
568547 }
569548 }
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 );
574556
575 - this.pOut = recurse_magic_swap( node);
576 -
577557 },
 558+
 559+ /*
 560+ * parsed template api ~losely based off of ~POM~
 561+ * http://www.mediawiki.org/wiki/Extension:Page_Object_Model
 562+ */
 563+
578564 /**
 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+ /**
579590 * 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
584595 * (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'
587598 * 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
589600 */
590601 getHTML : function(){
591602 //wikiText updates should invalidate pOut
@@ -597,8 +608,9 @@
598609 //return the parserObj
599610 return new parseObj( wikiText, opt) ;
600611 }
 612+
 613+})(window.$mw);
601614
602 -})(window.$mw);
603615 //setup legacy global shortcuts:
604616 var loadGM = $mw.lang.loadGM;
605617 var loadRS = $mw.lang.loadRS;
@@ -618,7 +630,8 @@
619631 "mwe-size-kilobytes" : "$1 K",
620632 "mwe-size-bytes" : "$1 B",
621633 "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"
623636 });
624637
625638
@@ -666,10 +679,6 @@
667680 * This is used by the script loader to auto-load classes (so we only define
668681 * this once for PHP & JavaScript)
669682 *
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 - *
674683 * Right now the PHP AutoLoader only reads this mv_embed.js file.
675684 * In the future we could have multiple lcPath calls that PHP reads
676685 * (if our autoloading class list becomes too long) just have to add those
@@ -685,13 +694,15 @@
686695 "$j.ui" : "jquery/jquery.ui/ui/ui.core.js",
687696 "$j.fn.ColorPicker" : "libClipEdit/colorpicker/js/colorpicker.js",
688697 "$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+
691702 "ctrlBuilder" : "skins/ctrlBuilder.js",
692703 "kskinConfig" : "skins/kskin/kskin.js",
693704 "mvpcfConfig" : "skins/mvpcf/mvpcf.js",
694705
695 - "$j.secureEvalJSON" : "jquery/plugins/jquery.secureEvalJSON.js",
 706+ "JSON" : "libMwApi/json2.js",
696707 "$j.cookie" : "jquery/plugins/jquery.cookie.js",
697708 "$j.contextMenu" : "jquery/plugins/jquery.contextMenu.js",
698709 "$j.fn.suggestions" : "jquery/plugins/jquery.suggestions.js",
@@ -725,12 +736,13 @@
726737 "mvAdvFirefogg" : "libAddMedia/mvAdvFirefogg.js",
727738 "mvBaseUploadInterface" : "libAddMedia/mvBaseUploadInterface.js",
728739 "remoteSearchDriver" : "libAddMedia/remoteSearchDriver.js",
729 - "seqRemoteSearchDriver" : "libAddMedia/seqRemoteSearchDriver.js",
 740+ "seqRemoteSearchDriver" : "libSequencer/seqRemoteSearchDriver.js",
730741
731742 "baseRemoteSearch" : "libAddMedia/searchLibs/baseRemoteSearch.js",
732743 "mediaWikiSearch" : "libAddMedia/searchLibs/mediaWikiSearch.js",
733744 "metavidSearch" : "libAddMedia/searchLibs/metavidSearch.js",
734745 "archiveOrgSearch" : "libAddMedia/searchLibs/archiveOrgSearch.js",
 746+ "flickrSearch" : "libAddMedia/searchLibs/flickrSearch.js",
735747 "baseRemoteSearch" : "libAddMedia/searchLibs/baseRemoteSearch.js",
736748
737749 "mvClipEdit" : "libClipEdit/mvClipEdit.js",
@@ -778,10 +790,6 @@
779791 * mvJsLoader class handles initialization and js file loads
780792 */
781793
782 -// Shortcut
783 -function mwLoad( loadSet, callback ) {
784 - mvJsLoader.doLoad( loadSet, callback );
785 -}
786794 var mvJsLoader = {
787795 libreq : {},
788796 libs : {},
@@ -1066,6 +1074,13 @@
10671075 }
10681076 }
10691077
 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+
10701085 // Load an external JS file. Similar to jquery .require plugin,
10711086 // but checks for object availability rather than load state.
10721087
@@ -1172,15 +1187,30 @@
11731188 /*
11741189 * Store all the mwEmbed jQuery-specific bindings
11751190 * (set up after jQuery is available).
1176 - * This lets you call rewrites in a jQuery way
11771191 *
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+ *
11801195 *
11811196 */
11821197 function mv_jqueryBindings() {
11831198 js_log( 'mv_jqueryBindings' );
11841199 (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+ }
11851215 //non selector based add-media-wizard direct invocation with loader
11861216 $.addMediaWiz = function( iObj, callback ){
11871217 js_log(".addMediaWiz call");
@@ -1253,7 +1283,7 @@
12541284 'mvPlayList',
12551285 '$j.ui',
12561286 '$j.contextMenu',
1257 - '$j.secureEvalJSON',
 1287+ 'JSON',
12581288 'mvSequencer'
12591289 ],
12601290 [
@@ -1421,14 +1451,15 @@
14221452 *
14231453 * @param msg text text of the loader msg
14241454 */
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();
14291461 //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 +
14331464 '</div>');
14341465 //turn the loader into a real dialog loader:
14351466 mvJsLoader.doLoadDepMode([
@@ -1444,14 +1475,21 @@
14451476 draggable: false,
14461477 resizable: false,
14471478 height: 140,
1448 - modal: true
 1479+ modal: true,
 1480+ buttons: btn
14491481 });
14501482 });
14511483 }
1452 - $.closeLoaderDialog = function(){
 1484+ $.closeLoaderDialog = function(){
14531485 $('#mwe_tmp_loader').dialog('close');
14541486 }
1455 -
 1487+
 1488+ $.mwProxy = function( apiConf ){
 1489+ mvJsLoader.doLoad( ['$mw.apiProxy'],
 1490+ function(){
 1491+ $mw.apiProxy( apiConf );
 1492+ });
 1493+ }
14561494 })(jQuery);
14571495 }
14581496 /*
@@ -1876,7 +1914,11 @@
18771915 * Utility functions
18781916 */
18791917 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 ) {
18811923 window.console.log( string );
18821924 } else {
18831925 /*
Index: trunk/phase3/js2/mwEmbed/libEmbedVideo/nativeEmbed.js
@@ -37,13 +37,12 @@
3838
3939 //continue with the other attr:
4040 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();" >' +
4847 '</video>';
4948 return eb;
5049 },
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 @@
360360 //@@check if we are done
361361 if( data.upload['apiUploadResult'] ){
362362 //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(){
373368 var apiResult = {};
374369 try{
375370 apiResult = JSON.parse ( data.upload['apiUploadResult'] ) ;
@@ -377,7 +372,7 @@
378373 js_log('errro: could not parse apiUploadResult ')
379374 }
380375 _this.processApiResult( apiResult );
381 - }
 376+ });
382377 return ;
383378 }
384379
Index: trunk/phase3/js2/mwEmbed/libAddMedia/searchLibs/baseRemoteSearch.js
@@ -35,9 +35,9 @@
3636
3737 //default search result values for paging:
3838 offset :0,
39 - limit :20,
40 - more_results :false,
41 - num_results :0,
 39+ limit : 30,
 40+ more_results : false,
 41+ num_results : 0,
4242
4343 //init the object:
4444 init: function( iObj ){
@@ -53,8 +53,9 @@
5454 //do global getSearchResults bindings
5555 this.last_query = $j('#rsd_q').val();
5656 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+ },
5960 /*
6061 * Parses and adds video rss based input format
6162 * @param $data XML data to parse
@@ -146,6 +147,37 @@
147148 _this.num_results++;
148149 });
149150 },
 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+ },
150182 //by default just return the existing image with callback
151183 getImageObj:function( rObj, size, callback){
152184 callback( {'url':rObj.poster} );
Index: trunk/phase3/js2/mwEmbed/libAddMedia/searchLibs/archiveOrgSearch.js
@@ -23,23 +23,21 @@
2424 },
2525 getSearchResults:function(){
2626 //call parent:
27 - this.parent_getSearchResults();
28 -
29 - var _this = this;
30 - this.loading=true;
 27+ this.parent_getSearchResults();
 28+ var _this = this;
3129 js_log('f:getSearchResults for:' + $j('#rsd_q').val() );
3230 //build the query var
3331 var q = $j('#rsd_q').val();
3432 //@@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
3634 q+=' format:(Ogg video)';
3735 q+=' licenseurl:(http\\:\\/\\/*)';
3836 var reqObj = {
3937 'q': q, //just search for video atm
4038 'fl':"description,title,identifier,licenseurl,format,license,thumbnail",
4139 'wt':'json',
42 - 'rows':'30',
43 - 'indent':'yes'
 40+ 'rows' : this.cp.limit,
 41+ 'start' : this.cp.offset
4442 }
4543 do_api_req( {
4644 'data':reqObj,
@@ -77,15 +75,7 @@
7876 'pSobj' :_this
7977
8078 };
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;
9080 }
9181 }
9282 },
Index: trunk/phase3/js2/mwEmbed/libAddMedia/searchLibs/metavidSearch.js
@@ -26,10 +26,8 @@
2727 getSearchResults:function(){
2828 //call parent:
2929 this.parent_getSearchResults();
30 -
31 - var _this = this;
32 - //start loading:
33 - _this.loading= 1;
 30+ //set local ref:
 31+ var _this = this;
3432 js_log('metavidSearch::getSearchResults()');
3533 //proccess all options
3634 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){
320 return this.init( iObj );
421 }
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+ },
635 init:function( iObj ){
736 //init base class and inherit:
837 var baseSearch = new baseRemoteSearch( iObj );
@@ -14,9 +43,111 @@
1544 }
1645 //inherit the cp settings for
1746 },
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)
2051 this.parent_getSearchResults();
2152 //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+
22153 }
23154 }
\ No newline at end of file
Index: trunk/phase3/js2/mwEmbed/libAddMedia/searchLibs/mediaWikiSearch.js
@@ -88,9 +88,9 @@
8989 getSearchResults:function(){
9090 //call parent:
9191 this.parent_getSearchResults();
92 -
 92+ //set local ref:
9393 var _this = this;
94 - this.loading = true;
 94+
9595 js_log('f:getSearchResults for:' + $j('#rsd_q').val() );
9696 //do two queries against the Image / File / MVD namespace:
9797
@@ -207,7 +207,7 @@
208208 }
209209 }
210210 }
211 -
 211+
212212 //likely a audio clip if no poster and type application/ogg
213213 //@@todo we should return audio/ogg for the mime type or some other way to specify its "audio"
214214 if( ! rObj.poster && rObj.mime == 'application/ogg' ){
@@ -307,36 +307,20 @@
308308 if(!cEdit)
309309 var cEdit = _this.cEdit;
310310 },
311 - getEmbedHTML: function( rObj , options) {
 311+ getEmbedHTML: function( rObj , options) {
312312 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 );
335318 }
 319+ //for video and audio output:
336320 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 +
339323 ' src="' + rObj.src + '" ' +
340 - style_attr +
 324+ options.style_attr +
341325 ' poster="'+ rObj.poster + '" '
342326 if(rObj.mime.indexOf('application/ogg')!=-1){
343327 return '<video ' + ahtml + '></video>';
@@ -346,13 +330,17 @@
347331 return '<audio ' + ahtml + '></audio>';
348332 }
349333 }
350 - js_log('ERROR:unsupored mime type: ' + rObj.mime);
 334+ js_log( 'ERROR:unsupored mime type: ' + rObj.mime );
351335 },
352336 getInlineDescWiki:function( rObj ){
353337 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+
354342 //just grab the description tag for inline desc:
355343 var descMatch = new RegExp(/Description=(\{\{en\|)?([^|]*|)/);
356 - var dparts = desc.match(descMatch);
 344+ var dparts = desc.match(descMatch);
357345
358346 if( dparts && dparts.length > 1){
359347 desc = (dparts.length == 2) ? dparts[1] : dparts[2].replace('}}','');
@@ -363,9 +351,6 @@
364352 js_log('Error: No Description Tag, Using::' + desc );
365353 return desc;
366354 },
367 - parseWikiTemplate: function( text ){
368 - //@@todo parse wiki Template return object with properties and values
369 - },
370355 //returns the inline wikitext for insertion (template based crops for now)
371356 getEmbedWikiCode: function( rObj ){
372357 //set default layout to right justified
Index: trunk/phase3/js2/mwEmbed/libAddMedia/remoteSearchDriver.js
@@ -35,8 +35,8 @@
3636 "mwe-results_from" : "Results from <a href=\"$1\" target=\"_new\" >$2<\/a>",
3737 "mwe-missing_desc_see_source" : "This asset is missing a description. Please see the [$1 orginal source] and help describe it.",
3838 "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",
4141 "mwe-resource_page_desc" : "Resource page description:",
4242 "mwe-edit_resource_desc" : "Edit wiki text resource description:",
4343 "mwe-local_resource_title" : "Local resource title:",
@@ -47,7 +47,7 @@
4848 "mwe-importing_asset" : "Importing asset",
4949 "mwe-preview_insert_resource" : "Preview insert of resource: $1",
5050 "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",
5252 "mwe-ftype-svg" : "SVG vector file",
5353 "mwe-ftype-jpg" : "JPEG image file",
5454 "mwe-ftype-png" : "PNG image file",
@@ -81,7 +81,9 @@
8282 'cFileNS':'File', //What is the canonical namespace prefix for images
8383 //@@todo (should get that from the api or in-page vars)
8484
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
8688
8789 'enabled_cps':'all', //can be keyword 'all' or an array of enabled content provider keys
8890
@@ -173,9 +175,6 @@
174176 'local_domains': ['wikimedia','wikipedia','wikibooks'],
175177 //specific to wiki commons config:
176178 'search_title':false, //disable title search
177 - //set up default range limit
178 - 'offset' : 0,
179 - 'limit' : 30,
180179 'tab_img':true
181180 },
182181 'archive_org':{
@@ -191,11 +190,24 @@
192191 'resource_prefix': 'AO_',
193192 'tab_img':true
194193 },
195 - 'metavid':{
 194+ 'flickr':{
196195 'enabled':1,
197196 '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',
200212 'desc' : 'Metavid hosts thousands of hours of US house and senate floor proceedings',
201213 'api_url':'http://metavid.org/w/index.php?title=Special:MvExportSearch',
202214 'lib' : 'metavid',
@@ -216,7 +228,7 @@
217229 'upload':{
218230 'enabled':1,
219231 'checked':1,
220 - 'title' :'Upload'
 232+ 'title' :'Upload',
221233 }
222234 },
223235 //define the licenses
@@ -309,6 +321,10 @@
310322 * @param licence_url the url of the license
311323 */
312324 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+
313329 //js_log("getLicenceFromUrl::" + license_url);
314330 //first do a direct lookup check:
315331 for(var j =0; j < this.licenses.cc.licenses.length; j++){
@@ -370,6 +386,7 @@
371387
372388 cUpLoader : null,
373389 cEdit : null,
 390+ proxySetupDone : null,
374391 dmodalCss : {},
375392
376393 init: function( options ){
@@ -394,7 +411,11 @@
395412 }
396413 }
397414 }
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+
399420 //set up the target invocation:
400421 if( $j( this.target_invocation ).length==0 ){
401422 js_log("RemoteSearchDriver:: no target invocation provided (will have to run your own doInitDisplay() )");
@@ -478,14 +499,13 @@
479500 init_modal:function(){
480501 js_log("init_modal");
481502 var _this = this;
 503+ _this.target_container = '#rsd_modal_target';
482504 //add the parent target_container if not provided or missing
483505 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>');
486507 //js_log('appended: #rsd_modal_target' + $j(_this.target_container).attr('id'));
487508 //js_log('added target id:' + $j(_this.target_container).attr('id'));
488509 //get layout
489 - //layout = _this.getMaxModalLayout();
490510 js_log( 'width: ' + $j(window).width() + ' height: ' + $j(window).height());
491511 var cConf = {};
492512 cConf['cancel'] = function(){
@@ -508,9 +528,8 @@
509529 close: function() {
510530 //if we are 'editing' a item close that
511531 //@@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');
515534 }
516535 });
517536 doResize();
@@ -528,27 +547,9 @@
529548 'left':'0px',
530549 'right':'0px',
531550 '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+ });
540552 }
541553 },
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 - },
553554 //sets up the initial html interface
554555 init_interface_html:function(){
555556 js_log('init_interface_html');
@@ -623,82 +624,85 @@
624625 _this.upload_api_target = _this.local_wiki_api_url;
625626 }
626627 }
 628+
627629 //make sure we have a url for the upload target:
628630 if( parseUri( _this.upload_api_target ).host == _this.upload_api_target ){
629631 $j('#tab-upload').html( gM('rsd_config_error', 'bad_api_url') );
630632 return false;
631633 }
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+ }
701641 },1);
702642 },
 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+ },
703707 runSearch: function(){
704708 js_log("f:runSearch::" + this.disp_item);
705709 //draw_direct_flag
@@ -709,9 +713,9 @@
710714 this.doUploadInteface();
711715 return true;
712716 }
713 - //else do runSearch
714717
715 - cp = this.content_providers[this.disp_item];
 718+ //else do runSearch
 719+ var cp = this.content_providers[this.disp_item];
716720
717721 //check if we need to update:
718722 if( typeof cp.sObj != 'undefined' ){
@@ -737,6 +741,15 @@
738742 checkForCopyURLSupport:function ( callback ){
739743 var _this = this;
740744 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+
741754 //see if we already have the import mode:
742755 if( this.import_url_mode != 'autodetect'){
743756 js_log('import mode: ' + _this.import_url_mode);
@@ -860,7 +873,7 @@
861874 var cp = this.content_providers[ cp_id ];
862875 if(typeof cp['sObj'] != 'undefined'){
863876 if( cp.sObj.loading )
864 - loading_done=false;
 877+ loading_done = false;
865878 }
866879 }
867880 if( loading_done ){
@@ -996,10 +1009,10 @@
9971010 _this.setResultBarControl();
9981011 }
9991012
1000 - var drawResultCount =0;
 1013+ var drawResultCount = 0;
10011014
10021015 //output all the results for the current disp_item
1003 - if( typeof cp['sObj'] != 'undefined' ){
 1016+ if( typeof cp['sObj'] != 'undefined' ){
10041017 $j.each(cp.sObj.resultsObj, function(rInx, rItem){
10051018 if( _this.result_display_mode == 'box' ){
10061019 o+='<div id="mv_result_' + rInx + '" class="mv_clip_box_result" style="width:' +
@@ -1051,7 +1064,7 @@
10521065 $j(tab_target).append( o + '<div style="clear:both"/>');
10531066 }
10541067
1055 - js_log( ' drawResultCount :: ' + drawResultCount + ' append: ' + $j('#rsd_q').val() );
 1068+ js_log( 'did drawResultCount :: ' + drawResultCount + ' append: ' + $j('#rsd_q').val() );
10561069
10571070 //remove any old search res
10581071 $j('#rsd_no_search_res').remove();
@@ -1206,7 +1219,7 @@
12071220 });
12081221 },
12091222 cancelClipEditCB:function(){
1210 - var _this = this;
 1223+ var _this = this;
12111224 js_log('cancelClipEditCB');
12121225 var b_target = _this.target_container + '~ .ui-dialog-buttonpane';
12131226 $j('#rsd_resource_edit').remove();
@@ -1218,12 +1231,12 @@
12191232 //restore the title:
12201233 $j( _this.target_container ).dialog( 'option', 'title', gM('mwe-add_media_wizard'));
12211234 js_log("should update: " + b_target + ' with: cancel');
1222 - //restore the buttons:
 1235+ //restore the buttons:
12231236 $j(b_target).html( $j.btnHtml( 'Cancel' , 'mv_cancel_rsd', 'close'))
12241237 .children('.mv_cancel_rsd')
12251238 .btnBind()
12261239 .click(function(){
1227 - $j( _this.target_container).dialog('close');
 1240+ $j( _this.target_container).dialog('close');
12281241 })
12291242
12301243 },
@@ -1253,16 +1266,17 @@
12541267 js_log('remoteSearchDriver::doMediaEdit: ' + mediaType);
12551268
12561269 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 )
12641277 };
1265 -
 1278+ //set the base clip edit lib class req set:
12661279 var clibs = ['mvClipEdit'];
 1280+
12671281 if( mediaType == 'image'){
12681282 //display the mvClipEdit obj once we are done loading:
12691283 mvJsLoader.doLoad( clibs, function(){
@@ -1432,7 +1446,7 @@
14331447 $j( _this.target_container ).append('<div id="rsd_resource_import" '+
14341448 'class="ui-state-highlight ui-widget-content ui-state-error" ' +
14351449 '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>' +
14371451 '<div id="rsd_preview_import_container" style="position:absolute;width:50%;bottom:0px;left:0px;overflow:auto;top:30px;">' +
14381452 rObj.pSobj.getEmbedHTML( rObj, {
14391453 'id': _this.target_container + '_rsd_pv_vid',
@@ -1468,7 +1482,8 @@
14691483 //add hover:
14701484
14711485 //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');
14731488
14741489 //load the preview text:
14751490 _this.getParsedWikiText( wt, _this.cFileNS +':'+ rObj.target_resource_title, function( o ){
@@ -1487,7 +1502,14 @@
14881503 js_log("do import asset:" + _this.import_url_mode);
14891504 //check import mode:
14901505 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+ }
14921514 }else{
14931515 js_log("Error: import mode is not form or API (can not copy asset)");
14941516 }
@@ -1497,7 +1519,33 @@
14981520 $j(this).remove();
14991521 });
15001522 });
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+ },
15021550 checkForFile:function( fName, callback){
15031551 js_log("checkForFile::");
15041552 var _this = this;
@@ -1559,7 +1607,7 @@
15601608
15611609 //close the loader now that we are ready to present the progress dialog::
15621610 $j.closeLoaderDialog();
1563 -
 1611+
15641612 myUp.doHttpUpload({
15651613 'url' : rObj.src,
15661614 'filename' : rObj.target_resource_title,
@@ -1755,7 +1803,7 @@
17561804 var cp = _this.content_providers['this_wiki'];
17571805 }else{
17581806 var cp = this.content_providers[ this.disp_item ];
1759 - }
 1807+ }
17601808 //js_log('getPaging:'+ cp_id + ' len: ' + cp.sObj.num_results);
17611809 var to_num = ( cp.limit > cp.sObj.num_results )?
17621810 (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 @@
2929 importScriptURI( mwEmbedHostPath + '/uploadPage.js' + reqAguments );
3030 } );
3131 }
 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+
3241
3342 // OggHandler rewrite for view pages:
3443 var vidIdList = [];
Index: trunk/phase3/js2/editPage.js
@@ -24,7 +24,7 @@
2525 js2AddOnloadHook( function() {
2626 var amwConf = $j.extend( true, defaultAddMediaConfig, mwAddMediaConfig );
2727 // 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' ) {
2929 $j( 'textarea#wpTextbox1' ).bind( 'wikiEditor-toolbar-buildSection-main',
3030 function( e, section ) {
3131 if ( typeof section.groups.insert.tools.file !== 'undefined' ) {
Index: trunk/phase3/includes/AutoLoader.php
@@ -619,6 +619,7 @@
620620 'uploadPage' => 'js2/uploadPage.js',
621621 'editPage' => 'js2/editPage.js',
622622 'ajaxCategories' => 'js2/ajaxcategories.js',
 623+ 'apiProxyPage' => 'js2/apiProxyPage.js'
623624 );
624625
625626 class AutoLoader {
Index: trunk/phase3/includes/Skin.php
@@ -363,6 +363,7 @@
364364 global $wgVersion, $wgEnableAPI, $wgEnableWriteAPI;
365365 global $wgRestrictionTypes, $wgLivePreview;
366366 global $wgMWSuggestTemplate, $wgDBname, $wgEnableMWSuggest;
 367+ global $wgSitename, $wgEnableIframeApiProxy, $wgEnableJS2system;
367368
368369 $ns = $wgTitle->getNamespace();
369370 $nsname = MWNamespace::exists( $ns ) ? MWNamespace::getCanonicalName( $ns ) : $wgTitle->getNsText();
@@ -413,6 +414,7 @@
414415 'wgMainPageTitle' => $mainPage ? $mainPage->getPrefixedText() : null,
415416 'wgFormattedNamespaces' => $wgContLang->getFormattedNamespaces(),
416417 'wgNamespaceIds' => $wgContLang->getNamespaceIds(),
 418+ 'wgSiteName' => $wgSitename,
417419 );
418420 if ( $wgContLang->hasVariants() ) {
419421 $vars['wgUserVariant'] = $wgContLang->getPreferredVariant();
@@ -442,6 +444,17 @@
443445 $vars['wgLivepreviewMessageError'] = wfMsg( 'livepreview-error' );
444446 }
445447
 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+
446459 if ( $wgOut->isArticleRelated() && $wgUseAjax && $wgAjaxWatch && $wgUser->isLoggedIn() ) {
447460 $msgs = (object)array();
448461 foreach ( array( 'watch', 'unwatch', 'watching', 'unwatching' ) as $msgName ) {
@@ -864,7 +877,7 @@
865878 $catlinks = $this->getCategoryLinks();
866879
867880 $classes = 'catlinks';
868 -
 881+
869882 // Check what we're showing
870883 global $wgOut, $wgUser;
871884 $allCats = $wgOut->getCategoryLinks();
@@ -960,7 +973,7 @@
961974 else
962975 $ret .= str_repeat( "<ul><li>\n", $diff );
963976 $ret .= $display . "\n";
964 -
 977+
965978 $curIdent = $ident;
966979 }
967980 $ret .= str_repeat( '</li></ul>', $curIdent ) . '</li>';
Index: trunk/phase3/includes/DefaultSettings.php
@@ -213,9 +213,9 @@
214214 * thumbScriptUrl The URL for thumb.php (optional, not recommended)
215215 * transformVia404 Whether to skip media file transformation on parse and rely on a 404
216216 * 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
220220 * when the local $wgCapitalLinks and initialCapital are mismatched.
221221 * pathDisclosureProtection
222222 * May be 'paranoid' to remove all parameters from error messages, 'none' to
@@ -462,7 +462,7 @@
463463
464464
465465 /**
466 - * Enable Firefogg support. Adds support for in-browser transcoding to Ogg
 466+ * Enable Firefogg support. Adds support for in-browser transcoding to Ogg
467467 * Theora, chunked uploads for large image files and client side hash checks.
468468 *
469469 * Ignored unless $wgEnableJS2system is true.
@@ -2438,11 +2438,11 @@
24392439
24402440 /**
24412441 * @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
24472447 * NS_FILE.
24482448 * EX: $wgCapitalLinkOverrides[ NS_FILE ] = false;
24492449 */
@@ -2787,7 +2787,7 @@
27882788 *
27892789 * note this will only check core scripts that are directly included on the page.
27902790 * (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)
27922792 *
27932793 * and or you can update $wgStyleVersion
27942794 */
@@ -2800,13 +2800,18 @@
28012801 $wgEnableJS2system = false;
28022802
28032803 /*
 2804+ * enable api iframe proxy
 2805+ */
 2806+$wgEnableIframeApiProxy = false;
 2807+
 2808+/*
28042809 * boolean; if we should minify the output. (note if you send ?debug=true in
28052810 * the page request it will automatically not group and not minify)
28062811 */
28072812 $wgEnableScriptMinify = true;
28082813
28092814 /*
2810 - * boolean; if we should enable javascript localization (it loads loadGM json
 2815+ * boolean; if we should enable javascript localization (it loads loadGM json
28112816 * call with mediaWiki msgs)
28122817 */
28132818 $wgEnableScriptLocalization = true;
@@ -2817,7 +2822,7 @@
28182823 $wgMwEmbedDirectory = "js2/mwEmbed/";
28192824
28202825 /*
2821 - * Turn on debugging for the javascript script-loader & forces fresh copies
 2826+ * Turn on debugging for the javascript script-loader & forces fresh copies
28222827 * of javascript
28232828 */
28242829 $wgDebugJavaScript = false;
@@ -3729,7 +3734,7 @@
37303735 $wgAjaxUploadDestCheck = true;
37313736
37323737 /**
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
37343739 * progress on uploads for browsers that support it)
37353740 */
37363741 $wgAjaxUploadInterface = true;
@@ -4010,7 +4015,7 @@
40114016 * Page property link table invalidation lists. When a page property
40124017 * changes, this may require other link tables to be updated (eg
40134018 * 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).
40154020 * This array can be added to by extensions.
40164021 */
40174022 $wgPagePropLinkInvalidations = array(

Follow-up revisions

RevisionCommit summaryAuthorDate
r57907* removed extra comma that breaks IE r57858#c4283dale18:48, 19 October 2009

Comments

#Comment by Umherirrender (talk | contribs)   17:24, 19 October 2009

change of line 231 in /trunk/phase3/js2/mwEmbed/libAddMedia/remoteSearchDriver.js breaks IE7 (trailing comma after } without following definition)

//special cp "upload"
		'upload':{
			'enabled':1,
			'checked':1,
			'title'	:'Upload',
		}
#Comment by Mdale (talk | contribs)   18:48, 19 October 2009

opps .. nice catch (fixed in r57907)

Status & tagging log