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()), dirents_hd_mobile_template: _.template($('#dirents-hd-mobile-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'; } this.contextOptions = {}; // for image files this.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: { titleSrc: function(item) { var img_name = Common.HTMLescape(item.data.name); var img_link = '' + gettext("Open in New Tab") + ''; return img_name + '
' + img_link; }, tError: gettext('The image could not be loaded.') // Error message when image could not be loaded } }; 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(); var _this = this; // scroll window: get 'more', fix 'op bar' $(window).scroll(function() { if ($(_this.el).is(':visible')) { _this.onWindowScroll(); } }); $(window).resize(function() { _this.updateDirOpBarUI(); }); // 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.$loading_tip = this.$('.loading-tip'); this.$error = this.$('.error'); this.$el_con = this.$('.repo-file-list-topbar, .js-dir-content'); this.$path_bar = this.$('.path-bar'); // For compatible with css, we use .repo-op instead of .dir-op this.$dir_op_bar = this.$('.repo-op'); }, // 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.dir.dirent_more = false; 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(); this.$el_con.show(); this.setFileInput(); this.updateDirOpBarUI(); // should be after `setFileInput()` // there may be a 'style' added via 'onWindowScroll()' when visiting last dir this.$('.js-dir-content').removeAttr('style'); if (this.view_mode == 'list') { this.renderDirentsHd(); } 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(); } // sort Common.updateSortIconByMode({'context': this.$el}); this.sortDirents(); this.updateMagnificPopupOptions(); this.dir.last_start = 0; this.dir.limit = 100; this.render_dirents_slice(this.dir.last_start, this.dir.limit); this.getImageThumbnail(); }, updateDirOpBarUI: function() { var width; if ($(window).width() > 500) { width = this.$('.repo-op').width() - parseInt(this.$('.repo-op-misc').css('margin-left')) - 5; width -= $('#multi-dirents-op').is(':visible') ? $('#multi-dirents-op').width() : $('#cur-dir-ops').width(); this.$('.repo-op-misc').css({'width': width}); } else { this.$('.repo-op-misc').removeAttr('style'); } }, updateMagnificPopupOptions: function() { var imgs = this.dir.where({is_img: true}); var items = []; var repo_id = this.dir.repo_id, path = this.dir.path; $(imgs).each(function(index, model) { var name = model.get('obj_name'); var dirent_path = Common.pathJoin([path, name]); items.push({ 'name': name, 'url': model.getWebUrl(), 'src': app.config.siteRoot + 'repo/' + repo_id + '/raw' + Common.encodePath(dirent_path) }); }); this.magnificPopupOptions.items = items; }, // for fileupload setFileInput: function() { var dir = this.dir; if (!dir.user_perm || dir.user_perm != 'rw') { return; } if (dir.no_quota) { return; } var $popup = this.fileUploadView.$el; if (app.pageOptions.enable_upload_folder) { if ('webkitdirectory' in $('#basic-upload-input')[0]) { 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"]'), // set 'replaceFileInput: false' for Firefox(v50) replaceFileInput: navigator.userAgent.indexOf('Firefox') == -1 ? true : false }); } 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.$loading_tip.show(); this.$error.hide(); this.$el_con.hide(); 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() { _this.$loading_tip.hide(); }, error: function(collection, response, opts) { _this.$loading_tip.hide(); _this.$el_con.hide(); 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.'); } _this.$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, no_quota: dir.no_quota, encrypted: dir.encrypted, mode: this.view_mode, path: dir.path, repo_id: dir.repo_id, site_root: app.pageOptions.site_root, is_repo_owner: dir.is_repo_owner, can_generate_share_link: app.pageOptions.can_generate_share_link, can_generate_upload_link: app.pageOptions.can_generate_upload_link, enable_upload_folder: app.pageOptions.enable_upload_folder }))) .removeAttr('style'); // there may be a 'style' added via 'onWindowScroll()' when visiting last dir if (dir.user_perm == 'rw') { // add new folder/file this.new_dropdown = new DropdownView({ el: this.$("#add-new") }); } }, renderDirentsHd: function() { var tmpl = $(window).width() < 768 ? this.dirents_hd_mobile_template : this.dirents_hd_template; this.$('thead').html(tmpl()); }, 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 #add-new-dir': 'newDir', 'click #add-new-file': 'newCommonFile', 'click #add-new-md-file': 'newMdFile', 'click #add-new-excel-file': 'newExcelFile', 'click #add-new-ppt-file': 'newPPTFile', 'click #add-new-word-file': 'newWordFile', '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 = { 'operation': 'mkdir' }, post_url = Common.getUrl({name: "new_dir", repo_id: dir.repo_id}) + '?p=' + encodeURIComponent(Common.pathJoin([dir.path, dirent_name])); var after_op_success = function(data) { $.modal.close(); var new_dirent = dir.add({ 'is_dir': true, 'obj_name': data['obj_name'], 'perm': 'rw', 'last_modified': new Date().getTime() / 1000, 'last_update': gettext("Just now"), 'p_dpath': Common.pathJoin([dir.path, data['obj_name']]) }, {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; }); return false; }, newFile: function(options) { var $form = $(this.newFileTemplate(options)), form_id = $form.attr('id'), $input = $('input[name="name"]', $form), dir = this.dir, dirView = this; $form.modal({ appendTo: '#main', focus: false, containerCss: {'padding':'20px 25px'} }); $('#simplemodal-container').css({'height':'auto'}); Common.setCaretPos($input[0], 0); $input.focus(); $form.submit(function() { var dirent_name = $.trim($input.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 = { 'operation': 'create' }, post_url = Common.getUrl({name: "new_file", repo_id: dir.repo_id}) + '?p=' + encodeURIComponent(Common.pathJoin([dir.path, dirent_name])); var after_op_success = function(data) { $.modal.close(); var new_dirent = dir.add({ 'is_file': true, 'is_img': Common.imageCheck(data.obj_name), 'obj_name': data.obj_name, 'file_size': Common.fileSizeFormat(data.size), 'obj_id': data.obj_id, '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; }); }, newCommonFile: function() { this.newFile({ title: gettext('New File'), initial_file_name: '' }); return false; }, newMdFile: function() { this.newFile({ title: gettext('New Markdown File'), initial_file_name: '.md' }); return false; }, newExcelFile: function() { this.newFile({ title: gettext('New Excel File'), initial_file_name: '.xlsx' }); return false; }, newPPTFile: function() { this.newFile({ title: gettext('New PowerPoint File'), initial_file_name: '.pptx' }); return false; }, newWordFile: function() { this.newFile({ title: gettext('New Word File'), initial_file_name: '.docx' }); 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; } }, sortDirents: function() { var sort_mode = app.pageOptions.sort_mode; switch(sort_mode) { case 'name_up': 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; } var result = Common.compareTwoWord(a.get('obj_name'), b.get('obj_name')); return result; }; break; case 'name_down': 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; } var result = Common.compareTwoWord(a.get('obj_name'), b.get('obj_name')); return -result; }; break; case 'time_up': 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; } return a.get('last_modified') < b.get('last_modified') ? -1 : 1; }; break; case 'time_down': 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; } return a.get('last_modified') < b.get('last_modified') ? 1 : -1; }; break; } this.dir.sort(); }, sortByName: function() { Common.toggleSortByNameMode(); Common.updateSortIconByMode({'context': this.$el}); this.sortDirents(); this.$dirent_list_body.empty(); this.render_dirents_slice(0, this.dir.limit); this.dir.comparator = null; return false; }, sortByTime: function () { Common.toggleSortByTimeMode(); Common.updateSortIconByMode({'context': this.$el}); this.sortDirents(); this.$dirent_list_body.empty(); this.render_dirents_slice(0, this.dir.limit); this.dir.comparator = null; return false; }, 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.$('#cur-dir-ops'); 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(); } this.updateDirOpBarUI(); }, download: function () { var dirents = this.dir; var parent_dir = dirents.path; var selected_dirents = dirents.where({'selected':true}); // select 1 item, and it is a file if (selected_dirents.length == 1 && selected_dirents[0].get('is_file')) { location.href = selected_dirents[0].getDownloadUrl(); return; } var selected_names = []; var interval; var zip_token; var packagingTip = gettext("Packaging..."); var $tip = $('

'); var queryZipProgress = function() { $.ajax({ url: Common.getUrl({name: 'query_zip_progress'}) + '?token=' + zip_token, dataType: 'json', cache: false, success: function(data) { var progress = data.total == 0 ? '100%' : (data.zipped/data.total*100).toFixed(0) + '%'; $tip.html(packagingTip + ' ' + progress); if (data['total'] == data['zipped']) { setTimeout(function() { $.modal.close(); }, 500); clearInterval(interval); location.href = Common.getUrl({ name: 'download_dir_zip_url', zip_token: zip_token }); } }, error: function(xhr) { Common.ajaxErrorHandler(xhr); clearInterval(interval); } }); }; $(selected_dirents).each(function() { selected_names.push(this.get('obj_name')); }); $.ajax({ url: Common.getUrl({name: 'zip_task', repo_id: dirents.repo_id}), data: { 'parent_dir': parent_dir, 'dirents': selected_names }, traditional: true, dataType: 'json', success: function(data) { zip_token = data['zip_token']; $tip.html(packagingTip).modal(); $('#simplemodal-container').css({'width':'auto'}); queryZipProgress(); interval = setInterval(queryZipProgress, 1000); }, 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(); _this.$('#cur-dir-ops').show(); } 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', 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', 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(); _this.$('#cur-dir-ops').show(); } 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', 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', 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()) { // scroll to the bottom 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.$('.js-dir-content'); // 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, 'background-color': $('#header').css('background-color'), 'z-index': 12 // make 'op_bar' shown on top of the checkboxes }; if (!op_bar_top) { return; } 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; });