define([
'jquery',
'jquery.ui.progressbar',
'jquery.magnific-popup',
'simplemodal',
'underscore',
'backbone',
'common',
'file-tree',
'js.cookie',
'app/collections/dirents',
'app/views/dirent',
'app/views/dirent-grid',
'app/views/fileupload',
'app/views/share',
'app/views/widgets/dropdown'
], function($, progressbar, magnificPopup, simplemodal, _, Backbone, Common,
FileTree, Cookies, DirentCollection, DirentView, DirentGridView,
FileUploadView, ShareView, DropdownView) {
'use strict';
var DirView = Backbone.View.extend({
id: 'dir-view',
template: _.template($('#dir-view-tmpl').html()),
path_bar_template: _.template($('#dir-path-bar-tmpl').html()),
dir_op_bar_template: _.template($('#dir-op-bar-tmpl').html()),
dirents_hd_template: _.template($('#dirents-hd-tmpl').html()),
top_search_form_template: _.template($('#top-search-form-tmpl').html()),
newDirTemplate: _.template($("#add-new-dir-form-template").html()),
newFileTemplate: _.template($("#add-new-file-form-template").html()),
mvcpTemplate: _.template($("#mvcp-form-template").html()),
mvProgressTemplate: _.template($("#mv-progress-popup-template").html()),
initialize: function(options) {
var view_mode = Cookies.get('view_mode');
if (view_mode == 'grid') {
this.view_mode = 'grid';
} else {
this.view_mode = 'list';
}
var sort_mode = Cookies.get('sort_mode');
if (sort_mode == 'time_up') {
this.sort_mode = 'time_up';
} else if (sort_mode == 'time_down') {
this.sort_mode = 'time_down';
} else if (sort_mode == 'name_down') {
this.sort_mode = 'name_down';
} else {
this.sort_mode = 'name_up';
}
this.contextOptions = {};
this.dir = new DirentCollection();
this.listenTo(this.dir, 'add', this.addOne);
this.listenTo(this.dir, 'reset', this.reset);
this.fileUploadView = new FileUploadView({dirView: this});
this.render();
// scroll window: get 'more', fix 'op bar'
var _this = this;
$(window).scroll(function() {
if ($(_this.el).is(':visible')) {
_this.onWindowScroll();
}
});
// hide 'rename form'
$(document).click(function(e) {
var target = e.target || event.srcElement;
var $form = $('#rename-form');
if ($form.length && !$form.find('*').is(target)) {
var $tr = $form.closest('tr'); // get $tr before $form removed in `.cancel click()`
$('.cancel', $form).click();
}
});
// for 'grid view': click to hide the contextmenu of '.grid-item'
$(document).click(function(e) {
var target = e.target || event.srcElement;
var $popup = $('.grid-item-op');
if ($popup.length > 0 &&
!$popup.is(target) &&
!$popup.find('*').is(target) &&
!$popup.closest('.grid-item').is(target) &&
!$popup.closest('.grid-item').find('*').is(target)) {
$popup.remove();
}
});
},
render: function() {
this.$el.html(this.template());
this.attached = false;
this.$dirent_list = this.$('.repo-file-list');
this.$dirent_grid = this.$('.grid-view');
this.$dirent_list_body = this.$('.repo-file-list tbody');
this.$path_bar = this.$('.path');
// For compatible with css, we use .repo-op instead of .dir-op
this.$dir_op_bar = this.$('.repo-op');
// magnificPopup for image files
var magnificPopupOptions = {
type: 'image',
tClose: gettext("Close (Esc)"), // Alt text on close button
tLoading: gettext("Loading..."), // Text that is displayed during loading. Can contain %curr% and %total% keys
gallery: {
enabled: true,
tPrev: gettext("Previous (Left arrow key)"), // Alt text on left arrow
tNext: gettext("Next (Right arrow key)"), // Alt text on right arrow
tCounter: gettext("%curr% of %total%") // Markup for "1 of 7" counter
},
image: {
tError: gettext('The image could not be loaded.') // Error message when image could not be loaded
}
};
// magnificPopup: for 'list view'
this.$dirent_list.magnificPopup($.extend({}, magnificPopupOptions, {
delegate: '.img-name-link',
image: {
titleSrc: function(item) {
var el = item.el;
var img_name = el[0].innerHTML;
var img_link = '' + gettext("Open in New Tab") + '';
return img_name + '
' + img_link;
}
}
}));
// magnificPopup: for 'grid view'
this.$dirent_grid.magnificPopup($.extend({}, magnificPopupOptions, {
delegate: '.image-grid-item',
image: {
titleSrc: function(item) {
var $el = $(item.el);
var img_name = Common.HTMLescape($el.attr('data-name'));
var img_link = '' + gettext("Open in New Tab") + '';
return img_name + '
' + img_link;
}
}
}));
},
// public function
// show a folder
// 'category' is sth. like url prefix
// options: for rendering from group view, currently is { group_name: group_name }
showDir: function(category, repo_id, path, options) {
$('#top-search-form').html(this.top_search_form_template({
search_repo_id: repo_id
}));
this.contextOptions = options;
if (!this.attached) {
this.attached = true;
$("#right-panel").html(this.$el);
}
this.dir.setPath(category, repo_id, path);
this.renderDir();
},
// public function
// hide the folder view
hide: function() {
$('#top-search-form').html(this.top_search_form_template({
search_repo_id: ''
}));
this.$el.detach();
this.attached = false;
},
/***** private functions *****/
addOne: function(dirent) {
var view;
if (this.view_mode == 'list') {
view = new DirentView({model: dirent, dirView: this});
this.$dirent_list_body.append(view.render().el);
} else {
view = new DirentGridView({model: dirent, dirView: this});
this.$dirent_grid.append(view.render().el);
}
},
reset: function() {
this.renderPath();
this.renderDirOpBar();
if (this.view_mode == 'list') {
this.renderDirentsHd();
}
this.updateSortIconByMode(this.sort_mode);
this.sortDirents(this.sort_mode);
this.dir.last_start = 0;
this.dir.limit = 100;
this.render_dirents_slice(this.dir.last_start, this.dir.limit);
this.setFileInput();
this.getImageThumbnail();
},
// for fileupload
setFileInput: function () {
var dir = this.dir;
if (!dir.user_perm || dir.user_perm != 'rw') {
return;
}
var $popup = this.fileUploadView.$el;
if (app.pageOptions.enable_upload_folder) {
if ('webkitdirectory' in $('#basic-upload-input')[0]) {
// if enable_upload_folder and is chrome
this.$("#basic-upload").remove();
this.$("#advanced-upload").show();
this.upload_dropdown = new DropdownView({
el: this.$("#advanced-upload")
});
$popup.fileupload(
'option',
'fileInput',
this.$('#advanced-upload input[type="file"]'));
} else {
this.$("#advanced-upload").remove();
$popup.fileupload(
'option',
'fileInput',
this.$('#basic-upload-input'));
}
} else {
$popup.fileupload(
'option',
'fileInput',
this.$('#basic-upload-input'));
}
},
getImageThumbnail: function() {
if (!app.pageOptions.enable_thumbnail || this.dir.encrypted) {
return false;
}
var images_with_no_thumbnail = this.dir.filter(function(dirent) {
// 'dirent' is a model
return dirent.get('is_img') && !dirent.get('encoded_thumbnail_src');
});
if (images_with_no_thumbnail.length == 0) {
return ;
}
var images_len = images_with_no_thumbnail.length,
repo_id = this.dir.repo_id,
cur_path = this.dir.path,
_this = this;
var thumbnail_size = app.pageOptions.thumbnail_default_size;
if (this.view_mode == 'grid') {
thumbnail_size = app.pageOptions.thumbnail_size_for_grid;
}
var get_thumbnail = function(i) {
var cur_img = images_with_no_thumbnail[i];
var cur_img_path = Common.pathJoin([cur_path, cur_img.get('obj_name')]);
$.ajax({
url: Common.getUrl({name: 'thumbnail_create', repo_id: repo_id}),
data: {
'path': cur_img_path,
'size': thumbnail_size
},
cache: false,
dataType: 'json',
success: function(data) {
cur_img.set({
'encoded_thumbnail_src': data.encoded_thumbnail_src
});
},
complete: function() {
// cur path may be changed. e.g., the user enter another directory
if (i < images_len - 1 &&
_this.dir.repo_id == repo_id &&
_this.dir.path == cur_path) {
get_thumbnail(++i);
}
}
});
};
get_thumbnail(0);
},
_showLibDecryptDialog: function() {
var _this = this;
var form = $($('#repo-decrypt-form-template').html());
var decrypt_success = false;
form.modal({
containerCss: {'padding': '1px'},
onClose: function () {
$.modal.close();
_this.$el_con.show();
if (!decrypt_success) {
app.router.navigate(
_this.dir.category + '/', // need to append '/' at end
{trigger: true}
);
}
}
});
$('#simplemodal-container').css({'height':'auto'});
form.submit(function() {
var passwd = $.trim($('[name="password"]', form).val());
if (!passwd) {
$('.error', form).html(gettext("Password is required.")).removeClass('hide');
return false;
}
Common.ajaxPost({
form: form,
form_id: form.attr('id'),
post_url: Common.getUrl({
'name': 'api_v2.1_repo_set_password',
'repo_id': _this.dir.repo_id
}),
post_data: {
password: passwd
},
after_op_success: function() {
decrypt_success = true;
$.modal.close();
_this.renderDir();
}
});
return false;
});
},
renderDir: function() {
this.$dirent_grid.empty();
this.$dirent_list_body.empty();
if (this.view_mode == 'list') {
this.$dirent_list.show();
this.$dirent_grid.hide();
} else {
this.$dirent_list.hide();
this.$dirent_grid.show();
}
var loading_tip = this.$('.loading-tip').show();
var _this = this;
var thumbnail_size = app.pageOptions.thumbnail_default_size;
if (this.view_mode == 'grid') {
thumbnail_size = app.pageOptions.thumbnail_size_for_grid;
}
var dir = this.dir;
dir.fetch({
cache: false,
reset: true,
data: {
'p': dir.path,
'thumbnail_size': thumbnail_size
},
success: function() {
loading_tip.hide();
},
error: function(collection, response, opts) {
loading_tip.hide();
_this.$el_con = _this.$('.repo-file-list-topbar, .js-dir-content').hide();
var $error = _this.$('.error');
var err_msg;
if (response.responseText) {
if (response.responseJSON.lib_need_decrypt) {
_this._showLibDecryptDialog();
return;
} else {
err_msg = response.responseJSON.error;
}
} else {
err_msg = gettext('Please check the network.');
}
$error.html(err_msg).show();
}
});
},
renderPath: function() {
var dir = this.dir;
var path = dir.path;
var context = 'my';
var category_start = dir.category.split('/')[0];
if (category_start == 'org') {
context = 'org';
} else if (category_start == 'group') {
context = 'group';
} else if (category_start == 'common') {
context = 'common';
}
var obj = {
path: path,
repo_name: dir.repo_name,
category: dir.category,
context: context
};
$.extend(obj, this.contextOptions);
var path_list = path.substr(1).split('/');
var path_list_encoded = Common.encodePath(path.substr(1)).split('/');
if (path != '/') {
$.extend(obj, {
path_list: path_list,
path_list_encoded: path_list_encoded,
repo_id: dir.repo_id
});
}
this.$path_bar.html(this.path_bar_template(obj));
},
renderDirOpBar: function() {
var dir = this.dir;
this.$dir_op_bar.html($.trim(this.dir_op_bar_template({
user_perm: dir.user_perm,
encrypted: dir.encrypted,
mode: this.view_mode,
path: dir.path,
repo_id: dir.repo_id,
site_root: app.pageOptions.site_root,
can_generate_shared_link: app.pageOptions.can_generate_shared_link,
enable_upload_folder: app.pageOptions.enable_upload_folder
})));
},
renderDirentsHd: function() {
this.$('thead').html(this.dirents_hd_template());
},
render_dirents_slice: function(start, limit) {
var dir = this.dir;
_.each(dir.slice(start, start + limit), this.addOne, this);
if (dir.length > start + limit) {
dir.dirent_more = true;
dir.last_start = start + limit;
} else {
dir.dirent_more = false;
}
},
// Directory Operations
events: {
'click .path-link': 'visitDir',
'click #add-new-dir': 'newDir',
'click #add-new-file': 'newFile',
'click #share-cur-dir': 'share',
'click #js-switch-grid-view': 'switchToGridView',
'click #js-switch-list-view': 'switchToListView',
'click th.select': 'select',
'click #mv-dirents': 'mv',
'click #cp-dirents': 'cp',
'click #del-dirents': 'del',
'click #download-dirents': 'download',
'click .by-name': 'sortByName',
'click .by-time': 'sortByTime',
'click .basic-upload-btn': 'uploadFile',
'click .advanced-upload-file': 'advancedUploadFile',
'click .advanced-upload-folder': 'advancedUploadFolder'
},
uploadFile: function() {
this.$('#basic-upload-input').trigger('click');
},
advancedUploadFile: function() {
this.$('#advanced-upload-file-input').trigger('click');
return false;
},
advancedUploadFolder: function() {
this.$('#advanced-upload-folder-input').trigger('click');
return false;
},
newDir: function() {
var form = $(this.newDirTemplate()),
form_id = form.attr('id'),
dir = this.dir,
dirView = this;
form.modal({appendTo:'#main'});
$('#simplemodal-container').css({'height':'auto'});
form.submit(function() {
var dirent_name = $.trim($('input[name="name"]', form).val());
if (!dirent_name) {
Common.showFormError(form_id, gettext("It is required."));
return false;
};
var post_data = {'dirent_name': dirent_name},
post_url = Common.getUrl({name: "new_dir", repo_id: dir.repo_id})
+ '?parent_dir=' + encodeURIComponent(dir.path);
var after_op_success = function(data) {
$.modal.close();
var new_dirent = dir.add({
'is_dir': true,
'obj_name': data['name'],
'perm': 'rw',
'last_modified': new Date().getTime() / 1000,
'last_update': gettext("Just now"),
'p_dpath': data['p_dpath']
}, {silent:true});
dirView.addNewDir(new_dirent);
};
Common.ajaxPost({
'form': form,
'post_url': post_url,
'post_data': post_data,
'after_op_success': after_op_success,
'form_id': form_id
});
return false;
});
},
newFile: function() {
var form = $(this.newFileTemplate()),
form_id = form.attr('id'),
file_name = form.find('input[name="name"]'),
dir = this.dir,
dirView = this;
form.modal({
appendTo: '#main',
focus: false,
containerCss: {'padding':'20px 25px'}
});
$('#simplemodal-container').css({'height':'auto'});
$('.set-file-type', form).click(function() {
file_name.val('.' + $(this).data('filetype'));
Common.setCaretPos(file_name[0], 0);
file_name.focus();
});
form.submit(function() {
var dirent_name = $.trim(file_name.val());
if (!dirent_name) {
Common.showFormError(form_id, gettext("It is required."));
return false;
};
// if it has an extension, make sure it has a name
if (dirent_name.lastIndexOf('.') != -1 && dirent_name.substr(0, dirent_name.lastIndexOf('.')).length == 0) {
Common.showFormError(form_id, gettext("Only an extension there, please input a name."));
return false;
}
var post_data = {'dirent_name': dirent_name},
post_url = Common.getUrl({name: "new_file", repo_id: dir.repo_id})
+ '?parent_dir=' + encodeURIComponent(dir.path);
var after_op_success = function(data) {
$.modal.close();
var new_dirent = dir.add({
'is_file': true,
'is_img': Common.imageCheck(data['name']),
'obj_name': data['name'],
'file_size': Common.fileSizeFormat(0),
'obj_id': '0000000000000000000000000000000000000000',
'file_icon': 'file.png',
'starred': false,
'perm': 'rw',
'last_modified': new Date().getTime() / 1000,
'last_update': gettext("Just now")
}, {silent: true});
dirView.addNewFile(new_dirent);
};
Common.ajaxPost({
'form': form,
'post_url': post_url,
'post_data': post_data,
'after_op_success': after_op_success,
'form_id': form_id
});
return false;
});
},
addNewFile: function(new_dirent) {
var dirView = this,
dir = this.dir;
if (this.view_mode == 'list') {
var view = new DirentView({model: new_dirent, dirView: dirView});
var new_file = view.render().el;
// put the new file as the first file
if ($('tr', dirView.$dirent_list_body).length == 0) {
dirView.$dirent_list_body.append(new_file);
} else {
var dirs = dir.where({'is_dir':true});
if (dirs.length == 0) {
dirView.$dirent_list_body.prepend(new_file);
} else {
// put the new file after the last dir
$($('tr', dirView.$dirent_list_body)[dirs.length - 1]).after(new_file);
}
}
} else {
var gview = new DirentGridView({model: new_dirent, dirView: dirView});
var grid_new_file = gview.render().el;
if ($('.grid-item', dirView.$dirent_grid).length == 0) {
dirView.$dirent_grid.append(grid_new_file);
} else {
var dirs = dir.where({'is_dir':true});
if (dirs.length == 0) {
dirView.$dirent_grid.prepend(grid_new_file);
} else {
// put the new file after the last dir
$($('.grid-item', dirView.$dirent_grid)[dirs.length - 1]).after(grid_new_file);
}
}
}
},
addNewDir: function(new_dirent) {
var dirView = this;
if (this.view_mode == 'list') {
var view = new DirentView({model: new_dirent, dirView: dirView});
// put the new dir as the first one
dirView.$dirent_list_body.prepend(view.render().el);
} else {
var gview = new DirentGridView({model: new_dirent, dirView: dirView});
dirView.$dirent_grid.prepend(gview.render().el);
}
},
share: function () {
var dir = this.dir;
var path = dir.path;
var options = {
'is_repo_owner': dir.is_repo_owner,
'is_virtual': dir.is_virtual,
'user_perm': dir.user_perm,
'repo_id': dir.repo_id,
'is_dir': true,
'dirent_path': path,
'obj_name': path == '/' ? dir.repo_name : path.substr(path.lastIndexOf('/') + 1)
};
new ShareView(options);
},
switchToGridView: function() {
if (this.view_mode == 'grid') {
return false;
} else {
this.view_mode = 'grid';
Cookies.set('view_mode', 'grid');
this.renderDir();
return false;
}
},
switchToListView: function() {
if (this.view_mode == 'list') {
return false;
} else {
this.view_mode = 'list';
Cookies.set('view_mode', 'list');
this.renderDir();
return false;
}
},
sortByName: function() {
if (this.sort_mode == 'name_up') {
// change sort mode
Cookies.set('sort_mode', 'name_down');
this.sort_mode = 'name_down';
} else {
Cookies.set('sort_mode', 'name_up');
this.sort_mode = 'name_up';
}
this.updateSortIconByMode(this.sort_mode);
this.sortDirents(this.sort_mode);
this.$dirent_list_body.empty();
this.render_dirents_slice(0, this.dir.limit);
this.dir.comparator = null;
return false;
},
sortByTime: function () {
if (this.sort_mode == 'time_up') {
// change sort mode
Cookies.set('sort_mode', 'time_down');
this.sort_mode = 'time_down';
} else {
Cookies.set('sort_mode', 'time_up');
this.sort_mode = 'time_up';
}
this.updateSortIconByMode(this.sort_mode);
this.sortDirents(this.sort_mode);
this.$dirent_list_body.empty();
this.render_dirents_slice(0, this.dir.limit);
this.dir.comparator = null;
return false;
},
sortDirents: function(sort_mode) {
// set collection comparator
this.dir.comparator = function(a, b) {
if (a.get('is_dir') && b.get('is_file')) {
return -1;
}
if (a.get('is_file') && b.get('is_dir')) {
return 1;
}
if (sort_mode == 'name_up' || sort_mode == 'name_down') {
// if sort by name
var result = Common.compareTwoWord(a.get('obj_name'), b.get('obj_name'));
if (sort_mode == 'name_up') {
return -result;
} else {
return result;
}
} else {
// if sort by time
if (sort_mode == 'time_up') {
return a.get('last_modified') < b.get('last_modified') ? -1 : 1;
} else {
return a.get('last_modified') < b.get('last_modified') ? 1 : -1;
}
}
};
// sort collection
this.dir.sort();
},
updateSortIconByMode: function(sort_mode) {
// first hide all icon
this.$('.by-name .sort-icon, .by-time .sort-icon').hide();
// show icon according sort mode
if (sort_mode == 'name_up') {
this.$('.by-name .sort-icon').removeClass('icon-caret-up').addClass('icon-caret-down').show();
} else if (sort_mode == 'name_down') {
this.$('.by-name .sort-icon').removeClass('icon-caret-down').addClass('icon-caret-up').show();
} else if (sort_mode == 'time_up') {
this.$('.by-time .sort-icon').removeClass('icon-caret-up').addClass('icon-caret-down').show();
} else if (sort_mode == 'time_down') {
this.$('.by-time .sort-icon').removeClass('icon-caret-down').addClass('icon-caret-up').show();
} else {
// if no sort mode, show name up icon
this.$('.by-name .sort-icon').removeClass('icon-caret-down').addClass('icon-caret-up').show();
}
},
select: function () {
var $el = this.$('th [type=checkbox]');
var dir = this.dir;
var $all_dirent_checkbox = this.$('[type=checkbox]');
var $dirents_op = this.$('#multi-dirents-op');
var $curDirOps = this.$('#upload-file, #add-new-dir, #add-new-file, #share-cur-dir');
if ($el.prop('checked')) {
$all_dirent_checkbox.prop('checked', true);
dir.each(function(model) {
model.set({'selected': true}, {silent: true});
});
$dirents_op.css({'display':'inline-block'});
$curDirOps.hide();
} else {
$all_dirent_checkbox.prop('checked', false);
dir.each(function(model) {
model.set({'selected': false}, {silent: true});
});
$dirents_op.hide();
$curDirOps.show();
}
},
download: function () {
var dirents = this.dir,
selected_dirents = dirents.where({'selected':true}),
selected_names = '';
$(selected_dirents).each(function() {
selected_names += this.get('obj_name') + ',';
});
$.ajax({
url: Common.getUrl({
name: 'download_dirents',
repo_id: dirents.repo_id
}) + '?parent_dir=' + encodeURIComponent(dirents.path) + '&dirents=' + encodeURIComponent(selected_names),
dataType: 'json',
success: function(data) {
location.href = data['url'];
},
error: function (xhr) {
Common.ajaxErrorHandler(xhr);
}
});
},
del: function () {
var dirents = this.dir;
var _this = this;
var del_dirents = function() {
$('#confirm-popup').append('
' + gettext("Processing...") + '
'); var selected_dirents = dirents.where({'selected':true}), selected_names = []; $(selected_dirents).each(function() { selected_names.push(this.get('obj_name')); }); $.ajax({ url: Common.getUrl({ name: 'del_dirents', repo_id: dirents.repo_id }) + '?parent_dir=' + encodeURIComponent(dirents.path), type: 'POST', dataType: 'json', beforeSend: Common.prepareCSRFToken, traditional: true, data: { 'dirents_names': selected_names }, success: function(data) { var del_len = data['deleted'].length, not_del_len = data['undeleted'].length, msg_s, msg_f; if (del_len > 0) { if (del_len == selected_names.length) { dirents.remove(selected_dirents); _this.$('th .checkbox').removeClass('checkbox-checked'); _this.$('#multi-dirents-op').hide(); } else { $(selected_dirents).each(function() { if (data['deleted'].indexOf(this.get('obj_name')) != -1) { dirents.remove(this); } }); } if (del_len == 1) { msg_s = gettext("Successfully deleted %(name)s."); } else if (del_len == 2) { msg_s = gettext("Successfully deleted %(name)s and 1 other item."); } else { msg_s = gettext("Successfully deleted %(name)s and %(amount)s other items."); } msg_s = msg_s.replace('%(name)s', Common.HTMLescape(data['deleted'][0])).replace('%(amount)s', del_len - 1); Common.feedback(msg_s, 'success'); } if (not_del_len > 0) { if (not_del_len == 1) { msg_f = gettext("Failed to delete %(name)s."); } else if (not_del_len == 2) { msg_f = gettext("Failed to delete %(name)s and 1 other item."); } else { msg_f = gettext("Failed to delete %(name)s and %(amount)s other items."); } msg_f = msg_f.replace('%(name)s', Common.HTMLescape(data['undeleted'][0])).replace('%(amount)s', not_del_len - 1); Common.feedback(msg_f, 'error'); } $.modal.close(); }, error: function(xhr, textStatus, errorThrown) { $.modal.close(); Common.ajaxErrorHandler(xhr, textStatus, errorThrown); } }); }; Common.showConfirm(gettext("Delete Items"), gettext("Are you sure you want to delete these selected items?"), del_dirents); }, mv: function () { this.mvcp({'op':'mv'}); }, cp: function () { this.mvcp({'op':'cp'}); }, mvcp: function (params) { var dir = this.dir; var op = params.op; var title = op == 'mv' ? gettext("Move selected item(s) to:") : gettext("Copy selected item(s) to:"); var show_cur_repo = true; if (dir.user_perm == 'r') { show_cur_repo = false; } var form = $(this.mvcpTemplate({ form_title: title, op_type: op, obj_type: '', obj_name: '', show_cur_repo: show_cur_repo, show_other_repos: !dir.encrypted })); form.modal({appendTo:'#main', autoResize:true, focus:false}); $('#simplemodal-container').css({'width':'auto', 'height':'auto'}); if (show_cur_repo) { FileTree.renderTreeForPath({ $form: form, $container: $('#current-repo-dirs'), repo_name: dir.repo_name, repo_id: dir.repo_id, path: dir.path }); } if (!dir.encrypted) { FileTree.prepareOtherReposTree({cur_repo_id: dir.repo_id}); } var _this = this; var dirents = this.dir; // get models var dirs = dirents.where({'is_dir':true, 'selected':true}), files = dirents.where({'is_file':true, 'selected':true}); var dir_names = [], file_names = []; $(dirs).each(function() { dir_names.push(this.get('obj_name')); }); $(files).each(function() { file_names.push(this.get('obj_name')); }); form.submit(function() { var dst_repo = $('[name="dst_repo"]', form).val(), dst_path = $('[name="dst_path"]', form).val(), url_main; var cur_path = dirents.path; var url_obj = {repo_id:dirents.repo_id}; if (!$.trim(dst_repo) || !$.trim(dst_path)) { $('.error', form).removeClass('hide'); return false; } if (dst_repo == dirents.repo_id && dst_path == cur_path) { $('.error', form).html(gettext("Invalid destination path")).removeClass('hide'); return false; } Common.disableButton($('[type="submit"]', form)); form.append('' + gettext("Processing...") + '
'); if (dst_repo == dirents.repo_id) { // when mv/cp in current lib, files/dirs can be handled in batch, and no need to show progress url_obj.name = op == 'mv' ? 'mv_dirents' : 'cp_dirents'; $.ajax({ url: Common.getUrl(url_obj) + '?parent_dir=' + encodeURIComponent(cur_path), type: 'POST', dataType: 'json', beforeSend: Common.prepareCSRFToken, traditional: true, data: { 'file_names': file_names, 'dir_names': dir_names, 'dst_repo': dst_repo, 'dst_path': dst_path }, success: function(data) { var success_len = data['success'].length, msg_s, msg_f, view_url = data['url']; $.modal.close(); if (success_len > 0) { if (op == 'mv') { if (success_len == files.length + dirs.length) { dirents.remove(dirs); dirents.remove(files); _this.$('th .checkbox').removeClass('checkbox-checked'); _this.$('#multi-dirents-op').hide(); } else { $(dirs).each(function() { if (this.get('obj_name') in data['success']) { dirents.remove(this); } }); $(files).each(function() { if (this.get('obj_name') in data['success']) { dirents.remove(this); } }); } if (success_len == 1) { msg_s = gettext("Successfully moved %(name)s."); } else if (success_len == 2) { msg_s = gettext("Successfully moved %(name)s and 1 other item."); } else { msg_s = gettext("Successfully moved %(name)s and %(amount)s other items."); } } else { // cp if (success_len == 1) { msg_s = gettext("Successfully copied %(name)s."); } else if (success_len == 2) { msg_s = gettext("Successfully copied %(name)s and 1 other item."); } else { msg_s = gettext("Successfully copied %(name)s and %(amount)s other items."); } } msg_s = msg_s.replace('%(name)s', Common.HTMLescape(data['success'][0])).replace('%(amount)s', success_len - 1); //msg_s += ' ' + "View" + ''; Common.feedback(msg_s, 'success'); } if (data['failed'].length > 0) { if (op == 'mv') { if (data['failed'].length > 1) { msg_f = gettext("Internal error. Failed to move %(name)s and %(amount)s other item(s)."); } else { msg_f = gettext("Internal error. Failed to move %(name)s."); } } else { if (data['failed'].length > 1) { msg_f = gettext("Internal error. Failed to copy %(name)s and %(amount)s other item(s)."); } else { msg_f = gettext("Internal error. Failed to copy %(name)s."); } } msg_f = msg_f.replace('%(name)s', Common.HTMLescape(data['failed'][0])).replace('%(amount)s', data['failed'].length - 1); Common.feedback(msg_f, 'error'); } }, error: function(xhr, textStatus, errorThrown) { $.modal.close(); Common.ajaxErrorHandler(xhr, textStatus, errorThrown); } }); } else { // when mv/cp to another lib, files/dirs should be handled one by one, and need to show progress var op_objs = dirents.where({'selected':true}), i = 0; // progress popup var mv_progress_popup = $(_this.mvProgressTemplate()); var details = $('#mv-details', mv_progress_popup), cancel_btn = $('#cancel-mv', mv_progress_popup), other_info = $('#mv-other-info', mv_progress_popup); var mvcpDirent = function () { var op_obj = op_objs[i], obj_type = op_obj.get('is_dir') ? 'dir':'file', obj_name = op_obj.get('obj_name'), post_url, post_data; if (op == 'mv') { url_obj.name = obj_type == 'dir' ? 'mv_dir' : 'mv_file'; } else { url_obj.name = obj_type == 'dir' ? 'cp_dir' : 'cp_file'; } post_url = Common.getUrl(url_obj) + '?path=' + encodeURIComponent(cur_path) + '&obj_name=' + encodeURIComponent(obj_name); post_data = { 'dst_repo': dst_repo, 'dst_path': dst_path }; var after_op_success = function (data) { var det_text = op == 'mv' ? gettext("Moving file %(index)s of %(total)s") : gettext("Copying file %(index)s of %(total)s"); details.html(det_text.replace('%(index)s', i + 1).replace('%(total)s', op_objs.length)).removeClass('vh'); cancel_btn.removeClass('hide'); var req_progress = function () { var task_id = data['task_id']; cancel_btn.data('task_id', task_id); $.ajax({ url: Common.getUrl({name:'get_cp_progress'}) + '?task_id=' + encodeURIComponent(task_id), dataType: 'json', success: function(data) { var bar = $('.ui-progressbar-value', $('#mv-progress')); if (!data['failed'] && !data['canceled'] && !data['successful']) { setTimeout(req_progress, 1000); } else { if (data['successful']) { bar.css('width', parseInt((i + 1)/op_objs.length*100, 10) + '%').show(); if (op == 'mv') { dirents.remove(op_obj); } endOrContinue(); } else { // failed or canceled if (data['failed']) { var error_msg = op == 'mv' ? gettext('Failed to move %(name)s') : gettext('Failed to copy %(name)s'); cancel_btn.after('' + error_msg.replace('%(name)s', Common.HTMLescape(obj_name)) + '
'); end(); } } } }, error: function(xhr, textStatus, errorThrown) { var error; if (xhr.responseText) { error = $.parseJSON(xhr.responseText).error; } else { error = gettext("Failed. Please check the network."); } cancel_btn.after('' + error + '
'); end(); } }); }; // 'req_progress' ends if (i == 0) { $.modal.close(); setTimeout(function () { mv_progress_popup.modal({containerCss: { width: 300, height: 150, paddingTop: 50 }, focus:false}); $('#mv-progress').progressbar(); req_progress(); }, 100); } else { req_progress(); } }; // 'after_op_success' ends Common.ajaxPost({ 'form': form, 'post_url': post_url, 'post_data': post_data, 'after_op_success': after_op_success, 'form_id': form.attr('id') }); }; // 'mvcpDirent' ends var endOrContinue = function () { if (i == op_objs.length - 1) { setTimeout(function () { $.modal.close(); }, 500); } else { mvcpDirent(++i); } }; var end = function () { setTimeout(function () { $.modal.close(); }, 500); }; mvcpDirent(); cancel_btn.click(function() { Common.disableButton(cancel_btn); var task_id = $(this).data('task_id'); $.ajax({ url: Common.getUrl({name:'cancel_cp'}) + '?task_id=' + encodeURIComponent(task_id), dataType: 'json', success: function(data) { other_info.html(gettext("Canceled.")).removeClass('hide'); cancel_btn.addClass('hide'); end(); }, error: function(xhr, textStatus, errorThrown) { var error; if (xhr.responseText) { error = $.parseJSON(xhr.responseText).error; } else { error = gettext("Failed. Please check the network."); } other_info.html(error).removeClass('hide'); Common.enableButton(cancel_btn); } }); }); } return false; }); }, onWindowScroll: function () { // 'more' if (this.dir.dirent_more && $(window).scrollTop() + $(window).height() > $(document).height() - $('#footer').outerHeight(true)) { this.render_dirents_slice(this.dir.last_start, this.dir.limit); this.getImageThumbnail(); } // fixed 'dir-op-bar' var op_bar = this.$dir_op_bar, path_bar = this.$path_bar, // the element before op_bar repo_file_list = this.$('.repo-file-list'); // the element after op_bar var op_bar_top = path_bar.offset().top + path_bar.outerHeight(true); var fixed_styles = { 'position': 'fixed', 'top': 0, 'left': path_bar.offset().left, 'z-index': 12 // make 'op_bar' shown on top of the checkboxes }; if ($(window).scrollTop() >= op_bar_top) { repo_file_list.css({'margin-top':op_bar.outerHeight(true)}); op_bar.outerWidth(this.$el.width()).css(fixed_styles); } else { repo_file_list.css({'margin-top':0}); op_bar.removeAttr('style'); } } }); return DirView; });