Files
modoboa/extensions/webmail/static/js/webmail.js
T

793 lines
22 KiB
JavaScript

var Webmail = new Class({
Implements: [Options],
/*
* Default values for options
*/
defaults: {
refreshRate: 0,
modify_url: "",
delete_url: "",
move_url: ""
},
/*
* Constructor
*/
initialize: function(options) {
this.setOptions(options);
this.rtimer = null;
this.editorid = "id_body";
this.init_menubar();
this.init_folders_buttons();
this.init_folders_browsing();
this.init_emails_table();
current_anchor.register_callback("viewmail", this.viewmail_callback.bind(this));
current_anchor.register_callback("compose", this.compose_callback.bind(this));
current_anchor.register_callback("reply", this.compose_callback.bind(this));
current_anchor.register_callback("replyall", this.compose_callback.bind(this));
current_anchor.register_callback("forward", this.compose_callback.bind(this));
},
/*
* Menubar initialization
*/
init_menubar: function() {
searchbox_init();
$$("a[name=mark-read]").addEvent("click", this.send_mark_request.bind(this));
$$("a[name=mark-unread]").addEvent("click", this.send_mark_request.bind(this));
$$("a[name=fdaction]").addEvent("click", function(evt) {
this.simple_request(evt.target.get("href"), {});
evt.stop();
}.bind(this));
},
send_mark_request: function(evt) {
evt.stop();
if (!this.emails_table._selectedRows.length) {
return;
}
var ids = new Array();
this.emails_table._selectedRows.each(function(item, index) {
ids.include(item.get("id"));
});
this.simple_request(evt.target.get("href"), {
ids : ids.join()
});
},
/*
* Initializes the misc. buttons available to manipulate folders.
*/
init_folders_buttons: function() {
$$("li[class*=clickable]").removeEvents();
$$("a[name=loadfolder]").addEvent("click", this.folder_loader.bind(this));
SqueezeBox.assign($("folders").getElements('a[class=boxed]'), {
parse: 'rel'
});
var fdbuttons = $$("img[class*=footer]");
var fdmenu = new FdMenu({
modify_url: this.options.modify_url,
delete_url: this.options.delete_url
});
fdbuttons.addEvents({
click: function(evt) {
var parent = this.getParent();
var fdname = parent.getFirst("a[name=loadfolder]").get("href");
fdmenu.toggle(this, fdname);
evt.stop();
}
});
},
/*
* Enables folders opening/closing
*
* Available for folders with subfolders.
*/
init_folders_browsing: function() {
$$("div[class*=clickbox]").addEvent("click", function(evt) {
var parent = this.getParent();
var ul = parent.getFirst("ul[name=" + parent.get("name") + "]");
if (!$defined(ul)) {
return;
}
if (ul.hasClass("hidden")) {
this.removeClass("collapsed").addClass("expanded");
ul.removeClass("hidden").addClass("visible");
} else {
this.removeClass("expanded").addClass("collapsed");
ul.removeClass("visible").addClass("hidden");
}
evt.stop();
});
},
/*
* Select a particular folder
*/
select_folder: function(obj) {
$$("a[name=loadfolder]").each(function(item) {
item.getParent().removeClass("selected");
item.getParent().addClass("droppable");
});
obj.getParent().removeClass("droppable");
obj.getParent().addClass("selected");
$$(obj.getParents("ul[class*=hidden]")).each(function(item) {
item.removeClass("hidden");
item.addClass("visible");
$$("li[name=" + item.get("name") + "]").each(function(item) {
item.setStyle(
"background",
"url('" + static_url("pics/folder-open.png") + "') no-repeat"
);
});
});
},
/*
* Automatic folder listing refresh
*
* Called at a regular frequency to make an asynchronous request that
* retrieves a folder's content (ie. mails)
*/
refresh_folder: function() {
var query = current_anchor.serialized.substring(1);
clearInterval(this.rtimer);
infobox.show(gettext("Reloading..."), {
profile : "gray",
spinner : true
});
new Request.JSON({url: query, noCache : true, onSuccess: function(resp) {
var callback = ($defined(resp.callback)) ? resp.callback : "default";
current_anchor.get_callback(callback)(resp);
infobox.info(gettext("Done"));
infobox.hide(1);
}}).get();
},
init_automatic_refresh: function() {
this.rtimer = this.refresh_folder
.periodical(this.options.refreshRate);
},
/*
* Emails table initialization.
*/
init_emails_table: function() {
this.emails_table = new HtmlTable($("emails"), {
selectable: true,
shiftForMultiSelect: true
}).addEvents({
rowFocus: function(tr) {
clearInterval(this.rtimer);
}.bind(this),
rowUnfocus: function(tr) {
if (this.emails_table._selectedRows.length == 0) {
this.init_automatic_refresh();
}
}.bind(this)
});
/* The IE way for disabling default selection */
/* Actually it doesn't work :p */
$$("tbody>tr").set("unselectable", "on");
if ($("toggleselect")) {
$("toggleselect").addEvent("click", function(evt) {
if (evt.target.checked) {
this.emails_table.selectAll();
} else {
this.emails_table.selectNone();
}
}.bind(this));
}
init_sortable_columns();
update_sortable_column();
$$("td[class*=draggable]").each(function(item) {
new Drag.Move(item, {
droppables: ".droppable"
}).addEvents({
beforeStart: this.bstart_dragging,
start: this.start_dragging,
enter: this.enter_droppable,
leave: this.leave_droppable,
drop: this.drop_element,
cancel: this.cancel_dragging
});
});
$$("tbody>tr").addEvent("dblclick", viewmail);
},
/*
* Drag & Drop feature
*/
/*
* 'before start' event callback
*/
bstart_dragging: function(item) {
var block = new Element("div", {id: "draggeditems"})
.setStyles({"position" : "absolute",
"opacity" : 0.8,
"width" : "200px",
"padding" : "5px",
"text-align" : "center",
"height" : "25px",
"border" : "1px solid #333",
"background" : "white",
display: "none",
"z-index" : 3,
top : this.element.getCoordinates()['top'],
left : this.element.getCoordinates()['left']})
.inject(document.body);
block.store("parent", this.element);
this.element = block;
clearInterval(rtimer);
},
start_dragging: function(item) {
var tr = this.element.retrieve("parent").getParent();
if (!emails_table.isSelected(tr)) {
emails_table.selectNone();
emails_table.selectRow(tr);
}
item.set("html", "Moving " + emails_table._selectedRows.length + " messages");
this.element.setStyle("display", "block");
},
enter_droppable: function(item, droppable) {
droppable.addClass("dragging");
},
leave_droppable: function(item, droppable) {
droppable.removeClass("dragging");
},
restore_parent: function(drag, item) {
var parent = item.retrieve("parent");
drag.element = parent;
this.init_automatic_refresh();
},
drop_element: function(item, droppable, event) {
this.element.dispose();
delete(this.element);
if (!droppable) {
restore_parent(this, item);
return;
}
droppable.removeClass("dragging");
dest = gethref(droppable.getFirst("a"));
msgset = new Array();
this.emails_table._selectedRows.each(function(item, index) {
msgset.include(item.get("id"));
});
this.simple_request(this.options.move_url, {
msgset : msgset.join(),
to : dest
});
},
cancel_dragging: function(item) {
this.element.dispose();
delete(this.element);
restore_parent(this, item);
},
/*
* Bottom left quota bar initialisation.
*/
init_quota_bar: function() {
this.quota_pb = new ProgressBar({
container: $("quotabox"),
startPercentage: 0,
boxID: "box",
percentageID: "perc",
displayText: true,
displayID: "quotatext"
});
},
/*
*
*/
page_update: function(response) {
},
/*
* Webmail actions start here
*/
/*
* Onclick callback used to load the content of a particular
* folder. (activated when clicking on a folder's name)
*/
_folder_loader: function(event, obj) {
event.stop();
if (!$defined(obj)) {
obj = $(event.target);
}
current_anchor.parse_string(gethref(obj), true).setparams(navparams);
current_anchor.update();
},
folder_loader: function(event) {
this.select_folder(event.target);
this._folder_loader(event, event.target);
},
/*
* Callback for 'folder' action
*/
folder_callback: function(resp) {
},
/*
* Callback of the 'viewmail' action
*/
viewmail_callback: function(resp) {
wm_updatelisting(resp, "hidden");
$$("a[name=back]").addEvent("click", this._folder_loader);
$$("a[name=reply]").addEvent("click", this.reply_loader);
$$("a[name=replyall]").addEvent("click", this.replyall_loader);
$$("a[name=forward]").addEvent("click", this.forward_loader);
$$("a[name=delete]").addEvent("click", function(event) {
var lnk = event.target;
event.stop();
this.simple_request(lnk.get("href"));
}.bind(this));
$$("a[name=activate_links]").addEvent("click", function(evt) {
evt.stop();
current_anchor.setparam("links", "1").update();
});
$$("a[name=disable_links]").addEvent("click", function(evt) {
evt.stop();
current_anchor.setparam("links", "0").update();
});
setDivHeight("mailcontent", 5, 0);
},
/*
* Loader of the 'compose' action (called when the associated button
* is clicked)
*/
compose_loader: function(event) {
event.stop();
current_anchor.baseurl("compose").update();
},
/*
* Loader of the 'reply' action (called when the associated button
* is clicked).
*/
reply_loader: function(event) {
event.stop();
location.hash += event.target.get("href");
},
/*
* Loader of the 'replyall' action (called when the associated button
* is clicked).
*/
replyall_loader: function(event) {
event.stop();
location.hash += event.target.get("href") + "?all=1";
},
/*
* Loader of the 'forward' action (called when the associated button
* is clicked).
*/
forward_loader: function(event) {
event.stop();
location.hash += event.target.get("href");
},
/*
* Resize the current editor on page resizing.
*/
resize_window_callback: function(event) {
CKEDITOR.instances[this.editorid]
.resize("100%", $("body_container").getSize().y);
},
/*
* Callback of the 'compose' action.
*
* It is also shared with other similar actions : reply, forward.
*/
compose_callback: function(resp) {
wm_updatelisting(resp);
window.addEvent("resize", this.resize_window_callback.bind(this));
var editormode = resp.editor;
if (editormode == "html") {
var instance = CKEDITOR.instances[editorid];
if (instance) {
CKEDITOR.remove(instance);
}
CKEDITOR.replace(editorid, {
customConfig: static_url("js/editor_config.js")
});
CKEDITOR.on("instanceReady", function(evt) {
this.resize_window_callback();
}.bind(this));
}
if (resp.id) {
current_anchor.setparam("id", resp.id).update(0, 1);
}
$("attachments").addEvent("click", function(evt) {
SqueezeBox.open(this.get("name"), {
handler: "iframe",
size: {x: 350, y: 400},
closeBtn: false
});
});
$$("a[name=back]")
.removeEvents("click")
.addEvent("click", this._folder_loader);
$$("a[name=sendmail]")
.store("editormode", editormode)
.removeEvents("click")
.addEvent("click", this.sendmail_callback.bind(this));
},
/*
* Callback of the 'sendmail' action.
*/
sendmail_callback: function(evt) {
evt.stop();
infobox.show(gettext("Sending..."), {
profile : "gray",
spinner : true
});
disable_link(this);
$("composemail").set("send", {
onSuccess: function(resp) {
resp = JSON.decode(resp);
if (resp.status == "ko") {
current_anchor.get_callback("compose")(resp);
if ($defined(resp.respmsg)) {
infobox.error(resp.respmsg);
}
enable_link(this, sendmail_callback);
return;
}
current_anchor.parse_string(resp.url, true).setparams(navparams);
current_anchor.update();
this.eliminate("editormode");
}.bind(this)
});
if (this.retrieve("editormode") == "html") {
CKEDITOR.instances[editorid].updateElement();
}
$("composemail").send();
},
/*
* Simple AJAX request
*
* Initialize the infobox with a loading message and wait for a JSON
* encoded answer. The infobox is cleared by the request callback
* function.
*/
simple_request: function(url, params) {
infobox.show(gettext("Waiting..."), {
profile: "gray",
spinner: true
});
new Request.JSON({
url : url,
onSuccess : function(response) {
if (response.status == "ok") {
if (!$defined(response.next)) {
current_anchor.get_callback("folder")(response);
}
infobox.info(gettext("Done"));
if ($defined(response.next)) {
(function(response) {
current_anchor.parse_string(response.next).update();
select_folder($$("a[href=" + current_anchor.getbaseurl() + "]"));
}).delay(500, this, response);
} else {
infobox.hide(1);
}
} else {
infobox.error(response.respmsg);
}
}
}).get(params);
}
});
/*
* Globals
*/
var rtimer = null;
var editorid = "id_body";
/*
* Enables folders opening/closing
*
* Available for folders with subfolders.
*/
function init_folders_browsing() {
$$("div[class*=clickbox]").addEvent("click", function(evt) {
var parent = this.getParent();
var ul = parent.getFirst("ul[name=" + parent.get("name") + "]");
if (!$defined(ul)) {
return;
}
if (ul.hasClass("hidden")) {
this.removeClass("collapsed").addClass("expanded");
ul.removeClass("hidden").addClass("visible");
} else {
this.removeClass("expanded").addClass("collapsed");
ul.removeClass("visible").addClass("hidden");
}
evt.stop();
});
}
/*
* Select a particular folder
*/
function select_folder(obj) {
$$("a[name=loadfolder]").each(function(item) {
item.getParent().removeClass("selected");
item.getParent().addClass("droppable");
});
obj.getParent().removeClass("droppable");
obj.getParent().addClass("selected");
$$(obj.getParents("ul[class*=hidden]")).each(function(item) {
item.removeClass("hidden");
item.addClass("visible");
$$("li[name=" + item.get("name") + "]").each(function(item) {
item.setStyle("background",
"url('" + static_url("pics/folder-open.png") + "') no-repeat");
});
});
}
/*
* Callback of the 'viewmail' action
*/
function viewmail_cb(resp) {
wm_updatelisting(resp, "hidden");
$$("a[name=back]").addEvent("click", loadFolder);
$$("a[name=reply]").addEvent("click", reply_loader);
$$("a[name=replyall]").addEvent("click", replyall_loader);
$$("a[name=forward]").addEvent("click", forward_loader);
$$("a[name=delete]").addEvent("click", function(event) {
var lnk = event.target;
event.stop();
simple_request(lnk.get("href"));
});
$$("a[name=activate_links]").addEvent("click", function(evt) {
evt.stop();
current_anchor.setparam("links", "1").update();
});
$$("a[name=disable_links]").addEvent("click", function(evt) {
evt.stop();
current_anchor.setparam("links", "0").update();
});
setDivHeight("mailcontent", 5, 0);
}
/*
* Loader of the 'compose' action (called when the associated button
* is clicked)
*/
function compose_loader(event) {
event.stop();
current_anchor.baseurl("compose").update();
}
function resize_window_callback(event) {
CKEDITOR.instances["id_body"].resize("100%", $("body_container").getSize().y);
}
/*
* Callback of the 'sendmail' action.
*/
function sendmail_callback(evt) {
evt.stop();
infobox.show(gettext("Sending..."), {
profile : "gray",
spinner : true
});
disable_link(this);
$("composemail").set("send", {
onSuccess: function(resp) {
resp = JSON.decode(resp);
if (resp.status == "ko") {
current_anchor.get_callback("compose")(resp);
if ($defined(resp.respmsg)) {
infobox.error(resp.respmsg);
}
enable_link(this, sendmail_callback);
return;
}
current_anchor.parse_string(resp.url, true).setparams(navparams);
current_anchor.update();
this.eliminate("editormode");
}.bind(this)
});
if (this.retrieve("editormode") == "html") {
CKEDITOR.instances[editorid].updateElement();
}
$("composemail").send();
}
/*
* Callback of the 'compose' action
*/
function compose_callback(resp) {
wm_updatelisting(resp);
window.addEvent("resize", resize_window_callback);
var editormode = resp.editor;
if (editormode == "html") {
var instance = CKEDITOR.instances[editorid];
if (instance) {
CKEDITOR.remove(instance);
}
CKEDITOR.replace(editorid, {
customConfig: static_url("js/editor_config.js")
});
CKEDITOR.on("instanceReady", function(evt) {
resize_window_callback();
});
}
if (resp.id) {
current_anchor.setparam("id", resp.id).update(0, 1);
}
$("attachments").addEvent("click", function(evt) {
SqueezeBox.open(this.get("name"), {
handler: "iframe",
size: {x: 350, y: 400},
closeBtn: false
});
});
$$("a[name=back]")
.removeEvents("click")
.addEvent("click", loadFolder);
$$("a[name=sendmail]")
.store("editormode", editormode)
.removeEvents("click")
.addEvent("click", sendmail_callback);
}
/*
* Loader of the 'reply' action (called when the associated button
* is clicked).
*/
function reply_loader(event) {
event.stop();
location.hash += event.target.get("href");
}
/*
* Loader of the 'replyall' action (called when the associated button
* is clicked).
*/
function replyall_loader(event) {
event.stop();
location.hash += event.target.get("href") + "?all=1";
}
/*
* Loader of the 'forward' action (called when the associated button
* is clicked).
*/
function forward_loader(event) {
event.stop();
location.hash += event.target.get("href");
}
/*
* Onclick callback used to load the content of a particular
* folder. (activated when clicking on a folder's name)
*/
function loadFolder(event, obj) {
event.stop();
if (!$defined(obj)) {
obj = $(event.target);
}
current_anchor.parse_string(gethref(obj), true).setparams(navparams);
current_anchor.update();
}
function foldercallback(event) {
select_folder(event.target);
loadFolder(event, event.target);
}
/*
* Automatic folder listing refresh
*
* Called at a regular frequency to make an asynchronous request that
* retrieves a folder's content (ie. mails)
*/
function refreshFolder() {
var query = current_anchor.serialized.substring(1);
clearInterval(rtimer);
infobox.show(gettext("Reloading..."), {
profile : "gray",
spinner : true
});
new Request.JSON({url: query, noCache : true, onSuccess: function(resp) {
var callback = ($defined(resp.callback)) ? resp.callback : "default";
current_anchor.get_callback(callback)(resp);
infobox.info(gettext("Done"));
infobox.hide(1);
}}).get();
}
/*
* Simple AJAX request
*
* Initialize the infobox with a loading message and wait for a JSON
* encoded answer. The infobox is cleared by the request callback
* function.
*/
function simple_request(url, params) {
infobox.show(gettext("Waiting..."), {
profile: "gray",
spinner: true
});
new Request.JSON({
url : url,
onSuccess : function(response) {
if (response.status == "ok") {
if (!$defined(response.next)) {
current_anchor.get_callback("folder")(response);
}
infobox.info(gettext("Done"));
if ($defined(response.next)) {
(function(response) {
current_anchor.parse_string(response.next).update();
select_folder($$("a[href=" + current_anchor.getbaseurl() + "]"));
}).delay(500, this, response);
} else {
infobox.hide(1);
}
} else {
infobox.error(response.respmsg);
}
}
}).get(params);
}