Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F1975024
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
94 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/public_html/js/files_ui.js b/public_html/js/files_ui.js
index 7127a72..66f1a83 100644
--- a/public_html/js/files_ui.js
+++ b/public_html/js/files_ui.js
@@ -1,1997 +1,2048 @@
/*
+--------------------------------------------------------------------------+
| This file is part of the Kolab File API |
| |
| Copyright (C) 2012-2013, Kolab Systems AG |
| |
| This program is free software: you can redistribute it and/or modify |
| it under the terms of the GNU Affero General Public License as published |
| by the Free Software Foundation, either version 3 of the License, or |
| (at your option) any later version. |
| |
| This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU Affero General Public License for more details. |
| |
| You should have received a copy of the GNU Affero General Public License |
| along with this program. If not, see <http://www.gnu.org/licenses/> |
+--------------------------------------------------------------------------+
| Author: Aleksander Machniak <machniak@kolabsys.com> |
+--------------------------------------------------------------------------+
*/
function files_ui()
{
var ref = this;
this.request_timeout = 300;
this.message_time = 3000;
this.events = {};
this.commands = {};
this.requests = {};
this.uploads = {};
this.ie = document.all && !window.opera;
this.env = {
url: 'api/',
sort_col: 'name',
sort_reverse: 0,
search_threads: 1,
directory_separator: '/',
resources_dir: 'resources'
};
// set jQuery ajax options
$.ajaxSetup({
cache: false,
error: function(request, status, err) { ref.http_error(request, status, err); },
beforeSend: function(xmlhttp) { xmlhttp.setRequestHeader('X-Session-Token', ref.env.token); }
});
/*********************************************************/
/********* basic utilities *********/
/*********************************************************/
// initialize interface
this.init = function()
{
if (!this.env.token)
return;
if (this.env.task == 'main') {
this.enable_command('folder.list', 'folder.create', 'file.search', true);
this.command('folder.list');
}
else if (this.env.task == 'file') {
this.load_file('#file-content', this.env.filedata);
this.enable_command('file.delete', 'file.download', true);
}
if (!this.env.browser_capabilities)
this.browser_capabilities_check();
};
// set environment variable(s)
this.set_env = function(p, value)
{
if (p != null && typeof p === 'object' && !value)
for (var n in p)
this.env[n] = p[n];
else
this.env[p] = value;
};
// execute a specific command on the web client
this.command = function(command, props, obj)
{
if (obj && obj.blur)
obj.blur();
if (this.busy)
return false;
if (!this.commands[command])
return;
var ret = undefined,
func = command.replace(/[^a-z]/g, '_'),
task = command.replace(/\.[a-z-_]+$/g, '');
if (this[func] && typeof this[func] === 'function') {
ret = this[func](props);
}
return ret === false ? false : obj ? false : true;
};
this.set_busy = function(a, message)
{
if (a && this.busy)
return;
if (a && message) {
var msg = this.t(message);
if (msg == message)
msg = 'Loading...';
this.display_message(msg, 'loading');
}
else if (!a) {
this.hide_message('loading');
}
this.busy = a;
// if (this.gui_objects.editform)
// this.lock_form(this.gui_objects.editform, a);
// clear pending timer
if (this.request_timer)
clearTimeout(this.request_timer);
// set timer for requests
if (a && this.request_timeout)
this.request_timer = window.setTimeout(function() { ref.request_timed_out(); }, this.request_timeout * 1000);
};
// called when a request timed out
this.request_timed_out = function()
{
this.set_busy(false);
this.display_message('Request timed out!', 'error');
};
// Add variable to GET string, replace old value if exists
this.add_url = function(url, name, value)
{
value = urlencode(value);
if (/(\?.*)$/.test(url)) {
var urldata = RegExp.$1,
datax = RegExp('((\\?|&)'+RegExp.escape(name)+'=[^&]*)');
if (datax.test(urldata))
urldata = urldata.replace(datax, RegExp.$2 + name + '=' + value);
else
urldata += '&' + name + '=' + value
return url.replace(/(\?.*)$/, urldata);
}
return url + '?' + name + '=' + value;
};
this.trigger_event = function(event, data)
{
if (this.events[event])
for (var i in this.events[event])
this.events[event][i](data);
};
this.add_event_listener = function(event, func)
{
if (!this.events[event])
this.events[event] = [];
this.events[event].push(func);
};
this.buttons = function(p)
{
$.each(p, function(i, v) {
if (!ui.buttons[i])
ui.buttons[i] = [];
if (typeof v == 'object')
ui.buttons[i] = $.merge(ui.buttons[i], v);
else
ui.buttons[i].push(v);
});
};
this.enable_command = function()
{
var i, n, args = Array.prototype.slice.call(arguments),
enable = args.pop(), cmd;
for (n=0; n<args.length; n++) {
cmd = args[n];
// argument of type array
if (typeof cmd === 'string') {
this.commands[cmd] = enable;
if (this.buttons[cmd])
$.each(this.buttons[cmd], function (i, button) {
$('#'+button)[enable ? 'removeClass' : 'addClass']('disabled');
});
this.trigger_event('enable-command', {command: cmd, status: enable});
}
// push array elements into commands array
else {
for (i in cmd)
args.push(cmd[i]);
}
}
};
/*********************************************************/
/********* GUI functionality *********/
/*********************************************************/
// write to the document/window title
this.set_pagetitle = function(title)
{
if (title && document.title)
document.title = title;
};
// display a system message (types: loading, notice, error)
this.display_message = function(msg, type, timeout)
{
var obj, ref = this;
if (!type)
type = 'notice';
if (msg)
msg = this.t(msg);
if (type == 'loading') {
timeout = this.request_timeout * 1000;
if (!msg)
msg = this.t('loading');
}
else if (!timeout)
timeout = this.message_time * (type == 'error' || type == 'warning' ? 2 : 1);
obj = $('<div>');
if (type != 'loading') {
msg = '<div><span>' + msg + '</span></div>';
obj.addClass(type).click(function() { return ref.hide_message(); });
}
if (timeout > 0)
window.setTimeout(function() { ref.hide_message(type, type != 'loading'); }, timeout);
obj.attr('id', type == 'loading' ? 'loading' : 'message')
.appendTo('body').html(msg).show();
};
// make a message to disapear
this.hide_message = function(type, fade)
{
if (type == 'loading')
$('#loading').remove();
else
$('#message').fadeOut('normal', function() { $(this).remove(); });
};
this.set_watermark = function(id)
{
if (this.env.watermark)
$('#'+id).html(this.env.watermark);
};
- /********************************************************/
- /********* Remote request methods *********/
- /********************************************************/
-/*
- // send a http POST request to the server
- this.http_post = function(action, postdata)
- {
- var url = this.url(action);
-
- if (postdata && typeof postdata === 'object')
- postdata.remote = 1;
- else {
- if (!postdata)
- postdata = '';
- postdata += '&remote=1';
- }
-
- this.set_request_time();
-
- return $.ajax({
- type: 'POST', url: url, data: postdata, dataType: 'json',
- success: function(response) { ui.http_response(response); },
- error: function(o, status, err) { ui.http_error(o, status, err); }
- });
- };
-
- // handle HTTP response
- this.http_response = function(response)
- {
- var i;
-
- if (!response)
- return;
-
- // set env vars
- if (response.env)
- this.set_env(response.env);
-
- // we have translation labels to add
- if (typeof response.labels === 'object')
- this.tdef(response.labels);
-
- // HTML page elements
- if (response.objects)
- for (i in response.objects)
- $('#'+i).html(response.objects[i]);
-
- this.update_request_time();
- this.set_busy(false);
-
- // if we get javascript code from server -> execute it
- if (response.exec)
- eval(response.exec);
-
- this.trigger_event('http-response', response);
- };
-
- // handle HTTP request errors
- this.http_error = function(request, status, err)
- {
- var errmsg = request.statusText;
-
- this.set_busy(false);
- request.abort();
-
- if (request.status && errmsg)
- this.display_message(this.t('servererror') + ' (' + errmsg + ')', 'error');
- };
-*/
-
/********************************************************/
/********* Helper methods *********/
/********************************************************/
// disable/enable all fields of a form
this.lock_form = function(form, lock)
{
if (!form || !form.elements)
return;
var n, len, elm;
if (lock)
this.disabled_form_elements = [];
for (n=0, len=form.elements.length; n<len; n++) {
elm = form.elements[n];
if (elm.type == 'hidden')
continue;
// remember which elem was disabled before lock
if (lock && elm.disabled)
this.disabled_form_elements.push(elm);
// check this.disabled_form_elements before inArray() as a workaround for FF5 bug
// http://bugs.jquery.com/ticket/9873
else if (lock || (this.disabled_form_elements && $.inArray(elm, this.disabled_form_elements)<0))
elm.disabled = lock;
}
};
this.set_request_time = function()
{
this.env.request_time = (new Date()).getTime();
};
// Update request time element
this.update_request_time = function()
{
if (this.env.request_time) {
var t = ((new Date()).getTime() - this.env.request_time)/1000,
el = $('#reqtime');
el.text(el.text().replace(/[0-9.,]+/, t));
}
};
// position and display popup
this.popup_show = function(e, popup)
{
var popup = $(popup),
pos = this.mouse_pos(e),
win = $(window),
w = popup.width(),
h = popup.height(),
left = pos.left - w + 20,
top = pos.top - 10;
if (top + h > win.height())
top -= h;
if (left + w > win.width())
left -= w;
popup.css({left: left + 'px', top: top + 'px'})
.click(function(e) { e.stopPropagation(); $(this).hide(); }).show();
e.stopPropagation();
};
// Return absolute mouse position of an event
this.mouse_pos = function(e)
{
if (!e) e = window.event;
var mX = e.pageX ? e.pageX : e.clientX,
mY = e.pageY ? e.pageY : e.clientY;
if (document.body && document.all) {
mX += document.body.scrollLeft;
mY += document.body.scrollTop;
}
if (e._offset) {
mX += e._offset.left;
mY += e._offset.top;
}
return {left:mX, top:mY};
};
this.serialize_form = function(id)
{
var i, v, json = {},
form = $(id),
query = form.serializeArray();
for (i in query)
json[query[i].name] = query[i].value;
// serializeArray() doesn't work properly for multi-select
$('select[multiple="multiple"]', form).each(function() {
var name = this.name;
json[name] = [];
$(':selected', this).each(function() {
json[name].push(this.value);
});
});
return json;
};
/*********************************************************/
/********* Commands and response handlers *********/
/*********************************************************/
this.logout = function()
{
this.main_logout();
};
this.main_logout = function(params)
{
location.href = '?task=main&action=logout' + (params ? '&' + $.param(params) : '');
return false;
};
// folder list request
this.folder_list = function()
{
this.set_busy(true, 'loading');
this.request('folder_list', {}, 'folder_list_response');
};
// folder list response handler
this.folder_list_response = function(response)
{
if (!this.response(response))
return;
var elem = $('#folderlist'), table = $('table', elem);
this.env.folders = this.folder_list_parse(response.result && response.result.list ? response.result.list : response.result);
table.empty();
$.each(this.env.folders, function(i, f) {
var row = ui.folder_list_row(i, f);
table.append(row);
});
// add virtual collections
$.each(['audio', 'video', 'image', 'document'], function(i, n) {
var row = $('<tr><td><span class="name"></span></td></tr>'),
span = $('span.name', row);
row.attr('id', 'folder-collection-' + n);
span.text(ui.t('collection.' + n))
.click(function() { ui.folder_select(n, true); });
if (n == ui.env.collection)
row.addClass('selected');
table.append(row);
});
// add tree icons
this.folder_list_tree(this.env.folders);
// handle authentication errors on external sources
this.folder_list_auth_errors(response.result);
};
this.folder_select = function(folder, is_collection)
{
this.env.search = null;
this.file_search_stop();
var list = $('#folderlist');
$('tr.selected', list).removeClass('selected');
if (is_collection) {
var found = $('#folder-collection-' + folder, list).addClass('selected');
this.env.folder = null;
this.enable_command('file.list', true);
this.enable_command('folder.delete', 'folder.edit', 'file.upload', false);
this.file_list({collection: folder});
}
else {
var found = $('#' + this.env.folders[folder].id, list).addClass('selected');
this.env.collection = null;
this.enable_command('file.list', 'folder.delete', 'folder.edit', 'file.upload', found.length);
this.file_list({folder: folder});
}
};
this.folder_unselect = function()
{
this.env.search = null;
this.env.folder = null;
this.env.collection = null;
this.file_search_stop();
var list = $('#folderlist');
$('tr.selected', list).removeClass('selected');
this.enable_command('file.list', 'folder.delete', 'folder.edit', 'file.upload', false);
};
// folder create request
this.folder_create = function(folder)
{
if (!folder) {
this.folder_create_start();
return;
}
if (typeof folder != 'object') {
folder = {folder: folder};
}
this.set_busy(true, 'saving');
this.request('folder_create', folder, 'folder_create_response');
};
// folder create response handler
this.folder_create_response = function(response)
{
if (!this.response(response))
return;
this.folder_create_stop();
this.folder_list();
};
// folder rename request
this.folder_edit = function(folder)
{
if (!folder) {
this.folder_edit_start();
return;
}
this.set_busy(true, 'saving');
this.env.folder_rename = folder['new'];
this.request('folder_move', {folder: folder.folder, 'new': folder['new']}, 'folder_rename_response');
};
// folder rename response handler
this.folder_rename_response = function(response)
{
if (!this.response(response))
return;
this.env.folder = this.env.folder_rename;
this.folder_list();
this.file_list();
};
// folder delete request
this.folder_delete = function(folder)
{
if (folder === undefined)
folder = this.env.folder;
if (!folder)
return;
// @todo: confirm
this.set_busy(true, 'saving');
this.request('folder_delete', {folder: folder}, 'folder_delete_response');
};
// folder delete response handler
this.folder_delete_response = function(response)
{
if (!this.response(response))
return;
this.env.folder = null;
$('#filelist tbody').empty();
this.enable_command('folder.delete', 'folder.edit', 'file.list', 'file.search', 'file.upload', false);
this.folder_list();
};
// file list request
this.file_list = function(params)
{
if (!params)
params = {};
var i, req = (new Date).getTime();
// reset all pending list requests
for (i in this.requests) {
this.requests[i].abort();
delete this.requests[i];
}
if (params.all_folders) {
params.collection = null;
params.folder = null;
this.folder_unselect();
}
if (params.collection == undefined)
params.collection = this.env.collection;
if (params.folder == undefined)
params.folder = this.env.folder;
if (params.sort == undefined)
params.sort = this.env.sort_col;
if (params.reverse == undefined)
params.reverse = this.env.sort_reverse;
if (params.search == undefined)
params.search = this.env.search;
this.env.collection = params.collection;
this.env.folder = params.folder;
this.env.sort_col = params.sort;
this.env.sort_reverse = params.reverse;
// empty the list
$('#filelist tbody').empty();
this.env.file_list = [];
this.env.list_shift_start = null;
this.enable_command('file.open', 'file.get', 'file.rename', 'file.delete', 'file.copy', 'file.move', false);
// request
if (params.collection || params.all_folders)
this.file_list_loop(params);
else {
this.set_busy(true, 'loading');
this.requests[req] = this.request('file_list', params, 'file_list_response');
}
};
// call file.list request for every folder (used for search and virt. collections)
this.file_list_loop = function(params)
{
var i, folders = [], req = (new Date).getTime(),
limit = Math.max(this.env.search_threads || 1, 1);
if (params.collection) {
if (!params.search)
params.search = {};
params.search['class'] = params.collection;
delete params['collection'];
}
delete params['all_folders'];
$.each(this.env.folders, function(i, f) {
if (!f.virtual)
folders.push(i);
});
this.env.folders_loop = folders;
this.env.folders_loop_params = params;
this.env.folders_loop_lock = false;
for (i=0; i<folders.length && i<limit; i++) {
this.set_busy(true, 'loading');
params.folder = folders.shift();
this.requests[req+'-'+i] = this.request('file_list', params, 'file_list_loop_response');
}
};
// file list response handler
this.file_list_response = function(response)
{
if (!this.response(response))
return;
var table = $('#filelist'), list = [];
$.each(response.result, function(key, data) {
var row = ui.file_list_row(key, data);
table.append(row);
data.row = row;
list.push(data);
});
this.env.file_list = list;
};
// file list response handler for loop'ed request
this.file_list_loop_response = function(response)
{
var i, folders = this.env.folders_loop,
params = this.env.folders_loop_params,
limit = Math.max(this.env.search_threads || 1, 1),
valid = this.response(response),
req = (new Date).getTime();
for (i=0; i<folders.length && i<limit; i++) {
this.set_busy(true, 'loading');
params.folder = folders.shift();
this.requests[req+'-'+i] = this.request('file_list', params, 'file_list_loop_response');
}
if (!valid)
return;
this.file_list_loop_result_add(response.result);
};
// add files from list request to the table (with sorting)
this.file_list_loop_result_add = function(result)
{
// chack if result (hash-array) is empty
if (!object_is_empty(result))
return;
if (this.env.folders_loop_lock) {
setTimeout(function() { ui.file_list_loop_result_add(result); }, 100);
return;
}
// lock table, other list responses will wait
this.env.folders_loop_lock = true;
var n, i, len, elem, list = [], table = $('#filelist');
for (n=0, len=this.env.file_list.length; n<len; n++) {
elem = this.env.file_list[n];
for (i in result) {
if (this.sort_compare(elem, result[i]) < 0)
break;
var row = this.file_list_row(i, result[i]);
elem.row.before(row);
result[i].row = row;
list.push(result[i]);
delete result[i];
}
list.push(elem);
}
// add the rest of rows
$.each(result, function(key, data) {
var row = ui.file_list_row(key, data);
table.append(row);
result[key].row = row;
list.push(result[key]);
});
this.env.file_list = list;
this.env.folders_loop_lock = false;
};
// sort files list (without API request)
this.file_list_sort = function(col, reverse)
{
var n, len, list = this.env.file_list,
table = $('#filelist'), tbody = $('<tbody>');
this.env.sort_col = col;
this.env.sort_reverse = reverse;
if (!list || !list.length)
return;
// sort the list
list.sort(function (a, b) {
return ui.sort_compare(a, b);
});
// add rows to the new body
for (n=0, len=list.length; n<len; n++) {
tbody.append(list[n].row);
}
// replace table bodies
$('tbody', table).replaceWith(tbody);
};
// file delete request
this.file_delete = function(file)
{
if (!file) {
file = [];
if (this.env.file)
file.push(this.env.file);
else
file = this.file_list_selected();
}
this.set_busy(true, 'deleting');
this.request('file_delete', {file: file}, 'file_delete_response');
};
// file delete response handler
this.file_delete_response = function(response)
{
if (!this.response(response))
return;
if (this.env.file) {
var path = this.file_path(this.env.file);
if (window.opener && opener.ui && (!opener.ui.env.folder || opener.ui.env.folder == path))
opener.ui.file_list();
window.close();
}
else
this.file_list();
};
// file rename request
this.file_rename = function(file, newname)
{
if (file === newname)
return;
this.set_busy(true, 'saving');
this.request('file_move', {file: file, 'new': newname}, 'file_rename_response');
};
// file rename response handler
this.file_rename_response = function(response)
{
if (!this.response(response))
return;
// @TODO: we could update list/file metadata and just sort
this.file_list();
};
// file copy request
this.file_copy = function(folder)
{
var count = 0, list = {}, files = this.file_list_selected();
if (!files || !files.length || !folder)
return;
$.each(files, function(i, v) {
var name = folder + ui.env.directory_separator + ui.file_name(v);
if (name != v) {
list[v] = name;
count++;
}
});
if (!count)
return;
this.set_busy(true, 'copying');
this.request('file_copy', {file: list}, 'file_copy_response');
};
// file copy response handler
this.file_copy_response = function(response)
{
if (!this.response(response))
return;
if (response.result && response.result.already_exist && response.result.already_exist.length)
this.file_move_ask_user(response.result.already_exist);
};
// file move request
this.file_move = function(folder)
{
var count = 0, list = {}, files = this.file_list_selected();
if (!files || !files.length || !folder)
return;
$.each(files, function(i, v) {
var name = folder + ui.env.directory_separator + ui.file_name(v);
if (name != v) {
list[v] = name;
count++;
}
});
if (!count)
return;
this.set_busy(true, 'moving');
this.request('file_move', {file: list}, 'file_move_response');
};
// file move response handler
this.file_move_response = function(response)
{
if (!this.response(response))
return;
if (response.result && response.result.already_exist && response.result.already_exist.length)
this.file_move_ask_user(response.result.already_exist, true);
else
this.file_list();
};
this.file_download = function(file)
{
if (!file)
file = this.env.file;
location.href = this.env.url + this.url('file_get', {token: this.env.token, file: file, 'force-download': 1});
};
// file upload request
this.file_upload = function()
{
- var i, size = 0, maxsize = this.env.capabilities.MAX_UPLOAD,
- form = $('#uploadform'),
+ var form = $('#uploadform'),
field = $('input[type=file]', form).get(0),
files = field.files ? field.files.length : field.value ? 1 : 0;
- if (files) {
- // check upload max size
- if (field.files && maxsize) {
- for (i=0; i < files; i++)
- size += field.files[i].size;
+ if (!files || !this.file_upload_size_check(field.files))
+ return;
+
+ // submit form and read server response
+ this.file_upload_form(form, 'file_upload', function(e, frame, folder) {
+ var doc, response, res;
- if (size > maxsize) {
- alert(this.t('upload.size.error').replace('$size', this.file_size(maxsize)));
+ try {
+ doc = frame.contentDocument ? frame.contentDocument : frame.contentWindow.document;
+ response = doc.body.innerHTML;
+
+ // in Opera onload is called twice, once with empty body
+ if (!response)
return;
- }
+ // response may be wrapped in <pre> tag
+ if (response.match(/^<pre[^>]*>(.*)<\/pre>$/i))
+ response = RegExp.$1;
+
+ response = eval('(' + response + ')');
+ }
+ catch (err) {
+ response = {status: 'ERROR'};
}
- // submit form and read server response
- this.file_upload_form(form, 'file_upload', function(e, frame, folder) {
- var doc, response, res;
+ if ((res = ui.response_parse(response)) && folder == ui.env.folder)
+ ui.file_list();
- try {
- doc = frame.contentDocument ? frame.contentDocument : frame.contentWindow.document;
- response = doc.body.innerHTML;
+ return res;
+ });
+ };
- // in Opera onload is called twice, once with empty body
- if (!response)
- return;
- // response may be wrapped in <pre> tag
- if (response.match(/^<pre[^>]*>(.*)<\/pre>$/i))
- response = RegExp.$1;
+ // handler when files are dropped to a designated area.
+ // compose a multipart form data and submit it to the server
+ this.file_drop = function(e)
+ {
+ var files = e.target.files || e.dataTransfer.files;
- response = eval('(' + response + ')');
- }
- catch (err) {
- response = {status: 'ERROR'};
+ if (!files || !files.length || !this.file_upload_size_check(files))
+ return;
+
+ // prepare multipart form data composition
+ var ts = new Date().getTime(),
+ progress = this.env.capabilities.PROGRESS_NAME && window.progress_update,
+ formdata = window.FormData ? new FormData() : null,
+ fieldname = 'file[]',
+ boundary = '------multipartformboundary' + (new Date).getTime(),
+ dashdash = '--', crlf = '\r\n',
+ multipart = dashdash + boundary + crlf;
+
+ // inline function to submit the files to the server
+ var submit_data = function() {
+ var multiple = files.length > 1;
+
+ ui.uploads[ts] = ui.env.folder;
+
+ // start progress meter
+ if (progress)
+ ui.file_upload_progress(ts);
+
+ // complete multipart content and post request
+ multipart += dashdash + boundary + dashdash + crlf;
+
+ $.ajax({
+ type: 'POST',
+ dataType: 'json',
+ url: ui.env.url + ui.url('file_upload', {folder: ui.env.folder}),
+ contentType: formdata ? false : 'multipart/form-data; boundary=' + boundary,
+ processData: false,
+ timeout: 0, // disable default timeout set in ajaxSetup()
+ data: formdata || multipart,
+ success: function(response) {
+ if (ui.response_parse(response) && ui.uploads[ts] == ui.env.folder)
+ ui.file_list();
+ ui.file_upload_progress_stop(ts);
+ },
+ error: function(o, status, err) {
+ ui.http_error(o, status, err);
+ ui.file_upload_progress_stop(ts);
+ },
+ xhr: function() {
+ var xhr = jQuery.ajaxSettings.xhr();
+ if (!formdata && xhr.sendAsBinary)
+ xhr.send = xhr.sendAsBinary;
+ return xhr;
}
+ });
+ };
- if ((res = ui.response_parse(response)) && folder == ui.env.folder)
- ui.file_list();
+ // upload progress supported (and handler exists)
+ // add progress ID to the request - need to be added before files
+ if (progress) {
+ if (formdata)
+ formdata.append(this.env.capabilities.PROGRESS_NAME, ts);
+ else
+ multipart += 'Content-Disposition: form-data; name="' + ts.env.capabilities.PROGRESS_NAME + '"'
+ + crlf + crlf + ts + crlf + dashdash + boundary + crlf;
+ }
- return res;
- });
+ // get contents of all dropped files
+ var f, j, i = 0, last = files.length - 1;
+ for (j = 0; j <= last && (f = files[i]); i++) {
+ if (!f.name) f.name = f.fileName;
+ if (!f.size) f.size = f.fileSize;
+ if (!f.type) f.type = 'application/octet-stream';
+
+ // file name contains non-ASCII characters, do UTF8-binary string conversion.
+ if (!formdata && /[^\x20-\x7E]/.test(f.name))
+ f.name_bin = unescape(encodeURIComponent(f.name));
+
+ // do it the easy way with FormData (FF 4+, Chrome 5+, Safari 5+)
+ if (formdata) {
+ formdata.append(fieldname, f);
+ if (j == last)
+ return submit_data();
+ }
+ // use FileReader supporetd by Firefox 3.6
+ else if (window.FileReader) {
+ var reader = new FileReader();
+
+ // closure to pass file properties to async callback function
+ reader.onload = (function(file, j) {
+ return function(e) {
+ multipart += 'Content-Disposition: form-data; name="' + fieldname + '"';
+ multipart += '; filename="' + (f.name_bin || file.name) + '"' + crlf;
+ multipart += 'Content-Length: ' + file.size + crlf;
+ multipart += 'Content-Type: ' + file.type + crlf + crlf;
+ multipart += reader.result + crlf;
+ multipart += dashdash + boundary + crlf;
+
+ if (j == last) // we're done, submit the data
+ return submit_data();
+ }
+ })(f,j);
+ reader.readAsBinaryString(f);
+ }
+
+ j++;
}
};
/*********************************************************/
/********* Command helpers *********/
/*********************************************************/
// handle auth errors on folder list
this.folder_list_auth_errors = function(result)
{
if (result && result.auth_errors) {
if (!this.auth_errors)
this.auth_errors = {};
$.extend(this.auth_errors, result.auth_errors);
}
// ask for password to the first storage on the list
$.each(this.auth_errors || [], function(i, v) {
ui.folder_list_auth_dialog(i, v);
return false;
});
};
// create dialog for user credentials of external storage
this.folder_list_auth_dialog = function(label, driver)
{
var div, buttons = {},
content = this.folder_list_auth_form(driver),
title = this.t('folder.authenticate').replace('$title', label);
buttons['form.submit'] = function() {
var data = {folder: label, list: 1};
$('input', this.modal).each(function() {
data[this.name] = this.type == 'checkbox' && !this.checked ? '' : this.value;
});
ui.open_dialog = this;
ui.set_busy(true, 'authenticating');
ui.request('folder_auth', data, 'folder_auth_response');
};
buttons['form.cancel'] = function() {
delete ui.auth_errors[label];
this.hide();
// go to the next one
ui.folder_list_auth_errors();
};
// copy "remember password" checkbox into the dialog
div = $('.drivers-footer').first().clone();
if (div.length) {
div.find('input').each(function() { this.id += '-dialog'; });
div.find('label').each(function() { $(this).prop('for', $(this).prop('for') + '-dialog'); });
content.append(div.show());
}
this.modal_dialog(content, buttons, {
title: title,
fxOpen: function(win) {
// focus first empty input
$('input', win.modal).each(function() {
if (!this.value) {
this.focus();
return false;
}
});
}
});
};
// folder_auth handler
this.folder_auth_response = function(response)
{
if (!this.response(response))
return;
var cnt = 0, folders,
folder = response.result.folder,
parent = $('#' + this.env.folders[folder].id);
delete this.auth_errors[folder];
this.open_dialog.hide();
// go to the next one
this.folder_list_auth_errors();
// count folders on the list
$.each(this.env.folders, function() { cnt++; });
// parse result
folders = this.folder_list_parse(response.result.list, cnt);
delete folders[folder]; // remove root added in folder_list_parse()
// add folders from the external source to the list
$.each(folders, function(i, f) {
var row = ui.folder_list_row(i, f);
parent.after(row);
parent = row;
});
// add tree icons
this.folder_list_tree(folders);
$.extend(this.env.folders, folders);
};
// returns content of the external storage authentication form
this.folder_list_auth_form = function(driver)
{
var elements = [];
$.each(driver.form, function(fi, fv) {
var id = 'authinput' + fi,
attrs = {type: fi.match(/pass/) ? 'password' : 'text', size: 25, name: fi, id: id},
input = $('<input>').attr(attrs);
if (driver.form_values && driver.form_values[fi])
input.attr({value: driver.form_values[fi]});
elements.push($('<span class="formrow">').append($('<label>').attr('for', id).text(fv)).append(input));
});
return $('<div class="form">').append(elements);
};
// create folders table row
this.folder_list_row = function(folder, data)
{
var row = $('<tr><td><span class="branch"></span><span class="name"></span></td></tr>'),
span = $('span.name', row);
span.text(data.name);
row.attr('id', data.id).data('folder', folder);
if (data.depth)
$('span.branch', row).width(15 * data.depth);
if (data.virtual)
row.addClass('virtual');
else {
span.click(function() { ui.folder_select(folder); })
row.mouseenter(function() {
if (ui.drag_active && (!ui.env.folder || ui.env.folder != $(this).data('folder')))
$(this).addClass('droptarget');
})
.mouseleave(function() {
if (ui.drag_active)
$(this).removeClass('droptarget');
});
if (folder == this.env.folder)
row.addClass('selected');
}
return row;
};
// create files table row
this.file_list_row = function(filename, data)
{
var row = $('<tr><td class="filename"></td>'
+' <td class="filemtime"></td><td class="filesize"></td></tr>'),
link = $('<span></span>').text(data.name).click(function(e) { ui.file_menu(e, filename, data.type); });
$('td.filename', row).addClass(ui.file_type_class(data.type)).append(link);
$('td.filemtime', row).text(data.mtime);
$('td.filesize', row).text(ui.file_size(data.size));
row.attr('data-file', filename)
.click(function(e) { ui.file_list_click(e, this); })
.mousedown(function(e) { return ui.file_list_drag(e, this); });
// disables selection in IE
if (document.all)
row.on('selectstart', function() { return false; });
return row;
};
// file row click event handler
this.file_list_click = function(e, row)
{
var list = $('#filelist'), org = row, row = $(row),
found, selected, shift = this.env.list_shift_start;
if (e.shiftKey && shift && org != shift) {
$('tr', list).each(function(i, r) {
if (r == org) {
found = 1;
$(r).addClass('selected');
return;
}
else if (!selected && r == shift) {
selected = 1;
return;
}
if ((!found && selected) || (found && !selected))
$(r).addClass('selected');
else
$(r).removeClass('selected');
});
}
else if (e.ctrlKey)
row.toggleClass('selected');
else {
$('tr.selected', list).removeClass('selected');
$(row).addClass('selected');
this.env.list_shift_start = org;
}
selected = $('tr.selected', list).length;
if (!selected)
this.env.list_shift_start = null;
this.enable_command('file.delete', 'file.move', 'file.copy', selected);
this.enable_command('file.open', 'file.get', 'file.rename', selected == 1);
};
// file row drag start event handler
this.file_list_drag = function(e, row)
{
if (e.shiftKey || e.ctrlKey || $(e.target).is('input'))
return true;
// selects currently unselected row
if (!$(row).hasClass('selected'))
this.file_list_click(e, row);
this.drag_start = true;
this.drag_mouse_start = this.mouse_pos(e);
$(document)
.on('mousemove.draghandler', function(e) { ui.file_list_drag_mouse_move(e); })
.on('mouseup.draghandler', function(e) { ui.file_list_drag_mouse_up(e); });
/*
if (bw.mobile) {
$(document)
.on('touchmove.draghandler', function(e) { ui.file_list_drag_mouse_move(e); })
.on('touchend.draghandler', function(e) { ui.file_list_drag_mouse_up(e); });
}
*/
return false;
};
// file row mouse move event handler
this.file_list_drag_mouse_move = function(e)
{
/*
// convert touch event
if (e.type == 'touchmove') {
if (e.changedTouches.length == 1)
e = rcube_event.touchevent(e.changedTouches[0]);
else
return rcube_event.cancel(e);
}
*/
var max_rows = 10, pos = this.mouse_pos(e);
if (this.drag_start) {
// check mouse movement, of less than 3 pixels, don't start dragging
if (!this.drag_mouse_start || (Math.abs(pos.left - this.drag_mouse_start.left) < 3 && Math.abs(pos.top - this.drag_mouse_start.top) < 3))
return false;
if (!this.draglayer)
this.draglayer = $('<div>').attr('id', 'draglayer')
.css({position:'absolute', display:'none', 'z-index':2000})
.appendTo(document.body);
// reset content
this.draglayer.html('');
// get subjects of selected messages
$('#filelist tr.selected').slice(0, max_rows+1).each(function(i) {
if (i == 0)
ui.drag_start_pos = $(this).offset();
else if (i == max_rows) {
ui.draglayer.append('...');
return;
}
var subject = $('td.filename', this).text();
// truncate filename to 50 characters
if (subject.length > 50)
subject = subject.substring(0, 50) + '...';
ui.draglayer.append($('<div>').text(subject));
});
this.draglayer.show();
this.drag_active = true;
}
if (this.drag_active && this.draglayer)
this.draglayer.css({left:(pos.left+20)+'px', top:(pos.top-5 + (this.ie ? document.documentElement.scrollTop : 0))+'px'});
this.drag_start = false;
return false;
};
// file row mouse up event handler
this.file_list_drag_mouse_up = function(e)
{
document.onmousemove = null;
/*
if (e.type == 'touchend') {
if (e.changedTouches.length != 1)
return rcube_event.cancel(e);
}
*/
$(document).off('.draghandler');
this.drag_active = false;
var got_folder = this.file_list_drag_end(e);
if (this.draglayer && this.draglayer.is(':visible')) {
if (this.drag_start_pos && !got_folder)
this.draglayer.animate(this.drag_start_pos, 300, 'swing').hide(20);
else
this.draglayer.hide();
}
};
// files drag end handler
this.file_list_drag_end = function(e)
{
var folder = $('#folderlist tr.droptarget').removeClass('droptarget');
if (folder.length) {
folder = folder.data('folder');
if (e.shiftKey && this.commands['file.copy']) {
this.file_drag_menu(e, folder);
return true;
}
this.command('file.move', folder);
return true;
}
};
// display file drag menu
this.file_drag_menu = function(e, folder)
{
var menu = $('#file-drag-menu');
$('li.file-copy > a', menu).off('click').click(function() { ui.command('file.copy', folder); });
$('li.file-move > a', menu).off('click').click(function() { ui.command('file.move', folder); });
this.popup_show(e, menu);
};
// display file menu
this.file_menu = function(e, file, type)
{
var href, caps, viewer,
menu = $('#file-menu'),
open_action = $('li.file-open > a', menu);
if (viewer = this.file_type_supported(type)) {
caps = this.browser_capabilities().join();
href = '?' + $.param({task: 'file', action: 'open', token: this.env.token, file: file, caps: caps, viewer: viewer == 2 ? 1 : 0});
open_action.attr({target: '_blank', href: href}).removeClass('disabled').off('click');
}
else
open_action.click(function() { return false; }).addClass('disabled');
$('li.file-download > a', menu)
.attr({href: this.env.url + this.url('file_get', {token: this.env.token, file: file, 'force-download': 1})});
$('li.file-delete > a', menu).off('click').click(function() { ui.file_delete(file); });
$('li.file-rename > a', menu).off('click').click(function() { ui.file_rename_start(e); });
this.popup_show(e, menu);
};
// returns selected files (with paths)
this.file_list_selected = function()
{
var files = [];
$('#filelist tr.selected').each(function() {
files.push($(this).data('file'));
});
return files;
};
this.file_rename_start = function(e)
{
var list = $('#filelist'),
tr = $(e.target).parents('tr'),
td = $('td.filename', tr),
file = tr.data('file'),
name = this.file_name(file),
input = $('<input>').attr({type: 'text', name: 'filename', 'class': 'filerename'})
.val(name).data('file', file)
.click(function(e) { e.stopPropagation(); })
.keydown(function(e) {
switch (e.which) {
case 27: // ESC
ui.file_rename_stop();
break;
case 13: // Enter
var elem = $(this),
newname = elem.val(),
oldname = elem.data('file'),
path = ui.file_path(file);
ui.file_rename(oldname, path + ui.env.directory_separator + newname);
elem.parent().text(newname);
break;
}
});
$('span', td).text('').append(input);
input.focus();
};
this.file_rename_stop = function()
{
$('input.filerename').each(function() {
var elem = $(this), name = ui.file_name(elem.data('file'));
elem.parent().text(name);
});
};
// post the given form to a hidden iframe
this.file_upload_form = function(form, action, onload)
{
var ts = new Date().getTime(),
frame_name = 'fileupload' + ts;
this.uploads[ts] = this.env.folder;
// upload progress supported (and handler exists)
if (this.env.capabilities.PROGRESS_NAME && window.progress_update) {
var fname = this.env.capabilities.PROGRESS_NAME,
field = $('input[name='+fname+']', form);
if (!field.length) {
field = $('<input>').attr({type: 'hidden', name: fname});
field.prependTo(form);
}
field.val(ts);
this.file_upload_progress(ts);
}
// have to do it this way for IE
// otherwise the form will be posted to a new window
if (document.all) {
document.body.insertAdjacentHTML('BeforeEnd',
'<iframe id="'+frame_name+'" name="'+frame_name+'"'
+ ' src="' + this.env.resources_dir + '/blank.gif" '
+ ' style="width:0;height:0;visibility:hidden;"></iframe>');
}
// for standards-compliant browsers
else
$('<iframe>')
.attr({name: frame_name, id: frame_name})
.css({border: 'none', width: 0, height: 0, visibility: 'hidden'})
.appendTo(document.body);
// handle upload errors, parsing iframe content in onload
$('#'+frame_name).load(function(e) {
- // hide progressbar on upload error
- if (!onload(e, this, ui.uploads[ts]) && window.progress_update)
- window.progress_update({id: ts, done: true});
- delete ui.uploads[ts];
+ onload(e, this, ui.uploads[ts]);
+ ui.file_upload_progress_stop(ts);
});
$(form).attr({
target: frame_name,
- action: this.env.url + this.url(action, {folder: this.env.folder, token: this.env.token, uploadid:ts}),
+ action: this.env.url + this.url(action, {folder: this.env.folder, token: this.env.token}),
method: 'POST'
}).attr(form.encoding ? 'encoding' : 'enctype', 'multipart/form-data')
.submit();
};
// upload progress requests
this.file_upload_progress = function(id)
{
setTimeout(function() {
if (id && ui.uploads[id])
ui.request('upload_progress', {id: id}, 'file_upload_progress_response');
}, this.env.capabilities.PROGRESS_TIME * 1000);
};
// upload progress response
this.file_upload_progress_response = function(response)
{
if (!this.response(response))
return;
var param = response.result;
if (param.id && window.progress_update)
window.progress_update(param);
if (!param.done)
this.file_upload_progress(param.id);
};
+ this.file_upload_progress_stop = function(id)
+ {
+ if (window.progress_update)
+ window.progress_update({id: id, done: true});
+ delete ui.uploads[id];
+ };
+
+ // check upload max size
+ this.file_upload_size_check = function(files)
+ {
+ var i, size = 0, maxsize = this.env.capabilities.MAX_UPLOAD;
+
+ if (files && maxsize) {
+ for (i=0; i < files.length; i++)
+ size += files[i].size;
+
+ if (size > maxsize) {
+ alert(this.t('upload.size.error').replace('$size', this.file_size(maxsize)));
+ return false;
+ }
+ }
+
+ return true;
+ };
+
// Display file search form
this.file_search = function()
{
var form = this.form_show('file-search'),
has_folder = this.env.folder || this.env.collection,
radio1 = $('input[name="all_folders"][value="0"]', form);
$('input[name="name"]', form).val('').focus();
if (has_folder)
radio1.prop('disabled', false).click();
else {
radio1.prop('disabled', true);
$('input[name="all_folders"][value="1"]', form).click();
}
};
// Hide file search form
this.file_search_stop = function()
{
if (this.env.search)
this.file_list(null, {search: null});
this.form_hide('file-search');
this.env.search = null;
};
// Execute file search
this.file_search_submit = function()
{
var form = this.form_show('file-search'),
value = $('input[name="name"]', form).val(),
all = $('input[name="all_folders"]:checked', form).val();
if (value) {
this.env.search = {name: value};
this.file_list({search: this.env.search, all_folders: all == 1});
}
else
this.file_search_stop();
};
// Display folder creation form
this.folder_create_start = function()
{
var form = $('#folder-create-form');
$('.drivers', form).hide();
$('input[name="name"]', form).val('').focus();
$('input[name="parent"]', form).prop('checked', this.env.folder)
.prop('disabled', !this.env.folder);
$('#folder-driver-checkbox').prop('checked', false);
this.form_show('folder-create');
if (!this.folder_types)
this.request('folder_types', {}, 'folder_types_response');
else
this.folder_types_init();
};
// Hide folder creation form
this.folder_create_stop = function()
{
this.form_hide('folder-create');
};
// Submit folder creation form
this.folder_create_submit = function()
{
var args = {}, folder = '', data = this.serialize_form('#folder-create-form');
if (!data.name)
return;
if (data.parent && this.env.folder) {
folder = this.env.folder + this.env.directory_separator;
}
else if (data.external && data.driver) {
args.store_passwords = data.store_passwords;
args.driver = data.driver;
$.each(data, function(i, v) {
if (i.startsWith(data.driver + '[')) {
args[i.substring(data.driver.length + 1, i.length - 1)] = v;
}
});
}
folder += data.name;
args.folder = folder;
this.command('folder.create', args);
};
// folder_types response handler
this.folder_types_response = function(response)
{
if (!this.response(response))
return;
if (response.result) {
this.folder_types = response.result;
var list = [];
$.each(this.folder_types, function(i, v) {
var form = [], item = $('<div>').data('id', i),
content = $('<div class="content">')
label = $('<span class="name">').text(v.name),
desc = $('<span class="description">').text(v.description),
img = $('<img>').attr({alt: i, title: i, src: v.image}),
input = $('<input>').attr({type: 'radio', name: 'driver'}).val(i);
item.append(input)
.append(img)
.append(content);
content.append(label).append($('<br>')).append(desc);
$.each(v.form || [], function(fi, fv) {
var id = 'input' +i + fi,
attrs = {type: fi.match(/pass/) ? 'password' : 'text', size: 25, name: i + '[' + fi + ']', id: id};
form.push($('<span class="formrow">')
.append($('<label>').attr('for', id).text(fv))
.append($('<input>').attr(attrs))
);
});
if (form.length) {
$('<div class="form">').append(form).appendTo(content);
}
list.push(item);
});
if (list.length) {
var drivers_list = $('.drivers-list');
drivers_list.append(list);
this.form_show('folder-create');
$.each(list, function() {
this.click(function() {
$('.selected', drivers_list).removeClass('selected');
drivers_list.find('.form').hide();
$(this).addClass('selected').find('.form').show();
$('input[type="radio"]', this).prop('checked', true);
ref.form_show('folder-create');
});
});
$('#folder-parent-checkbox').change(function() {
if (this.checked)
$('#folder-create-form div.drivers').hide();
ref.folder_types_init();
});
$('#folder-driver-checkbox').change(function() {
drivers_list[this.checked ? 'show' : 'hide']();
$('.drivers-footer')[this.checked ? 'show' : 'hide']();
ref.folder_types_init();
});
this.folder_types_init();
}
}
};
// initialize folder types list on folder create form display
this.folder_types_init = function()
{
var form = $('#folder-create-form'),
list = $('.drivers-list > div', form);
if (list.length && !$('input[name="parent"]', form).is(':checked')) {
$('#folder-create-form div.drivers').show();
list[0].click();
}
$('.drivers-list,.drivers-footer')[list.length && $('#folder-driver-checkbox:checked').length ? 'show' : 'hide']();
ref.form_show('folder-create');
};
// Display folder edit form
this.folder_edit_start = function()
{
var opts = [], separator = this.env.directory_separator,
form = this.form_show('folder-edit'),
select = $('#folder-edit-parent-select'),
arr = this.env.folder.split(separator),
name = arr.pop();
$('input[name="name"]', form).val(name).focus();
$('option[value!=""]', select).remove();
$.each(this.env.folders, function(i, v) {
var n, arr = i.split(separator),
name = arr.pop(), prefix = '', level = ' ';
for (n=arr.length; n>0; n--)
prefix += level;
opts.push($('<option>').attr('value', i).html(prefix).append($('<span>').text(name)));
});
select.append(opts).val(arr.join(separator));
};
// Hide folder edit form
this.folder_edit_stop = function()
{
this.form_hide('folder-edit');
};
// Submit folder edit form
this.folder_edit_submit = function()
{
var folder = '', data = this.serialize_form('#folder-edit-form');
if (!data.name)
return;
if (data.parent)
folder = data.parent + this.env.directory_separator;
folder += data.name;
this.folder_edit_stop();
this.command('folder.edit', {folder: this.env.folder, 'new': folder});
};
// when file move/copy operation returns file-exists error
// this displays a dialog where user can decide to skip
// or overwrite destination file(s)
this.file_move_ask_user = function(list, move)
{
var file = list[0], buttons = {},
label = this.t('file.moveconfirm').replace('$file', file.dst);
buttons['file.overwrite'] = function() {
var file = list.shift(), f = {},
action = move ? 'file_move' : 'file_copy';
f[file.src] = file.dst;
ui.file_move_ask_list = list;
ui.file_move_ask_mode = move;
this.hide();
ui.set_busy(true, move ? 'moving' : 'copying');
ui.request(action, {file: f, overwrite: 1}, 'file_move_ask_user_response');
};
if (list.length > 1)
buttons['file.overwriteall'] = function() {
var f = {}, action = move ? 'file_move' : 'file_copy';
$.each(list, function() { f[this.src] = this.dst; });
this.hide();
ui.set_busy(true, move ? 'moving' : 'copying');
ui.request(action, {file: f, overwrite: 1}, action + '_response');
};
buttons['file.skip'] = function() {
list.shift();
this.hide();
if (list.length)
ui.file_move_ask_user(list, move);
else if (move)
ui.file_list();
};
if (list.length > 1)
buttons['file.skipall'] = function() {
this.hide();
if (move)
ui.file_list();
};
this.modal_dialog(label, buttons);
};
// file move (with overwrite) response handler
this.file_move_ask_user_response = function(response)
{
var mode = this.file_move_ask_mode, list = this.file_move_ask_list;
this.response(response);
if (list && list.length)
this.file_move_ask_user(list, mode);
else if (mode)
this.file_list();
};
this.file_edit = function()
{
if (this.file_editor) {
this.file_editor.enable();
this.enable_command('file.save', true);
}
};
this.file_save = function()
{
if (!this.file_editor)
return;
var content = this.file_editor.getContent();
this.file_editor.disable();
// because we currently can edit only text file
// and we do not expect them to be very big, we save
// file in a very simple way, no upload progress, etc.
this.set_busy(true, 'saving');
this.request('file_update', {file: this.env.file, content: content, info: 1}, 'file_save_response');
};
this.file_save_response = function(response)
{
this.file_editor.enable();
if (!this.response(response))
return;
// update file properties table
var table = $('#filedata table'), file = response.result;
if (response.result) {
$('td.filetype', table).text(file.type);
$('td.filesize', table).text(this.file_size(file.size));
$('td.filemtime', table).text(file.mtime);
}
};
/*********************************************************/
/********* Utilities *********/
/*********************************************************/
// modal dialog popup
this.modal_dialog = function(content, buttons, opts)
{
var settings = {position: 'cm', btns: {}, fxShow: 'fade'},
dialog = $('<div class="_wModal"></div>'),
body = $('<div class="_wModal"></div>'),
head, foot, footer = [];
// title bar
if (opts && opts.title)
$('<div class="_wModal_header"></div>')
.append($('<span>').text(opts.title))
.appendTo(body);
// dialog content
if (typeof content != 'object')
content = $('<div></div>').html(content);
content.addClass('_wModal_msg').appendTo(body);
// buttons
$.each(buttons, function(i, v) {
var n = i.replace(/[^a-z0-9_]/ig, '');
settings.btns[n] = v;
footer.push({name: n, label: ui.t(i)});
});
// open function
settings.fxOpen = opts.fxOpen;
// if (!settings.btns.cancel && (!opts || !opts.no_cancel))
// settings.btns.cancel = function() { this.hide(); };
if (footer.length) {
foot = $('<div class="_wModal_btns"></div>');
$.each(footer, function() {
$('<div tabindex="0"></div>').addClass('_wModal_btn_' + this.name).text(this.label).appendTo(foot)
});
body.append(foot);
// make buttons focusable and key-pressable
$(document).off('keydown.dialog').on('keydown.dialog', function(e) {
if (e.which == 13 && $(e.target).parent().is('._wModal_btns')) {
$(e.target).click();
}
});
}
// configure and display dialog
dialog.append(body).wModal(settings).wModal('show');
};
// Display folder creation form
this.form_show = function(name)
{
var form = $('#' + name + '-form');
if (form.is(':hidden')) {
$('#forms > form').hide();
form.show();
}
$('#taskcontent').css('top', form.height() + 20);
return form;
};
// Display folder creation form
this.form_hide = function(name)
{
var form = $('#' + name + '-form');
form.hide();
$('#taskcontent').css('top', 10);
};
// loads a file content into an iframe (with loading image)
this.load_file = function(content, filedata)
{
var iframe = $(content);
if (!iframe.length)
return;
var href = filedata.href,
div = iframe.parent(),
loader = $('#loader'),
offset = div.offset(),
w = loader.width(), h = loader.height(),
width = div.width(), height = div.height();
loader.css({
top: offset.top + height/2 - h/2 - 20,
left: offset.left + width/2 - w/2
}).show();
iframe.css('opacity', 0.1)
.load(function() { ui.loader_hide(this); })
.attr('src', href);
// some content, e.g. movies or flash doesn't execute onload on iframe
// let's wait some time and check document ready state
if (!/^text/i.test(filedata.mimetype))
setTimeout(function() {
// there sometimes "Permission denied to access propert document", use try/catch
try {
$(iframe.get(0).contentWindow.document).ready(function() {
parent.ui.loader_hide(content);
});
} catch (e) {};
}, 1000);
};
// hide content loader element, show content element
this.loader_hide = function(content)
{
$('#loader').hide();
$(content).css('opacity', 1);
var win = content.contentWindow;
this.file_editor = null;
try {
// it throws "permission denied" sometimes
if (win.file_editor && win.file_editor.editable)
this.file_editor = win.file_editor;
}
catch (e) {}
if (this.file_editor)
ui.enable_command('file.edit', true);
};
};
// Initialize application object (don't change var name!)
var ui = $.extend(new files_api(), new files_ui());
// general click handler
$(document).click(function() {
$('.popup').hide();
ui.file_rename_stop();
}).ready(function() {
ui.init();
});
diff --git a/public_html/skins/default/style.css b/public_html/skins/default/style.css
index 0a78506..d085e5e 100644
--- a/public_html/skins/default/style.css
+++ b/public_html/skins/default/style.css
@@ -1,1520 +1,1540 @@
body {
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 12px;
color: #333;
margin: 0;
color: #514949;
background: url(images/body.png) top repeat-x #f0f0f0;
}
a {
color: #1E90FF;
text-decoration: none;
}
h1, h2, h3, h4, h5, h6 {
margin-top: 5px;
color: #ff9900;
}
input[type="text"],
input[type="password"],
select[multiple="multiple"],
textarea {
border: 1px solid #d0d0d0;
border-radius: 3px;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
padding-left: 2px;
color: black;
}
input[type="checkbox"],
input[type="radio"] {
vertical-align: middle;
}
select[multiple="multiple"] {
padding-left: 0;
}
table.list {
width: 100%;
table-layout: fixed;
border-spacing: 0;
border-radius: 3px;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
}
table.list td {
padding: 2px 4px;
border: 1px solid white;
border-left: none;
border-top: none;
user-select: none;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
}
table.list thead tr {
background-color: #e0e0e0;
font-weight: bold;
}
table.list tbody tr {
background-color: #f0f0f0;
}
table.list tfoot tr {
background-color: #e0e0e0;
}
table.list tfoot tr td {
padding: 3px 3px;
font-size: 10px;
text-shadow: white 1px 1px;
}
table.list tfoot tr td {
border-top: solid 1px white;
border-bottom: none;
}
table.list td:last-child {
border-right: none;
}
table.list tbody tr.selectable td {
cursor: default;
}
table.list tbody tr.selectable:hover {
background-color: #d6efff;
}
table.list tbody tr td.empty-body {
height: 150px;
color: #ff9900;
text-align: center;
}
fieldset {
border: 1px solid #d0d0d0;
border-radius: 3px;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
margin-top: 10px;
}
legend {
padding-left: 0;
color: #909090;
}
table.form {
width: 100%;
}
table.form td {
padding: 1px 5px;
}
table.form tr.required input,
table.form tr.required select,
table.form tr.required textarea {
background-color: #f0f9ff;
}
table.form tr input.error,
table.form tr select.error,
table.form tr textarea.error {
background-color: #f5e3e3;
}
td.label {
width: 1%;
min-width: 120px;
text-align: right;
font-weight: bold;
white-space: nowrap;
}
table tbody tr.selected {
background-color: #d6efff;
}
/**** Common UI elements ****/
#topmenu {
text-align: right;
height: 20px;
padding: 0 10px;
margin: 0;
white-space: nowrap;
background: url(images/linen_header.jpg) 0 0 repeat-x;
}
#topmenu > span {
color: #aaa;
font-size: 11px;
padding-top: 2px;
display: inline-block;
height: 18px;
}
#navigation {
margin: 0 15px;
text-align: right;
height: 36px;
z-index: 2;
white-space: nowrap;
}
#task_navigation {
margin: 0 15px;
text-align: right;
height: 21px;
z-index: 2;
white-space: nowrap;
}
#message {
position: absolute;
top: 80px;
left: 20px;
width: 350px;
height: 60px;
z-index: 20;
}
#message div {
opacity: 0.97;
padding-left: 70px;
border: 1px solid #d0d0d0;
border-radius: 3px;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
-moz-box-shadow: 1px 1px 3px #999;
-webkit-box-shadow: #999 1px 1px 3px;
width: 100%;
height: 100%;
display: table;
}
#message.notice div {
border-color: #aec1db;
color: #3465a4;
background: url(images/info.png) 10px center no-repeat #c0e0ff;
}
#message.error div {
border-color: #db9999;
color: #a40000;
background: url(images/error.png) 10px center no-repeat #edcccc;
}
#message div span {
vertical-align: middle;
display: table-cell;
line-height: 20px;
}
#logo {
position: absolute;
top: 0px;
left: 10px;
width: 198px;
height: 74px;
cursor: pointer;
background: url(images/logo.png) 0 0 no-repeat;
}
#content {
position: absolute;
left: 0;
right: 0;
top: 74px;
bottom: 55px;
margin: 0 15px;
padding: 10px;
background-color: #f5f5f5;
border: 1px solid #d0d0d0;
border-radius: 3px;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
}
#footer {
position: absolute;
left: 0;
right: 0;
bottom: 0;
height: 50px;
margin: 2px 15px;
color: #b0b0b0;
font-size: 9px;
}
#loading {
position: absolute;
display: none;
top: 2px;
left: 15px;
width: 150px;
height: 18px;
padding-left: 86px;
color: #aaa;
font-size: 11px;
z-index: 1;
background: url(images/loading.gif) 0 3px no-repeat;
white-space: nowrap;
}
#topmenu .logout {
background: url(images/buttons.png) -1px -100px no-repeat;
padding-left: 20px;
margin-right: 10px;
color: white;
}
#topmenu .login {
padding-left: 20px;
margin-right: 20px;
background: url(images/user_ico.png) 0 2px no-repeat;
}
#topmenu .domain {
padding-left: 20px;
margin-right: 10px;
background: url(images/domain_ico.png) 0 3px no-repeat;
}
#navigation ul {
list-style-type: none;
margin: 0;
padding: 8px 0;
}
#navigation ul li {
display: inline;
font-size: 13px;
font-weight: bold;
padding: 8px 0;
}
#navigation ul li a {
padding: 8px 10px;
text-decoration: none;
color: #514949;
}
#navigation ul li.active {
background: url(images/navbg.png) 0 0 repeat-x;
}
#navigation ul li.active a {
text-shadow: white 1px 1px;
color: #ff9900;
}
#task_navigation ul {
list-style-type: none;
margin: 0;
padding: 2px 0;
}
#task_navigation ul li {
padding: 1px 0;
display: inline;
font-size: 12px;
font-weight: bold;
text-shadow: white 1px 1px;
}
#task_navigation ul li a {
padding: 1px 10px;
text-decoration: none;
color: #808080;
}
#navigation ul li a:active,
#task_navigation ul li a:active {
outline: none;
}
#search {
padding: 7px;
margin-bottom: 10px;
border: 1px solid #d0d0d0;
border-radius: 3px;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
background-color: #e0e0e0;
}
#searchinput {
border: none;
background-color: white;
margin-top: 2px;
}
#searchinput:focus {
outline: none;
}
.searchinput {
height: 20px;
margin: 0;
padding: 0;
background-color: white;
border: 1px solid #d0d0d0;
border-radius: 3px;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
overflow: hidden;
}
.searchactions {
float: left;
padding: 1px;
margin-left: -1px;
height: 18px;
width: 37px;
background-color: #f0f0f0;
cursor: pointer;
border-right: 1px solid #e0e0e0;
border-top-left-radius: 3px;
border-bottom-left-radius: 3px;
-moz-border-radius-topleft: 3px;
-moz-border-radius-bottomleft: 3px;
-webkit-border-top-left-radius: 3px;
-webkit-border-left-right-radius: 3px;
}
#search-reset,
#search-details {
display: block;
float: left;
width: 18px;
height: 18px;
background: url(images/buttons.png) -1px 0 no-repeat;
}
#search-reset:hover,
#search-details:hover {
background-color: white;
}
#search-reset {
border-left: 1px solid #e0e0e0;
}
#search-details {
background-position: -1px 20px;
}
.searchdetails {
display: none;
}
.searchfilter {
color: #909090;
font-weight: bold;
margin-top: 5px;
}
#search fieldset {
margin: 0;
color: #909090;
margin-top: 5px;
}
#search td.label {
min-width: 0;
}
div.vsplitter {
float: left;
width: 10px;
min-height: 400px;
}
/* fix cursor on upload button */
input[type="file"]::-webkit-file-upload-button {
cursor: pointer;
}
#draglayer {
min-width: 300px;
width: auto !important;
width: 300px;
border: 1px solid #999999;
background-color: #fff;
padding-left: 8px;
padding-right: 8px;
padding-top: 3px;
padding-bottom: 3px;
white-space: nowrap;
opacity: 0.9;
border-radius: 3px;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
-moz-box-shadow: 1px 1px 12px #999;
-webkit-box-shadow: #999 1px 1px 12px;
}
/**** Common classes ****/
a.disabled {
opacity: 0.5;
filter: alpha(opacity=50);
}
.nowrap {
white-space: nowrap;
}
.clear {
clear: both;
}
.watermark {
padding-top: 40px;
text-align: center;
width: 100%;
}
.link {
cursor: pointer;
}
.icon {
width: 16px;
height: 16px;
}
input.inactive {
color: #d0d0d0;
}
.formtitle {
color: #ff9900;
font-size: 18px;
font-weight: bold;
margin-left: 5px;
}
.formbuttons {
text-align: center;
white-space: nowrap;
}
.formbuttons input {
margin: 5px;
}
div.scroller {
left: 0;
top: 0;
width: 100%;
overflow-y: auto;
overflow-x: hidden;
position: absolute;
bottom: 19px;
}
.listnav {
width: 100%;
text-align: right;
}
.listnav a {
float: left;
display: block;
width: 16px;
height: 16px;
background: url(images/arrow_left.png) center no-repeat;
}
.listnav a.next {
background: url(images/arrow_right.png) center no-repeat;
}
.listnav a.disabled {
opacity: .3;
cursor: default;
}
.listnav span span {
float: left;
display: block;
height: 14px;
padding: 1px 5px;
}
.disabled,
.readonly,
.select.readonly option {
color: #a0a0a0;
}
input.disabled,
input.readonly,
select.disabled,
select.readonly,
textarea.disabled,
textarea.readonly {
background-color: #f5f5f5;
color: #a0a0a0;
}
input.maxsize {
width: 368px; /* span.listarea width - 2px */
}
pre.debug {
border: 1px solid #d0d0d0;
border-radius: 3px;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
background-color: white;
padding: 2px;
width: 500px;
height: 200px;
margin: 0;
overflow: auto;
}
.popup {
display: none;
position: absolute;
border: 1px solid #d0d0d0;
border-radius: 3px;
box-shadow: 0 2px 6px 0 #d0d0d0;
-moz-box-shadow: 0 2px 6px 0 #d0d0d0;
-webkit-box-shadow: 0 2px 6px 0 #d0d0d0;
-o-box-shadow: 0 2px 6px 0 #d0d0d0;
background-color: #f0f0f0;
}
a.button {
display: inline-block;
width: 18px;
height: 18px;
background: url(images/buttons.png) 0 0 no-repeat;
}
a.button.edit {
background-position: -1px -81px;
}
a.button.add {
background-position: -1px -41px;
}
a.button.delete {
background-position: -1px -1px;
}
.popup ul {
list-style-type: none;
margin: 0;
padding: 0;
}
.popup ul li {
padding: 2px 4px;
min-width: 100px;
cursor: default;
}
.popup ul li a {
cursor: default;
display: block;
}
.popup ul li:hover {
background-color: #d6efff;
}
div.boxfooter {
position: absolute;
height: 18px;
left: 0;
right: 0;
bottom: 0;
background-color: #e0e0e0;
border-top: 1px solid #d0d0d0;
}
div.boxfooter a.button {
width: auto;
white-space: nowrap;
color: #514949;
display: inline;
line-height: 18px;
padding: 0 5px 0 20px;
}
/********* Form smart inputs *********/
span.listarea {
display: block;
width: 370px;
max-height: 209px;
overflow-y: auto;
overflow-x: hidden;
margin: 0;
padding: 0;
background-color: white;
border: 1px solid #d0d0d0;
border-radius: 3px;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
text-align: left;
text-shadow: none;
color: black;
}
span.listelement {
display: block;
padding: 0;
margin: 0;
height: 18px;
overflow: hidden;
border-top: 1px solid #d0d0d0;
white-space: nowrap;
}
span.listelement:first-child {
border: none;
}
span.listelement input {
border: none;
background-color: transparent;
padding-left: 2px;
width: 328px;
height: 16px;
}
span.listarea.disabled span.listelement input,
span.listarea.readonly span.listelement input {
width: 370px;
}
span.listelement input:focus {
outline: none;
}
span.listelement span.actions {
float: left;
padding: 1px 0;
margin-left: -1px;
margin-top: -1px;
height: 18px;
width: 37px;
border: 1px solid #d0d0d0;
background-color: #f0f0f0;
cursor: pointer;
}
span.listelement span.actions span {
display: block;
float: left;
width: 18px;
height: 18px;
background: url(images/buttons.png) 0 0 no-repeat;
}
span.listelement span.actions span:hover {
background-color: white;
}
span.listelement span.actions span.reset {
background-position: -1px -1px;
border-left: 1px solid #e0e0e0;
}
span.listelement span.actions span.add {
background-position: -41px -2px;
}
span.listelement span.actions span.search {
background-position: -61px -1px;
cursor: default;
}
span.listarea.disabled,
span.listarea.readonly {
background-color: #f5f5f5;
}
input.disabled,
input.readonly,
span.listarea.disabled span.listelement input,
span.listarea.readonly span.listelement input {
color: #a0a0a0;
cursor: default;
}
span.listarea.autocomplete span.listelement input {
color: #514949;
}
span.listarea.autocomplete span.listelement input.autocomplete {
color: black;
}
.autocomplete > span.listelement input {
width: 346px;
}
.autocomplete > span.listelement span.actions {
width: 18px;
}
.autocomplete > span.listelement span.actions span.reset {
border-left: none;
}
.autocomplete > span.listelement span.actions span.search:hover {
background-color: #f0f0f0;
}
span.listarea.select {
width: 200px;
}
span.listarea.select > span.listelement input {
width: 180px;
}
span.listcontent {
display: block;
padding: 0;
margin: 0;
overflow: hidden;
max-height: 94px;
overflow-x: hidden;
overflow-y: auto;
border-top: 1px solid #d0d0d0;
background-color: #f5f5f5;
cursor: default;
}
span.listcontent span.listelement {
padding-left: 3px;
}
span.listcontent span.listelement:hover {
background-color: #d6efff;
}
span.listcontent span.listelement.selected {
background-color: #d6efff;
}
span.form_error {
color: #FF0000;
font-weight: bold;
font-size: 90%;
padding-left: 5px;
}
/***** progress bar ****/
table.progress {
width: 100%;
height: 5px;
background-color: #f0f0f0;
border: 1px solid #d0d0d0;
border-spacing: 0;
border-radius: 3px;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
margin-bottom: 3px;
}
table.progress td.bar {
background-color: #71b9e1;
}
table.progressinfo {
font-size: 9px;
border: 1px solid #d0d0d0;
width: 5%;
background-color: #f0f0f0;
z-index: 100;
border-spacing: 0;
border-radius: 3px;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
padding: 3px;
}
table.progressinfo td {
padding: 0 1px;
white-space: nowrap;
}
table.progressinfo td.label {
text-align: left;
font-weight: normal;
padding-right: 10px;
min-width: 50px;
width: 1%;
}
table.progressinfo td.value {
text-align: right;
width: 99%;
}
+/***** drag-n-drop *****/
+
+#taskcontent.droptarget.hover,
+#taskcontent.droptarget.active {
+ border-color: #019bc6;
+ box-shadow: 0 0 3px 2px rgba(71,135,177, 0.5);
+ -webkit-box-shadow: 0 0 3px 2px rgba(71,135,177, 0.5);
+}
+
+#taskcontent.droptarget.hover {
+ background-color: #d9ecf4;
+ box-shadow: 0 0 5px 2px rgba(71,135,177, 0.9);
+ -webkit-box-shadow: 0 0 5px 2px rgba(71,135,177, 0.9);
+}
+
+#taskcontent.droptarget.hover table tbody td {
+ background-color: #d9ecf4;
+}
+
+
/***** autocomplete list *****/
#autocompletepane
{
background-color: white;
border: 1px solid #d0d0d0;
min-width: 351px;
}
#autocompletepane ul
{
margin: 0px;
padding: 2px;
list-style-image: none;
list-style-type: none;
}
#autocompletepane ul li
{
display: block;
height: 16px;
font-size: 11px;
padding-left: 6px;
padding-top: 2px;
padding-right: 6px;
white-space: nowrap;
cursor: pointer;
}
#autocompletepane ul li.selected
{
background-color: #d6efff;
}
/***** tabbed interface elements *****/
div.tabsbar
{
height: 22px;
border-bottom: 1px solid #d0d0d0;
white-space: nowrap;
margin: 10px 5px 0 5px;
}
span.tablink,
span.tablink-selected
{
float: left;
height: 23px !important;
height: 22px;
overflow: hidden;
background: url(images/tabs-left.gif) top left no-repeat;
font-weight: bold;
}
span.tablink
{
cursor: pointer;
text-shadow: white 1px 1px;
}
span.tablink-selected
{
cursor: default;
background-position: 0px -23px;
}
span.tablink a,
span.tablink-selected a
{
display: inline-block;
padding: 4px 10px 0 5px;
margin-left: 5px;
height: 23px;
color: #808080;
max-width: 185px;
text-decoration: none;
overflow: hidden;
text-overflow: ellipsis;
-o-text-overflow: ellipsis;
background: url(images/tabs-right.gif) top right no-repeat;
outline: none;
}
span.tablink-selected a
{
cursor: inherit;
color: #514949;
background-position: right -23px;
}
fieldset.tabbed
{
margin-top: 0;
padding-top: 12px;
border-top: none;
}
/***** Dialog windows *****/
#_wModal_bg {
background-color: #000;
z-index: 10000;
opacity: 0.2;
filter: alpha(opacity=20);
}
#_wModal_pixel {
z-index: 10001;
}
._wModal {
position: relative;
min-width: 350px;
overflow: hidden;
line-height: 15px;
background-color: #FFF;
color: #333;
border: 1px solid rgba(51, 51, 51, 0.5);
border-radius: 4px;
box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);
}
._wModal_header {
padding: 10px;
font-size: 14px;
font-weight: bold;
border-bottom: solid 1px #DDD;
}
._wModal_close {
position: absolute;
right: 10px;
top: 10px;
font-weight: normal;
font-size: 12px;
cursor: pointer;
color: #BABABA;
}
._wModal_msg {
font-size: 12px;
padding: 20px;
color: #3A3A3A;
text-shadow: rgba(255, 255, 255, 0.75) 0 1px 1px;
}
._wModal_btns {
padding: 10px;
font-size: 10px;
font-weight: bold;
border-top: solid 1px #DDD;
background-color: #EFEFEF;
text-align: right;
white-space: nowrap;
}
._wModal_btns div {
display: inline-block;
min-width: 40px;
padding: 0 10px;
height: 25px;
line-height: 25px;
margin-left: 10px;
text-align: center;
cursor: pointer;
border-radius: 4px;
box-shadow: rgba(255, 255, 255, 0.2) 0px 1px 0px 0px inset, rgba(0, 0, 0, 0.0470588) 0px 1px 2px 0px;
text-shadow: rgba(255, 255, 255, 0.75) 0 1px 1px;
border: 1px solid rgba(0, 0, 0, 0.14902);
border-bottom-color: rgba(0, 0, 0, 0.247059);
background-color: #F5F5F5;
color: #333;
}
._wModal_btns div:hover,
._wModal_btns div:focus {
background-color: #E6E6E6;
outline: none;
}
._wModal_btns div.default {
text-shadow: rgba(0, 0, 0, 0.247059) 0px -1px 0px;
border: 1px solid rgba(0, 0, 0, 0.0980392);
background-color: #006DCC;
color: #FFF;
}
._wModal_btns div.default:hover,
._wModal_btns div.default:focus {
background-color: #0044CC
}
/**** Login form elements ****/
#login_form {
margin: auto;
margin-top: 75px;
padding: 20px;
width: 330px;
background-color: #e0e0e0;
border: 1px solid #d0d0d0;
border-radius: 3px;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
text-align: center;
}
#login_form span {
display: block;
line-height: 24px;
width: 330px;
text-align: left;
}
#login_form label {
display: block;
width: 80px;
text-align: right;
float: left;
margin-right: 10px;
}
#login_form select,
#login_form input[type="text"],
#login_form input[type="password"] {
width: 210px;
}
#login_submit {
margin-top: 5px;
}
/**** Main screen elements ****/
#main {
padding: 5px 30px;
}
#footer .foot {
white-space: nowrap;
vertical-align: top;
text-align: right;
}
#folder-edit-form label {
display: inline-block;
width: 100px;
}
/***** tree indicators *****/
td span.branch span
{
float: left;
height: 16px;
}
td span.branch span.tree
{
height: 17px;
width: 15px;
background: url(images/tree.gif) 0 0 no-repeat;
}
td span.branch span.l1
{
background-position: 0px 0px; /* L */
}
td span.branch span.l2
{
background-position: -30px 0px; /* | */
}
td span.branch span.l3
{
background-position: -15px 0px; /* |- */
}
/**** File manager elements ****/
#taskcontent {
position: absolute;
left: 310px;
right: 10px;
bottom: 10px;
top: 10px;
background-color: #f0f0f0;
border: 1px solid #d0d0d0;
border-radius: 3px;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
overflow-y: auto;
}
#actionbar {
position: absolute;
width: 82px;
top: 10px;
bottom: 10px;
overflow: hidden;
}
#forms {
position: absolute;
left: 310px;
right: 10px;
top: 10px;
}
#forms form {
display: none;
}
#forms fieldset {
margin: 0;
background-color: #f0f0f0;
}
#forms table {
border-spacing: 0;
margin: 0;
padding: 0;
}
#forms table td.buttons {
width: 1%;
white-space: nowrap;
}
#actionbar a {
display: block;
width: 80px;
height: 55px;
border: 1px solid #d0d0d0;
border-spacing: 0;
border-radius: 3px;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
background-color: #f0f0f0;
margin-bottom: 6px;
cursor: pointer;
color: #333;
}
#actionbar a span {
display: block;
position: absolute;
width: 100%;
text-align: center;
padding-top: 40px;
font-size: 9px;
}
#folder-create-button {
background: url(images/folder_new.png) center 6px no-repeat;
}
#file-create-button {
background: url(images/file_new.png) center 6px no-repeat;
}
#file-upload-button {
background: url(images/file_new.png) center 6px no-repeat;
}
#file-search-button {
background: url(images/search.png) center 6px no-repeat;
}
#file-save-button {
background: url(images/save.png) center 6px no-repeat;
}
#actionbar #file-save-button {
display: none;
}
#folderlist,
#filedata {
position: absolute;
width: 200px;
top: 10px;
bottom: 10px;
left: 98px;
border: 1px solid #d0d0d0;
border-radius: 3px;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
background-color: #f0f0f0;
padding: 2px;
}
#folderlist table,
#filelist table {
width: 100%;
border-spacing: 0;
}
#filelist td {
white-space: nowrap;
cursor: default;
width: 70px;
overflow: hidden;
}
#filelist td.filename {
width: 98%;
height: 20px;
padding: 0 4px;
text-overflow: ellipsis;
}
#filelist td.filesize {
text-align: right;
}
#filelist td.filemtime {
width: 115px;
}
#filelist tbody td.filename span {
background: url(images/mimetypes/unknown.png) 0 0 no-repeat;
padding: 0 0 0 20px;
height: 16px;
cursor: pointer;
}
#filelist tbody td.filename span input {
padding: 0 2px;
height: 18px;
}
#filelist thead td {
cursor: pointer;
}
#filelist thead td.sorted {
padding-right: 16px;
text-decoration: underline;
background: url(images/buttons.png) right -140px no-repeat;
}
#filelist thead td.sorted.reverse {
background-position: right -120px;
}
#folderlist td span.name {
background: url(images/folder.png) 0 0 no-repeat;
height: 18px;
padding-left: 20px;
margin-left: 3px;
cursor: pointer;
}
#folderlist tr.selected td span.name {
background-image: url(images/folder_open.png);
}
#folderlist tr.selected {
background-color: inherit;
}
#folderlist tr.selected td span.name {
font-weight: bold;
}
#folderlist tr.virtual td span.name {
color: #bbb;
cursor: default;
}
#folderlist tr.droptarget {
background-color: #e0e0e0;
}
#folder-collection-audio td span.name,
#folderlist #folder-collection-audio.selected td span.name {
background: url(images/audio.png) 1px 0 no-repeat;
}
#folder-collection-video td span.name,
#folderlist #folder-collection-video.selected td span.name {
background: url(images/video.png) 0 0 no-repeat;
}
#folder-collection-image td span.name,
#folderlist #folder-collection-image.selected td span.name {
background: url(images/image.png) 0 0 no-repeat;
}
#folder-collection-document td span.name,
#folderlist #folder-collection-document.selected td span.name {
background: url(images/document.png) 0 0 no-repeat;
}
#folder-create-form input {
vertical-align: middle;
}
#folder-create-form table td.buttons {
vertical-align: top;
}
.drivers-list {
max-height: 160px;
overflow: auto;
}
.drivers-list > div {
border: 1px solid white;
border-radius: 3px;
margin-top: 3px;
padding: 2px 0;
}
.drivers-list > div.selected {
background-color: #e8e8e8;
}
.drivers-list div.content {
display: inline-block;
vertical-align: middle;
margin-left: 5px;
}
.drivers-list .name {
font-weight: bold;
}
.drivers-list img {
vertical-align: middle;
background-color: #e0e0e0;
border-radius: 3px;
margin: 3px;
background-image: -moz-linear-gradient(center top, #888, #333);
background-image: -webkit-linear-gradient(top, #888, #333);
background-image: -ms-linear-gradient(top, #888, #333);
}
.drivers-list input {
vertical-align: middle;
}
.drivers-list div.content div.form {
padding-top: 4px;
width: 400px;
}
.drivers-footer .description,
.drivers-list .description {
font-size: 10px;
color: #666;
display: block;
}
.drivers-footer .description {
margin-left: 25px;
}
div.form .formrow {
display: block;
padding: 1px;
}
div.form .formrow label {
width: 80px;
display: inline-block;
}
div.form .drivers-footer {
margin-top: 10px;
}
/****** File open interface elements ******/
#actionbar #file-edit-button {
background: url(images/edit.png) center 6px no-repeat #f0f0f0;
}
#actionbar #file-delete-button {
background: url(images/trash.png) center 6px no-repeat #f0f0f0;
}
#actionbar #file-download-button {
background: url(images/download.png) center 6px no-repeat #f0f0f0;
}
#taskcontent iframe {
border: none;
width: 100%;
height: 100%;
background-color: white;
overflow: auto;
border-radius: 3px;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
opacity: 0.1;
}
.fileopen #taskcontent {
overflow: hidden;
background-color: white;
}
#filedata table {
width: 200px;
}
#filedata table td.label {
min-width: 30px;
}
#filedata table td.data {
/*
text-overflow: ellipsis;
overflow: hidden;
*/
}
#filedata table td.data.filename {
font-weight: bold;
}
#loader {
display: none;
z-index: 10;
width: 100px;
background-color: #fafafa;
color: #a0a0a0;
position: absolute;
border: 1px solid #e0e0e0;
border-radius: 3px;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
text-align: center;
padding: 10px;
font-weight: bold;
}
diff --git a/public_html/skins/default/ui.js b/public_html/skins/default/ui.js
index 1032df8..a0e1749 100644
--- a/public_html/skins/default/ui.js
+++ b/public_html/skins/default/ui.js
@@ -1,141 +1,187 @@
function file_list_sort(name, elem)
{
var td = $(elem), reverse = ui.env.sort_reverse;
if (ui.env.sort_col == name)
reverse = !reverse;
else
reverse = 0;
$('td', td.parent()).removeClass('sorted reverse');
td.addClass('sorted').removeClass('reverse');
if (reverse)
td.addClass('reverse');
ui.file_list_sort(name, reverse);
};
function hack_file_input(id)
{
var link = $('#'+id),
file = $('<input>'),
offset = link.offset();
function move_file_input(e) {
file.css({top: (e.pageY - offset.top - 10) + 'px', left: (e.pageX - offset.left - 10) + 'px'});
}
file.attr({name: 'file[]', type: 'file', multiple: 'multiple', size: 5, title: ''})
.change(function() { ui.file_upload(); })
.click(function() { setTimeout(function() { link.mouseleave(); }, 20); })
// opacity:0 does the trick, display/visibility doesn't work
.css({opacity: 0, cursor: 'pointer', position: 'relative', outline: 'none'});
// In FF and IE we need to move the browser file-input's button under the cursor
// Thanks to the size attribute above we know the length of the input field
if (navigator.userAgent.match(/Firefox|MSIE/))
file.css({marginLeft: '-80px'});
// Note: now, I observe problem with cursor style on FF < 4 only
link.css({overflow: 'hidden', cursor: 'pointer'})
.mouseenter(function() { this.__active = ui.commands['file.upload'] ? true : false; })
// place button under the cursor
.mousemove(function(e) {
if (ui.commands['file.upload'] && this.__active)
move_file_input(e);
// move the input away if button is disabled
else
$(this).mouseleave();
})
.mouseleave(function() {
file.css({top: '-10000px', left: '-10000px'});
this.__active = false;
})
.click(function(e) {
// forward click if mouse-enter event was missed
if (ui.commands['file.upload'] && !this.__active) {
this.__active = true;
move_file_input(e);
file.trigger(e);
}
})
.mouseleave()
.append(file);
};
function progress_update(data)
{
var txt = ui.t('file.progress'), id = 'progress' + data.id,
table = $('#' + id), content = $('#info' + id),
i, row, offset, rows = [];
- if (!data || data.done) {
+ if (!data || data.done || !data.total) {
if (table.length) {
table.remove();
content.remove();
}
return;
}
if (!table.length) {
table = $('<table class="progress" id="' + id + '"><tr><td class="bar"></td><td></td></tr></table>');
content = $('<table class="progressinfo" id="info' + id + '"></table>');
table.appendTo($('#actionbar'))
.on('mouseleave', function() { content.hide(); })
.on('mouseenter', function() { if (content.children().length) content.show(); });
offset = table.offset();
content.css({display: 'none', position: 'absolute', top: offset.top + 8, left: offset.left})
.appendTo(document.body);
}
$('td.bar', table).width((data.percent || 1) + '%');
if (data.total) {
rows[ui.t('upload.size')] = ui.file_size(data.total);
rows[ui.t('upload.progress')] = (data.percent || 0) + '%';
if (data.rate)
rows[ui.t('upload.rate')] = ui.file_size(data.rate) + '/s';
if (data.eta)
rows[ui.t('upload.eta')] = ui.time_format(data.eta);
content.empty();
for (i in rows)
$('<tr>').append($('<td class="label">').text(i))
.append($('<td class="value">').text(rows[i]))
.appendTo(content);
}
};
+// activate html5 file drop feature (if browser supports it)
+function init_drag_drop(container)
+{
+ if (!window.FormData && !(window.XMLHttpRequest && XMLHttpRequest.prototype && XMLHttpRequest.prototype.sendAsBinary)) {
+ return;
+ }
+
+ $(document.body).bind('dragover dragleave drop', function(e) {
+ if (!ui.env.folder)
+ return;
+
+ e.preventDefault();
+ container[e.type == 'dragover' ? 'addClass' : 'removeClass']('active');
+ });
+
+ container.bind('dragover dragleave', function(e) {
+ return drag_hover(e, e.type == 'dragover');
+ })
+ container.children('table').bind('dragover dragleave', function(e) {
+ return drag_hover(e, e.type == 'dragover');
+ })
+ container.get(0).addEventListener('drop', function(e) {
+ // abort event and reset UI
+ drag_hover(e, false);
+ return ui.file_drop(e);
+ }, false);
+};
+
+// handler for drag/drop on element
+function drag_hover(e, over)
+{
+ if (!ui.env.folder)
+ return;
+
+ e.preventDefault();
+ e.stopPropagation();
+
+ var elem = $(e.target);
+
+ if (!elem.hasClass('droptarget'))
+ elem = elem.parents('.droptarget');
+
+ elem[over ? 'addClass' : 'removeClass']('hover');
+};
+
function enable_command_handler(p)
{
if (p.command == 'file.save') {
$('#'+ui.buttons['file.edit']).css('display', p.status ? 'none' : 'block');
$('#'+ui.buttons['file.save']).css('display', p.status ? 'block' : 'none');
}
};
$(window).load(function() {
hack_file_input('file-upload-button');
$('#forms > form').hide();
ui.add_event_listener('enable-command', enable_command_handler);
+ init_drag_drop($('#taskcontent'));
});
// register buttons
ui.buttons({
'folder.create': 'folder-create-button',
'folder.edit': 'folder-edit-button',
'folder.delete': 'folder-delete-button',
'file.upload': 'file-upload-button',
'file.search': 'file-search-button',
'file.delete': 'file-delete-button',
'file.download': 'file-download-button',
'file.edit': 'file-edit-button',
'file.copy': 'file-copy-button',
'file.move': 'file-move-button',
'file.save': 'file-save-button'
});
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Mon, Sep 15, 9:09 PM (1 d, 21 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
287614
Default Alt Text
(94 KB)
Attached To
Mode
R26 chwala
Attached
Detach File
Event Timeline
Log In to Comment