summaryrefslogtreecommitdiff
path: root/program/js/app.js
diff options
context:
space:
mode:
Diffstat (limited to 'program/js/app.js')
-rw-r--r--program/js/app.js214
1 files changed, 133 insertions, 81 deletions
diff --git a/program/js/app.js b/program/js/app.js
index c748d497a..9b33c4e21 100644
--- a/program/js/app.js
+++ b/program/js/app.js
@@ -21,7 +21,6 @@
function rcube_webmail()
{
- this.env = { recipients_separator:',', recipients_delimiter:', ' };
this.labels = {};
this.buttons = {};
this.buttons_sel = {};
@@ -33,22 +32,24 @@ function rcube_webmail()
this.messages = {};
this.group2expand = {};
- // create protected reference to myself
- this.ref = 'rcmail';
- var ref = this;
-
// webmail client settings
this.dblclick_time = 500;
this.message_time = 4000;
-
this.identifier_expr = new RegExp('[^0-9a-z\-_]', 'gi');
- // default environment vars
- this.env.keep_alive = 60; // seconds
- this.env.request_timeout = 180; // seconds
- this.env.draft_autosave = 0; // seconds
- this.env.comm_path = './';
- this.env.blankpage = 'program/resources/blank.gif';
+ // environment defaults
+ this.env = {
+ request_timeout: 180, // seconds
+ draft_autosave: 0, // seconds
+ comm_path: './',
+ blankpage: 'program/resources/blank.gif',
+ recipients_separator: ',',
+ recipients_delimiter: ', '
+ };
+
+ // create protected reference to myself
+ this.ref = 'rcmail';
+ var ref = this;
// set jQuery ajax options
$.ajaxSetup({
@@ -58,6 +59,7 @@ function rcube_webmail()
beforeSend: function(xmlhttp){ xmlhttp.setRequestHeader('X-Roundcube-Request', ref.env.request_token); }
});
+ // unload fix
$(window).bind('beforeunload', function() { rcmail.unload = true; });
// set environment variable(s)
@@ -82,14 +84,15 @@ function rcube_webmail()
// add a button to the button list
this.register_button = function(command, id, type, act, sel, over)
{
- if (!this.buttons[command])
- this.buttons[command] = [];
-
var button_prop = {id:id, type:type};
+
if (act) button_prop.act = act;
if (sel) button_prop.sel = sel;
if (over) button_prop.over = over;
+ if (!this.buttons[command])
+ this.buttons[command] = [];
+
this.buttons[command].push(button_prop);
if (this.loaded)
@@ -188,7 +191,6 @@ function rcube_webmail()
this.enable_command('list', 'checkmail', 'add-contact', 'search', 'reset-search', 'collapse-folder', true);
if (this.gui_objects.messagelist) {
-
this.message_list = new rcube_list_widget(this.gui_objects.messagelist, {
multiselect:true, multiexpand:true, draggable:true, keyboard:true,
column_movable:this.env.col_movable, dblclick_time:this.dblclick_time
@@ -215,9 +217,8 @@ function rcube_webmail()
}
if (this.gui_objects.qsearchbox) {
- if (this.env.search_text != null) {
+ if (this.env.search_text != null)
this.gui_objects.qsearchbox.value = this.env.search_text;
- }
$(this.gui_objects.qsearchbox).focusin(function() { rcmail.message_list.blur(); });
}
@@ -323,7 +324,6 @@ function rcube_webmail()
this.enable_command('list', 'listgroup', 'listsearch', 'advanced-search', true);
if (this.gui_objects.contactslist) {
-
this.contact_list = new rcube_list_widget(this.gui_objects.contactslist,
{multiselect:true, draggable:this.gui_objects.folderlist?true:false, keyboard:true});
this.contact_list.row_init = function(row){ p.triggerEvent('insertrow', { cid:row.uid, row:row }); };
@@ -339,9 +339,8 @@ function rcube_webmail()
this.gui_objects.contactslist.parentNode.onmousedown = function(e){ return p.click_on_list(e); };
document.onmouseup = function(e){ return p.doc_mouse_up(e); };
- if (this.gui_objects.qsearchbox) {
+ if (this.gui_objects.qsearchbox)
$(this.gui_objects.qsearchbox).focusin(function() { rcmail.contact_list.blur(); });
- }
this.update_group_commands();
this.command('list');
@@ -365,9 +364,8 @@ function rcube_webmail()
this.init_contact_form();
}
- if (this.gui_objects.qsearchbox) {
+ if (this.gui_objects.qsearchbox)
this.enable_command('search', 'reset-search', 'moveto', true);
- }
break;
@@ -424,12 +422,14 @@ function rcube_webmail()
$('#rcmloginpwd').focus();
// detect client timezone
- var dt = new Date(),
- tz = dt.getTimezoneOffset() / -60,
- stdtz = dt.getStdTimezoneOffset() / -60;
-
- $('#rcmlogintz').val(stdtz);
- $('#rcmlogindst').val(tz > stdtz ? 1 : 0);
+ if (window.jstz && !bw.ie6) {
+ var timezone = jstz.determine();
+ if (timezone.name())
+ $('#rcmlogintz').val(timezone.name());
+ }
+ else {
+ $('#rcmlogintz').val(new Date().getStdTimezoneOffset() / -60);
+ }
// display 'loading' message on form submit, lock submit button
$('form').submit(function () {
@@ -480,7 +480,8 @@ function rcube_webmail()
this.onloads[i]();
}
- // start keep-alive interval
+ // start keep-alive and refresh intervals
+ this.start_refresh();
this.start_keepalive();
};
@@ -505,6 +506,11 @@ function rcube_webmail()
if (this.busy)
return false;
+ // let the browser handle this click (shift/ctrl usually opens the link in a new window/tab)
+ if ((obj && obj.href && String(obj.href).indexOf(location.href) < 0) && rcube_event.get_modifier(event)) {
+ return true;
+ }
+
// command not supported or allowed
if (!this.commands[command]) {
// pass command to parent window
@@ -560,7 +566,7 @@ function rcube_webmail()
break;
case 'about':
- location.href = '?_task=settings&_action=about';
+ this.redirect('?_task=settings&_action=about', false);
break;
case 'permaurl':
@@ -590,7 +596,7 @@ function rcube_webmail()
case 'open':
if (uid = this.get_single_uid()) {
- obj.href = '?_task='+this.env.task+'&_action=show&_mbox='+urlencode(this.env.mailbox)+'&_uid='+uid;
+ obj.href = this.url('show', {_mbox: this.env.mailbox, _uid: uid});
return true;
}
break;
@@ -603,9 +609,8 @@ function rcube_webmail()
case 'list':
if (props && props != '')
this.reset_qsearch();
- if (this.env.action == 'compose' && this.env.extwin) {
+ if (this.env.action == 'compose' && this.env.extwin)
window.close();
- }
else if (this.task == 'mail') {
this.list_mailbox(props);
this.set_button_titles();
@@ -773,9 +778,8 @@ function rcube_webmail()
uid = props._row.uid;
// toggle read/unread
- if (this.message_list.rows[uid].deleted) {
+ if (this.message_list.rows[uid].deleted)
flag = 'undelete';
- }
else if (!this.message_list.rows[uid].unread)
flag = 'unread';
}
@@ -794,7 +798,7 @@ function rcube_webmail()
// toggle flagged/unflagged
if (this.message_list.rows[uid].flagged)
flag = 'unflagged';
- }
+ }
this.mark_message(flag, uid);
break;
@@ -870,7 +874,7 @@ function rcube_webmail()
case 'previousmessage':
if (this.env.prev_uid)
- this.show_message(this.env.prev_uid, false, this.env.action=='preview');
+ this.show_message(this.env.prev_uid, false, this.env.action == 'preview');
break;
case 'firstmessage':
@@ -878,10 +882,6 @@ function rcube_webmail()
this.show_message(this.env.first_uid);
break;
- case 'checkmail':
- this.check_for_recent(true);
- break;
-
case 'compose':
url = {};
@@ -950,9 +950,6 @@ function rcube_webmail()
break;
}
- // re-set keep-alive timeout
- this.start_keepalive();
-
this.submit_messageform(true);
break;
@@ -2062,6 +2059,15 @@ function rcube_webmail()
}
};
+ // sends request to check for recent messages
+ this.checkmail = function()
+ {
+ var lock = this.set_busy(true, 'checkingmail'),
+ params = this.check_recent_params();
+
+ this.http_request('check-recent', params, lock);
+ };
+
// list messages of a specific mailbox using filter
this.filter_mailbox = function(filter)
{
@@ -3016,10 +3022,13 @@ function rcube_webmail()
var url = this.url('mail/compose', p);
// open new compose window
- if (this.env.compose_extwin)
+ if (this.env.compose_extwin && !this.env.extwin) {
this.open_window(url, 1150, 900);
- else
+ }
+ else {
this.redirect(url);
+ window.resizeTo(Math.max(1150, $(window).width()), Math.max(900, $(window).height()));
+ }
};
// init message compose form: set focus and eventhandlers
@@ -3039,6 +3048,7 @@ function rcube_webmail()
// close compose step in opener
if (window.opener && opener.rcmail && opener.rcmail.env.action == 'compose') {
setTimeout(function(){ opener.history.back(); }, 100);
+ this.env.opened_extwin = true;
}
// configure parallel autocompletion
@@ -3059,7 +3069,7 @@ function rcube_webmail()
this.set_caret_pos(input_message, this.env.top_posting ? 0 : $(input_message).val().length);
// add signature according to selected identity
// if we have HTML editor, signature is added in callback
- if (input_from.prop('type') == 'select-one') {
+ if (input_from.prop('type') == 'select-one' && !this.env.opened_extwin) {
this.change_identity(input_from[0]);
}
}
@@ -3407,6 +3417,10 @@ function rcube_webmail()
message = message.substring(0, p) + sig + message.substring(p, message.length);
cursor_pos = p - 1;
}
+ else if (!message) { // empty message
+ cursor_pos = 0;
+ message = '\n\n' + sig;
+ }
else if (pos = this.get_caret_pos(input_message.get(0))) { // at cursor position
message = message.substring(0, pos) + '\n' + sig + '\n\n' + message.substring(pos, message.length);
cursor_pos = pos;
@@ -6039,10 +6053,18 @@ function rcube_webmail()
if (lock || lock === null)
this.set_busy(true);
- if (this.is_framed())
+ if (this.is_framed()) {
parent.rcmail.redirect(url, lock);
- else
+ }
+ else {
+ if (this.env.extwin) {
+ if (typeof url == 'string')
+ url += (url.indexOf('?') < 0 ? '?' : '&') + '_extwin=1';
+ else
+ url._extwin = 1;
+ }
this.location_href(url, window);
+ }
};
this.goto_url = function(action, query, lock)
@@ -6063,6 +6085,9 @@ function rcube_webmail()
$('<a>').attr('href', url).appendTo(document.body).get(0).click();
else
target.location.href = url;
+
+ // reset keep-alive interval
+ this.start_keepalive();
};
// send a http request to the server
@@ -6091,6 +6116,9 @@ function rcube_webmail()
success: function(data){ ref.http_response(data); },
error: function(o, status, err) { ref.http_error(o, status, err, lock, action); }
});
+
+ // reset keep-alive interval
+ this.start_keepalive();
};
// send a http POST request to the server
@@ -6108,7 +6136,7 @@ function rcube_webmail()
// trigger plugin hook
var result = this.triggerEvent('request'+action, postdata);
if (result !== undefined) {
- // abort if one the handlers returned false
+ // abort if one of the handlers returned false
if (result === false)
return false;
else
@@ -6123,6 +6151,9 @@ function rcube_webmail()
success: function(data){ ref.http_response(data); },
error: function(o, status, err) { ref.http_error(o, status, err, lock, action); }
});
+
+ // reset keep-alive interval
+ this.start_keepalive();
};
// aborts ajax request
@@ -6217,6 +6248,7 @@ function rcube_webmail()
}
break;
+ case 'refresh':
case 'check-recent':
case 'getunread':
case 'search':
@@ -6250,6 +6282,9 @@ function rcube_webmail()
this.triggerEvent('responseafter', {response: response});
this.triggerEvent('responseafter'+response.action, {response: response});
+
+ // reset keep-alive interval
+ this.start_keepalive();
};
// handle HTTP request errors
@@ -6278,9 +6313,7 @@ function rcube_webmail()
// re-send keep-alive requests after 30 seconds
if (action == 'keep-alive')
- setTimeout(function(){ ref.keep_alive(); }, 30000);
- else if (action == 'check-recent')
- setTimeout(function(){ ref.check_for_recent(false); }, 30000);
+ setTimeout(function(){ ref.keep_alive(); ref.start_keepalive(); }, 30000);
};
// post the given form to a hidden iframe
@@ -6450,20 +6483,28 @@ function rcube_webmail()
}
};
-
- // starts interval for keep-alive/check-recent signal
+ // starts interval for keep-alive signal
this.start_keepalive = function()
{
- if (!this.env.keep_alive || this.env.framed)
+ if (!this.env.session_lifetime || this.env.framed || this.env.extwin || this.task == 'login' || this.env.action == 'print')
return;
- if (this._int)
- clearInterval(this._int);
+ if (this._keepalive)
+ clearInterval(this._keepalive);
- if (this.task == 'mail' && this.gui_objects.mailboxlist)
- this._int = setInterval(function(){ ref.check_for_recent(false); }, this.env.keep_alive * 1000);
- else if (this.task != 'login' && this.env.action != 'print')
- this._int = setInterval(function(){ ref.keep_alive(); }, this.env.keep_alive * 1000);
+ this._keepalive = setInterval(function(){ ref.keep_alive(); }, this.env.session_lifetime * 0.5 * 1000);
+ };
+
+ // starts interval for refresh signal
+ this.start_refresh = function()
+ {
+ if (!this.env.refresh_interval || this.env.framed || this.env.extwin || this.task == 'login' || this.env.action == 'print')
+ return;
+
+ if (this._refresh)
+ clearInterval(this._refresh);
+
+ this._refresh = setInterval(function(){ ref.refresh(); }, this.env.refresh_interval * 1000);
};
// sends keep-alive signal
@@ -6473,29 +6514,39 @@ function rcube_webmail()
this.http_request('keep-alive');
};
- // sends request to check for recent messages
- this.check_for_recent = function(refresh)
+ // sends refresh signal
+ this.refresh = function()
{
- if (this.busy)
+ if (this.busy) {
+ // try again after 10 seconds
+ setTimeout(function(){ ref.refresh(); ref.start_refresh(); }, 10000);
return;
+ }
- var lock, url = {_mbox: this.env.mailbox};
+ var params = {}, lock = this.set_busy(true, 'refreshing');
- if (refresh) {
- lock = this.set_busy(true, 'checkingmail');
- url._refresh = 1;
- // reset check-recent interval
- this.start_keepalive();
- }
+ if (this.task == 'mail' && this.gui_objects.mailboxlist)
+ params = this.check_recent_params();
+ // plugins should bind to 'requestrefresh' event to add own params
+ this.http_request('refresh', params, lock);
+ };
+
+ // returns check-recent request parameters
+ this.check_recent_params = function()
+ {
+ var params = {_mbox: this.env.mailbox};
+
+ if (this.gui_objects.mailboxlist)
+ params._folderlist = 1;
if (this.gui_objects.messagelist)
- url._list = 1;
+ params._list = 1;
if (this.gui_objects.quotadisplay)
- url._quota = 1;
+ params._quota = 1;
if (this.env.search_request)
- url._search = this.env.search_request;
+ params._search = this.env.search_request;
- this.http_request('check-recent', url, lock);
+ return params;
};
@@ -6521,7 +6572,8 @@ function rcube_webmail()
{
if (obj.selectionEnd !== undefined)
return obj.selectionEnd;
- else if (document.selection && document.selection.createRange) {
+
+ if (document.selection && document.selection.createRange) {
var range = document.selection.createRange();
if (range.parentElement() != obj)
return 0;
@@ -6535,10 +6587,10 @@ function rcube_webmail()
gm.setEndPoint('EndToStart', range);
var p = gm.text.length;
- return p<=obj.value.length ? p : -1;
+ return p <= obj.value.length ? p : -1;
}
- else
- return obj.value.length;
+
+ return obj.value.length;
};
// moves cursor to specified position