2 * a library for doing remote media searches
4 * initial targeted archives are:
11 "add_media_wizard" : "Add media wizard",
12 "mv_media_search" : "Media search",
13 "rsd_box_layout" : "Box layout",
14 "rsd_list_layout" : "List layout",
15 "rsd_results_desc" : "Results",
16 "rsd_results_next" : "next",
17 "rsd_results_prev" : "previous",
18 "rsd_no_results" : "No search results for <b>$1<\/b>",
19 "upload_tab" : "Upload",
20 "rsd_layout" : "Layout : ",
21 "rsd_resource_edit" : "Edit resource : $1",
22 "resource_description_page" : "Resource description page",
23 "rsd_local_resource_title" : "Local resource title",
24 "rsd_do_insert" : "Do insert",
25 "cc_title" : "Creative Commons",
26 "cc_by_title" : "Attribution",
27 "cc_nc_title" : "Noncommercial",
28 "cc_nd_title" : "No Derivative Works",
29 "cc_sa_title" : "Share Alike",
30 "cc_pd_title" : "Public Domain",
31 "unknown_license" : "Unknown license",
32 "no_import_by_url" : "This user or wiki <b>can not<\/b> import assets from remote URLs.<\/p><p>Do you need to login?<\/p><p>If permissions are set, you may have to enable $wgAllowCopyUploads (<a href=\"http : \/\/www.mediawiki.org\/wiki\/Manual : $wgAllowCopyUploads\">more information<\/a>).<\/p>",
33 "results_from" : "Results from <a href=\"$1\" target=\"_new\" >$2<\/a>",
34 "missing_desc_see_soruce" : "This asset is missing a description. Please see the [$1 orginal source] and help describe it.",
35 "rsd_config_error" : "Add media wizard configuration error : $1",
36 "uploaded_itmes" : "Uploaded Items:",
38 "your_recent_uploads" : "Your Recent Uploads",
39 "upload_a_file": "Upload a New File",
41 "resource_page_desc":"Resource Page Description:",
42 "edit_resource_desc": "Edit WikiText Resource Description:",
43 "local_resource_title": "Local Resource Title:",
44 "watch_this_page": "Watch this page",
45 "do_import_resource": "Do Import Resource",
46 "update_preview": "Update Preview",
47 "cancel_import": "Cancel Import",
48 "importing_asset" : "Importing Asset",
49 "preview_insert_resource": "Preview Insert of Resource: $1"
51 var default_remote_search_options
= {
52 'profile':'mediawiki_edit',
53 'target_container':null, //the div that will hold the search interface
54 //if using a modeal dialog (instead of target_container) how close to the edge of the window should we go:
55 'modal_edge_padding':'20px',
57 'target_invocation': null, //the button or link that will invoke the search interface
59 'default_provider_id':'all', //all or one of the content_providers ids
62 'local_wiki_api_url':null,
64 //can be 'api', 'form', 'autodetect', 'remote_link'
65 'import_url_mode': 'autodetect',
69 'target_textbox':null,
70 'target_render_area': null, //where output render should go:
71 'instance_name': null, //a globally accessible callback instance name
72 'default_query':null, //default search query
73 //specific to sequence profile
75 'cFileNS':'File', //what is the cannonical namespace for images
76 //@@todo (should get that from the api or inpage vars)
78 'enable_upload_tab':true, // if we want to enable an uploads tab:
79 'upload_api_target' : 'http://localhost/wiki_trunk/api.php' // can be local or the url of the upload api.
81 if(typeof wgServer
== 'undefined')
83 if(typeof wgScriptPath
== 'undefined')
85 if(typeof stylepath
== 'undefined')
89 * base remoteSearch Driver interface
91 var remoteSearchDriver = function(iObj
){
92 return this.init( iObj
);
94 remoteSearchDriver
.prototype = {
95 results_cleared
:false,
96 //here we define the set of possible media content providers:
99 'title': 'Select Providers'
102 'title': 'Advanced Options'
106 * sets the default display item:
107 * can be any content_providers key or 'all'
109 disp_item
: 'wiki_commons',
110 /** the default content providers list.
112 * (should be note that special tabs like "upload" and "combined" don't go into the content proviers list:
113 * @note do not use double underscore in content providers names (used for id lookup)
115 * @@todo we will want to load more per user-preference and per category lookup
118 /*content_providers documentation:
119 * @@todo we should move the bulk of the configuration to each file
122 @enabled: whether the search provider can be selected
123 @checked: whether the search provider will show up as seleatable tab (todo: user prefrence)
124 @d: default: if the current cp should be displayed (only one should be the default)
125 @title: the title of the search provider
126 @desc: can use html... todo: need to localize
127 @api_url: the url to query against given the library type:
128 @lib: the search library to use corresponding to the
129 search object ie: 'mediaWiki' = new mediaWikiSearchSearch()
130 @tab_img: the tab image (if set to false use title text)
131 if === "ture" use standard location skin/images/{cp_id}_tab.png
132 if === string use as url for image
134 @linkback_icon default is: /wiki/skins/common/images/magnify-clip.png
136 //domain insert: two modes: simple config or domain list:
137 @local : if the content provider assets need to be imported or not.
138 @local_domains : sets of domains for which the content is local
139 //@@todo should query wgForeignFileRepos setting maybe interwikimap from the api
144 'title' : 'This Wiki',
145 'desc' : '(should be updated with the proper text) maybe import from some config value',
146 'api_url': ( wgServer
&& wgScriptPath
)? wgServer
+ wgScriptPath
+ '/api.php': null,
154 'title' :'Wikimedia Commons',
155 'desc' : 'Wikimedia Commons is a media file repository making available public domain '+
156 'and freely-licensed educational media content (images, sound and video clips) to all.',
157 'homepage': 'http://commons.wikimedia.org/wiki/Main_Page',
158 'api_url':'http://commons.wikimedia.org/w/api.php',
160 'resource_prefix': 'WC_', //prefix on imported resources (not applicable if the repository is local)
162 //list all the domains where commons is local?
163 // probably should set this some other way by doing an api query
164 // or by seeding this config when calling the remote search?
165 'local_domains': ['wikimedia','wikipedia','wikibooks'],
166 //specific to wiki commons config:
167 'search_title':false, //disable title search
168 //set up default range limit
176 'title' : 'Archive.org',
177 'desc' : 'The Internet Archive, a digital library of cultural artifacts',
178 'homepage':'http://www.archive.org/about/about.php',
180 'api_url':'http://homeserver7.us.archive.org:8983/solr/select',
181 'lib' : 'archiveOrg',
183 'resource_prefix': 'AO_',
189 'title' :'Metavid.org',
190 'homepage':'http://metavid.org',
191 'desc' : 'Metavid hosts thousands of hours of US house and senate floor proceedings',
192 'api_url':'http://metavid.org/w/index.php?title=Special:MvExportSearch',
194 'local' :false, //if local set to true we can use local
195 'resource_prefix': 'MV_', //what prefix to use on imported resources
197 'local_domains': ['metavid'], // if the domain name contains metavid
198 // no need to import metavid content to metavid sites
200 'stream_import_key': 'mv_ogg_low_quality', // which stream to import, could be mv_ogg_high_quality
201 //or flash stream, see ROE xml for keys
203 'remote_embed_ext': false, //if running the remoteEmbed extension no need to copy local
204 //syntax will be [remoteEmbed:roe_url link title]
208 //define the licenses
209 // ... this will get complicated quick...
210 // (just look at complexity for creative commons without exessive "duplicate data")
211 // ie cc_by could be "by/3.0/us/" or "by/2.1/jp/" to infinitum...
212 // some complexity should be negated by license equivalances.
214 // but we will have to abstract into another class let content providers provide license urls
215 // and we have to clone the license object and allow local overrides
218 //for now only support creative commons type licenses
219 //used page: http://creativecommons.org/licenses/
221 'base_img_url':'http://upload.wikimedia.org/wikipedia/commons/thumb/',
222 'base_license_url': 'http://creativecommons.org/licenses/',
225 'by-sa': 'by-sa/3.0/',
226 'by-nc-nd': 'by-nc-nd/3.0/',
227 'by-nc': 'by-nc/3.0/',
228 'by-nd': 'by-nd/3.0/',
229 'by-nc-sa': 'by-nc-sa/3.0/',
230 'by-sa': 'by-nc/3.0',
231 'pd': 'publicdomain/'
235 'im':'1/11/Cc-by_new_white.svg/20px-Cc-by_new_white.svg.png'
238 'im':'2/2f/Cc-nc_white.svg/20px-Cc-nc_white.svg.png'
241 'im':'b/b3/Cc-nd_white.svg/20px-Cc-nd_white.svg.png'
244 'im':'d/df/Cc-sa_white.svg/20px-Cc-sa_white.svg.png'
247 'im':'5/51/Cc-pd-new_white.svg/20px-Cc-pd-new_white.svg.png'
254 * @param license_key the license key (ie "by-sa" or "by-nc-sa" etc)
256 getlicenseImgSet: function( licenseObj
){
257 //js_log('output images: '+ imgs);
258 return '<div class="rsd_license" title="'+ licenseObj
.title
+ '" >' +
259 '<a target="_new" href="'+ licenseObj
.lurl
+'" ' +
260 'title="' + licenseObj
.title
+ '">'+
261 licenseObj
.img_html
+
266 * getLicenceKeyFromKey
267 * @param license_key the key of the license (must be defined in: this.licenses.cc.licenses)
269 getLicenceFromKey:function( license_key
, force_url
){
270 if( typeof( this.licenses
.cc
.licenses
[ license_key
]) == 'undefined')
271 return js_error('could not find:' + license_key
);
272 //set the current license pointer:
273 var cl
= this.licenses
.cc
;
274 var title
= gM('cc_title');
276 var license_set
= license_key
.split('-');
277 for(var i
=0;i
< license_set
.length
; i
++){
278 lkey
= license_set
[i
];
279 title
+= ' ' + gM( 'cc_' + lkey
+ '_title');
280 imgs
+='<img class="license_desc" width="20" src="' + cl
.base_img_url
+
281 cl
.license_img
[ lkey
].im
+ '">';
283 var url
= (force_url
) ? force_url
: cl
.base_license_url
+ cl
.licenses
[ license_key
];
292 * getLicenceKeyFromUrl
293 * @param licence_url the url of the license
295 getLicenceFromUrl: function( license_url
){
296 //js_log("getLicenceFromUrl::" + license_url);
297 //first do a direct lookup check:
298 for(var i
in this.licenses
.cc
.licenses
){
299 var lkey
= this.licenses
.cc
.licenses
[i
].split('/')[0];
301 if( parseUri(license_url
).path
.indexOf('/'+ lkey
+'/') != -1){
302 return this.getLicenceFromKey( i
, license_url
);
305 //could not find it return unknown_license
307 'title' : gM('unknown_license'),
308 'img_html' : '<span>' + gM('unknown_license') + '</span>',
312 //some default layout values:
314 image_edit_width
: 400,
315 video_edit_width
: 400,
316 insert_text_pos
: 0, //insert at the start (will be overwritten by the user cursor pos)
317 result_display_mode
: 'box', //box or list
323 init: function( iObj
){
325 js_log('remoteSearchDriver:init');
326 for( var i
in default_remote_search_options
) {
330 this[ i
] = default_remote_search_options
[i
];
333 //update the base text:
334 if(_this
.target_textbox
)
335 _this
.getTexboxSelection();
337 //set up the content provider config:
339 for(var cpc
in cpconfig
){
340 for(var cinx
in this.cpconfig
[cpc
]){
341 if( this.content_providers
[cpc
] )
342 this.content_providers
[ cpc
][ cinx
] = this.cpconfig
[cpc
][ cinx
];
347 //make sure the selected cp has an api to query against (if its a content_provider
348 if( this.content_providers
[ this.disp_item
] &&
349 !this.content_providers
[ this.disp_item
].api_url
){
350 for(var inx
in this.content_providers
){
351 if( this.content_providers
[ inx
].api_url
){
352 this.disp_item
= inx
;
359 //set up the default model config:
363 'top' : this.modal_edge_padding
,
364 'left' : this.modal_edge_padding
,
365 'right' : this.modal_edge_padding
,
366 'bottom': this.modal_edge_padding
370 //set up the target invocation:
371 if( $j(this.target_invocation
).length
==0 ){
372 js_log("RemoteSearchDriver:: no target invocation provided (will have to run your own doInitDisplay() )");
374 if(this.target_invocation
){
375 $j(this.target_invocation
).css('cursor','pointer').attr('title', gM('add_media_wizard')).click(function(){
376 _this
.doInitDisplay();
381 doInitDisplay:function(){
383 //setup the parent container:
386 this.init_interface_html();
388 this.add_interface_bindings();
390 //update the target bining to just unhide the dialog:
391 $j(this.target_invocation
).unbind().click(function(){
393 //update the base text:
394 if( _this
.target_textbox
)
395 _this
.getTexboxSelection();
396 //$j(_this.target_container).dialog("open");
397 $j(_this
.target_container
).parents('.ui-dialog').fadeIn('slow');
400 //gets the in and out points for insert position or grabs the selected text for search
401 getTexboxSelection:function(){
402 //update the caretPos
405 //if we have highlighted text use that as the query: (would be fun to add context menu once we have rich editor in-place)
406 if( this.caret_pos
.selection
)
407 this.default_query
= this.caret_pos
.selection
410 getCaretPos:function(){
412 var txtarea
= $j(this.target_textbox
).get(0);
413 var getTextCusorStartPos = function (o
){
414 if (o
.createTextRange
) {
415 var r
= document
.selection
.createRange().duplicate()
416 r
.moveEnd('character', o
.value
.length
)
417 if (r
.text
== '') return o
.value
.length
418 return o
.value
.lastIndexOf(r
.text
)
419 } else return o
.selectionStart
421 var getTextCusorEndPos = function (o
){
422 if (o
.createTextRange
) {
423 var r
= document
.selection
.createRange().duplicate();
424 r
.moveStart('character', -o
.value
.length
);
425 return r
.text
.length
;
427 return o
.selectionEnd
430 this.caret_pos
.s
= getTextCusorStartPos( txtarea
);
431 this.caret_pos
.e
= getTextCusorEndPos( txtarea
);
432 this.caret_pos
.text
= txtarea
.value
;
433 if(this.caret_pos
.s
&& this.caret_pos
.e
&&
434 (this.caret_pos
.s
!= this.caret_pos
.e
))
435 this.caret_pos
.selection
= this.caret_pos
.text
.substring(this.caret_pos
.s
, this.caret_pos
.e
).replace(/ /g
, '\xa0') || '\xa0';
437 js_log('got caret_pos:' + this.caret_pos
.s
);
438 //restore text value: (creating textRanges sometimes screws with the text content)
439 $j(this.target_textbox
).val(this.caret_pos
.text
);
441 init_modal:function(){
442 js_log("init_modal");
444 //add the parent target_container if not provided or missing
445 if(!_this
.target_container
|| $j(_this
.target_container
).length
==0){
446 $j('body').append('<div id="rsd_modal_target" style="position:absolute;top:30px;left:0px;bottom:45px;right:0px;" title="' + gM('add_media_wizard') + '" ></div>');
447 _this
.target_container
= '#rsd_modal_target';
448 //js_log('appended: #rsd_modal_target' + $j(_this.target_container).attr('id'));
449 //js_log('added target id:' + $j(_this.target_container).attr('id'));
451 //layout = _this.getMaxModalLayout();
452 $j(_this
.target_container
).dialog({
458 //just a place-holder
462 js_log('closed modal');
463 $j(this).parents('.ui-dialog').fadeOut('slow');
465 }).parent('.ui-dialog').css( _this
.dmodalCss
)
466 //@@bind on resize to disable css dialog to update dmodelCss
467 .bind('resizestart', function(event
, ui
) {
468 _this
.dmodalCss
= {};
471 //bind on drag to remove preset style as well
472 .bind('dragstart', function(event
, ui
) {
473 _this
.dmodalCss
= {};
476 //update the child position: (some of this should be pushed up-stream via dialog config options
477 $j(_this
.target_container
+'~ .ui-dialog-buttonpane').css({
478 'position':'absolute',
483 //re add cancel button
484 _this
.cancelClipEditCB();
485 js_log('done setup of target_container: ' +
486 $j(_this
.target_container
+'~ .ui-dialog-buttonpane').length
);
489 /*var resizeTimer = false;
490 $j(window).bind('resize', function() {
491 var adjustModal = function(){
492 var layout = _this.getMaxModalLayout();
493 //js_log("should adjust: h " + layout.h + ' width:' + layout.w);
494 $j(_this.target_container).dialog('option', 'width', layout.w);
495 $j(_this.target_container).dialog('option', 'height', layout.h);
497 if (resizeTimer) clearTimeout(resizeTimer);
498 var resizeTimer = setTimeout(adjustModal, 100);
502 getMaxModalLayout:function(border
){
505 //js_log('setting h:' + (parseInt( $j(document).height() ) - parseInt(border*2)) + ' from:' + $j(document).height() );
507 'h': parseInt( $j(document
).height() ) - parseInt(border
*4),
508 'w': parseInt( $j(document
).width() ) - parseInt(border
*2),
513 //sets up the initial html interface
514 init_interface_html:function(){
515 js_log('init_interface_html');
517 var dq
= (this.default_query
)? this.default_query
: '';
518 js_log('f::init_interface_html');
520 var o
= '<div class="rsd_control_container" style="width:100%">' +
521 '<form id="rsd_form" action="javascript:return false;" method="GET">'+
522 '<input class="ui-widget-content ui-corner-all" type="text" tabindex="1" value="' + dq
+ '" maxlength="512" id="rsd_q" name="rsd_q" '+
523 'size="20" autocomplete="off"/> '+
524 $j
.btnHtml( gM('mv_media_search'), 'rms_search_button', 'search') +
526 //close up the control container:
529 //search provider tabs based on "checked" and "enabled" and "combined tab"
530 o
+='<div id="rsd_results_container" style="top:0px;bottom:0px;left:0px;right:0px;"></div>';
531 $j(this.target_container
).html( o
);
534 $j(this.target_container
+ ' .rms_search_button').btnBind().click(function(){
540 //run the default search:
541 if( this.default_query
)
544 add_interface_bindings:function(){
546 js_log("f:add_interface_bindings:");
549 $j('#mso_selprovider,#mso_selprovider_close').unbind().click(function(){
550 if($j('#rsd_options_bar:hidden').length
!=0 ){
551 $j('#rsd_options_bar').animate({
556 $j('#rsd_options_bar').animate({
559 }, "normal", function(){
565 $j('#rsd_form').unbind().submit(function(){
567 //don't submit the form
571 doUploadInteface:function(){
572 js_log("doUploadInteface::");
575 mv_set_loading('#tab-upload');
576 //do things async to keep interface snapy
577 setTimeout(function(){
578 //do config variable reality checks:
579 if( _this
.upload_api_target
== 'local' ){
580 if( ! _this
.local_wiki_api_url
){
581 $j('#tab-upload').html( gM( 'rsd_config_error', 'missing_local_api_url' ) );
584 _this
.upload_api_target
= _this
.local_wiki_api_url
;
587 //make sure we have a url for the upload target:
588 if( parseUri( _this
.upload_api_target
).host
== _this
.upload_api_target
){
589 $j('#tab-upload').html( gM('rsd_config_error', 'bad_api_url') );
593 //set the form action based on domain:
594 if( parseUri( document
.URL
).host
== parseUri( _this
.upload_api_target
).host
){
595 mvJsLoader
.doLoad(['$j.fn.simpleUploadForm'],function(){
597 //get extened info about the file
598 var cp
= _this
.content_providers
['this_wiki'];
599 //check for "this_wiki" enabled
601 $j('#tab-upload').html('error this_wiki not enabled (can\'t get uploaded file info)');
605 //load this_wiki search system to grab the rObj
606 _this
.loadSearchLib(cp
, function(){
607 //do basic layout form on left upload "bin" on right
608 $j('#tab-upload').html('<table cellspacing="10">' +
610 '<td valign="top" style="width:350px;">' +
611 '<h4>' + gM('upload_a_file') + '</h4>' +
612 '<div id="upload_form">' +
613 mv_get_loading_img() +
616 '<td valign="top" id="upload_bin_cnt">' +
617 '<h4>' + gM('your_recent_uploads') + '</h4>' +
618 '<div id="upload_bin">' +
619 mv_get_loading_img() +
626 //fill in the user page:
627 if(typeof wgUserName
!= 'undefined' && wgUserName
){
628 //load the upload bin with anything the current user has uploaded
629 cp
.sObj
.getUserRecentUploads( wgUserName
, function(){
630 _this
.drawOutputResults();
633 $j('#upload_bin_cnt').empty();
636 //deal with the api form upload form directly:
637 $j('#upload_form').simpleUploadForm({
638 "api_target" : _this
.upload_api_target
,
639 "ondone_cb" : function( resultData
){
640 var wTitle
= resultData
['wpDestFile'];
642 $j( _this
.target_container
).append('<div id="temp_edit_loader" '+
643 'style="position:absolute;top:0px;left:0px;bottom:5px;right:4px;background-color:#FFF;">' +
644 mv_get_loading_img('position:absolute;top:30px;left:30px') +
646 cp
.sObj
.addByTitle( wTitle
, function( rObj
){
647 $j( _this
.target_container
).find('#temp_edit_loader').remove();
648 //redraw (with added result if new)
649 _this
.drawOutputResults();
650 //pull up recource editor:
651 _this
.resourceEdit( rObj
, $j('#res_upload_' + rObj
.id
).get(0) );
653 //return false to close progress window:
661 js_log('do proxy:: ' + parseUri( _this
.upload_api_target
).host
);
662 $j('#tab-upload').html('proxy upload not yet ready');
666 runSearch: function(){
667 js_log("f:runSearch::" + this.disp_item
);
669 var draw_direct_flag
= true;
670 if( !this.content_providers
[this.disp_item
] ){
671 //check if its the special upload tab case:
672 if( this.disp_item
== 'upload'){
673 this.doUploadInteface();
675 js_log("can't run search for:" + this.disp_item
);
679 cp
= this.content_providers
[this.disp_item
];
681 //check if we need to update:
682 if( typeof cp
.sObj
!= 'undefined' ){
683 if(cp
.sObj
.last_query
== $j('#rsd_q').val() && cp
.sObj
.last_offset
== cp
.offset
){
684 js_log('last query is: ' + cp
.sObj
.last_query
+ ' matches: ' + $j('#rsd_q').val() );
686 js_log('last query is: ' + cp
.sObj
.last_query
+ ' not match: ' + $j('#rsd_q').val() );
687 draw_direct_flag
= false;
690 draw_direct_flag
= false;
692 if( !draw_direct_flag
){
693 //set the content to loading while we do the search:
694 $j('#tab-' + this.disp_item
).html( mv_get_loading_img() );
696 //make sure the search library is loaded and issue the search request
697 this.getLibSearchResults( cp
);
700 //issue a api request & cache the result
701 //this check can be avoided by setting the this.import_url_mode = 'api' | 'form' | insted of 'autodetect' or 'none'
702 checkForCopyURLSupport:function ( callback
){
704 js_log('checkForCopyURLSupport:: ');
705 //see if we already have the import mode:
706 if( this.import_url_mode
!= 'autodetect'){
707 js_log('import mode: ' + _this
.import_url_mode
);
710 //if we don't have the local wiki api defined we can't auto-detect use "link"
711 if(!_this
.local_wiki_api_url
){
712 js_log('import mode: remote link (no import_wiki_api_url)');
713 _this
.import_url_mode
= 'remote_link';
716 if( this.import_url_mode
== 'autodetect' ){
718 'data': { 'action':'paraminfo', 'modules':'upload' },
719 'url': _this
.local_wiki_api_url
721 if( typeof data
.paraminfo
.modules
[0].classname
== 'undefined'){
722 //@@todo would be nice if API permission on: action=query&meta=userinfo&uiprop=rights
723 // upload_by_url property reflected if $wgAllowCopyUploads config value .. oh well.
727 url
: wgArticlePath
.replace( '$1', 'Special:Upload' ), //@@todo may have problems in localized special pages
728 //(could hit meta=siteinfo & specialpagealiases )
729 // but might be overkill for now cuz we want to switch to new-upload branch soon.
730 success: function( form_html
){
731 if( form_html
.indexOf( 'wpUploadFileURL' ) != -1){
732 _this
.import_url_mode
= 'form';
734 _this
.import_url_mode
= 'none';
736 js_log('import mode: ' + _this
.import_url_mode
);
740 js_log('error in getting Special:Upload page');
741 _this
.import_url_mode
= 'none';
743 js_log('import mode: ' + _this
.import_url_mode
);
748 for( var i
in data
.paraminfo
.modules
[0].parameters
){
749 var pname
= data
.paraminfo
.modules
[0].parameters
[i
].name
;
750 if( pname
== 'url' ){
751 js_log( 'Autodetect Upload Mode: api: copy by url:: ' );
752 //check permission too:
753 _this
.checkForCopyURLPermission(function( canCopyUrl
){
755 _this
.import_url_mode
= 'api';
756 js_log('import mode: ' + _this
.import_url_mode
);
759 _this
.import_url_mode
= 'none';
760 js_log('import mode: ' + _this
.import_url_mode
);
772 * checkForCopyURLPermission:
773 * not really nessesary the api request to upload will return apopprirate error if the user lacks permission. or $wgAllowCopyUploads is set to false
774 * (use this function if we want to issue a warning up front)
776 checkForCopyURLPermission:function( callback
){
780 'data':{ 'action' : 'query', 'meta' : 'userinfo', 'uiprop' : 'rights' },
781 'url': _this
.local_wiki_api_url
,
784 for( var i
in data
.query
.userinfo
.rights
){
785 var right
= data
.query
.userinfo
.rights
[i
];
786 //js_log('checking: ' + right ) ;
787 if(right
== 'upload_by_url'){
789 return true; //break out of the function
795 getLibSearchResults:function( cp
){
798 //first check if we should even run the search at all (can we import / insert into the page? )
799 if( !this.checkRepoLocal( cp
) && this.import_url_mode
== 'autodetect' ){
800 //cp is not local check if we can support the import mode:
801 this.checkForCopyURLSupport( function(){
802 _this
.getLibSearchResults( cp
);
805 }else if( !this.checkRepoLocal( cp
) && this.import_url_mode
== 'none'){
806 if( this.disp_item
== 'combined' ){
807 //combined results are harder to error handle just ignore that repo
808 cp
.sObj
.loading
= false;
810 $j('#tab-' + this.disp_item
).html( '<div style="padding:10px">'+ gM('no_import_by_url') +'</div>');
814 _this
.loadSearchLib(cp
, function(){
816 cp
.sObj
.getSearchResults();
817 _this
.checkResultsDone();
820 loadSearchLib:function(cp
, callback
){
822 //set up the library req:
827 js_log("loaded lib:: " + cp
.lib
);
828 //else we need to run the search:
829 var iObj
= {'cp':cp
, 'rsd':_this
};
830 eval('cp.sObj = new '+cp
.lib
+'Search( iObj );');
832 js_log('Error: could not find search lib for ' + cp_id
);
836 //inherit defaults if not set:
837 cp
.limit
= (cp
.limit
) ? cp
.limit
: cp
.sObj
.limit
;
838 cp
.offset
= (cp
.offset
) ? cp
.offset
: cp
.sObj
.offset
;
842 /* check for all the results to finish */
843 checkResultsDone: function(){
844 //js_log('rsd:checkResultsDone');
846 var loading_done
= true;
848 for(var cp_id
in this.content_providers
){
849 var cp
= this.content_providers
[ cp_id
];
850 if(typeof cp
['sObj'] != 'undefined'){
851 if( cp
.sObj
.loading
)
856 this.drawOutputResults();
858 //make sure the instance name is up-to-date refrence to _this;
859 eval( _this
.instance_name
+ ' = _this');
860 setTimeout( _this
.instance_name
+ '.checkResultsDone()', 50);
863 drawTabs: function(){
865 //add the tabs to the rsd_results container:
866 var o
='<div id="rsd_tabs_container" style="width:100%;">';
867 var selected_tab
= 0;
871 for(var cp_id
in this.content_providers
){
872 var cp
= this.content_providers
[cp_id
];
873 if( cp
.enabled
&& cp
.checked
&& cp
.api_url
){
874 //add selected default if set
875 if( this.disp_item
== cp_id
)
878 o
+='<li class="rsd_cp_tab">';
879 o
+='<a id="rsd_tab_' + cp_id
+ '" href="#tab-' + cp_id
+ '">';
880 if(cp
.tab_img
=== true){
881 o
+='<img alt="' + cp
.title
+'" src="' + mv_skin_img_path
+ 'remote_cp/' + cp_id
+ '_tab.png">';
889 tabc
+='<div id="tab-'+ cp_id
+'" class="rsd_results"/>';
892 //do an upload tab if enabled:
893 if( this.enable_upload_tab
){
894 o
+='<li class="rsd_cp_tab" ><a id="rsd_tab_upload" href="#tab-upload">' + gM('upload_tab') + '</a></li>';
895 tabc
+='<div id="tab-upload" />';
896 if(this.disp_item
== 'upload')
897 selected_tab
= inx
++;
900 //output the tab content containers:
902 o
+='</div>'; //close tab container
904 //output the respective results holders
905 $j('#rsd_results_container').html(o
);
906 //setup bindings for tabs make them sortable: (@@todo remember order)
907 js_log('selected tab is: ' + selected_tab
);
908 $j("#rsd_tabs_container").tabs({
909 selected
:selected_tab
,
910 select: function(event
, ui
) {
911 _this
.selectTab( $j(ui
.tab
).attr('id').replace('rsd_tab_', '') );
914 }).find(".ui-tabs-nav").sortable({axis
:'x'});
916 /*$j('.rsd_cp_tab').click(function(){
917 _this.selectTab( $j(this).attr('id').replace(/rsd_tab_/, '') );
920 //setup key binding (no longer nessesary tabs provide this functionality)
921 /*$j().keyup(function(e){
922 js_log('keyup on : ' +e.which );
923 //if escape pressed clear the interface:
930 getResourceFromTitle:function( rTitle
, callback
){
934 'titles': _this
.cFileNS
+ ':' + rTitle
938 'url':this.local_wiki_api_url
940 //@@todo propogate the rObj
945 //@@todo we could load the id with the content provider id to find the object faster...
946 getResourceFromId:function( rid
){
947 js_log('getResourceFromId:' + rid
);
948 //strip out /res/ if preset:
949 rid
= rid
.replace(/res_/, '');
950 //js_log("looking at: " + rid);
955 if(cp_id
== 'upload')
958 var cp
= this.content_providers
[cp_id
];
959 if(cp
&& cp
['sObj'] && cp
.sObj
.resultsObj
[rid
]){
960 return cp
.sObj
.resultsObj
[rid
];
962 js_log("ERROR: could not find " + rid
);
965 drawOutputResults: function(){
966 js_log('f:drawOutputResults::' + this.disp_item
);
970 var cp_id
= this.disp_item
;
972 if(this.disp_item
== 'upload'){
973 tab_target
= '#upload_bin';
974 var cp
= this.content_providers
['this_wiki'];
976 var cp
= this.content_providers
[this.disp_item
];
977 tab_target
= '#tab-' + cp_id
;
979 //empty the existing results:
980 $j(tab_target
).empty();
982 //output the results bar / controls
983 _this
.setResultBarControl();
985 var drawResultCount
=0;
987 //output all the results for the current disp_item
988 if( typeof cp
['sObj'] != 'undefined' ){
989 $j
.each(cp
.sObj
.resultsObj
, function(rInx
, rItem
){
990 if( _this
.result_display_mode
== 'box' ){
991 o
+='<div id="mv_result_' + rInx
+ '" class="mv_clip_box_result" style="width:' +
992 _this
.thumb_width
+ 'px;height:'+ (_this
.thumb_width
-20) +'px;position:relative;">';
993 //check for missing poster types for audio
994 if( rItem
.mime
=='audio/ogg' && !rItem
.poster
){
995 rItem
.poster
= mv_skin_img_path
+ 'sound_music_icon-80.png';
997 //get a thumb with proper resolution transform if possible:
998 o
+='<img title="'+rItem
.title
+'" class="rsd_res_item" id="res_' + cp_id
+ '__' + rInx
+
999 '" style="width:' + _this
.thumb_width
+ 'px;" src="' +
1000 cp
.sObj
.getImageTransform( rItem
, {'width':_this
.thumb_width
} )
1002 //add a linkback to resource page in upper right:
1004 o
+='<a target="_new" style="position:absolute;top:0px;right:0px" title="' +
1005 gM('resource_description_page') +
1006 '" href="' + rItem
.link
+ '"><img src="http://upload.wikimedia.org/wikipedia/commons/6/6b/Magnify-clip.png"></a>';
1007 //add license icons if present
1009 o
+= _this
.getlicenseImgSet( rItem
.license
);
1011 }else if(_this
.result_display_mode
== 'list'){
1012 o
+='<div id="mv_result_' + rInx
+ '" class="mv_clip_list_result" style="width:90%">';
1013 o
+='<img title="'+rItem
.title
+'" class="rsd_res_item" id="res_' + cp_id
+ '_' + rInx
+'" style="float:left;width:' +
1014 _this
.thumb_width
+ 'px;" src="' +
1015 cp
.sObj
.getImageTransform( rItem
, {'width':_this
.thumb_width
} )
1017 //add license icons if present
1019 o
+= _this
.getlicenseImgSet( rItem
.license
);
1022 o
+='<div style="clear:both" />';
1027 js_log('append to: ' + '#tab-' + cp_id
);
1028 //put in the tab output (plus clear the output)
1029 $j(tab_target
).append( o
+ '<div style="clear:both"/>');
1032 js_log( ' drawResultCount :: ' + drawResultCount
+ ' append: ' + $j('#rsd_q').val() );
1034 //remove any old search res
1035 $j('#rsd_no_search_res').remove();
1036 if( drawResultCount
== 0 )
1037 $j('#tab-' + cp_id
).append( '<span style="padding:10px">' + gM( 'rsd_no_results', $j('#rsd_q').val() ) + '</span>');
1039 this.addResultBindings();
1041 addResultBindings:function(){
1043 $j('.mv_clip_'+_this
.result_display_mode
+'_result').hover(function(){
1044 $j(this).addClass('mv_clip_'+_this
.result_display_mode
+'_result_over');
1045 //also set the animated image if avaliable
1046 var res_id
= $j(this).children('.rsd_res_item').attr('id');
1047 var rObj
= _this
.getResourceFromId( res_id
);
1048 if( rObj
.poster_ani
)
1049 $j('#' + res_id
).attr('src', rObj
.poster_ani
);
1051 $j(this).removeClass('mv_clip_'+_this
.result_display_mode
+'_result_over');
1052 var res_id
= $j(this).children('.rsd_res_item').attr('id');
1053 var rObj
= _this
.getResourceFromId( res_id
);
1054 //restore the original (non animated)
1055 if( rObj
.poster_ani
)
1056 $j('#' + res_id
).attr('src', rObj
.poster
);
1058 //resource click action: (bring up the resource editor)
1059 $j('.rsd_res_item').unbind().click(function(){
1060 var rObj
= _this
.getResourceFromId( $j(this).attr("id") );
1061 _this
.resourceEdit( rObj
, this );
1064 addResourceEditLoader:function(maxWidth
, overflow_style
){
1066 if(!maxWidth
)maxWidth
=400;
1067 if(!overflow_style
)overflow_style
='overflow:auto;';
1068 //remove any old instance:
1069 $j( _this
.target_container
).find('#rsd_resource_edit').remove();
1070 //add the edit layout window with loading place holders
1071 $j( _this
.target_container
).append('<div id="rsd_resource_edit" '+
1072 'style="position:absolute;top:0px;left:0px;bottom:5px;right:4px;background-color:#FFF;">' +
1073 '<div id="clip_edit_disp" style="position:absolute;' + overflow_style
+ 'width:100%;height:100%;padding:5px;'+
1074 'width:' + (maxWidth
) + 'px;" >' +
1075 mv_get_loading_img('position:absolute;top:30px;left:30px') +
1077 '<div id="clip_edit_ctrl" class="ui-widget ui-widget-content ui-corner-all" style="position:absolute;'+
1078 'left:' + ( maxWidth
+ 10 ) +'px;top:5px;bottom:10px;right:0px;overflow:auto;padding:5px;">'+
1079 mv_get_loading_img() +
1083 resourceEdit:function( rObj
, rsdElement
){
1084 js_log('f:resourceEdit:' + rObj
.title
);
1086 //remove any existing resource edit interface:
1087 $j('#rsd_resource_edit').remove();
1088 //set the media type:
1089 if(rObj
.mime
.indexOf('image')!=-1){
1090 //set width to default image_edit_width
1091 var maxWidth
= _this
.image_edit_width
;
1092 var mediaType
= 'image';
1093 }else if(rObj
.mime
.indexOf('audio')!=-1){
1094 var maxWidth
= _this
.video_edit_width
;
1095 var mediaType
= 'audio';
1097 //set to default video size:
1098 var maxWidth
= _this
.video_edit_width
;
1099 var mediaType
= 'video';
1101 //so that transcripts show ontop
1102 var overflow_style
= ( mediaType
=='video' )?'':'overflow:auto;';
1103 //append to the top level of model window:
1104 _this
.addResourceEditLoader(maxWidth
, overflow_style
);
1105 //update add media wizard title:
1106 $j( _this
.target_container
).dialog( 'option', 'title', gM('add_media_wizard')+': '+ gM('rsd_resource_edit', rObj
.title
) );
1107 js_log('did append to: '+ _this
.target_container
);
1109 $j('#rsd_resource_edit').css('opacity',0);
1111 $j('#rsd_edit_img').remove();//remove any existing rsd_edit_img
1113 //left side holds the image right size the controls /
1114 $j(rsdElement
).clone().attr('id', 'rsd_edit_img').appendTo('#clip_edit_disp').css({
1115 'position':'absolute',
1123 //try and keep aspect ratio for the thumbnail that we clicked:
1124 var tRatio
= $j('#rsd_edit_img').width() / $j('#rsd_edit_img').height() ;
1126 var tRatio
= 1; //set ratio to 1 if the width of the thumbnail can't be found for some reason
1128 js_log('set from ' + $j('#rsd_edit_img').width()+'x'+ $j('#rsd_edit_img').height() + ' to init thumbimage to ' + maxWidth
+ ' x ' + parseInt( tRatio
* maxWidth
) );
1129 //scale up image and to swap with high res version
1130 $j('#rsd_edit_img').animate({
1134 'width': maxWidth
+ 'px',
1135 'height': parseInt( tRatio
* maxWidth
) + 'px'
1136 }, "slow"); // do it slow to give it a chance to finish loading the HQ version
1138 if( mediaType
== 'image' ){
1139 _this
.loadHQImg(rObj
, {'width':maxWidth
}, 'rsd_edit_img', function(){
1140 $j('.mv_loading_img').remove();
1143 //also fade in the container:
1144 $j('#rsd_resource_edit').animate({
1146 'background-color':'#FFF',
1149 js_log('do load the media editor:');
1150 //do load the media Editor
1151 _this
.doMediaEdit( rObj
, mediaType
);
1153 loadHQImg:function(rObj
, size
, target_img_id
, callback
){
1154 //get the HQ image url:
1155 rObj
.pSobj
.getImageObj( rObj
, size
, function( imObj
){
1156 rObj
['edit_url'] = imObj
.url
;
1158 js_log("edit url: " + rObj
.edit_url
);
1160 rObj
['width'] = imObj
.width
;
1161 rObj
['height'] = imObj
.height
;
1163 //see if we need to animate some transition
1164 if( size
.width
!= imObj
.width
){
1165 js_log('loadHQImg:size mismatch: ' + size
.width
+ ' != ' + imObj
.width
);
1166 //set the target id to the new size:
1167 $j('#'+target_img_id
).animate( {
1168 'width':imObj
.width
+ 'px',
1169 'height':imObj
.height
+ 'px'
1172 js_log('using req size: ' + imObj
.width
+ 'x' + imObj
.height
);
1173 $j('#'+target_img_id
).animate( {'width':imObj
.width
+'px', 'height' : imObj
.height
+ 'px'});
1175 //don't swap it in until its loaded:
1176 var img
= new Image();
1177 // load the image image:
1178 $j(img
).load(function () {
1179 $j('#'+target_img_id
).attr('src', rObj
.edit_url
);
1180 //let the caller know we are done and what size we ended up with:
1182 }).error(function () {
1183 js_log("Error with: " + rObj
.edit_url
);
1184 }).attr('src', rObj
.edit_url
);
1187 cancelClipEditCB:function(){
1189 var b_target
= _this
.target_container
+ '~ .ui-dialog-buttonpane';
1190 $j('#rsd_resource_edit').remove();
1191 //restore the resource container:
1192 $j('#rsd_results_container').show();
1193 //restore the title:
1194 $j( _this
.target_container
).dialog( 'option', 'title', gM('add_media_wizard'));
1195 js_log("should update: " + b_target
+ ' with: cancel');
1196 //restore the buttons:
1197 $j(b_target
).html( $j
.btnHtml( 'Cancel' , 'mv_cancel_rsd', 'close'))
1198 .children('.mv_cancel_rsd')
1201 $j( _this
.target_container
).dialog('close');
1205 /*set-up the control actions for clipEdit with relevent callbacks */
1206 getClipEditControlActions:function( cp
){
1210 cConf
['insert'] = function(rObj
){
1211 _this
.insertResource(rObj
);
1213 //if not directly inserting the resource is support a preview option:
1214 if( _this
.import_url_mode
!= 'remote_link'){
1215 cConf
['preview'] = function(rObj
){
1216 _this
.previewResource( rObj
)
1219 cConf
['cancel'] = function(){
1220 _this
.cancelClipEditCB()
1224 //loads the media editor:
1225 doMediaEdit:function( rObj
, mediaType
){
1227 var cp
= rObj
.pSobj
.cp
;
1229 'rObj':rObj
, //the resource object
1230 'parent_ct' : 'rsd_modal_target',
1231 'clip_disp_ct' : 'clip_edit_disp',
1232 'control_ct' : 'clip_edit_ctrl',
1233 'media_type' : mediaType
,
1235 'controlActionsCb' : _this
.getClipEditControlActions( cp
)
1238 var clibs
= ['mvClipEdit'];
1239 if( mediaType
== 'image'){
1240 //display the mvClipEdit obj once we are done loading:
1241 mvJsLoader
.doLoad( clibs
, function(){
1242 //run the image clip tools
1243 _this
.cEdit
= new mvClipEdit( mvClipInit
);
1246 if( mediaType
== 'video' || mediaType
== 'audio'){
1247 //get any additonal embedding helper meta data prior to doing the acutal embed
1248 // normally this meta should be provided in the search result (but archive.org has a seperate query for more meida meta)
1249 rObj
.pSobj
.getEmbedTimeMeta( rObj
, function(){
1250 //make sure we have the embedVideo libs:
1251 mvJsLoader
.embedVideoCheck( function(){
1252 js_log('append html: ' + rObj
.pSobj
.getEmbedHTML( rObj
, {id
:'embed_vid'}) );
1253 $j('#clip_edit_disp').html(
1254 rObj
.pSobj
.getEmbedHTML( rObj
, {id
:'embed_vid'})
1257 rewrite_by_id('embed_vid',function(){
1258 //grab any information that we got from the ROE xml or parsed from the media file
1259 rObj
.pSobj
.getEmbedObjParsedInfo( rObj
, 'embed_vid' );
1260 //add the re-sizable to the doLoad request:
1261 clibs
.push( '$j.ui.resizable');
1262 clibs
.push( '$j.fn.hoverIntent');
1263 mvJsLoader
.doLoad(clibs
, function(){
1264 //make sure the rsd_edit_img is hidden:
1265 $j('#rsd_edit_img').remove();
1266 //run the image clip tools
1267 _this
.cEdit
= new mvClipEdit( mvClipInit
);
1274 checkRepoLocal:function( cp
){
1278 //check if we can embed the content locally per a domain name check:
1279 var local_host
= parseUri( this.local_wiki_api_url
).host
;
1280 if( cp
.local_domains
) {
1281 for(var i
=0;i
< cp
.local_domains
.length
; i
++){
1282 var ld
= cp
.local_domains
[i
];
1283 if( local_host
.indexOf( ld
) != -1)
1290 checkImportResource:function( rObj
, cir_callback
){
1291 //@@todo get the localized File/Image namespace name or do a general {NS}:Title
1292 var cp
= rObj
.pSobj
.cp
;
1295 //update base target_resource_title:
1296 rObj
.target_resource_title
= rObj
.titleKey
.replace(/File:|Image:/,'')
1298 //check if local repository
1299 //or if import mode if just "linking" (we should alaredy have the 'url'
1301 if( this.checkRepoLocal( cp
) || this.import_url_mode
== 'remote_link'){
1302 //local repo jump directly to check Import Resource callback:
1303 cir_callback( rObj
);
1305 //update target_resource_title with resource repository prefix:
1306 rObj
.target_resource_title
= cp
.resource_prefix
+ rObj
.target_resource_title
;
1308 //check if the resource is not already on this wiki
1311 'titles': _this
.cFileNS
+ ':' + rObj
.target_resource_title
,
1312 'prop' : 'imageinfo',
1319 'url':this.local_wiki_api_url
1321 var found_title
= false;
1322 for(var i
in data
.query
.pages
){
1323 if( i
!= '-1' && i
!= '-2' ){
1324 js_log('found title: ' + i
+ ':' + data
.query
.pages
[i
]['title']);
1325 found_title
=data
.query
.pages
[i
]['title'];
1326 //update to local src
1327 rObj
.local_src
= data
.query
.pages
[i
]['imageinfo'][0].url
;
1328 //@@todo maybe update poster too?
1329 rObj
.local_poster
= data
.query
.pages
[i
]['imageinfo'][0].thumburl
;
1333 js_log("checkImportResource:found title:" + found_title
);
1334 //resource is already present (or resource with same name is already present)
1335 rObj
.target_resource_title
= found_title
.replace(/File:|Image:/,'');
1336 cir_callback( rObj
);
1338 js_log("resource not present: update:"+ _this
.cFileNS
+ ':' + rObj
.target_resource_title
);
1340 //update the rObj with import info
1341 rObj
.pSobj
.updateDataForImport( rObj
);
1343 //setup the resource description from resource description:
1344 var wt
= '{{Information '+"\n";
1347 wt
+= '|Description= ' + rObj
.desc
+ "\n";
1349 wt
+= '|Description= ' + gM('missing_desc_see_soruce', rObj
.link
) + "\n";
1352 //output search specific info
1353 wt
+='|Source=' + rObj
.pSobj
.getImportResourceDescWiki( rObj
) + "\n";
1356 wt
+='|Author=' + rObj
.author
+"\n";
1359 wt
+='|Date=' + rObj
.date
+"\n";
1361 //add the Permision info:
1362 wt
+='|Permission=' + rObj
.pSobj
.getPermissionWikiTag( rObj
) +"\n";
1364 if( rObj
.other_versions
)
1365 wt
+='|other_versions=' + rObj
.other_versions
+ "\n";
1369 //get any extra categories or helpful links
1370 wt
+= rObj
.pSobj
.getExtraResourceDescWiki( rObj
);
1373 $j('#rsd_resource_import').remove();//remove any old resource imports
1375 //@@ show user dialog to import the resource
1376 $j( _this
.target_container
).append('<div id="rsd_resource_import" '+
1377 'class="ui-state-highlight ui-widget-content ui-state-error" ' +
1378 'style="position:absolute;top:50px;left:50px;right:50px;bottom:50px;z-index:5">' +
1379 '<h3 style="color:red">Resource: <span style="color:black">' + rObj
.title
+ '</span> needs to be imported</h3>'+
1380 '<div id="rsd_preview_import_container" style="position:absolute;width:50%;bottom:0px;left:0px;overflow:auto;top:30px;">' +
1381 rObj
.pSobj
.getEmbedHTML( rObj
, {'id': _this
.target_container
+ '_rsd_pv_vid', 'max_height':'200','only_poster':true} )+ //get embedHTML with small thumb:
1382 '<br style="clear both">'+
1383 '<strong>'+gM('resource_page_desc') +'</strong>'+
1384 '<div id="rsd_import_desc" syle="display:inline;">'+
1385 mv_get_loading_img('position:absolute;top:5px;left:5px') +
1388 '<div id="rds_edit_import_container" style="position:absolute;left:50%;' +
1389 'bottom:0px;top:30px;right:0px;overflow:auto;">'+
1390 '<strong>' + gM('local_resource_title') + '</strong><br>'+
1391 '<input type="text" size="30" value="' + rObj
.target_resource_title
+ '" readonly="true"><br>'+
1392 '<strong>' + gM('edit_resource_desc') + '</strong>' +
1393 '<textarea id="rsd_import_ta" id="mv_img_desc" style="width:90%;" rows="8" cols="50">' +
1396 '<input type="checkbox" value="true" id="wpWatchthis" name="wpWatchthis" tabindex="7"/>' +
1397 '<label for="wpWatchthis">'+gM('watch_this_page')+'</label><br><br><br>' +
1399 $j
.btnHtml(gM('do_import_resource'), 'rsd_import_doimport', 'check' ) + ' ' +
1401 $j
.btnHtml(gM('update_preview'), 'rsd_import_apreview', 'refresh' ) + '<div style="clear:both;height:20px;"/>' +
1403 $j
.btnHtml(gM('cancel_import'), 'rsd_import_acancel', 'close' ) + ' ' +
1406 //output the rendered and non-renderd version of description for easy swiching:
1410 rewrite_by_id(_this
.target_container
+ '_rsd_pv_vid');
1411 //load the preview text:
1412 _this
.getParsedWikiText( wt
, _this
.cFileNS
+':'+ rObj
.target_resource_title
, function( o
){
1413 $j('#rsd_import_desc').html(o
);
1416 $j( _this
.target_container
+ ' .rsd_import_apreview').btnBind().click(function(){
1417 /*$j('#rsd_import_desc').show().html(
1418 mv_get_loading_img()
1420 //load the preview text:
1421 _this
.getParsedWikiText( $j('#rsd_import_ta').val(), _this
.cFileNS
+':'+ rObj
.target_resource_title
, function( o
){
1422 js_log('got updated preivew: ');
1423 $j('#rsd_import_desc').html(o
);
1426 $j(_this
.target_container
+ ' .rsd_import_doimport').btnBind().click(function(){
1427 //check import mode:
1428 if(_this
.import_url_mode
=='form'){
1429 _this
.doImportSpecialPage( rObj
, cir_callback
);
1430 }else if( _this
.import_url_mode
=='api'){
1431 _this
.doImportAPI( rObj
, cir_callback
);
1433 js_log("Error: import mode is not form or API (can not copy asset)");
1436 $j( _this
.target_container
+ ' .rsd_import_acancel').btnBind().click(function(){
1437 $j('#rsd_resource_import').fadeOut("fast",function(){
1446 doImportAPI:function(rObj
, cir_callback
){
1448 //baseUploadInterface
1450 'mvBaseUploadInterface',
1453 //initicate a download similar to url copy:
1454 myUp
= new mvBaseUploadInterface({
1455 'api_url' : _this
.local_wiki_api_url
,
1456 'done_upload_cb':function(){
1457 //we have finished the upload:
1459 //close up the rsd_resource_import
1460 $j('#rsd_resource_import').remove();
1461 //run the parent callback:
1463 //return false to avoid BaseUploadInterface done actions
1467 //set the edit token if we have it handy
1468 _this
.getEditToken(function( token
){
1469 myUp
.etoken
= token
;
1472 'filename' : rObj
.target_resource_title
,
1473 'comment' : $j('#rsd_import_ta').val()
1480 getEditToken:function(callback
){
1481 //first try the page form:
1482 var etoken
= $j("input[name='wpEditToken']").val();
1487 //@@todo try to load over ajax if( _this.local_wiki_api_url ) is set
1488 // (your on the api domain but are inserting from a normal page view)
1489 if( _this
.local_wiki_api_url
){
1490 get_mw_token(null, _this
.local_wiki_api_url
, function(token
){
1498 * doImportSpecialPage
1499 * can be depricated once we support upload api support is widespred.
1501 doImportSpecialPage:function(rObj
, cir_callback
){
1505 'data': { 'action':'query',
1508 'titles': rObj
.titleKey
1510 'url':_this
.local_wiki_api_url
1512 //could recheck if it has been created in the mean time
1513 if( data
.query
.pages
[-1] ){
1514 var editToken
= data
.query
.pages
[-1]['edittoken'];
1516 //@@todo give an ajax login or be more friendly in some way:
1517 js_error("You don't have permission to upload (are you logged in?)");
1519 $j('#modalbox').fadeOut("normal",function(){
1521 $j('#mv_overlay').remove();
1524 //not sure if we can do remote url uploads (so just do a local post)
1525 js_log('got token for new page:' +editToken
);
1527 'wpSourceType' :'web',
1528 'wpUploadFileURL' : rObj
.src
,
1529 'wpDestFile' : rObj
.target_resource_title
,
1530 'wpUploadDescription' : $j('#rsd_import_ta').val(),
1531 'wpWatchthis' : $j('#wpWatchthis').val(),
1532 'wpUpload' : 'Upload file'
1535 $j('#rsd_resource_import').append('<div id="rsd_import_progress"'+
1536 'style="position:absolute;top:0px;'+
1537 'left:0px;width:100%;height:100%;'+
1538 'z-index:5;background:#FFF;overflow:auto;">'+
1539 '<div style="position:absolute;left:30%;right:30%"><h3>'+gM('importing_asset')+'</h3><br>' +
1540 mv_get_loading_img('','mv_loading_bar_img') +
1544 $j
.post(wgArticlePath
.replace(/\$1/,'Special:Upload'),
1547 //@@todo this will be replaced once we add upload image support to the api.
1549 //very basic test to see if we got passed to the image page:
1550 //@@todo more normalization stuff
1551 var sstring
='var wgPageName = "' + _this
.cFileNS
+ ':' + rObj
.target_resource_title
.replace(/ /g
,'_') +'"';
1552 if(data
.indexOf( sstring
) !=-1){
1553 js_log('found: ' + sstring
);
1554 $j('#rsd_resource_import').remove();
1555 cir_callback( rObj
);
1557 js_log("Error or warning: (did not find: \"" + sstring
+ ' in output' );
1558 pos_etitle
= '<h1 class="firstHeading">';
1559 var error_txt
= form_txt
= '';
1560 var res
= grabWikiFormError( data
);
1563 error_txt
= res
.error_txt
;
1566 form_txt
= res
.form_txt
;
1568 js_log( 'error text is: ' + error_txt
);
1569 $j( '#rsd_resource_import' ).html( '<h3>Error</h3>' + error_txt
+ '<br>' + form_txt
+
1571 '<a href="#" id="rsd_import_error" >' + gM('cancel_import') + '</a>'
1573 //set up cancel action:
1574 $j('#rsd_import_error').click(function(){
1575 $j('#rsd_resource_import').remove();
1586 previewResource:function( rObj
){
1588 this.checkImportResource( rObj
, function(){
1589 //put another window ontop:
1590 $j( _this
.target_container
).append('<div id="rsd_preview_display"' +
1591 'style="position:absolute;overflow:hidden;z-index:4;top:0px;bottom:75px;right:0px;left:0px;background-color:#FFF;">' +
1592 mv_get_loading_img('top:30px;left:30px') +
1595 var bPlaneTarget
= _this
.target_container
+'~ .ui-dialog-buttonpane';
1596 var pTitle
= $j( _this
.target_container
).dialog('option', 'title');
1599 $j( _this
.target_container
).dialog('option', 'title', gM('preview_insert_resource', rObj
.title
) );
1601 //update buttons preview:
1602 $j(bPlaneTarget
).html( $j
.btnHtml( gM('rsd_do_insert'), 'preview_do_insert', 'check') + ' ' )
1603 .children('.preview_do_insert')
1605 _this
.insertResource( rObj
);
1607 //update cancel button
1608 $j(bPlaneTarget
).append('<a href="#" class="preview_close">Do More Modification</a>')
1609 .children('.preview_close')
1611 $j('#rsd_preview_display').remove();
1613 $j( _this
.target_container
).dialog('option', 'title', pTitle
);
1614 //restore buttons (from the clipEdit object::)
1615 _this
.cEdit
.updateInsertControlActions();
1618 //update the preview_wtext
1619 _this
.updatePreviewText( rObj
);
1620 _this
.getParsedWikiText(_this
.preview_wtext
, _this
.target_title
,
1622 $j('#rsd_preview_display').html( phtml
);
1623 //update the display of video tag items (if any)
1629 updatePreviewText:function( rObj
){
1632 if( _this
.import_url_mode
== 'remote_link' ){
1633 _this
.cur_embed_code
= rObj
.pSobj
.getEmbedHTML(rObj
);
1635 _this
.cur_embed_code
= rObj
.pSobj
.getEmbedWikiCode( rObj
);
1638 //insert at start if textInput cursor has not been set (ie == length)
1639 if( _this
.caret_pos
&& _this
.caret_pos
.text
){
1640 if( _this
.caret_pos
.text
.length
== _this
.caret_pos
.s
)
1641 _this
.caret_pos
.s
=0;
1642 _this
.preview_wtext
= _this
.caret_pos
.text
.substring(0, _this
.caret_pos
.s
) +
1643 _this
.cur_embed_code
+
1644 _this
.caret_pos
.text
.substring( _this
.caret_pos
.s
);
1646 _this
.preview_wtext
= $j(_this
.target_textbox
).val() + _this
.cur_embed_code
;
1648 //check for missing </refrences>
1649 if( _this
.preview_wtext
.indexOf('<references/>') ==-1 && _this
.preview_wtext
.indexOf('<ref>') != -1 )
1650 _this
.preview_wtext
= _this
.preview_wtext
+ '<references/>';
1652 getParsedWikiText:function( wikitext
, title
, callback
){
1654 'data':{'action':'parse',
1657 'url':this.local_wiki_api_url
1659 callback( data
.parse
.text
['*'] );
1663 insertResource:function( rObj
){
1664 js_log('insertResource: ' + rObj
.title
);
1666 //dobule check that the resource is present:
1667 this.checkImportResource( rObj
, function(){
1668 _this
.updatePreviewText( rObj
);
1669 $j(_this
.target_textbox
).val( _this
.preview_wtext
);
1671 //update the render area (if present)
1672 if(_this
.target_render_area
&& _this
.cur_embed_code
){
1673 //output with some padding:
1674 $j(_this
.target_render_area
).append( _this
.cur_embed_code
+ '<div style="clear:both;height:10px">')
1675 //update if its video or audio:
1676 if( rObj
.mime
.indexOf('audio')!=-1 ||
1677 rObj
.mime
.indexOf('video')!=-1 ||
1678 rObj
.mime
.indexOf('/ogg') !=-1){
1679 mvJsLoader
.embedVideoCheck(function(){
1687 closeAll:function(){
1689 js_log("close all:: " + _this
.target_container
);
1690 _this
.cancelClipEditCB();
1691 $j(_this
.target_container
).dialog('close');
1693 setResultBarControl:function( ){
1695 var box_dark_url
= mv_skin_img_path
+ 'box_layout_icon_dark.png';
1696 var box_light_url
= mv_skin_img_path
+ 'box_layout_icon.png';
1697 var list_dark_url
= mv_skin_img_path
+ 'list_layout_icon_dark.png';
1698 var list_light_url
= mv_skin_img_path
+ 'list_layout_icon.png';
1701 if( this.content_providers
[this.disp_item
] ){
1702 var cp
= this.content_providers
[this.disp_item
];
1703 about_desc
='<span style="position:relative;top:0px;font-style:italic;">' +
1704 '<i>' + gM('results_from', [cp
.homepage
, cp
.title
]) + '</i></span>';
1705 $j('#tab-'+this.disp_item
).append( '<div id="rds_results_bar">'+
1706 '<span style="float:left;top:0px;font-style:italic;">'+
1707 gM('rsd_layout')+' '+
1708 '<img id="msc_box_layout" ' +
1709 'title = "' + gM('rsd_box_layout') + '" '+
1710 'src = "' + ( (_this
.result_display_mode
=='box')?box_dark_url
:box_light_url
) + '" ' +
1711 'style="width:20px;height:20px;cursor:pointer;"> ' +
1712 '<img id="msc_list_layout" '+
1713 'title = "' + gM('rsd_list_layout') + '" '+
1714 'src = "' + ( (_this
.result_display_mode
=='list')?list_dark_url
:list_light_url
) + '" '+
1715 'style="width:20px;height:20px;cursor:pointer;">'+
1718 '<span id="rsd_paging_ctrl" style="float:right;"></span>'+
1721 //get paging with bindings:
1722 this.getPaging('#rsd_paging_ctrl');
1724 $j('#msc_box_layout').hover(function(){
1725 $j(this).attr("src", box_dark_url
);
1727 $j(this).attr("src", ( (_this
.result_display_mode
=='box')?box_dark_url
:box_light_url
) );
1728 }).click(function(){
1729 $j(this).attr("src", box_dark_url
);
1730 $j('#msc_list_layout').attr("src", list_light_url
);
1731 _this
.setDispMode('box');
1734 $j('#msc_list_layout').hover(function(){
1735 $j(this).attr("src", list_dark_url
);
1737 $j(this).attr("src", ( (_this
.result_display_mode
=='list')?list_dark_url
:list_light_url
) );
1738 }).click(function(){
1739 $j(this).attr("src", list_dark_url
);
1740 $j('#msc_box_layout').attr("src", box_light_url
);
1741 _this
.setDispMode('list');
1745 getPaging:function(target
){
1747 var cp_id
= this.disp_item
;
1748 var cp
= this.content_providers
[ this.disp_item
];
1749 //js_log('getPaging:'+ cp_id + ' len: ' + cp.sObj.num_results);
1750 var to_num
= ( cp
.limit
> cp
.sObj
.num_results
)?
1751 (cp
.offset
+ cp
.sObj
.num_results
):
1752 (cp
.offset
+ cp
.limit
);
1753 var out
= gM('rsd_results_desc') + ' ' + (cp
.offset
+1) + ' to ' + to_num
;
1754 //check if we have more results (next prev link)
1755 if( cp
.offset
>= cp
.limit
)
1756 out
+=' <a href="#" id="rsd_pprev">' + gM('rsd_results_prev') + ' ' + cp
.limit
+ '</a>';
1758 if( cp
.sObj
.more_results
)
1759 out
+=' <a href="#" id="rsd_pnext">' + gM('rsd_results_next') + ' ' + cp
.limit
+ '</a>';
1761 $j(target
).html(out
);
1763 $j('#rsd_pnext').click(function(){
1764 cp
.offset
+= cp
.limit
;
1767 $j('#rsd_pprev').click(function(){
1768 cp
.offset
-= cp
.limit
;
1777 selectTab:function( selected_cp_id
){
1778 js_log('select tab: ' + selected_cp_id
);
1779 this.disp_item
= selected_cp_id
;
1780 if( this.disp_item
== 'upload' ){
1781 this.doUploadInteface();
1783 //update the search results:
1787 setDispMode:function(mode
){
1788 js_log('setDispMode:' + mode
);
1789 this.result_display_mode
=mode
;
1790 //run /update search display:
1791 this.drawOutputResults();