58
55
default_type_icon = "txt.png";
60
57
/* Relative to IVLE root */
61
type_icons_path = "+media/ivle.webapp.core/images/mime";
62
type_icons_path_large = "+media/ivle.webapp.core/images/mime/large";
58
type_icons_path = "media/images/mime";
59
type_icons_path_large = "media/images/mime/large";
64
61
/* Mapping SVN status to icons, just the file's basename */
66
"unversioned": "unversioned.png",
67
"ignored": null, /* Supposed to be innocuous */
68
64
"normal": "normal.png",
69
65
"added": "added.png",
70
66
"missing": "missing.png",
71
67
"deleted": "deleted.png",
72
"replaced": "replaced.png",
73
68
"modified": "modified.png",
74
69
"conflicted": "conflicted.png",
75
70
"revision": "revision.png"
140
134
* May be "application/x-www-form-urlencoded" or "multipart/form-data".
141
135
* Defaults to "application/x-www-form-urlencoded".
142
136
* "multipart/form-data" is recommended for large uploads.
143
* \param callback, optional.
144
* A callback function for after the action has been handled.
146
function do_action(action, path, args, content_type, callback)
138
function do_action(action, path, args, content_type, ignore_response)
148
140
args.action = action;
149
141
/* Callback action, when the server returns */
150
var callback_inner = function(response)
142
var callback = function(response)
152
144
/* Check for action errors reported by the server, and report them
154
146
var error = response.getResponseHeader("X-IVLE-Action-Error");
155
if (error != null && error != "")
156
148
/* Note: This header (in particular) comes URI-encoded, to
157
149
* allow multi-line error messages. Decode */
158
150
alert("Error: " + decodeURIComponent(error.toString()) + ".");
159
151
/* Now read the response and set up the page accordingly */
160
if (callback != null)
161
callback(path, response);
152
if (ignore_response != true)
153
handle_response(path, response, true);
163
155
/* Call the server and perform the action. This mutates the server. */
164
ajax_call(callback_inner, service_app, path, args, "POST", content_type);
156
ajax_call(callback, service_app, path, args, "POST", content_type);
167
159
/** Calls the server using Ajax, requesting a directory listing. This should
322
310
setup_for_listing();
325
/* Top-level dir, with subjects */
326
special_home_listing(listing, subjects, path);
330
/* Not the top-level dir. Do a normal dir listing. */
331
handle_dir_listing(path, listing.listing);
311
home_listing(listing, subjects, path);
336
/* Read the response and set up the page accordingly */
337
var content_type = current_file.type;
338
handle_contents_response(path, content_type, url_args);
315
/* Need to make a 2nd ajax call, this time get the actual file
317
callback = function(response)
319
/* Read the response and set up the page accordingly */
320
handle_contents_response(path, response);
322
/* Call the server and request the listing. */
324
args = shallow_clone_object(url_args);
327
/* This time, get the contents of the file, not its metadata */
328
args['return'] = "contents";
329
ajax_call(callback, service_app, path, args, "GET");
341
331
update_actions(isdir);
344
function handle_contents_response(path, content_type)
334
function handle_contents_response(path, response)
346
336
/* Treat this as an ordinary file. Get the file type. */
347
//var content_type = response.getResponseHeader("Content-Type");
337
var content_type = response.getResponseHeader("Content-Type");
348
338
var handler_type = get_handler_type(content_type);
339
would_be_handler_type = handler_type;
349
340
/* handler_type should now be set to either
350
* "text", "image", "video", "audio" or "binary". */
341
* "text", "image", "audio" or "binary". */
351
342
switch (handler_type)
354
handle_text(path, content_type);
345
handle_text(path, response.responseText,
346
would_be_handler_type);
360
handle_html5_media(path, content_type, "video");
349
/* TODO: Custom image handler */
350
handle_binary(path, response.responseText);
363
handle_html5_media(path, content_type, "audio");
366
handle_object(path, content_type);
353
/* TODO: Custom audio handler */
354
handle_binary(path, response.responseText);
369
357
handle_binary(path);
524
507
return default_svn_nice;
527
/** Returns true if a file is versioned (not unversioned or ignored).
529
function svnstatus_versioned(svnstatus)
531
return svnstatus != "unversioned" && svnstatus != "ignored";
534
510
/** Displays a download link to the binary file.
536
512
function handle_binary(path)
538
// Disable save button
539
using_codepress = false;
542
// Show download link
543
514
var files = document.getElementById("filesbody");
544
515
var div = document.createElement("div");
545
516
files.appendChild(div);
546
517
div.setAttribute("class", "padding");
547
var download_link = app_url(download_app, path);
518
var download_link = app_path(download_app, path);
548
519
var par1 = dom_make_text_elem("p",
549
520
"The file " + path + " is a binary file. To download this file, " +
550
521
"click the following link:");
554
525
div.appendChild(par2);
557
/** Displays an image file.
559
function handle_image(path)
561
/* Disable save button */
562
using_codepress = false;
566
var url = app_url(service_app, path) + "?return=contents";
569
var img = $("<img />");
570
img.attr("alt", path);
571
img.attr("src", url);
574
var div = $('<div class="padding" />');
575
div.append('<h1>Image Preview</h1>');
577
$("#filesbody").append(div);
580
/* Displays a media file using an HTML5 <audio> or <video> tag.
581
* Falls back to <object> if the format is unsupported.
583
function handle_html5_media(path, type, tag_name)
585
/* Disable save button and hide the save panel */
586
using_codepress = false;
590
var url = app_url(service_app, path) + "?return=contents";
591
var download_url = app_url(download_app, path);
593
/* Fallback download link */
595
'<p>Could not play ' + tag_name + ' file. ' +
596
'Try <a>downloading it</a> instead.</p>');
597
link.find('a').attr("href", download_url);
599
/* HTML 5 media element */
600
var html5_element = $(
601
'<' + tag_name + ' controls="true" autoplay="true" />');
602
html5_element.attr("src", url);
603
var support = (html5_element[0].canPlayType &&
604
html5_element[0].canPlayType(type));
606
/* If the browser thinks it might be able to play it, use the HTML5
607
* element. Otherwise, fall back to an <object>, which might work.
609
if (support == "probably" || support == "maybe") {
610
var element = html5_element;
612
var element = $('<object />');
613
element.attr("type", type);
614
element.attr("data", url);
616
element.append(link);
619
var div = $('<div class="padding" />');
620
div.append('<h1>File preview</h1>');
622
$("#filesbody").append(div);
625
/** Display generic object content
627
function handle_object(path, content_type)
629
/* Disable save button and hide the save panel */
630
using_codepress = false;
634
var url = app_url(service_app, path) + "?return=contents";
635
var download_url = app_url(download_app, path);
637
/* Fallback Download Link */
638
var link = $('<p><a /></p>');
639
var a = link.find('a');
640
a.attr("href", download_url);
641
a.text("Download " + path);
644
var obj = $('<object width="100%" height="500px" />');
645
obj.attr("type", content_type);
646
obj.attr("data", url);
647
obj.append('Could not load object');
650
var div = $('<div class="padding" />');
651
div.append('<h1>Preview</h1>');
654
$("#filesbody").append(div);
657
/* Present an element for the given path.
658
* Gives it a title and download link.
660
function present_custom_handler(path, type, element)
662
/* Disable save button and hide the save panel */
663
using_codepress = false;
667
var url = app_url(service_app, path) + "?return=contents";
668
var download_url = app_url(download_app, path);
670
/* Fallback download link */
672
'<p>Could not play ' + tag_name + ' file. ' +
673
'Try <a>downloading it</a> instead.</p>');
674
link.find('a').attr("href", download_url);
676
/* HTML 5 media element */
677
var html5_element = $(
678
'<' + tag_name + ' controls="true" autoplay="true" />');
679
html5_element.attr("src", url);
680
var support = (html5_element[0].canPlayType &&
681
html5_element[0].canPlayType(type));
683
/* If the browser thinks it might be able to play it, use the HTML5
684
* element. Otherwise, fall back to an <object>, which might work.
686
if (support == "probably" || support == "maybe") {
687
var element = html5_element;
689
var element = $('<object />');
690
element.attr("type", type);
691
element.attr("data", url);
693
element.append(link);
696
var div = $('<div class="padding" />');
697
div.append('<h1>File preview</h1>');
699
$("#filesbody").append(div);
702
528
/* Enable or disable actions1 moreactions actions. Takes either a single
703
529
* name, or an array of them.*/
704
530
function set_action_state(names, which, allow_on_revision)
934
760
/* Subversion actions */
935
761
/* These are only useful if we are in a versioned directory and have some
936
762
* files selected. */
937
set_action_state(["svnrename"], numsel == 1 && current_file.svnstatus);
938
set_action_state(["svnadd"], numsel >= 1 && current_file.svnstatus);
939
/* And these are only useful is ALL the selected files are versioned */
940
set_action_state(["svnremove", "svnrevert", "svncopy", "svncut"],
941
numsel >= 1 && current_file.svnstatus && svn_selection);
942
/* Commit is useful if ALL selected files are versioned, or the current
943
* directory is versioned */
944
set_action_state(["svncommit"], current_file.svnstatus &&
945
(numsel >= 1 && svn_selection || numsel == 0));
763
set_action_state(["svnadd",], numsel >= 1 && current_file.svnstatus);
764
/* And these are only usefull is ALL the selected files are versioned */
765
set_action_state(["svnremove", "svnrevert", "svncommit", "svncopy",
766
"svncut"], numsel >= 1 && current_file.svnstatus && svn_selection);
947
768
/* Diff, log and update only support one path at the moment, so we must
948
769
* have 0 or 1 versioned files selected. If 0, the directory must be
960
781
/* Log should be available for revisions as well. */
961
782
set_action_state("svnlog", single_versioned_path, true);
963
/* Cleanup should be available for revisions as well. */
964
set_action_state("svncleanup", single_versioned_path, true);
966
single_ivle_versioned_path = (
968
(numsel == 1 && (stat = file_listing[selected_files[0]])) ||
969
(numsel == 0 && (stat = current_file))
970
) && svnstatus_versioned(stat.svnstatus)
972
&& stat.svnurl.substr(0, svn_base.length) == svn_base);
973
set_action_state(["submit"], single_ivle_versioned_path);
975
784
/* There is currently nothing on the More Actions menu of use
976
785
* when the current file is not a directory. Hence, just remove
1021
835
action_unpublish(selected_files);
1024
window.open(public_app_url("~" + current_path, filename), 'share')
838
//alert("Not yet implemented: Sharing files");
839
window.open(public_app_path(serve_app, current_path, filename), 'share')
1027
if (selected_files.length == 1)
1028
stat = file_listing[selected_files[0]];
1030
stat = current_file;
1031
url = stat.svnurl.substr(svn_base.length); // URL-encoded
1032
path = decodeURIComponent(url);
1034
/* The working copy might not have an up-to-date version of the
1035
* directory. While submitting like this could yield unexpected
1036
* results, we should really submit the latest revision to minimise
1037
* terrible mistakes - so we run off and ask fileservice for the
1038
* latest revision.*/
1039
$.post(app_path(service_app, current_path),
1040
{"action": "svnrepostat", "path": path},
1043
window.location = path_join(app_path('+submit'), url) + '?revision=' + result.svnrevision;
843
alert("Not yet implemented: Submit");
1049
846
action_rename(filename);