'uploadPage' => 'js2/uploadPage.js',
'editPage' => 'js2/editPage.js',
'ajaxCategories' => 'js2/ajaxcategories.js',
+ 'apiProxyPage' => 'js2/apiProxyPage.js'
);
class AutoLoader {
* thumbScriptUrl The URL for thumb.php (optional, not recommended)
* transformVia404 Whether to skip media file transformation on parse and rely on a 404
* handler instead.
- * initialCapital Equivalent to $wgCapitalLinks (or $wgCapitalLinkOverrides[NS_FILE],
- * determines whether filenames implicitly start with a capital letter.
- * The current implementation may give incorrect description page links
+ * initialCapital Equivalent to $wgCapitalLinks (or $wgCapitalLinkOverrides[NS_FILE],
+ * determines whether filenames implicitly start with a capital letter.
+ * The current implementation may give incorrect description page links
* when the local $wgCapitalLinks and initialCapital are mismatched.
* pathDisclosureProtection
* May be 'paranoid' to remove all parameters from error messages, 'none' to
/**
- * Enable Firefogg support. Adds support for in-browser transcoding to Ogg
+ * Enable Firefogg support. Adds support for in-browser transcoding to Ogg
* Theora, chunked uploads for large image files and client side hash checks.
*
* Ignored unless $wgEnableJS2system is true.
/**
* @since 1.16 - This can now be set per-namespace. Some special namespaces (such
- * as Special, see Namespace::$alwaysCapitalizedNamespaces for the full list) must be
- * true by default (and setting them has no effect), due to various things that
- * require them to be so. Also, since Talk namespaces need to directly mirror their
- * associated content namespaces, the values for those are ignored in favor of the
- * subject namespace's setting. Setting for NS_MEDIA is taken automatically from
+ * as Special, see Namespace::$alwaysCapitalizedNamespaces for the full list) must be
+ * true by default (and setting them has no effect), due to various things that
+ * require them to be so. Also, since Talk namespaces need to directly mirror their
+ * associated content namespaces, the values for those are ignored in favor of the
+ * subject namespace's setting. Setting for NS_MEDIA is taken automatically from
* NS_FILE.
* EX: $wgCapitalLinkOverrides[ NS_FILE ] = false;
*/
*
* note this will only check core scripts that are directly included on the page.
* (not scripts loaded after the initial page display since after initial page
- * display scripts inherit the unique request id)
+ * display scripts inherit the unique request id)
*
* and or you can update $wgStyleVersion
*/
*/
$wgEnableJS2system = false;
+/*
+ * enable api iframe proxy
+ */
+$wgEnableIframeApiProxy = false;
+
/*
* boolean; if we should minify the output. (note if you send ?debug=true in
* the page request it will automatically not group and not minify)
$wgEnableScriptMinify = true;
/*
- * boolean; if we should enable javascript localization (it loads loadGM json
+ * boolean; if we should enable javascript localization (it loads loadGM json
* call with mediaWiki msgs)
*/
$wgEnableScriptLocalization = true;
$wgMwEmbedDirectory = "js2/mwEmbed/";
/*
- * Turn on debugging for the javascript script-loader & forces fresh copies
+ * Turn on debugging for the javascript script-loader & forces fresh copies
* of javascript
*/
$wgDebugJavaScript = false;
$wgAjaxUploadDestCheck = true;
/**
- * Enable the AJAX upload interface (needed for large http uploads & to display
+ * Enable the AJAX upload interface (needed for large http uploads & to display
* progress on uploads for browsers that support it)
*/
$wgAjaxUploadInterface = true;
* Page property link table invalidation lists. When a page property
* changes, this may require other link tables to be updated (eg
* adding __HIDDENCAT__ means the hiddencat tracking category will
- * have been added, so the categorylinks table needs to be rebuilt).
+ * have been added, so the categorylinks table needs to be rebuilt).
* This array can be added to by extensions.
*/
$wgPagePropLinkInvalidations = array(
global $wgVersion, $wgEnableAPI, $wgEnableWriteAPI;
global $wgRestrictionTypes, $wgLivePreview;
global $wgMWSuggestTemplate, $wgDBname, $wgEnableMWSuggest;
+ global $wgSitename, $wgEnableIframeApiProxy, $wgEnableJS2system;
$ns = $wgTitle->getNamespace();
$nsname = MWNamespace::exists( $ns ) ? MWNamespace::getCanonicalName( $ns ) : $wgTitle->getNsText();
'wgMainPageTitle' => $mainPage ? $mainPage->getPrefixedText() : null,
'wgFormattedNamespaces' => $wgContLang->getFormattedNamespaces(),
'wgNamespaceIds' => $wgContLang->getNamespaceIds(),
+ 'wgSiteName' => $wgSitename,
);
if ( $wgContLang->hasVariants() ) {
$vars['wgUserVariant'] = $wgContLang->getPreferredVariant();
$vars['wgLivepreviewMessageError'] = wfMsg( 'livepreview-error' );
}
+ //add api proxy var and script link if on the special proxy page:
+ if( $wgEnableJS2system &&
+ $wgTitle->getNamespace() == NS_MEDIAWIKI &&
+ $wgTitle->getDBKey() == 'ApiProxy' )
+ {
+ $vars['wgEnableIframeApiProxy'] = $wgEnableIframeApiProxy;
+ //also add the apiProxy Page script if we are on that page
+ if( $wgEnableIframeApiProxy )
+ $wgOut->addScriptClass( 'apiProxyPage' );
+ }
+
if ( $wgOut->isArticleRelated() && $wgUseAjax && $wgAjaxWatch && $wgUser->isLoggedIn() ) {
$msgs = (object)array();
foreach ( array( 'watch', 'unwatch', 'watching', 'unwatching' ) as $msgName ) {
$catlinks = $this->getCategoryLinks();
$classes = 'catlinks';
-
+
// Check what we're showing
global $wgOut, $wgUser;
$allCats = $wgOut->getCategoryLinks();
else
$ret .= str_repeat( "<ul><li>\n", $diff );
$ret .= $display . "\n";
-
+
$curIdent = $ident;
}
$ret .= str_repeat( '</li></ul>', $curIdent ) . '</li>';
--- /dev/null
+/*
+* mwProxy js2 page system.
+*
+* invokes the apiProxy system
+*/
+
+/*
+ * since this is proxy server set a pre-append debug flag to know which debug msgs are coming from where
+ */
+
+if( !mwApiProxyConfig )
+ var mwApiProxyConfig = {};
+
+//The default mwApiProxyConfig config
+//(presently hard coded but should read from user and site config)
+var mwApiProxyDefaultConfig = {
+ 'master_whitelist' : [ 'en.wikipedia.org', 'localhost', '127.1.1.100' ],
+ 'master_blacklist' : []
+};
+//user_white_list should also be checked and configured at runtime.
+
+js2AddOnloadHook( function() {
+ //build our configuration from the default and mwApiProxyConfig vars
+ mwApiProxyConfig = $j.extend(true, mwApiProxyDefaultConfig, mwApiProxyConfig);
+
+ $j.apiProxy( 'server', mwApiProxyConfig );
+});
js2AddOnloadHook( function() {
var amwConf = $j.extend( true, defaultAddMediaConfig, mwAddMediaConfig );
// kind of tricky, it would be nice to use run on ready "loader" call here
- if( typeof $j.wikiEditor != 'undefined' ) {
+ if( typeof $j.wikiEditor != 'undefined' ) {
$j( 'textarea#wpTextbox1' ).bind( 'wikiEditor-toolbar-buildSection-main',
function( e, section ) {
if ( typeof section.groups.insert.tools.file !== 'undefined' ) {
+++ /dev/null
-/*
- * jQuery JSON Plugin
- * version: 1.0 (2008-04-17)
- *
- * This document is licensed as free software under the terms of the
- * MIT License: http://www.opensource.org/licenses/mit-license.php
- *
- * Brantley Harris technically wrote this plugin, but it is based somewhat
- * on the JSON.org website's http://www.json.org/json2.js, which proclaims:
- * "NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.", a sentiment that
- * I uphold. I really just cleaned it up.
- *
- * It is also based heavily on MochiKit's serializeJSON, which is
- * copywrited 2005 by Bob Ippolito.
- */
-
-(function($) {
- function toIntegersAtLease(n)
- // Format integers to have at least two digits.
- {
- return n < 10 ? '0' + n : n;
- }
-
- Date.prototype.toJSON = function(date)
- // Yes, it polutes the Date namespace, but we'll allow it here, as
- // it's damned usefull.
- {
- return this.getUTCFullYear() + '-' +
- toIntegersAtLease(this.getUTCMonth()) + '-' +
- toIntegersAtLease(this.getUTCDate());
- };
-
- var escapeable = /["\\\x00-\x1f\x7f-\x9f]/g;
- var meta = { // table of character substitutions
- '\b': '\\b',
- '\t': '\\t',
- '\n': '\\n',
- '\f': '\\f',
- '\r': '\\r',
- '"' : '\\"',
- '\\': '\\\\'
- };
-
- $.quoteString = function(string)
- // Places quotes around a string, inteligently.
- // If the string contains no control characters, no quote characters, and no
- // backslash characters, then we can safely slap some quotes around it.
- // Otherwise we must also replace the offending characters with safe escape
- // sequences.
- {
- if (escapeable.test(string))
- {
- return '"' + string.replace(escapeable, function (a)
- {
- var c = meta[a];
- if (typeof c === 'string') {
- return c;
- }
- c = a.charCodeAt();
- return '\\u00' + Math.floor(c / 16).toString(16) + (c % 16).toString(16);
- }) + '"';
- }
- return '"' + string + '"';
- };
-
- $.toJSON = function(o, compact)
- {
- var type = typeof(o);
-
- if (type == "undefined")
- return "undefined";
- else if (type == "number" || type == "boolean")
- return o + "";
- else if (o === null)
- return "null";
-
- // Is it a string?
- if (type == "string")
- {
- return $.quoteString(o);
- }
-
- // Does it have a .toJSON function?
- if (type == "object" && typeof o.toJSON == "function")
- return o.toJSON(compact);
-
- // Is it an array?
- if (type != "function" && typeof(o.length) == "number")
- {
- var ret = [];
- for (var i = 0; i < o.length; i++) {
- ret.push( $.toJSON(o[i], compact) );
- }
- if (compact)
- return "[" + ret.join(",") + "]";
- else
- return "[" + ret.join(", ") + "]";
- }
-
- // If it's a function, we have to warn somebody!
- if (type == "function") {
- throw new TypeError("Unable to convert object of type 'function' to json.");
- }
-
- // It's probably an object, then.
- var ret = [];
- for (var k in o) {
- var name;
- type = typeof(k);
-
- if (type == "number")
- name = '"' + k + '"';
- else if (type == "string")
- name = $.quoteString(k);
- else
- continue; //skip non-string or number keys
-
- var val = $.toJSON(o[k], compact);
- if (typeof(val) != "string") {
- // skip non-serializable values
- continue;
- }
-
- if (compact)
- ret.push(name + ":" + val);
- else
- ret.push(name + ": " + val);
- }
- return "{" + ret.join(", ") + "}";
- };
-
- $.compactJSON = function(o)
- {
- return $.toJSON(o, true);
- };
-
- $.evalJSON = function(src)
- // Evals JSON that we know to be safe.
- {
- return eval("(" + src + ")");
- };
-
- $.secureEvalJSON = function(src)
- // Evals JSON in a way that is *more* secure.
- {
- var filtered = src;
- filtered = filtered.replace(/\\["\\\/bfnrtu]/g, '@');
- filtered = filtered.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']');
- filtered = filtered.replace(/(?:^|:|,)(?:\s*\[)+/g, '');
-
- if (/^[\],:{}\s]*$/.test(filtered))
- return eval("(" + src + ")");
- else
- throw new SyntaxError("Error parsing JSON, source is not valid.");
- };
-})(jQuery);
+++ /dev/null
-/*
- * jQuery JSON Plugin
- * version: 1.0 (2008-04-17)
- *
- * This document is licensed as free software under the terms of the
- * MIT License: http://www.opensource.org/licenses/mit-license.php
- *
- * Brantley Harris technically wrote this plugin, but it is based somewhat
- * on the JSON.org website's http://www.json.org/json2.js, which proclaims:
- * "NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.", a sentiment that
- * I uphold. I really just cleaned it up.
- *
- * It is also based heavily on MochiKit's serializeJSON, which is
- * copywrited 2005 by Bob Ippolito.
- */
-
-(function($) {
- function toIntegersAtLease(n)
- // Format integers to have at least two digits.
- {
- return n < 10 ? '0' + n : n;
- }
-
- Date.prototype.toJSON = function(date)
- // Yes, it polutes the Date namespace, but we'll allow it here, as
- // it's damned usefull.
- {
- return this.getUTCFullYear() + '-' +
- toIntegersAtLease(this.getUTCMonth()) + '-' +
- toIntegersAtLease(this.getUTCDate());
- };
-
- var escapeable = /["\\\x00-\x1f\x7f-\x9f]/g;
- var meta = { // table of character substitutions
- '\b': '\\b',
- '\t': '\\t',
- '\n': '\\n',
- '\f': '\\f',
- '\r': '\\r',
- '"' : '\\"',
- '\\': '\\\\'
- };
-
- $.quoteString = function(string)
- // Places quotes around a string, inteligently.
- // If the string contains no control characters, no quote characters, and no
- // backslash characters, then we can safely slap some quotes around it.
- // Otherwise we must also replace the offending characters with safe escape
- // sequences.
- {
- if (escapeable.test(string))
- {
- return '"' + string.replace(escapeable, function (a)
- {
- var c = meta[a];
- if (typeof c === 'string') {
- return c;
- }
- c = a.charCodeAt();
- return '\\u00' + Math.floor(c / 16).toString(16) + (c % 16).toString(16);
- }) + '"';
- }
- return '"' + string + '"';
- };
-
- $.toJSON = function(o, compact)
- {
- var type = typeof(o);
-
- if (type == "undefined")
- return "undefined";
- else if (type == "number" || type == "boolean")
- return o + "";
- else if (o === null)
- return "null";
-
- // Is it a string?
- if (type == "string")
- {
- return $.quoteString(o);
- }
-
- // Does it have a .toJSON function?
- if (type == "object" && typeof o.toJSON == "function")
- return o.toJSON(compact);
-
- // Is it an array?
- if (type != "function" && typeof(o.length) == "number")
- {
- var ret = [];
- for (var i = 0; i < o.length; i++) {
- ret.push( $.toJSON(o[i], compact) );
- }
- if (compact)
- return "[" + ret.join(",") + "]";
- else
- return "[" + ret.join(", ") + "]";
- }
-
- // If it's a function, we have to warn somebody!
- if (type == "function") {
- throw new TypeError("Unable to convert object of type 'function' to json.");
- }
-
- // It's probably an object, then.
- var ret = [];
- for (var k in o) {
- var name;
- type = typeof(k);
-
- if (type == "number")
- name = '"' + k + '"';
- else if (type == "string")
- name = $.quoteString(k);
- else
- continue; //skip non-string or number keys
-
- var val = $.toJSON(o[k], compact);
- if (typeof(val) != "string") {
- // skip non-serializable values
- continue;
- }
-
- if (compact)
- ret.push(name + ":" + val);
- else
- ret.push(name + ": " + val);
- }
- return "{" + ret.join(", ") + "}";
- };
-
- $.compactJSON = function(o)
- {
- return $.toJSON(o, true);
- };
-
- $.evalJSON = function(src)
- // Evals JSON that we know to be safe.
- {
- return eval("(" + src + ")");
- };
-
- $.secureEvalJSON = function(src)
- // Evals JSON in a way that is *more* secure.
- {
- var filtered = src;
- filtered = filtered.replace(/\\["\\\/bfnrtu]/g, '@');
- filtered = filtered.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']');
- filtered = filtered.replace(/(?:^|:|,)(?:\s*\[)+/g, '');
-
- if (/^[\],:{}\s]*$/.test(filtered))
- return eval("(" + src + ")");
- else
- throw new SyntaxError("Error parsing JSON, source is not valid.");
- };
-})(jQuery);
//@@check if we are done
if( data.upload['apiUploadResult'] ){
//update status to 100%
- _this.updateProgress( 1 );
- if(typeof JSON == 'undefined'){
- //we need to load the jQuery json parser: (older browsers don't have JSON.parse
- mvJsLoader.doLoad([
- '$j.secureEvalJSON'
- ],function(){
- var apiResult = $j.secureEvalJSON( data.upload['apiUploadResult'] );
- _this.processApiResult( apiResult );
- });
- }else{
+ _this.updateProgress( 1 );
+ //see if we need to load JSON substitue:
+ mvJsLoader.doLoad( [
+ 'JSON'
+ ],function(){
var apiResult = {};
try{
apiResult = JSON.parse ( data.upload['apiUploadResult'] ) ;
js_log('errro: could not parse apiUploadResult ')
}
_this.processApiResult( apiResult );
- }
+ });
return ;
}
"mwe-results_from" : "Results from <a href=\"$1\" target=\"_new\" >$2<\/a>",
"mwe-missing_desc_see_source" : "This asset is missing a description. Please see the [$1 orginal source] and help describe it.",
"rsd_config_error" : "Add media wizard configuration error: $1",
- "mwe-your_recent_uploads" : "Your recent uploads",
- "mwe-upload_a_file" : "Upload a new file",
+ "mwe-your_recent_uploads" : "Your recent uploads to $1",
+ "mwe-upload_a_file" : "Upload a new file to $1",
"mwe-resource_page_desc" : "Resource page description:",
"mwe-edit_resource_desc" : "Edit wiki text resource description:",
"mwe-local_resource_title" : "Local resource title:",
"mwe-importing_asset" : "Importing asset",
"mwe-preview_insert_resource" : "Preview insert of resource: $1",
"mwe-checking-resource": "Checking for resource",
- "mwe-resource-needs-import": "Resource $1 needs to be imported",
+ "mwe-resource-needs-import": "Resource $1 needs to be imported to $2",
"mwe-ftype-svg" : "SVG vector file",
"mwe-ftype-jpg" : "JPEG image file",
"mwe-ftype-png" : "PNG image file",
'cFileNS':'File', //What is the canonical namespace prefix for images
//@@todo (should get that from the api or in-page vars)
- 'upload_api_target': 'http://localhost/wiki_trunk/api.php', // can be local or the url of the upload api.
+ 'upload_api_target': 'local', // can be local or the url or remote
+ 'upload_api_name' : null,
+ 'upload_api_proxy_frame': null, //a page that will request mw.proxy.server
'enabled_cps':'all', //can be keyword 'all' or an array of enabled content provider keys
'local_domains': ['wikimedia','wikipedia','wikibooks'],
//specific to wiki commons config:
'search_title':false, //disable title search
- //set up default range limit
- 'offset' : 0,
- 'limit' : 30,
'tab_img':true
},
'archive_org':{
'resource_prefix': 'AO_',
'tab_img':true
},
- 'metavid':{
+ 'flickr':{
'enabled':1,
'checked':1,
- 'title' :'Metavid.org',
- 'homepage':'http://metavid.org',
+ 'title' : 'flickr.com',
+ 'desc' : 'flickr.com, a online photo sharing site',
+ 'homepage':'http://www.flickr.com/about/',
+
+ 'api_url':'http://www.flickr.com/services/rest/',
+ 'lib' : 'flickr',
+ 'local' : false,
+ 'resource_prefix': '',
+ 'tab_img':true
+ },
+ 'metavid':{
+ 'enabled' : 1,
+ 'checked' : 1,
+ 'title' : 'Metavid.org',
+ 'homepage':'http://metavid.org/wiki/Metavid_Overview',
'desc' : 'Metavid hosts thousands of hours of US house and senate floor proceedings',
'api_url':'http://metavid.org/w/index.php?title=Special:MvExportSearch',
'lib' : 'metavid',
'upload':{
'enabled':1,
'checked':1,
- 'title' :'Upload'
+ 'title' :'Upload',
}
},
//define the licenses
* @param licence_url the url of the license
*/
getLicenceFromUrl: function( license_url ){
+ //check for some pre-defined url types:
+ if( license_url == 'http://www.usa.gov/copyright.shtml')
+ return this.getLicenceFromKey('pd' , license_url);
+
//js_log("getLicenceFromUrl::" + license_url);
//first do a direct lookup check:
for(var j =0; j < this.licenses.cc.licenses.length; j++){
cUpLoader : null,
cEdit : null,
+ proxySetupDone : null,
dmodalCss : {},
init: function( options ){
}
}
}
-
+ //set the upload target name if unset
+ if( _this.upload_api_target == 'local' && ! _this.upload_api_name && wgSiteName)
+ _this.upload_api_name = wgSiteName;
+
+
//set up the target invocation:
if( $j( this.target_invocation ).length==0 ){
js_log("RemoteSearchDriver:: no target invocation provided (will have to run your own doInitDisplay() )");
init_modal:function(){
js_log("init_modal");
var _this = this;
+ _this.target_container = '#rsd_modal_target';
//add the parent target_container if not provided or missing
if(!_this.target_container || $j(_this.target_container).length==0){
- $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>');
- _this.target_container = '#rsd_modal_target';
+ $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>');
//js_log('appended: #rsd_modal_target' + $j(_this.target_container).attr('id'));
//js_log('added target id:' + $j(_this.target_container).attr('id'));
//get layout
- //layout = _this.getMaxModalLayout();
js_log( 'width: ' + $j(window).width() + ' height: ' + $j(window).height());
var cConf = {};
cConf['cancel'] = function(){
close: function() {
//if we are 'editing' a item close that
//@@todo maybe prompt the user?
- _this.cancelClipEditCB();
- //$j(this).dialog('close');
- $j(this).parents('.ui-dialog').fadeOut('slow');
+ _this.cancelClipEditCB();
+ $j(this).parents('.ui-dialog').fadeOut('slow');
}
});
doResize();
'left':'0px',
'right':'0px',
'bottom':'0px'
- });
- /*
-
-
- js_log('done setup of target_container: ' +
- $j(_this.target_container +'~ .ui-dialog-buttonpane').length);
- */
-
- }
- },
- getMaxModalLayout:function(border){
- if(!border)
- border = 50;
- //js_log('setting h:' + (parseInt( $j(document).height() ) - parseInt(border*2)) + ' from:' + $j(document).height() );
- return {
- 'h': parseInt( $j(document).height() ) - parseInt(border*4),
- 'w': parseInt( $j(document).width() ) - parseInt(border*2),
- 'r': border,
- 't': border
+ });
}
},
//sets up the initial html interface
_this.upload_api_target = _this.local_wiki_api_url;
}
}
+
//make sure we have a url for the upload target:
if( parseUri( _this.upload_api_target ).host == _this.upload_api_target ){
$j('#tab-upload').html( gM('rsd_config_error', 'bad_api_url') );
return false;
}
- //output the form
- //set the form action based on domain:
- if( parseUri( document.URL ).host == parseUri( _this.upload_api_target ).host ){
- mvJsLoader.doLoad(['$j.fn.simpleUploadForm'],function(){
-
- //get extends info about the file
- var cp = _this.content_providers['this_wiki'];
- //check for "this_wiki" enabled
- /*if(!cp.enabled){
- $j('#tab-upload').html('error this_wiki not enabled (can\'t get uploaded file info)');
- return false;
- }*/
-
- //load this_wiki search system to grab the rObj
- _this.loadSearchLib(cp, function(){
- //do basic layout form on left upload "bin" on right
- $j('#tab-upload').html('<table>' +
- '<tr>' +
- '<td valign="top" style="width:350px; padding-right: 12px;">' +
- '<h4>' + gM('mwe-upload_a_file') + '</h4>' +
- '<div id="upload_form">' +
- mv_get_loading_img() +
- '</div>' +
- '</td>' +
- '<td valign="top" id="upload_bin_cnt">' +
- '<h4>' + gM('mwe-your_recent_uploads') + '</h4>' +
- '<div id="upload_bin">' +
- mv_get_loading_img() +
- '</div>'+
- '</td>' +
- '</tr>' +
- '</table>');
-
-
- //fill in the user page:
- if(typeof wgUserName != 'undefined' && wgUserName){
- //load the upload bin with anything the current user has uploaded
- cp.sObj.getUserRecentUploads( wgUserName, function(){
- _this.drawOutputResults();
- });
- }else{
- $j('#upload_bin_cnt').empty();
- }
-
- //deal with the api form upload form directly:
- $j('#upload_form').simpleUploadForm({
- "api_target" : _this.upload_api_target,
- "ondone_cb" : function( resultData ){
- var wTitle = resultData['filename'];
- //add a loading div
- _this.addResourceEditLoader();
- //@@note: we have most of what we need in resultData imageinfo
- cp.sObj.addByTitle( wTitle, function( rObj ){
- //redraw (with added result if new)
- _this.drawOutputResults();
- //pull up resource editor:
- _this.resourceEdit( rObj, $j('#res_upload__' + rObj.id).get(0) );
- });
- //return false to close progress window:
- return false;
- }
- })
- });
- });
- }else{
- //setup the proxy
- js_log('do proxy:: ' + parseUri( _this.upload_api_target ).host);
- $j('#tab-upload').html('proxy upload not yet ready');
- }
+ //check if we need to setup the proxy::
+ if( parseUri( document.URL ).host != parseUri( _this.upload_api_target ).host ){
+ //setup proxy
+ $j('#tab-upload').html( 'do proxy setup');
+ }else{
+ _this.getUploadForm();
+ }
},1);
},
+ getUploadForm:function(){
+ var _this = this;
+ mvJsLoader.doLoad(['$j.fn.simpleUploadForm'],function(){
+ //get extends info about the file
+ var cp = _this.content_providers['this_wiki'];
+
+ //check for "this_wiki" enabled
+ /*if(!cp.enabled){
+ $j('#tab-upload').html('error this_wiki not enabled (can\'t get uploaded file info)');
+ return false;
+ }*/
+
+ //load this_wiki search system to grab the rObj
+ _this.loadSearchLib(cp, function(){
+ //do basic layout form on left upload "bin" on right
+ $j('#tab-upload').html('<table>' +
+ '<tr>' +
+ '<td valign="top" style="width:350px; padding-right: 12px;">' +
+ '<h4>' + gM('mwe-upload_a_file', _this.upload_api_name ) + '</h4>' +
+ '<div id="upload_form">' +
+ mv_get_loading_img() +
+ '</div>' +
+ '</td>' +
+ '<td valign="top" id="upload_bin_cnt">' +
+ '<h4>' + gM('mwe-your_recent_uploads', _this.upload_api_name) + '</h4>' +
+ '<div id="upload_bin">' +
+ mv_get_loading_img() +
+ '</div>'+
+ '</td>' +
+ '</tr>' +
+ '</table>');
+
+
+ //fill in the user page:
+ if(typeof wgUserName != 'undefined' && wgUserName){
+ //load the upload bin with anything the current user has uploaded
+ cp.sObj.getUserRecentUploads( wgUserName, function(){
+ _this.drawOutputResults();
+ });
+ }else{
+ $j('#upload_bin_cnt').empty();
+ }
+
+ //deal with the api form upload form directly:
+ $j('#upload_form').simpleUploadForm({
+ "api_target" : _this.upload_api_target,
+ "ondone_cb" : function( resultData ){
+ var wTitle = resultData['filename'];
+ //add a loading div
+ _this.addResourceEditLoader();
+ //@@note: we have most of what we need in resultData imageinfo
+ cp.sObj.addByTitle( wTitle, function( rObj ){
+ //redraw (with added result if new)
+ _this.drawOutputResults();
+ //pull up resource editor:
+ _this.resourceEdit( rObj, $j('#res_upload__' + rObj.id).get(0) );
+ });
+ //return false to close progress window:
+ return false;
+ }
+ });
+ }); //load searchLibs
+ }); //load simpleUploadForm
+ },
runSearch: function(){
js_log("f:runSearch::" + this.disp_item);
//draw_direct_flag
this.doUploadInteface();
return true;
}
- //else do runSearch
- cp = this.content_providers[this.disp_item];
+ //else do runSearch
+ var cp = this.content_providers[this.disp_item];
//check if we need to update:
if( typeof cp.sObj != 'undefined' ){
checkForCopyURLSupport:function ( callback ){
var _this = this;
js_log('checkForCopyURLSupport:: ');
+ //check if the import url is diffrent from
+ //check if we need to setup the proxy::
+ /*if( parseUri( document.URL ).host != parseUri( _this.upload_api_target ).host ){
+ //setup proxy
+ js_log(" doc.url:" + parseUri( document.URL ).host + ' != ' +parseUri( _this.upload_api_target ).host);
+ $j('#tab-' + this.disp_item ).html( 'do proxy setup');
+ return false;
+ }*/
+
//see if we already have the import mode:
if( this.import_url_mode != 'autodetect'){
js_log('import mode: ' + _this.import_url_mode);
var cp = this.content_providers[ cp_id ];
if(typeof cp['sObj'] != 'undefined'){
if( cp.sObj.loading )
- loading_done=false;
+ loading_done = false;
}
}
if( loading_done ){
_this.setResultBarControl();
}
- var drawResultCount =0;
+ var drawResultCount = 0;
//output all the results for the current disp_item
- if( typeof cp['sObj'] != 'undefined' ){
+ if( typeof cp['sObj'] != 'undefined' ){
$j.each(cp.sObj.resultsObj, function(rInx, rItem){
if( _this.result_display_mode == 'box' ){
o+='<div id="mv_result_' + rInx + '" class="mv_clip_box_result" style="width:' +
$j(tab_target).append( o + '<div style="clear:both"/>');
}
- js_log( ' drawResultCount :: ' + drawResultCount + ' append: ' + $j('#rsd_q').val() );
+ js_log( 'did drawResultCount :: ' + drawResultCount + ' append: ' + $j('#rsd_q').val() );
//remove any old search res
$j('#rsd_no_search_res').remove();
});
},
cancelClipEditCB:function(){
- var _this = this;
+ var _this = this;
js_log('cancelClipEditCB');
var b_target = _this.target_container + '~ .ui-dialog-buttonpane';
$j('#rsd_resource_edit').remove();
//restore the title:
$j( _this.target_container ).dialog( 'option', 'title', gM('mwe-add_media_wizard'));
js_log("should update: " + b_target + ' with: cancel');
- //restore the buttons:
+ //restore the buttons:
$j(b_target).html( $j.btnHtml( 'Cancel' , 'mv_cancel_rsd', 'close'))
.children('.mv_cancel_rsd')
.btnBind()
.click(function(){
- $j( _this.target_container).dialog('close');
+ $j( _this.target_container).dialog('close');
})
},
js_log('remoteSearchDriver::doMediaEdit: ' + mediaType);
var mvClipInit = {
- 'rObj':rObj, //the resource object
- 'parent_ct' : 'rsd_modal_target',
- 'clip_disp_ct' : 'clip_edit_disp',
- 'control_ct' : 'clip_edit_ctrl',
- 'media_type' : mediaType,
- 'p_rsdObj' : _this,
- 'controlActionsCb' : _this.getClipEditControlActions( cp )
+ 'rObj' : rObj, //the resource object
+ 'parent_ct' : 'rsd_modal_target',
+ 'clip_disp_ct' : 'clip_edit_disp',
+ 'control_ct' : 'clip_edit_ctrl',
+ 'media_type' : mediaType,
+ 'p_rsdObj' : _this,
+ 'controlActionsCb' : _this.getClipEditControlActions( cp )
};
-
+ //set the base clip edit lib class req set:
var clibs = ['mvClipEdit'];
+
if( mediaType == 'image'){
//display the mvClipEdit obj once we are done loading:
mvJsLoader.doLoad( clibs, function(){
$j( _this.target_container ).append('<div id="rsd_resource_import" '+
'class="ui-state-highlight ui-widget-content ui-state-error" ' +
'style="position:absolute;top:50px;left:50px;right:50px;bottom:50px;z-index:5">' +
- '<h3 style="color:red">' + gM('mwe-resource-needs-import', rObj.title) + '</h3>' +
+ '<h3 style="color:red">' + gM('mwe-resource-needs-import', [rObj.title, _this.upload_api_name] ) + '</h3>' +
'<div id="rsd_preview_import_container" style="position:absolute;width:50%;bottom:0px;left:0px;overflow:auto;top:30px;">' +
rObj.pSobj.getEmbedHTML( rObj, {
'id': _this.target_container + '_rsd_pv_vid',
//add hover:
//update video tag (if a video)
- rewrite_by_id( _this.target_container + '_rsd_pv_vid');
+ if( rObj.mime.indexOf('video/') !== -1 )
+ rewrite_by_id( $j(_this.target_container).attr('id') + '_rsd_pv_vid');
//load the preview text:
_this.getParsedWikiText( wt, _this.cFileNS +':'+ rObj.target_resource_title, function( o ){
js_log("do import asset:" + _this.import_url_mode);
//check import mode:
if( _this.import_url_mode == 'api' ){
- _this.doImportAPI( rObj , callback);
+ if( parseUri( document.URL ).host != parseUri( _this.upload_api_target ).host ){
+ _this.setupProxy( function(){
+ debugger;
+ //_this.doImportAPI( rObj , callback);
+ });
+ }else{
+ _this.doImportAPI( rObj , callback);
+ }
}else{
js_log("Error: import mode is not form or API (can not copy asset)");
}
$j(this).remove();
});
});
- },
+ },
+ /**
+ * sets up the proxy for the remote inserts
+ */
+ setupProxy:function(callback){
+ var _this = this;
+
+ if( _this.proxySetupDone ){
+ if(callback) callback();
+ return ;
+ }
+ //setup the the proxy via mv_embed $j.apiProxy loader:
+ if( ! _this.upload_api_proxy_frame ){
+ js_log("Error:: remote api but no proxy frame target");
+ return false;
+ }else{
+ $j.apiProxy(
+ 'client',
+ {
+ 'server_frame' : _this.upload_api_proxy_frame,
+ },function(){
+ //now that the api is setup call actual import
+ debugger;
+ }
+ );
+ }
+ },
checkForFile:function( fName, callback){
js_log("checkForFile::");
var _this = this;
//close the loader now that we are ready to present the progress dialog::
$j.closeLoaderDialog();
-
+
myUp.doHttpUpload({
'url' : rObj.src,
'filename' : rObj.target_resource_title,
var cp = _this.content_providers['this_wiki'];
}else{
var cp = this.content_providers[ this.disp_item ];
- }
+ }
//js_log('getPaging:'+ cp_id + ' len: ' + cp.sObj.num_results);
var to_num = ( cp.limit > cp.sObj.num_results )?
(cp.offset + cp.sObj.num_results):
},
getSearchResults:function(){
//call parent:
- this.parent_getSearchResults();
-
- var _this = this;
- this.loading=true;
+ this.parent_getSearchResults();
+ var _this = this;
js_log('f:getSearchResults for:' + $j('#rsd_q').val() );
//build the query var
var q = $j('#rsd_q').val();
//@@todo check advanced options: include audio and images media types
- //for now force (Ogg video) & a creativecommons license
+ //for now force (Ogg video) & url based license
q+=' format:(Ogg video)';
q+=' licenseurl:(http\\:\\/\\/*)';
var reqObj = {
'q': q, //just search for video atm
'fl':"description,title,identifier,licenseurl,format,license,thumbnail",
'wt':'json',
- 'rows':'30',
- 'indent':'yes'
+ 'rows' : this.cp.limit,
+ 'start' : this.cp.offset
}
do_api_req( {
'data':reqObj,
'pSobj' :_this
};
- this.resultsObj[ resource_id ] = rObj;
-
- //likely a audio clip if no poster and type application/ogg
- //@@todo we should return audio/ogg for the mime type or some other way to specify its "audio"
-
- //this.num_results++;
- //for(var i in this.resultsObj[page_id]){
- // js_log('added: '+ i +' '+ this.resultsObj[page_id][i]);
- //}
+ this.resultsObj[ resource_id ] = rObj;
}
}
},
//default search result values for paging:
offset :0,
- limit :20,
- more_results :false,
- num_results :0,
+ limit : 30,
+ more_results : false,
+ num_results : 0,
//init the object:
init: function( iObj ){
//do global getSearchResults bindings
this.last_query = $j('#rsd_q').val();
this.last_offset = this.cp.offset;
- //@@todo its possible that video rss is the "default" format we could put that logic here:
- },
+ //set the loading flag:
+ this.loading=true;
+ },
/*
* Parses and adds video rss based input format
* @param $data XML data to parse
_this.num_results++;
});
},
+ getEmbedHTML: function( rObj , options) {
+ if(!options)
+ options = {};
+ //set up the output var with the default values:
+ var outOpt = { 'width': rObj.width, 'height': rObj.height};
+ if( options['max_height'] ){
+ outOpt.height = (options.max_height > rObj.height) ? rObj.height : options.max_height;
+ outOpt.width = (rObj.width / rObj.height) *outOpt.height;
+ }
+ options.style_attr = 'style="width:' + outOpt.width + 'px;height:' + outOpt.height +'px"';
+ options.id_attr = (options['id'])?' id = "' + options['id'] +'" ': '';
+
+ if( rObj.mime.indexOf('image') != -1 ){
+ return this.getImageEmbedHTML( rObj, options );
+ }else{
+ js_log("ERROR:: no embed code for mime type: " + rObj.mime);
+ return ' Error missing embed code ';
+ }
+ },
+ getImageEmbedHTML:function( rObj, options ) {
+ //if crop is null do base output:
+ var imgHtml = '<img ' + options.id_attr + ' src="' + rObj.edit_url + '"' + options.style_attr + ' >';
+ if( rObj.crop == null)
+ return imgHtml
+ //else do crop output:
+ return '<div style="width:'+rObj.crop.w +'px;height: ' + rObj.crop.h +'px;overflow:hidden;position:relative">' +
+ '<div style="position:relative;top:-' + rObj.crop.y +'px;left:-' + rObj.crop.x +'px">'+
+ imgHtml +
+ '</div>'+
+ '</div>';
+ },
//by default just return the existing image with callback
getImageObj:function( rObj, size, callback){
callback( {'url':rObj.poster} );
-var flickrOrgSearch = function ( iObj){
+/*
+* basic flickr search uses flickr jsonp api
+* http://www.flickr.com/services/api/
+*
+* uses the "example api_key" 519b66e3fd8d8080e27a64fe51101e2c
+* should update with a difrent "public" key sometime soon
+http://www.flickr.com/services/rest/?method=flickr.test.echo&format=json&api_key=519b66e3fd8d8080e27a64fe51101e2c
+*
+* we look for licenses from method=flickr.photos.licenses.getInfo
+* per http://commons.wikimedia.org/wiki/Special:Upload?uselang=fromflickr
+* we are interested in:
+ (4) Attribution License
+ (5) Attribution-ShareAlike License,
+ (7) No known copyright restrictions,
+ (8) United States Government Work
+*/
+
+var flickrSearch = function ( iObj){
return this.init( iObj );
}
-flickrOrgSearch.prototype = {
+flickrSearch.prototype = {
+ dtUrl : 'http://www.flickr.com/photos/',
+ //@@todo probably would be good to read the api-key from configuration
+ apikey : '2867787a545cc66c0bce6f2e57aca1d1',
+ //what licence we are interested in
+ _licence_keys: '4,5,7,8',
+ _srctypes: ['t','sq','s','m','o'],
+ licenceMap:{
+ '4' : 'http://creativecommons.org/licenses+/by/3.0/',
+ '5' : 'http://creativecommons.org/licenses/by-sa/3.0/',
+ '7' : 'http://www.flickr.com/commons/usage/',
+ '8' : 'http://www.usa.gov/copyright.shtml'
+ },
init:function( iObj ){
//init base class and inherit:
var baseSearch = new baseRemoteSearch( iObj );
}
//inherit the cp settings for
},
- getSearchResults:function(){
- //call parent:
+ getSearchResults:function(){
+ var _this = this;
+ js_log("flickr::getSearchResults");
+ //call parent (sets loading sate and other setup stuff)
this.parent_getSearchResults();
//setup the flickr request:
+ var reqObj = {
+ 'method':'flickr.photos.search',
+ 'format':'json',
+ 'license':this._licence_keys,
+ 'api_key':this.apikey,
+ 'per_page': this.cp.limit,
+ 'page' : this.cp.offset,
+ 'text': $j('#rsd_q').val(),
+ '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'
+ }
+ do_api_req( {
+ 'data': reqObj,
+ 'url':this.cp.api_url,
+ 'jsonCB':'jsoncallback',
+ }, function( data ){
+ _this.addResults( data);
+ _this.loading = false;
+ });
+ },
+ addResults:function( data ){
+ var _this = this;
+ if(data.photos && data.photos.photo){
+ //set result info:
+ this.num_results = data.photos.total;
+ for(var resource_id in data.photos.photo){
+ var resource = data.photos.photo[resource_id];
+
+ var rObj = {
+ 'titleKey' : resource.title + '.jpg',
+ 'resourceKey': resource.id,
+ 'link' : _this.dtUrl + resource.pathalias + '/'+ resource.id,
+ 'title' : resource.title,
+ 'thumbwidth' : resource.width_t,
+ 'thumbheight': resource.height_t,
+ 'desc' : resource.title,
+ //set the license: (rsd is a pointer to the parent remoteSearchDriver )
+ 'license' : this.rsd.getLicenceFromUrl( _this.licenceMap[ resource.license ] ),
+ 'pSobj' : _this,
+ //assume image/jpeg for "photos"
+ 'mime' : 'image/jpeg'
+ };
+ //set all the provided srcs:
+ rObj['srcSet'] = {};
+ for( var i in _this._srctypes){
+ var st = _this._srctypes[i];
+ //if resource has a url add it to the srcSet:
+ if( resource['url_' + st] ){
+ rObj['srcSet'][st] = {
+ 'h': resource['height_' + st],
+ 'w': resource['width_' + st],
+ 'src': resource['url_' + st]
+ }
+ //set src to the largest
+ rObj['src'] = resource['url_' + st];
+ }
+ }
+
+ _this.resultsObj[ resource_id ] = rObj;
+ }
+ }
+ },
+ //return image transform via callback
+ getImageObj:function( rObj, size, callback){
+ if( size.width ){
+ var skey = this.getSrcTypeKey(rObj, size.width )
+ callback ({
+ 'url' : rObj.srcSet[ skey ].src,
+ 'width' : rObj.srcSet[ skey ].w,
+ 'height' : rObj.srcSet[ skey ].h
+ });
+ }
+ },
+ getImageTransform:function(rObj, opt){
+ if( opt.width ){
+ return rObj.srcSet[ this.getSrcTypeKey(rObj, opt.width) ].src;
+ }
+ },
+ getSrcTypeKey:function(rObj, width ){
+ if( width <= 75 ){
+ if( rObj.srcSet['sq'] )
+ return 'sq';
+ }else if( width <= 100 ){
+ if( rObj.srcSet['t'] )
+ return 't';
+ }else if( width <= 240 ){
+ if( rObj.srcSet['s'] )
+ return 's';
+ }else if( width <= 500 ){
+ if( rObj.srcSet['m'] )
+ return 'm';
+ }else{
+ if( rObj.srcSet['o'] )
+ return 'o';
+ }
+ //original was missing return medium or small
+ if( rObj.srcSet['m'] )
+ return 'm';
+ if( rObj.srcSet['s'] )
+ return 's';
+
}
}
\ No newline at end of file
getSearchResults:function(){
//call parent:
this.parent_getSearchResults();
-
+ //set local ref:
var _this = this;
- this.loading = true;
+
js_log('f:getSearchResults for:' + $j('#rsd_q').val() );
//do two queries against the Image / File / MVD namespace:
}
}
}
-
+
//likely a audio clip if no poster and type application/ogg
//@@todo we should return audio/ogg for the mime type or some other way to specify its "audio"
if( ! rObj.poster && rObj.mime == 'application/ogg' ){
if(!cEdit)
var cEdit = _this.cEdit;
},
- getEmbedHTML: function( rObj , options) {
+ getEmbedHTML: function( rObj , options) {
if(!options)
- options = {};
- //set up the output var with the default values:
- var outOpt = { 'width': rObj.width, 'height': rObj.height};
- if( options['max_height'] ){
- outOpt.height = (options.max_height > rObj.height) ? rObj.height : options.max_height;
- outOpt.width = (rObj.width / rObj.height) *outOpt.height;
- }
- var style_attr = 'style="width:' + outOpt.width + 'px;height:' + outOpt.height +'px"';
- var id_attr = (options['id'])?' id = "' + options['id'] +'" ': '';
- var cat = rObj;
- //return the html type:
- if(rObj.mime.indexOf('image')!=-1){
- //if crop is null do base output:
- var imgHtml = '<img ' + id_attr + ' src="' + rObj.edit_url + '"' + style_attr + ' >';
- if( rObj.crop == null)
- return imgHtml
- //else do crop output:
- return '<div style="width:'+rObj.crop.w +'px;height: ' + rObj.crop.h +'px;overflow:hidden;position:relative">' +
- '<div style="position:relative;top:-' + rObj.crop.y +'px;left:-' + rObj.crop.x +'px">'+
- imgHtml +
- '</div>'+
- '</div>';
+ options = {};
+ this.parent_getEmbedHTML( rObj, options);
+ //check for image output:
+ if( rObj.mime.indexOf('image') != -1 ){
+ return this.getImageEmbedHTML( rObj, options );
}
+ //for video and audio output:
var ahtml='';
- if(rObj.mime == 'application/ogg' || rObj.mime == 'audio/ogg'){
- ahtml = id_attr +
+ if( rObj.mime == 'application/ogg' || rObj.mime == 'audio/ogg' ){
+ ahtml = options.id_attr +
' src="' + rObj.src + '" ' +
- style_attr +
+ options.style_attr +
' poster="'+ rObj.poster + '" '
if(rObj.mime.indexOf('application/ogg')!=-1){
return '<video ' + ahtml + '></video>';
return '<audio ' + ahtml + '></audio>';
}
}
- js_log('ERROR:unsupored mime type: ' + rObj.mime);
+ js_log( 'ERROR:unsupored mime type: ' + rObj.mime );
},
getInlineDescWiki:function( rObj ){
var desc = this.parent_getInlineDescWiki( rObj );
+
+ //strip categories for inline Desc: (should strip license tags too but not as easy)
+ desc = desc.replace(/\[\[Category\:[^\]]*\]\]/, '');
+
//just grab the description tag for inline desc:
var descMatch = new RegExp(/Description=(\{\{en\|)?([^|]*|)/);
- var dparts = desc.match(descMatch);
+ var dparts = desc.match(descMatch);
if( dparts && dparts.length > 1){
desc = (dparts.length == 2) ? dparts[1] : dparts[2].replace('}}','');
js_log('Error: No Description Tag, Using::' + desc );
return desc;
},
- parseWikiTemplate: function( text ){
- //@@todo parse wiki Template return object with properties and values
- },
//returns the inline wikitext for insertion (template based crops for now)
getEmbedWikiCode: function( rObj ){
//set default layout to right justified
getSearchResults:function(){
//call parent:
this.parent_getSearchResults();
-
- var _this = this;
- //start loading:
- _this.loading= 1;
+ //set local ref:
+ var _this = this;
js_log('metavidSearch::getSearchResults()');
//proccess all options
var url = this.cp.api_url;
+++ /dev/null
-/*the sequence remote search driver
- extends the base remote search driver with sequence specific stuff
-*/
-
-var seqRemoteSearchDriver = function(iObj){
- return this.init( iObj )
-}
-seqRemoteSearchDriver.prototype = {
- sequence_add_target:false,
- init:function( this_seq ){
- var _this = this;
- js_log("init:seqRemoteSearchDriver");
- //setup remote search driver with a seq parent:
- this.pSeq = this_seq;
- var iObj = {
- 'target_container' : '#cliplib_ic',
- 'local_wiki_api_url': this_seq.getLocalApiUrl(),
- 'instance_name' : this_seq.instance_name + '.mySearch',
- 'default_query' : this.pSeq.plObj.title
- }
- if(typeof this_seq.amw_conf != 'undefined')
- $j.extend(iObj, this_seq.amw_conf);
- //inherit the remoteSearchDriver properties:n
- var tmpRSD = new remoteSearchDriver( iObj );
- for(var i in tmpRSD){
- if(this[i]){
- this['parent_'+i] = tmpRSD[i];
- }else{
- this[i] = tmpRSD[i];
- }
- }
- //extend parent_do_refresh_timeline actions:
- if(!this.pSeq.parent_do_refresh_timeline){
- this.pSeq.parent_do_refresh_timeline = this.pSeq.do_refresh_timeline;
- this.pSeq.do_refresh_timeline = function(){
- js_log("seqRemoteSearchDriver::" + _this.pSeq.disp_menu_item);
- //call the parent
- _this.pSeq.parent_do_refresh_timeline();
- //add our local bindings
- _this.addResultBindings();
- return true;
- }
- }
- },
- resourceEdit:function(){
- var _this = this;
-
- },
- addResultBindings:function(){
- //set up seq:
- var _this = this;
- //setup parent bindings:
- this.parent_addResultBindings();
-
- //add an aditional click binding
- $j('.rsd_res_item').click(function(){
- js_log('SeqRemoteSearch: rsd_res_item: click (remove sequence_add_target)');
- _this.sequence_add_target =false;
- });
-
- //add an additional drag binding
- $j( '.rsd_res_item' ).draggable('destroy').draggable({
- helper:function(){
- return $j( this ).clone().appendTo('body').css({'z-index':9999}).get(0);
- },
- revert:'invalid',
- start:function(){
- js_log('start drag');
- }
- });
- $j(".mv_clip_drag").droppable( 'destroy' ).droppable({
- accept: '.rsd_res_item',
- over:function(event, ui){
- //js_log("over : mv_clip_drag: " + $j(this).attr('id') );
- $j(this).css('border-right', 'solid thick red');
- },
- out:function(event, ui){
- $j(this).css('border-right', 'solid thin white');
- },
- drop: function(event, ui) {
- $j(this).css('border-right', 'solid thin white');
- js_log("Droped: "+ $j(ui.draggable).attr('id') +' on ' + $j(this).attr('id') );
- _this.sequence_add_target = $j(this).attr('id');
- //load the orginal draged item
- var rObj = _this.getResourceFromId( $j(ui.draggable).attr('id') );
- _this.resourceEdit(rObj, ui.draggable);
- }
- });
-
- },
- insertResource:function(rObj){
- var _this = this;
- js_log("SEQ insert resource after:" + _this.sequence_add_target + ' of type: ' + rObj.mime);
- if(_this.sequence_add_target ){
- var tClip = _this.pSeq.getClipFromSeqID( _this.sequence_add_target );
- var target_order = false;
- if(tClip)
- var target_order = tClip.order;
- }
- //@@todo show wating of sorts.
-
- //get target order:
- var cat = rObj;
- //check for target insert path
- this.checkImportResource( rObj, function(){
-
- var clipConfig = {
- 'type' : rObj.mime,
- 'uri' : _this.cFileNS + ':' + rObj.target_resource_title,
- 'title' : rObj.title
- };
- //set via local properites if avaliable
- clipConfig['src'] = (rObj.local_src) ? rObj.local_src : rObj.src;
- clipConfig['poster'] = ( rObj.local_poster ) ? rObj.local_poster : rObj.poster;
-
- if(rObj.start_time && rObj.end_time){
- clipConfig['dur'] = npt2seconds( rObj.end_time ) - npt2seconds( rObj.start_time );
- }else{
- //provide a default duration if none set
- clipConfig['dur'] = 4;
- }
-
- //create the media element (target order+1 (since we insert (after)
- _this.pSeq.plObj.tryAddMediaObj( clipConfig, (parseInt(target_order) + 1) );
- //refresh the timeline:
- _this.pSeq.do_refresh_timeline();
- js_log("run close all: ");
- _this.closeAll();
- });
- },
- getClipEditControlActions:function(){
- var _this = this;
- return {
- 'insert_seq':function(rObj){
- _this.insertResource( rObj )
- },
- 'cancel':function(rObj){
- _this.cancelClipEditCB( rObj )
- }
- };
- },
- resourceEdit:function(rObj, rsdElement){
- var _this = this;
- //don't resize to default (full screen behavior)
- _this.dmodalCss = {};
- //open up a new target_contaienr:
- if($j('#seq_resource_import').length == 0)
- $j('body').append('<div id="seq_resource_import" style="position:relative"></div>');
-
- $j('#seq_resource_import').dialog('destroy').dialog({
- bgiframe: true,
- width:750,
- height:480,
- modal: true,
- buttons: {
- "Cancel": function() {
- $j(this).dialog("close");
- }
- }
- });
- _this.target_container = '#seq_resource_import';
- //do parent resource edit (with updated target)
- this.parent_resourceEdit(rObj, rsdElement);
- },
- closeAll:function(){
- js_log( 'should close: seq_resource_import');
- $j('#seq_resource_import').dialog('close').dialog('destroy').remove();
- this.parent_closeAll();
- },
- getEditToken:function(callback){
- if(this.pSeq.sequenceEditToken){
- callback( this.pSeq.sequenceEditToken )
- }else{
- this.parent_getEditToken(callback);
- }
- },
- cancelClipEditCB:function(){
- js_log('seqRSD:cancelClipEditCB');
- $j('#seq_resource_import').dialog('close').dialog('destroy').remove();
- }
-};
//continue with the other attr:
eb+= 'oncanplaythrough="$j(\'#'+this.id+'\').get(0).oncanplaythrough();return false;" ' +
- 'onloadedmetadata="$j(\'#'+this.id+'\').get(0).onloadedmetadata();return false;" ' +
- 'loadedmetadata="$j(\'#'+this.id+'\').get(0).onloadedmetadata();return false;" ' +
- 'onprogress="$j(\'#'+this.id+'\').get(0).onprogress( event );return false;" '+
- 'onended="$j(\'#'+this.id+'\').get(0).onended();return false;" '+
- 'onseeking="$j(\'#'+this.id+'\').get(0).onseeking();" ' +
- 'onseeked="$j(\'#'+this.id+'\').get(0).onseeked();" ' +
- '>' +
+ 'onloadedmetadata="$j(\'#'+this.id+'\').get(0).onloadedmetadata();return false;" ' +
+ 'loadedmetadata="$j(\'#'+this.id+'\').get(0).onloadedmetadata();return false;" ' +
+ 'onprogress="$j(\'#'+this.id+'\').get(0).onprogress( event );return false;" '+
+ 'onended="$j(\'#'+this.id+'\').get(0).onended();return false;" '+
+ 'onseeking="$j(\'#'+this.id+'\').get(0).onseeking();" ' +
+ 'onseeked="$j(\'#'+this.id+'\').get(0).onseeked();" >' +
'</video>';
return eb;
},
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>Simple nested iframe callback page</title>
+<script type="text/javascript">
+window.onload = function (){
+ //call the nested callback in top most frame:
+ top.$mw.proxy.nested( window.location.href.split("#")[1] || false );
+}
+</script>
+</head>
+<body>
+Nested Iframe callback
+</body>
+</html>
\ No newline at end of file
--- /dev/null
+/*
+ http://www.JSON.org/json2.js
+ 2009-09-29
+
+ Public Domain.
+
+ NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+
+ See http://www.JSON.org/js.html
+
+ This file creates a global JSON object containing two methods: stringify
+ and parse.
+
+ JSON.stringify(value, replacer, space)
+ value any JavaScript value, usually an object or array.
+
+ replacer an optional parameter that determines how object
+ values are stringified for objects. It can be a
+ function or an array of strings.
+
+ space an optional parameter that specifies the indentation
+ of nested structures. If it is omitted, the text will
+ be packed without extra whitespace. If it is a number,
+ it will specify the number of spaces to indent at each
+ level. If it is a string (such as '\t' or ' '),
+ it contains the characters used to indent at each level.
+
+ This method produces a JSON text from a JavaScript value.
+
+ When an object value is found, if the object contains a toJSON
+ method, its toJSON method will be called and the result will be
+ stringified. A toJSON method does not serialize: it returns the
+ value represented by the name/value pair that should be serialized,
+ or undefined if nothing should be serialized. The toJSON method
+ will be passed the key associated with the value, and this will be
+ bound to the value
+
+ For example, this would serialize Dates as ISO strings.
+
+ Date.prototype.toJSON = function (key) {
+ function f(n) {
+ // Format integers to have at least two digits.
+ return n < 10 ? '0' + n : n;
+ }
+
+ return this.getUTCFullYear() + '-' +
+ f(this.getUTCMonth() + 1) + '-' +
+ f(this.getUTCDate()) + 'T' +
+ f(this.getUTCHours()) + ':' +
+ f(this.getUTCMinutes()) + ':' +
+ f(this.getUTCSeconds()) + 'Z';
+ };
+
+ You can provide an optional replacer method. It will be passed the
+ key and value of each member, with this bound to the containing
+ object. The value that is returned from your method will be
+ serialized. If your method returns undefined, then the member will
+ be excluded from the serialization.
+
+ If the replacer parameter is an array of strings, then it will be
+ used to select the members to be serialized. It filters the results
+ such that only members with keys listed in the replacer array are
+ stringified.
+
+ Values that do not have JSON representations, such as undefined or
+ functions, will not be serialized. Such values in objects will be
+ dropped; in arrays they will be replaced with null. You can use
+ a replacer function to replace those with JSON values.
+ JSON.stringify(undefined) returns undefined.
+
+ The optional space parameter produces a stringification of the
+ value that is filled with line breaks and indentation to make it
+ easier to read.
+
+ If the space parameter is a non-empty string, then that string will
+ be used for indentation. If the space parameter is a number, then
+ the indentation will be that many spaces.
+
+ Example:
+
+ text = JSON.stringify(['e', {pluribus: 'unum'}]);
+ // text is '["e",{"pluribus":"unum"}]'
+
+
+ text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
+ // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
+
+ text = JSON.stringify([new Date()], function (key, value) {
+ return this[key] instanceof Date ?
+ 'Date(' + this[key] + ')' : value;
+ });
+ // text is '["Date(---current time---)"]'
+
+
+ JSON.parse(text, reviver)
+ This method parses a JSON text to produce an object or array.
+ It can throw a SyntaxError exception.
+
+ The optional reviver parameter is a function that can filter and
+ transform the results. It receives each of the keys and values,
+ and its return value is used instead of the original value.
+ If it returns what it received, then the structure is not modified.
+ If it returns undefined then the member is deleted.
+
+ Example:
+
+ // Parse the text. Values that look like ISO date strings will
+ // be converted to Date objects.
+
+ myData = JSON.parse(text, function (key, value) {
+ var a;
+ if (typeof value === 'string') {
+ a =
+/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
+ if (a) {
+ return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
+ +a[5], +a[6]));
+ }
+ }
+ return value;
+ });
+
+ myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
+ var d;
+ if (typeof value === 'string' &&
+ value.slice(0, 5) === 'Date(' &&
+ value.slice(-1) === ')') {
+ d = new Date(value.slice(5, -1));
+ if (d) {
+ return d;
+ }
+ }
+ return value;
+ });
+
+
+ This is a reference implementation. You are free to copy, modify, or
+ redistribute.
+
+ This code should be minified before deployment.
+ See http://javascript.crockford.com/jsmin.html
+
+ USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
+ NOT CONTROL.
+*/
+
+/*jslint evil: true, strict: false */
+
+/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
+ call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
+ getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
+ lastIndex, length, parse, prototype, push, replace, slice, stringify,
+ test, toJSON, toString, valueOf
+*/
+
+
+// Create a JSON object only if one does not already exist. We create the
+// methods in a closure to avoid creating global variables.
+
+if (!this.JSON) {
+ this.JSON = {};
+}
+
+(function () {
+
+ function f(n) {
+ // Format integers to have at least two digits.
+ return n < 10 ? '0' + n : n;
+ }
+
+ if (typeof Date.prototype.toJSON !== 'function') {
+
+ Date.prototype.toJSON = function (key) {
+
+ return isFinite(this.valueOf()) ?
+ this.getUTCFullYear() + '-' +
+ f(this.getUTCMonth() + 1) + '-' +
+ f(this.getUTCDate()) + 'T' +
+ f(this.getUTCHours()) + ':' +
+ f(this.getUTCMinutes()) + ':' +
+ f(this.getUTCSeconds()) + 'Z' : null;
+ };
+
+ String.prototype.toJSON =
+ Number.prototype.toJSON =
+ Boolean.prototype.toJSON = function (key) {
+ return this.valueOf();
+ };
+ }
+
+ var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
+ escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
+ gap,
+ indent,
+ meta = { // table of character substitutions
+ '\b': '\\b',
+ '\t': '\\t',
+ '\n': '\\n',
+ '\f': '\\f',
+ '\r': '\\r',
+ '"' : '\\"',
+ '\\': '\\\\'
+ },
+ rep;
+
+
+ function quote(string) {
+
+// If the string contains no control characters, no quote characters, and no
+// backslash characters, then we can safely slap some quotes around it.
+// Otherwise we must also replace the offending characters with safe escape
+// sequences.
+
+ escapable.lastIndex = 0;
+ return escapable.test(string) ?
+ '"' + string.replace(escapable, function (a) {
+ var c = meta[a];
+ return typeof c === 'string' ? c :
+ '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
+ }) + '"' :
+ '"' + string + '"';
+ }
+
+
+ function str(key, holder) {
+
+// Produce a string from holder[key].
+
+ var i, // The loop counter.
+ k, // The member key.
+ v, // The member value.
+ length,
+ mind = gap,
+ partial,
+ value = holder[key];
+
+// If the value has a toJSON method, call it to obtain a replacement value.
+
+ if (value && typeof value === 'object' &&
+ typeof value.toJSON === 'function') {
+ value = value.toJSON(key);
+ }
+
+// If we were called with a replacer function, then call the replacer to
+// obtain a replacement value.
+
+ if (typeof rep === 'function') {
+ value = rep.call(holder, key, value);
+ }
+
+// What happens next depends on the value's type.
+
+ switch (typeof value) {
+ case 'string':
+ return quote(value);
+
+ case 'number':
+
+// JSON numbers must be finite. Encode non-finite numbers as null.
+
+ return isFinite(value) ? String(value) : 'null';
+
+ case 'boolean':
+ case 'null':
+
+// If the value is a boolean or null, convert it to a string. Note:
+// typeof null does not produce 'null'. The case is included here in
+// the remote chance that this gets fixed someday.
+
+ return String(value);
+
+// If the type is 'object', we might be dealing with an object or an array or
+// null.
+
+ case 'object':
+
+// Due to a specification blunder in ECMAScript, typeof null is 'object',
+// so watch out for that case.
+
+ if (!value) {
+ return 'null';
+ }
+
+// Make an array to hold the partial results of stringifying this object value.
+
+ gap += indent;
+ partial = [];
+
+// Is the value an array?
+
+ if (Object.prototype.toString.apply(value) === '[object Array]') {
+
+// The value is an array. Stringify every element. Use null as a placeholder
+// for non-JSON values.
+
+ length = value.length;
+ for (i = 0; i < length; i += 1) {
+ partial[i] = str(i, value) || 'null';
+ }
+
+// Join all of the elements together, separated with commas, and wrap them in
+// brackets.
+
+ v = partial.length === 0 ? '[]' :
+ gap ? '[\n' + gap +
+ partial.join(',\n' + gap) + '\n' +
+ mind + ']' :
+ '[' + partial.join(',') + ']';
+ gap = mind;
+ return v;
+ }
+
+// If the replacer is an array, use it to select the members to be stringified.
+
+ if (rep && typeof rep === 'object') {
+ length = rep.length;
+ for (i = 0; i < length; i += 1) {
+ k = rep[i];
+ if (typeof k === 'string') {
+ v = str(k, value);
+ if (v) {
+ partial.push(quote(k) + (gap ? ': ' : ':') + v);
+ }
+ }
+ }
+ } else {
+
+// Otherwise, iterate through all of the keys in the object.
+
+ for (k in value) {
+ if (Object.hasOwnProperty.call(value, k)) {
+ v = str(k, value);
+ if (v) {
+ partial.push(quote(k) + (gap ? ': ' : ':') + v);
+ }
+ }
+ }
+ }
+
+// Join all of the member texts together, separated with commas,
+// and wrap them in braces.
+
+ v = partial.length === 0 ? '{}' :
+ gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' +
+ mind + '}' : '{' + partial.join(',') + '}';
+ gap = mind;
+ return v;
+ }
+ }
+
+// If the JSON object does not yet have a stringify method, give it one.
+
+ if (typeof JSON.stringify !== 'function') {
+ JSON.stringify = function (value, replacer, space) {
+
+// The stringify method takes a value and an optional replacer, and an optional
+// space parameter, and returns a JSON text. The replacer can be a function
+// that can replace values, or an array of strings that will select the keys.
+// A default replacer method can be provided. Use of the space parameter can
+// produce text that is more easily readable.
+
+ var i;
+ gap = '';
+ indent = '';
+
+// If the space parameter is a number, make an indent string containing that
+// many spaces.
+
+ if (typeof space === 'number') {
+ for (i = 0; i < space; i += 1) {
+ indent += ' ';
+ }
+
+// If the space parameter is a string, it will be used as the indent string.
+
+ } else if (typeof space === 'string') {
+ indent = space;
+ }
+
+// If there is a replacer, it must be a function or an array.
+// Otherwise, throw an error.
+
+ rep = replacer;
+ if (replacer && typeof replacer !== 'function' &&
+ (typeof replacer !== 'object' ||
+ typeof replacer.length !== 'number')) {
+ throw new Error('JSON.stringify');
+ }
+
+// Make a fake root object containing our value under the key of ''.
+// Return the result of stringifying the value.
+
+ return str('', {'': value});
+ };
+ }
+
+
+// If the JSON object does not yet have a parse method, give it one.
+
+ if (typeof JSON.parse !== 'function') {
+ JSON.parse = function (text, reviver) {
+
+// The parse method takes a text and an optional reviver function, and returns
+// a JavaScript value if the text is a valid JSON text.
+
+ var j;
+
+ function walk(holder, key) {
+
+// The walk method is used to recursively walk the resulting structure so
+// that modifications can be made.
+
+ var k, v, value = holder[key];
+ if (value && typeof value === 'object') {
+ for (k in value) {
+ if (Object.hasOwnProperty.call(value, k)) {
+ v = walk(value, k);
+ if (v !== undefined) {
+ value[k] = v;
+ } else {
+ delete value[k];
+ }
+ }
+ }
+ }
+ return reviver.call(holder, key, value);
+ }
+
+
+// Parsing happens in four stages. In the first stage, we replace certain
+// Unicode characters with escape sequences. JavaScript handles many characters
+// incorrectly, either silently deleting them, or treating them as line endings.
+
+ cx.lastIndex = 0;
+ if (cx.test(text)) {
+ text = text.replace(cx, function (a) {
+ return '\\u' +
+ ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
+ });
+ }
+
+// In the second stage, we run the text against regular expressions that look
+// for non-JSON patterns. We are especially concerned with '()' and 'new'
+// because they can cause invocation, and '=' because it can cause mutation.
+// But just to be safe, we want to reject all unexpected forms.
+
+// We split the second stage into 4 regexp operations in order to work around
+// crippling inefficiencies in IE's and Safari's regexp engines. First we
+// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
+// replace all simple value tokens with ']' characters. Third, we delete all
+// open brackets that follow a colon or comma or that begin the text. Finally,
+// we look to see that the remaining characters are only whitespace or ']' or
+// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
+
+ if (/^[\],:{}\s]*$/.
+test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@').
+replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
+replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
+
+// In the third stage we use the eval function to compile the text into a
+// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
+// in JavaScript: it can begin a block or an object literal. We wrap the text
+// in parens to eliminate the ambiguity.
+
+ j = eval('(' + text + ')');
+
+// In the optional fourth stage, we recursively walk the new structure, passing
+// each name/value pair to a reviver function for possible transformation.
+
+ return typeof reviver === 'function' ?
+ walk({'': j}, '') : j;
+ }
+
+// If the text is not JSON parseable, then a SyntaxError is thrown.
+
+ throw new SyntaxError('JSON.parse');
+ };
+ }
+}());
--- /dev/null
+/*
+*
+* Api proxy system
+*
+* Built to support cross domain uploading, and api actions for a approved set of domains.
+* mwProxy enables a system for fluid contributions across wikis domains for which your logged in.
+*
+* The framework support a request approval system for per-user domain approval
+* and a central blacklisting of domains controlled by site or system administrators.
+*
+* Flow outline below:
+*
+* Domain A (lets say en.wiki)
+* invokes add-media-wizard and wants to upload to domain B ( commons.wiki )
+*
+* Domain A loads iframe to domain B ? with request param to to insert from Domain A
+* Domain B checks list of approved domains for (Domain A) & checks the user is logged in ( and if the same account name )
+* if user is not logged in
+* a _link_ to Domain B to new window login page is given
+* if user has not approved domain and (Domain A) is not pre-approved
+* a new page link is generated with a approve domain request
+* if user approves domain it goes into their User:{username}/apiProxyDomains.js config
+* If Domain A is approved we then:
+* loads a "push" and "pull" iframe back to Domain A
+ (Domain B can change the #hash values of these children thereby proxy the data)
+* Domain A now gets the iframe "loaded" callback a does a initial echo to confirm cross domain proxy
+* echo sends "echo" to push and (Domain A) js passes the echo onto the "pull"
+* Domain A now sends api requests to the iframe "push" child and gets results from the iframe "pull"
+* api actions happen with status updates and everything and we can reuse existing api interface code
+*
+* if the browser supports it we can pass msgs with the postMessage API
+* http://ejohn.org/blog/cross-window-messaging/
+*
+* @@todo it would be nice if this supported multiple proxy targets (ie to a bright widgets future)
+*
+*/
+
+loadGM({
+ "mwe-setting-up-proxy": "Setting up proxy"
+});
+
+(function( $ ) {
+ /**
+ * Base API Proxy object
+ *
+ */
+ $.proxy = {};
+
+ /**
+ * The clientApiProxy handles a request to external server
+ *
+ * This is (Domain A) in the above described setup
+ */
+ $.proxy.client = function( pConf, callback ){
+ var _this = this;
+ //do setup:
+ if( pConf.server_frame )
+ $.proxy.server_frame = pConf.server_frame;
+
+ if( pConf.client_frame_path )
+ $.proxy.client_frame_path = pConf.client_frame_path;
+
+ //setup a dialog to manage proxy setup:
+ $j.addLoaderDialog( gM('mwe-setting-up-proxy') );
+
+ if( parseUri( $.proxy.server_frame).host == parseUri( document.URL ).host ){
+ js_log("Error: why are you trying to proxy yourself? " );
+ return false;
+ }
+ //add an iframe to domain B with request for proxy just do the setup
+ $.proxy.doFrameProxy( { 'init' : 'echo' } );
+
+ //if we have a setup callback
+ $.proxy.callback = callback;
+ }
+ /* setup a iframe request hash */
+ $.proxy.doFrameProxy = function( reqObj ){
+ var hashPack = {
+ 'cd': parseUri( document.URL ).host,
+ 'cfp': $.proxy.client_frame_path,
+ 'req': reqObj
+ }
+ js_log( "Do frame proxy request on src: \n" + $.proxy.server_frame + "\n" +
+ JSON.stringify( reqObj ) );
+ //we can't update src's so we have to remove and add all the time :(
+ //@@todo we should support frame msg system
+ $j('#frame_proxy').remove();
+ $j('body').append('<iframe id="frame_proxy" name="frame_proxy" ' +
+ 'src="' + $.proxy.server_frame +
+ '#' + escape( JSON.stringify( hashPack ) ) +
+ '"></iframe>' );
+ }
+
+ /* the do_api_request with callback: */
+ $.proxy.doRequest = function( reqObj, callback){
+ js_log("doRequest:: " + JSON.stringify( reqObj ) );
+ //setup the callback:
+ $.proxy.callback = callback;
+ //do the proxy req:
+ $.proxy.doFrameProxy( reqObj );
+ }
+ /**
+ * The nested iframe action that passes its msg back up to the top instance
+ */
+ $.proxy.nested = function( hashResult ){
+ js_log( 'got $.proxy.nested callback!! :: ' + hashResult );
+ //try to parse the hash result:
+ try{
+ var rObj = JSON.parse( unescape( hashResult ) );
+ }catch (e) {
+ js_log("Error could not parse hashResult");
+ }
+ //hide the loader if the initial state = ready msg is fired:
+ if( rObj && rObj.state == 'ready')
+ $j.closeLoaderDialog();
+ //if all good pass it to the callback:
+ $.proxy.callback( rObj );
+ }
+ /**
+ * The serverApiProxy handles the actual proxy
+ * and child frames pointing to the parent "blank" frames
+ *
+ * This is (Domain B) in the above described setup
+ */
+ $.proxy.server = function( pConf, callback){
+ /* clear the body of any html */
+ $j('body').html( 'proxy setup' );
+
+ //read the anchor action from the requesting url
+ var jmsg = unescape( parseUri( document.URL ).anchor );
+ try{
+ var aObj = JSON.parse( jmsg );
+ }catch ( e ){
+ js_log("ProxyServer:: could not parse anchor");
+ }
+ if( !aObj.cd ){
+ js_log("Error: no client domain provided ");
+ return false;
+ }
+
+ js_log("Setup server on: " + parseUri( document.URL ).host +
+ ' client from: ' + aObj.cd +
+ ' to nested target: ' + aObj.cfp );
+
+ // make sure we are logged in
+ // (its a normal mediaWiki page so all site vars should be defined)
+ if( !wgUserName ){
+ js_log('error Not logged in');
+ return false;
+ }
+
+ var domain = parseUri( document.URL ).host;
+ var nested_frame_src = 'http://' + aObj.cd + aObj.cfp;
+ //check the master whitelist
+ for(var i in pConf.master_whitelist){
+ if( domain == pConf.master_whitelist[ i ] ){
+ //do the request:
+ return doNestedProxy( aObj.req );
+ }
+ }
+ //check master blacklist
+ for(var i in pConf.master_blacklist ){
+ if( domain == pConf.master_blacklist ){
+ js_log('domain: ' + domain + ' is blacklisted');
+ return false;
+ }
+ }
+ //@@todo grab the users whitelist for our current domain
+ /*var local_api = wgScriptPath + '/index' + wgScriptExtension + '?title=' +
+ 'User:' + wgUserName + '/apiProxyDomainList.js' +
+ '&action=raw&smaxage=0&gen=js';
+ $j.get( local_api, function( data ){
+ debugger;
+ });*/
+
+ //if still not found:
+ js_log("domain " + domain + " not approved");
+
+ function doNestedProxy( reqObj ){
+ js_log("doNestedProxy to: " + nested_frame_src);
+ var outputhash = escape( JSON.stringify( reqObj ) );
+ //check if its just a "echo" request (no need to hit the api)
+ if( reqObj.init && reqObj.init == 'echo'){
+ doNestedFrame( {'state': 'ready', "echo": true } );
+ }else{
+ //add some api stuff:
+ reqObj['format'] = 'json';
+ //process the api request
+ $j.get(wgScriptPath + '/api' + wgScriptExtension,
+ reqObj,
+ function( data ){
+ js_log("Proxy GOT Res: " + data );
+ //put it into the nested frame hash string:
+ doNestedFrame( JSON.parse( data ) );
+ }
+ );
+ }
+ }
+ //add the doNestedFrame iframe:
+ function doNestedFrame( resultObj ){
+ $j('#nested_push').remove();
+ //setup the nested proxy that points back to top domain:
+ $j('body').append( '<iframe id="nested_push" name="nested_push" ' +
+ 'src="'+ nested_frame_src +
+ '#' + escape( JSON.stringify( resultObj ) ) +
+ '"></iframe>' );
+ }
+ }
+
+})(window.$mw);
--- /dev/null
+
+var mwApiClientProxy = function(iObj){
+ return this.init( iObj );
+}
+mwApiClientProxy.prototype = {
+ init:function( iObj ){
+
+ },
+ //Gets the apiResult callback
+ mwApiProxy:resultCb( apiResult ){
+
+ }
+}
+
+var mwApiServerProxy = function(iObj){
+ return this.init(
+}
\ No newline at end of file
var mv_embed_path = getMvEmbedPath();
}
/**
-* wrap the global $mw object here:
+* The global $mw object:
*
* Any global functions/classes that are not jQuery plugins should make
* there way into the $mw namespace
//@@todo we need a formatNum and we need to request some special packaged info to deal with that case.
return gM( msg , size );
};
-
-
+
+
+
/**
* MediaWiki wikitext "Parser"
*
this.pOut = '';
},
parse : function(){
- this.pObj = {};
- this.pObj.tmpl = new Array();
-
- //refrences for swap key
- this.pObj.tmpl_text = new Array();
- this.pObj.tmpl_key = new Array();
- this.pObj.tmpl_ns = '' ; // wikiText with place-holder
-
- //get templates losly based on Magnus_Manske/tmpl.js code:
- var tcnt = 0 ;
- var ts = '' ;
- var curt = 0 ;
- var schar = 0;
-
-
- //build out nested template holders:
- var depth = 0;
- var tKey = 0;
- var ns = '';
-
/*
- * quickly recursive / parse out templates with top down recurse decent
+ * quickly recursive / parse out templates:
*/
// ~ probably a better algorithm out there / should mirror php parser flow ~
// ... but I am having fun with recursion so here it is...
- function rdpp ( txt ){
+ // or at least mirror: http://www.mediawiki.org/wiki/Extension:Page_Object_Model
+ function rdpp ( txt , cn){
var node = {};
- //if we should output node text
- var ont = true;
//inspect each char
for(var a=0; a < txt.length; a++){
if( txt[a] == '{' && txt[a+1] == '{' ){
if(!node['c'])
node['c'] = new Array();
- node['c'].push( rdpp( txt.substr( a ) ) );
- ont=true;
+ node['c'].push( rdpp( txt.substr( a ), true ) );
}else if( txt[a] == '}' && txt[a+1] == '}'){
if( !node['p'] ){
return node;
}
node = node['p'];
- ont=false;
a=a+2;
}
if(!node['t'])
node['t']='';
-
+
if( txt[a] )
node['t']+=txt[a];
+
}
return node;
}
tObj["arg"] = tname.split(':').pop();
}
- js_log("TNAME::" + tObj["arg"] + ' from:: ' + ts);
-
+ js_log("TNAME::" + tObj["name"] + ' from:: ' + ts);
+
var pSet = ts.split('\|');
pSet.splice(0,1);
if( pSet.length ){
return getMagicTxtFromTempNode( node );
}
}
- //get text node system:
- var node = rdpp ( this.wikiText );
- //debugger;
- //parse out stuff:
-
- this.pOut = recurse_magic_swap( node);
+ //parse out the template node structure:
+ this.pNode = rdpp ( this.wikiText );
+ //strip out the parent from the root
+ this.pNode['p'] = null;
+
+ //do the recusrive magic swap text:
+ this.pOut = recurse_magic_swap( this.pNode );
},
+
+ /*
+ * parsed template api ~losely based off of ~POM~
+ * http://www.mediawiki.org/wiki/Extension:Page_Object_Model
+ */
+
+ /**
+ * templates
+ *
+ * gets a requested template from the wikitext (if available)
+ *
+ */
+ templates: function( tname ){
+ this.parse();
+ var tmplSet = new Array();
+ function getMatchingTmpl( node ){
+ if( node['c'] ){
+ for(var i in node['c']){
+ getMatchingTmpl( node['c'] );
+ }
+ }
+ if( tname && node.tObj){
+ if( node.tObj['name'] == tname )
+ tmplSet.push( node.tObj );
+ }else if( node.tObj ){
+ tmplSet.push( node.tObj );
+ }
+ }
+ getMatchingTmpl( this.pNode );
+ return tmplSet;
+ },
/**
* Returns the transformed wikitext
- *
- * Build output from swapable index
- * (all transforms must be expanded in parse stage and linerarly rebuilt)
- * Alternativly we could build output using a placeholder & replace system
+ *
+ * Build output from swapable index
+ * (all transforms must be expanded in parse stage and linerarly rebuilt)
+ * Alternativly we could build output using a placeholder & replace system
* (this lets us be slightly more slopty with ordering and indexes, but probably slower)
- *
- * Ideal: we build a 'wiki DOM'
+ *
+ * Ideal: we build a 'wiki DOM'
* When editing you update the data structure directly
- * Then in output time you just go DOM->html-ish output without re-parsing anything
+ * Then in output time you just go DOM->html-ish output without re-parsing anything
*/
getHTML : function(){
//wikiText updates should invalidate pOut
//return the parserObj
return new parseObj( wikiText, opt) ;
}
-
+
})(window.$mw);
+
//setup legacy global shortcuts:
var loadGM = $mw.lang.loadGM;
var loadRS = $mw.lang.loadRS;
"mwe-size-kilobytes" : "$1 K",
"mwe-size-bytes" : "$1 B",
"mwe-error_load_lib" : "Error: JavaScript $1 was not retrievable or does not define $2",
- "mwe-loading-add-media-wiz": "Loading add media wizard"
+ "mwe-loading-add-media-wiz": "Loading add media wizard",
+ "mwe-apiproxy-setup" : " Setting up API proxy"
});
* This is used by the script loader to auto-load classes (so we only define
* this once for PHP & JavaScript)
*
- * This is more verbose than the earlier version that compressed paths
- * but it's all good, gzipping helps compress path strings
- * grouped by directory.
- *
* Right now the PHP AutoLoader only reads this mv_embed.js file.
* In the future we could have multiple lcPath calls that PHP reads
* (if our autoloading class list becomes too long) just have to add those
"$j.ui" : "jquery/jquery.ui/ui/ui.core.js",
"$j.fn.ColorPicker" : "libClipEdit/colorpicker/js/colorpicker.js",
"$j.Jcrop" : "libClipEdit/Jcrop/js/jquery.Jcrop.js",
- "$j.fn.simpleUploadForm": "libAddMedia/simpleUploadForm.js",
-
+ "$j.fn.simpleUploadForm" : "libAddMedia/simpleUploadForm.js",
+
+ "$mw.proxy" : "libMwApi/mw.proxy.js",
+
"ctrlBuilder" : "skins/ctrlBuilder.js",
"kskinConfig" : "skins/kskin/kskin.js",
"mvpcfConfig" : "skins/mvpcf/mvpcf.js",
- "$j.secureEvalJSON" : "jquery/plugins/jquery.secureEvalJSON.js",
+ "JSON" : "libMwApi/json2.js",
"$j.cookie" : "jquery/plugins/jquery.cookie.js",
"$j.contextMenu" : "jquery/plugins/jquery.contextMenu.js",
"$j.fn.suggestions" : "jquery/plugins/jquery.suggestions.js",
"mvAdvFirefogg" : "libAddMedia/mvAdvFirefogg.js",
"mvBaseUploadInterface" : "libAddMedia/mvBaseUploadInterface.js",
"remoteSearchDriver" : "libAddMedia/remoteSearchDriver.js",
- "seqRemoteSearchDriver" : "libAddMedia/seqRemoteSearchDriver.js",
+ "seqRemoteSearchDriver" : "libSequencer/seqRemoteSearchDriver.js",
"baseRemoteSearch" : "libAddMedia/searchLibs/baseRemoteSearch.js",
"mediaWikiSearch" : "libAddMedia/searchLibs/mediaWikiSearch.js",
"metavidSearch" : "libAddMedia/searchLibs/metavidSearch.js",
"archiveOrgSearch" : "libAddMedia/searchLibs/archiveOrgSearch.js",
+ "flickrSearch" : "libAddMedia/searchLibs/flickrSearch.js",
"baseRemoteSearch" : "libAddMedia/searchLibs/baseRemoteSearch.js",
"mvClipEdit" : "libClipEdit/mvClipEdit.js",
* mvJsLoader class handles initialization and js file loads
*/
-// Shortcut
-function mwLoad( loadSet, callback ) {
- mvJsLoader.doLoad( loadSet, callback );
-}
var mvJsLoader = {
libreq : {},
libs : {},
}
}
+// Shortcut ( @@todo consolidate shortcuts & re-factor mvJsLoader )
+function mwLoad( loadSet, callback ) {
+ mvJsLoader.doLoad( loadSet, callback );
+}
+//$mw.shortcut
+$mw.load = mwLoad;
+
// Load an external JS file. Similar to jquery .require plugin,
// but checks for object availability rather than load state.
/*
* Store all the mwEmbed jQuery-specific bindings
* (set up after jQuery is available).
- * This lets you call rewrites in a jQuery way
*
- * @@ eventually we should refactor mwCode over to jQuery style plugins
- * and mv_embed.js will just handle dependency mapping and loading.
+ * These functions are genneraly are loaders that do the dynamic mapping of
+ * dependencies for a given compoent
+ *
*
*/
function mv_jqueryBindings() {
js_log( 'mv_jqueryBindings' );
(function( $ ) {
+ /*
+ * apiProxy Loader loader:
+ *
+ * @param mode is either 'server' or 'client'
+ */
+ $.apiProxy = function( mode, pConf, callback ){
+ js_log('do apiProxy setup');
+ $.addLoaderDialog( gM('mwe-apiproxy-setup') );
+ mvJsLoader.doLoad( [
+ '$mw.proxy',
+ 'JSON'
+ ], function(){
+ $mw.proxy[mode]( pConf, callback );
+ });
+ }
//non selector based add-media-wizard direct invocation with loader
$.addMediaWiz = function( iObj, callback ){
js_log(".addMediaWiz call");
'mvPlayList',
'$j.ui',
'$j.contextMenu',
- '$j.secureEvalJSON',
+ 'JSON',
'mvSequencer'
],
[
*
* @param msg text text of the loader msg
*/
- $.addLoaderDialog = function( msg_txt ){
- if( $('#mwe_tmp_loader').length != 0 )
- $('#mwe_tmp_loader').remove();
-
+ $.addLoaderDialog = function( msg_txt ){
+ $.addDialog( msg_txt, msg_txt + '<br>' + mv_get_loading_img() );
+ }
+
+ $.addDialog = function ( title, msg_txt, btn ){
+ $('#mwe_tmp_loader').remove();
//append the style free loader ontop:
- $('body').append('<div id="mwe_tmp_loader" title="' + msg_txt + '" >' +
- msg_txt + '<br>' +
- mv_get_loading_img() +
+ $('body').append('<div id="mwe_tmp_loader" title="' + title + '" >' +
+ msg_txt +
'</div>');
//turn the loader into a real dialog loader:
mvJsLoader.doLoadDepMode([
draggable: false,
resizable: false,
height: 140,
- modal: true
+ modal: true,
+ buttons: btn
});
});
}
- $.closeLoaderDialog = function(){
+ $.closeLoaderDialog = function(){
$('#mwe_tmp_loader').dialog('close');
}
-
+
+ $.mwProxy = function( apiConf ){
+ mvJsLoader.doLoad( ['$mw.apiProxy'],
+ function(){
+ $mw.apiProxy( apiConf );
+ });
+ }
})(jQuery);
}
/*
* Utility functions
*/
function js_log( string ) {
- if( window.console ) {
+ ///add any prepend debug strings if nessesary
+ if( mwConfig['debug_pre'] )
+ string = mwConfig['debug_pre']+ string;
+
+ if( window.console ) {
window.console.log( string );
} else {
/*
'mwe-size-bytes' => '$1 B',
'mwe-error_load_lib' => 'Error: JavaScript $1 was not retrievable or does not define $2',
'mwe-loading-add-media-wiz' => "Loading add media wizard",
+ 'mwe-apiproxy-setup' => " Setting up API proxy",
/*
* js file: /libAddMedia/mvFirefogg.js
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>Api Proxy Test</title>
+<script type="text/javascript" src="../mv_embed.js"></script>
+
+<script type="text/javascript" >
+//HARD coded local test:
+var remote_wiki_host = 'http://127.1.1.100';
+var remote_script_path = '/wiki_trunk';
+
+js2AddOnloadHook( function(){
+ $j('#hostName').text( remote_wiki_host );
+ //run the api-proxy setup:
+ $j.apiProxy(
+ 'client',
+ {
+ 'server_frame': remote_wiki_host + remote_script_path + '/index.php/MediaWiki:ApiProxy',
+ 'client_frame_path' : '/wiki_trunk/js2/mwEmbed/libMwApi/NestedCallbackIframe.html',
+ },
+ function(){
+ //callback function here:
+ $j('#setupDone').show('slow');
+ $j('#doAppendCat').click( doCatAppend );
+ }
+ );
+});
+function doCatAppend(){
+ js_log('append cat to User page');
+ //first get our user name:
+ var rObj = {
+ 'action':'query',
+ 'meta':'userinfo'
+ }
+ //we use normal do_api_req with keywork 'proxy' for the url
+ $mw.proxy.doRequest( rObj,
+ function(data){
+ //now we get the data back for that domain
+ if( !data.query || !data.query.userinfo ){
+ js_log("Error no query.userinfo ");
+ return false;
+ }
+ if( data.query.userinfo.id == 0 ){
+ var btn = {};
+ btn['try again'] = function(){
+ doCatAppend();
+ }
+ btn['cancel'] = function(){
+ $j(this).close();
+ }
+ $j.addDialog("Not logged in",
+ "Are you logged in on" + remote_wiki_host + " ? Please loggin",
+ btn
+ )
+ }else{
+ $j('#helloTarget').hide().text( data.query.userinfo.name ).fadeIn('slow');
+ }
+ }
+ );
+ return false;
+}
+</script>
+
+</head>
+<body>
+<h3> Simple API proxy testing system </h3>
+
+<div id="setupProxy">Setting up Proxy ... ( <span id="hostName"></span> )</div>
+<div id="setupDone" style="display:none;">
+<br> <a href="#" id="doAppendCat" >Hello User</a> <span id="helloTarget"><span>
+<br> Some other fun api stuff here...
+</div>
+
+</body>
+</html>
\ No newline at end of file
importScriptURI( mwEmbedHostPath + '/uploadPage.js' + reqAguments );
} );
}
+
+ // Special api proxy page
+ if( wgPageName == 'MediaWiki:ApiProxy' ){
+ var wgEnableIframeApiProxy = true;
+ load_mv_embed( function() {
+ importScriptURI( mwEmbedHostPath + '/ApiProxyPage.js' + reqAguments );
+ });
+ }
+
// OggHandler rewrite for view pages:
var vidIdList = [];