Live loading in the Webmail module! See ChangeLog.

Monotone-Parent: c81c7151deb5466ad48ca5eb97d70f3b1172934c
Monotone-Revision: 4c3c63649f1424cf932228d812cb2a38ae67b434

Monotone-Author: flachapelle@inverse.ca
Monotone-Date: 2010-05-27T14:41:59
Monotone-Branch: ca.inverse.sogo
This commit is contained in:
Francis Lachapelle
2010-05-27 14:41:59 +00:00
parent 113a01009f
commit 3c0bf460bd
20 changed files with 2061 additions and 1443 deletions
+28 -5
View File
@@ -8,7 +8,7 @@ Element.addMethods({
if (element.bind)
element.bind();
},
childNodesWithTag: function(element, tagName) {
element = $(element);
@@ -165,15 +165,18 @@ Element.addMethods({
element.addClassName('_selected');
var parent = element.up();
if (!parent.selectedElements)
if (!parent.selectedElements) {
// Selected nodes are kept in a array at the
// container level.
parent.selectedElements = new Array();
parent.selectedIds = new Array();
}
for (var i = 0; i < parent.selectedElements.length; i++)
if (parent.selectedElements[i] == element) return;
parent.selectedElements.push(element); // use index instead ?
parent.selectedIds.push(element.id);
},
selectRange: function(element, startIndex, endIndex) {
element = $(element);
var s;
@@ -202,10 +205,11 @@ Element.addMethods({
deselect: function(element) {
element = $(element);
element.removeClassName('_selected');
var parent = element.up();
if (parent && parent.selectedElements)
if (parent && parent.selectedElements) {
parent.selectedElements = parent.selectedElements.without(element);
parent.selectedIds = parent.selectedIds.without(element.id);
}
},
deselectAll: function(element) {
@@ -215,6 +219,25 @@ Element.addMethods({
element.selectedElements[i].removeClassName('_selected');
element.selectedElements = null;
}
if (element.selectedIds) {
for (var i = 0; i < element.selectedIds.length; i++) {
var e = element.down('#' + element.selectedIds[i]);
if (e && e.hasClassName('_selected'))
e.removeClassName('_selected');
}
element.selectedIds = null;
}
},
refreshSelectionByIds: function(element) {
element = $(element);
if (element.selectedIds) {
for (var i = 0; i < element.selectedIds.length; i++) {
var e = element.down('#'+element.selectedIds[i]);
if (e && !e.hasClassName('_selected'))
e.addClassName('_selected');
}
}
},
setCaretTo: function(element, pos) {
+119 -131
View File
@@ -18,7 +18,6 @@
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
*/
/* TODO: is the section below used in the mailer? */
DIV#leftPanel
{
@@ -53,7 +52,10 @@ DIV#mailboxContent
right: 0px;
height: 15.5em;
border-left: 1px solid #9B9B9B;
overflow: auto;
overflow: hidden; }
DIV#mailboxList
{ overflow: auto;
overflow-x: hidden; }
DIV#messageContent
@@ -225,81 +227,160 @@ DIV.dTreeNode SPAN.unseen
/* mail tableview */
TD.mailer_readmailsubject
{
padding-left: 20px !important;
}
/* messages table with fixed headers */
TR.mailer_unreadmail TD
{
font-weight: bold !important;
}
TABLE.messageList
{ width: 100%;
-moz-user-select: none;
-khtml-user-select: none; }
TABLE.messageList TH,
TABLE.messageList TD
{ height: 20px;
min-height: 20px;
text-overflow: ellipsis;
overflow: hidden;
padding: 2px 3px;
min-width: 22px;
margin: 0;
white-space: nowrap; }
TR#messageCountHeader TH
{ border-top: 0px; }
TABLE.messageList TD
{ border-right: 1px solid #fff; }
TABLE.messageList .messageFlagColumn
{ width: 22px;
max-width: 22px;
text-align: center; }
TABLE.messageList .messageSubjectColumn
{ max-width: 30%;
width: 30%; }
TABLE.messageList .messageSubjectColumn SPAN
{ padding-left: 20px; }
TABLE.messageList .messageAddressColumn
{ max-width: 18%;
width: 18%; }
TABLE.messageList .messageDateColumn
{ max-width: 22%;
width: 22%; }
TABLE.messageList .messagePriorityColumn
{ width: 60px;
max-width: 60px; }
TABLE.messageList .messageSizeColumn
{ min-width: 40px; }
TR#rowTop TD
{ height: 0;
min-height: 0;
padding-top: 0;
padding-bottom: 0; }
TABLE.messageList TR._selected TD
{ background-color: #9ABCD8;
color: #fff; }
TABLE.messageList TR._deleted TD
{ text-decoration: line-through; }
TABLE.messageList TR[labels~="label5"] TD
{ color: #9c309c; }
TABLE.messageList TR[labels~="label5"]._selected TD
{ color: #fff;
background-color: #9c309c; }
TABLE.messageList TR[labels~="label4"] TD
{ color: #3130ff; }
TABLE.messageList TR[labels~="label4"]._selected TD
{ color: #fff;
background-color: #3130ff; }
TABLE.messageList TR[labels~="label3"] TD
{ color: #009a00; }
TABLE.messageList TR[labels~="label3"]._selected TD
{ color: #fff;
background-color: #009a00; }
TABLE.messageList TR[labels~="label2"] TD
{ color: #ff9a00; }
TABLE.messageList TR[labels~="label2"]._selected TD
{ color: #fff;
background-color: #ff9a00; }
TABLE.messageList TR[labels~="label1"] TD
{ color: #f00; }
TABLE.messageList TR[labels~="label1"]._selected TD
{ color: #fff;
background-color: #f00; }
TABLE.messageList TR.mailer_unreadmail TD
{ font-weight: bold !important; }
TR.mailer_unreadmail TD.messageSubjectColumn
{
background-image: url(icon-new.png);
{ background-image: url(icon-new.png);
background-repeat: no-repeat !important;
background-position: 0px 0px !important;
padding-left: 20px !important;
font-weight: bold !important;
}
background-position: 0px 3px !important;
font-weight: bold !important; }
TD.mailer_repliedmailsubject
{
background-image: url(icon-replied.png) !important;
TR.mailer_repliedmailsubject TD.messageSubjectColumn
{ background-image: url(icon-replied.png) !important;
background-repeat: no-repeat !important;
background-position: 0px 0px !important;
padding-left: 20px !important;
}
background-position: 0px 0px !important; }
TD.mailer_forwardedmailsubject
{
background-image: url(icon-forwarded.png) !important;
{ background-image: url(icon-forwarded.png) !important;
background-repeat: no-repeat !important;
background-position: 0px 0px !important;
padding-left: 20px !important;
}
background-position: 0px 0px !important; }
TD.mailer_forwardedrepliedmailsubject
{
background-image: url(icon-forwarded-replied.png) !important;
background-repeat: no-repeat !important;
background-position: 0px 0px !important;
padding-left: 20px !important;
}
background-position: 0px 0px !important; }
TD.mailer_deletedmailsubject
{
background-image: url(icon-deleted.png) !important;
background-repeat: no-repeat !important;
background-position: 0px 0px !important;
padding-left: 20px !important;
}
background-position: 0px 0px !important; }
TD.mailer_readmailsubject a
TD.mailer_readmailsubject A
{
color: black;
text-decoration: none;
}
TD.mailer_unreadmailsubject a
TD.mailer_unreadmailsubject A
{
color: black;
text-decoration: none;
}
tr.mailer_listcell_deleted td
TR.mailer_listcell_deleted TD
{
text-decoration: line-through;
}
tr.mailer_listcell_regular td a
TR.mailer_listcell_regular TD A
{
color: black;
text-decoration: none;
}
/* fields (key/value UI), eg used in mail viewer */
/* mail viewer */
INPUT#editDraftButton
{
position: absolute;
@@ -547,99 +628,6 @@ TABLE#addr_table
width: 100%;
}
TABLE#messageList
{ width: 100%;
-moz-user-select: none;
-khtml-user-select: none; }
TABLE#messageList TD,
TABLE#messageList TH
{ height: 20px;
overflow: hidden;
white-space: nowrap; }
TABLE#messageList TH
{ white-space: pre; }
TABLE#messageList TBODY TD
{ white-space: pre; }
TD#messageFlagHeader,
TABLE#messageList TD.messageFlagColumn
{ width: 22px;
text-align: center; }
TABLE#messageList TD.messageFlagColumn IMG
{ width: 14px;
height: 14px; }
TD#subjectHeader,
TABLE#messageList TD.mailer_readmailsubject
{ /*width: 40%;*/
min-width: 35%; }
TD#fromHeader,
TABLE#messageList TD.messageAddressColumn
{ /*width: 35%;*/
min-width: 30%;
overflow: hidden; }
TD#dateHeader
{ /*width: 25%;*/
overflow: hidden; }
TD#priorityHeader,
TD#sizeHeader
{ /*width: 25%;*/
width: 7%;
overflow: hidden; }
TABLE#messageList TR._selected TD
{
background-color: #9ABCD8;
color: #fff;
}
TABLE#messageList TR._deleted TD
{
text-decoration: line-through;
}
TABLE#messageList TR[labels~="label5"] TD
{ color: #9c309c; }
TABLE#messageList TR[labels~="label5"]._selected TD
{ color: #fff;
background-color: #9c309c; }
TABLE#messageList TR[labels~="label4"] TD
{ color: #3130ff; }
TABLE#messageList TR[labels~="label4"]._selected TD
{ color: #fff;
background-color: #3130ff; }
TABLE#messageList TR[labels~="label3"] TD
{ color: #009a00; }
TABLE#messageList TR[labels~="label3"]._selected TD
{ color: #fff;
background-color: #009a00; }
TABLE#messageList TR[labels~="label2"] TD
{ color: #ff9a00; }
TABLE#messageList TR[labels~="label2"]._selected TD
{ color: #fff;
background-color: #ff9a00; }
TABLE#messageList TR[labels~="label1"] TD
{ color: #f00; }
TABLE#messageList TR[labels~="label1"]._selected TD
{ color: #fff;
background-color: #f00; }
/* quota indicator */
DIV.quota
{ border-bottom: 1px solid #ccc;
+230 -240
View File
@@ -10,14 +10,6 @@ if (typeof textMailAccounts != 'undefined') {
else
mailAccounts = new Array();
}
var defaultColumnsOrder;
if (typeof textDefaultColumnsOrder != 'undefined') {
if (textDefaultColumnsOrder.length > 0)
defaultColumnsOrder = textDefaultColumnsOrder.evalJSON(true);
else
defaultColumnsOrder = new Array();
}
var Mailer = {
currentMailbox: null,
@@ -27,7 +19,9 @@ var Mailer = {
cachedMessages: new Array(),
foldersStateTimer: false,
popups: new Array(),
quotas: null
quotas: null,
dataTable: null
};
var usersRightsWindowHeight = 320;
@@ -113,8 +107,8 @@ function flagMailInWindow (win, msguid, flagged) {
var row = win.$("row_" + msguid);
if (row) {
var col = row.select("TD.messageFlag").first();
var img = col.select("img").first();
var col = row.down("TD.messageFlag");
var img = col.down("img");
if (flagged) {
img.setAttribute("src", ResourcesURL + "/flag.png");
img.addClassName("messageIsFlagged");
@@ -128,36 +122,34 @@ function flagMailInWindow (win, msguid, flagged) {
function markMailInWindow(win, msguid, markread) {
var row = win.$("row_" + msguid);
var subjectCell = win.$("div_" + msguid);
var unseenCount = 0;
if (row && subjectCell) {
if (row) {
if (markread) {
if (row.hasClassName("mailer_unreadmail")) {
row.removeClassName("mailer_unreadmail");
subjectCell.addClassName("mailer_readmailsubject");
var img = win.$("unreaddiv_" + msguid);
var img = win.$("readdiv_" + msguid);
if (img) {
img.removeClassName("mailerUnreadIcon");
img.addClassName("mailerReadIcon");
img.setAttribute("id", "readdiv_" + msguid);
img.setAttribute("src", ResourcesURL + "/dot.png");
var title = img.getAttribute("title-markunread");
if (title)
img.setAttribute("title", title);
}
else {
log ("No IMG found for " + msguid);
}
unseenCount = -1;
}
}
else {
if (!row.hasClassName("mailer_unreadmail")) {
row.addClassName("mailer_unreadmail");
subjectCell.removeClassName('mailer_readmailsubject');
var img = win.$("readdiv_" + msguid);
if (img) {
img.removeClassName("mailerReadIcon");
img.addClassName("mailerUnreadIcon");
img.setAttribute("id", "unreaddiv_" + msguid);
img.setAttribute("src", ResourcesURL + "/icon_unread.gif");
var title = img.getAttribute("title-markread");
if (title)
@@ -169,7 +161,7 @@ function markMailInWindow(win, msguid, markread) {
}
if (unseenCount != 0) {
/* Update unseen count only if it's the inbox */
// Update unseen count only if it's the inbox
for (var i = 0; i < mailboxTree.aNodes.length; i++)
if (mailboxTree.aNodes[i].datatype == "inbox") break;
if (i != mailboxTree.aNodes.length && Mailer.currentMailbox == mailboxTree.aNodes[i].dataname)
@@ -194,7 +186,7 @@ function openMessageWindowsForSelection(action, firstOnly) {
window.location.href = parts.join("/");
}
else {
var messageList = $("messageList");
var messageList = $("messageListBody");
var rows = messageList.getSelectedRowsId();
if (rows.length > 0) {
for (var i = 0; i < rows.length; i++) {
@@ -236,7 +228,9 @@ function mailListMarkMessage(event) {
}
function mailListMarkMessageCallback(http) {
if (isHttpStatus204(http.status)) {
if (isHttpStatus204(http.status)
|| http.status == 304) { // In some cases, Safari returns a 304 even
// though SOGo returns a 204!
var data = http.callbackData;
markMailInWindow(data["window"], data["msguid"], data["markread"]);
}
@@ -264,6 +258,7 @@ function mailListFlagMessageToggle (e) {
triggerAjaxRequest(url, mailListFlagMessageToggleCallback, data);
}
function mailListFlagMessageToggleCallback (http) {
if (isHttpStatus204(http.status)) {
var data = http.callbackData;
@@ -326,7 +321,7 @@ function onDocumentKeydown(event) {
nextRow = row.next("tr");
else
nextRow = row.previous("tr");
if (nextRow) {
if (nextRow && nextRow.id != 'rowTop' && nextRow.id != 'rowBottom') {
Mailer.currentMessages[Mailer.currentMailbox] = nextRow.getAttribute("id").substr(4);
row.up().deselectAll();
@@ -355,10 +350,11 @@ function onDocumentKeydown(event) {
/* bulk delete of messages */
function deleteSelectedMessages(sender) {
var messageList = $("messageList").down("TBODY");
var messageList = $("messageListBody").down("TBODY");
var rows = messageList.getSelectedNodes();
var uids = new Array(); // message IDs
var paths = new Array(); // row IDs
var unseenCount = 0;
if (rows.length > 0) {
for (var i = 0; i < rows.length; i++) {
@@ -368,6 +364,17 @@ function deleteSelectedMessages(sender) {
rows[i].hide();
uids.push(uid);
paths.push(path);
if (rows[i].hasClassName("mailer_unreadmail"))
unseenCount--;
}
messageList.deselectAll();
updateMessageListCounter(0 - rows.length, true);
if (unseenCount < 0) {
// Update unseen count only if it's the inbox
for (var i = 0; i < mailboxTree.aNodes.length; i++)
if (mailboxTree.aNodes[i].datatype == "inbox") break;
if (i != mailboxTree.aNodes.length && Mailer.currentMailbox == mailboxTree.aNodes[i].dataname)
updateStatusFolders(unseenCount, true);
}
var url = ApplicationBaseURL + encodeURI(Mailer.currentMailbox) + "/batchDelete";
var parameters = "uid=" + uids.join(",");
@@ -391,31 +398,35 @@ function deleteSelectedMessagesCallback(http) {
var div = $('messageContent');
if (Mailer.currentMessages[Mailer.currentMailbox] == data["id"][i]) {
div.update();
Mailer.currentMessages[Mailer.currentMailbox] = null;
Mailer.currentMessages[Mailer.currentMailbox] = null;
}
var row = $("row_" + data["id"][i]);
if (deleteMessageRequestCount == 0) {
var nextRow = row.next("tr");
if (!nextRow)
nextRow = row.previous("tr");
// row.addClassName("deleted"); // when we'll offer "mark as deleted"
if (nextRow) {
Mailer.currentMessages[Mailer.currentMailbox] = nextRow.getAttribute("id").substr(4);
nextRow.selectElement();
loadMessage(Mailer.currentMessages[Mailer.currentMailbox]);
var row = $("row_" + data["id"][i]);
if (row) {
var nextRow = row.next("tr");
if (!nextRow.id.startsWith('row_'))
nextRow = row.previous("tr");
// row.addClassName("deleted"); // when we'll offer "mark as deleted"
if (nextRow.id.startsWith('row_')) {
Mailer.currentMessages[Mailer.currentMailbox] = nextRow.getAttribute("id").substr(4);
nextRow.selectElement();
loadMessage(Mailer.currentMessages[Mailer.currentMailbox]);
}
}
else {
div.update();
}
refreshCurrentFolder();
Mailer.dataTable.remove(data["id"][i]);
Mailer.dataTable.render();
}
else {
Mailer.dataTable.remove(data["id"][i]);
}
row.parentNode.removeChild(row);
}
}
}
else {
log ("deleteSelectedMessagesCallback: problem during ajax request " + http.status);
window.alert(getLabel("Operation failed"));
refreshCurrentFolder();
}
}
@@ -485,15 +496,33 @@ function onMailboxTreeItemClick(event) {
if (head.rows[1])
head.rows[1].firstChild.update();
}
else
else {
var datatype = this.parentNode.getAttribute("datatype");
if (datatype == 'draft' || datatype == 'sent')
toggleAddressColumn("from", "to");
else
toggleAddressColumn("to", "from");
openMailbox(mailbox);
}
Event.stop(event);
}
function toggleAddressColumn(search, replace) {
var header = $(search + "Header");
if (header) {
header.id = replace + "Header";
header.update(getLabel(replace.capitalize()));
var i = UserDefaults["SOGoMailListViewColumnsOrder"].indexOf(search.capitalize());
if (i >= 0)
UserDefaults["SOGoMailListViewColumnsOrder"][i] = replace.capitalize();
}
}
function onMailboxMenuMove(event) {
var targetMailbox;
var messageList = $("messageList").down("TBODY");
var messageList = $("messageListBody").down("TBODY");
var rows = messageList.getSelectedNodes();
var uids = new Array(); // message IDs
var paths = new Array(); // row IDs
@@ -534,7 +563,7 @@ function onMailboxMenuMove(event) {
}
function onMailboxMenuCopy(event) {
var messageList = $("messageList").down("TBODY");
var messageList = $("messageListBody").down("TBODY");
var rows = messageList.getSelectedNodes();
var uids = new Array(); // message IDs
var paths = new Array(); // row IDs
@@ -590,138 +619,34 @@ function composeNewMessage() {
}
}
function openMailbox(mailbox, reload, idx, updateStatus) {
function openMailbox(mailbox, reload, updateStatus) {
if (mailbox != Mailer.currentMailbox || reload) {
Mailer.currentMailbox = mailbox;
var url = ApplicationBaseURL + encodeURI(mailbox) + "/view?noframe=1";
if (!reload || idx) {
var url = ApplicationBaseURL + encodeURI(mailbox);
var urlParams = new Hash();
if (!reload) {
var messageContent = $("messageContent");
messageContent.update();
$("messageCountHeader").down().update();
lastClickedRow = -1; // from generic.js
}
var currentMessage;
if (!idx) {
currentMessage = Mailer.currentMessages[mailbox];
if (currentMessage) {
url += '&pageforuid=' + currentMessage;
if (!reload)
loadMessage(currentMessage);
}
}
var searchValue = search["value"];
if (searchValue && searchValue.length > 0)
url += ("&search=" + search["criteria"]
+ "&value=" + escape(searchValue.utf8encode()));
if (searchValue && searchValue.length > 0) {
urlParams.set("search", search["criteria"]);
urlParams.set("value", escape(searchValue.utf8encode()));
}
var sortAttribute = sorting["attribute"];
if (sortAttribute && sortAttribute.length > 0)
url += ("&sort=" + sorting["attribute"]
+ "&asc=" + sorting["ascending"]);
if (idx)
url += "&idx=" + idx;
if (document.messageListAjaxRequest) {
document.messageListAjaxRequest.aborted = true;
document.messageListAjaxRequest.abort();
}
var mailboxContent = $("mailboxContent");
if (mailboxContent.getStyle('visibility') == "hidden") {
mailboxContent.setStyle({ visibility: "visible" });
var rightDragHandle = $("rightDragHandle");
rightDragHandle.setStyle({ visibility: "visible" });
messageContent.setStyle({ top: (rightDragHandle.offsetTop
+ rightDragHandle.offsetHeight
+ 'px') });
}
document.messageListAjaxRequest
= triggerAjaxRequest(url, messageListCallback,
currentMessage);
if (updateStatus != false)
getStatusFolders();
}
}
function openMailboxAtIndex(event) {
openMailbox(Mailer.currentMailbox, true, this.getAttribute("idx"));
Event.stop(event);
}
function messageListCallback(http) {
var div = $('mailboxContent');
var table = $('messageList');
var columnsOrder = UserDefaults["SOGoMailListViewColumnsOrder"];
if ( typeof(columnsOrder) == "undefined" ) {
columnsOrder = defaultColumnsOrder;
}
var addrIndex = 3;
for(var i=0; i<columnsOrder.length; i++) {
if (columnsOrder[i] == "From" || columnsOrder[i] == "To") {
addrIndex = i;
}
}
if (http.status == 200) {
document.messageListAjaxRequest = null;
if (table) {
// Update table
var thead = table.tHead;
var addressHeaderCell = thead.rows[0].cells[addrIndex];
var tbody = table.tBodies[0];
var tmp = document.createElement('div');
$(tmp).update(http.responseText);
var newRows = tmp.firstChild.tHead.rows;
thead.rows[1].parentNode.replaceChild(newRows[1], thead.rows[1]);
addressHeaderCell.replaceChild(newRows[0].cells[addrIndex].lastChild,
addressHeaderCell.lastChild);
addressHeaderCell.setAttribute("id", newRows[0].cells[addrIndex].getAttribute("id"));
table.replaceChild(tmp.firstChild.tBodies[0], tbody);
configureMessageListEvents(table);
}
else {
// Add table
div.update(http.responseText);
table = $("messageList");
configureMessageListEvents(table);
TableKit.Resizable.init(table, {'trueResize' : true, 'keepWidth' : true});
configureDraggables();
}
configureMessageListBodyEvents(table);
var selected = http.callbackData;
if (selected) {
var row = $("row_" + selected);
if (row) {
row.selectElement();
lastClickedRow = row.rowIndex - $(row).up('table').down('thead').getElementsByTagName('tr').length;
var rowPosition = row.rowIndex * row.getHeight();
if (rowPosition < div.scrollTop
|| rowPosition > div.scrollTop + div.getHeight ())
div.scrollTop = rowPosition; // scroll to selected message
}
else
$("messageContent").update();
}
else
div.scrollTop = 0;
if (sorting["attribute"] && sorting["attribute"].length > 0) {
if (sortAttribute && sortAttribute.length > 0) {
urlParams.set("sort", sorting["attribute"]);
urlParams.set("asc", sorting["ascending"]);
var sortHeader = $(sorting["attribute"] + "Header");
if (sortHeader) {
var sortImages = $(table.tHead).select(".sortImage");
var sortImages = sortHeader.up('THEAD').select(".sortImage");
$(sortImages).each(function(item) {
item.remove();
});
var sortImage = createElement("img", "messageSortImage", "sortImage");
sortHeader.insertBefore(sortImage, sortHeader.firstChild);
if (sorting["ascending"])
@@ -730,13 +655,73 @@ function messageListCallback(http) {
sortImage.src = ResourcesURL + "/arrow-up.png";
}
}
// TODO : refresh mailbox without removing all rows.
var messageList = $("messageListBody").down('TBODY');
var dataSource = new SOGoMailDataSource(Mailer.dataTable, url);
Mailer.dataTable.setSource('SOGoMailDataSource', url, urlParams);
messageList.deselectAll();
Mailer.dataTable.render();
configureDraggables();
Mailer.currentMailbox = mailbox;
/*
// TODO : restore previously selected message.
var currentMessage = Mailer.currentMessages[mailbox];
if (currentMessage) {
Mailer.dataTable.render(currentMessage);
if (!reload)
loadMessage(currentMessage);
}
*/
if (updateStatus != false)
getStatusFolders();
}
else {
var data = http.responseText;
var msg = data.replace(/^(.*\n)*.*<p>((.*\n)*.*)<\/p>(.*\n)*.*$/, "$2");
log("messageListCallback: problem during ajax request (readyState = " + http.readyState + ", status = " + http.status + ", response = " + msg + ")");
}
/*
* Called from SOGoDataTable.render()
*/
function messageListCallback(row, data, isNew) {
if (isNew) {
row.observe("mousedown", onRowClick);
row.observe("selectstart", listRowMouseDownHandler);
row.observe("contextmenu", onMessageContextMenu);
}
row.className = data['rowClasses'];
row.id = data['rowID'];
row.writeAttribute('labels', (data['labels']?data['labels']:""));
var columnsOrder = UserDefaults["SOGoMailListViewColumnsOrder"];
// if (typeof columnsOrder == "undefined") {
// columnsOrder = defaultColumnsOrder;
// }
var cells;
if (Prototype.Browser.IE)
cells = row.childNodes;
else
cells = row.cells;
for (var j = 0; j < cells.length; j++) {
var cell = $(cells[j]);
var cellType = columnsOrder[j];
if (data[cellType]) cell.update(data[cellType]);
cell.observe("mousedown", listRowMouseDownHandler);
if (cellType == "Subject" || cellType == "From" || cellType == "To" || cellType == "Date")
cell.observe("dblclick", onMessageDoubleClick.bindAsEventListener(cell));
else if (cellType == "Unread") {
var img = cell.down('img');
if (img)
img.observe("click", mailListMarkMessage.bindAsEventListener(img));
}
else if (cellType == 'Flagged' && isNew)
cell.observe("click", mailListFlagMessageToggle.bindAsEventListener(cell));
}
initFlagIcons ();
}
function getStatusFolders() {
@@ -784,9 +769,28 @@ function updateStatusFolders(count, isDelta) {
}
}
function updateMessageListCounter(count, isDelta) {
var cell = $("messageCountHeader").down();
if (isDelta) {
var value = parseInt(cell.innerHTML);
count += value;
}
if (count > 0)
cell.update(count + " " + getLabel("messages"));
else
cell.update(getLabel("No message"));
}
function onMessageListRender(event) {
// Event is fired from SOGoDataTable.
updateMessageListCounter(event.memo, false);
}
function onMessageContextMenu(event) {
var menu = $('messageListMenu');
var topNode = $('messageList');
var topNode = $('messageListBody');
var selectedNodes = topNode.getSelectedRows();
menu.observe("hideMenu", onMessageContextMenuHide);
@@ -1409,7 +1413,7 @@ function onMenuForwardMessage(event) {
}
function onMenuViewMessageSource(event) {
var messageList = $("messageList");
var messageList = $("messageListBody");
var rows = messageList.getSelectedRowsId();
if (rows.length > 0) {
@@ -1482,9 +1486,9 @@ function expandUpperTree(node) {
}
function onHeaderClick(event) {
if (TableKit.Resizable._onHandle)
if (SOGoResizableTable._onHandle)
return;
var headerId = this.getAttribute("id");
var newSortAttribute;
if (headerId == "subjectHeader")
@@ -1515,63 +1519,16 @@ function refreshCurrentFolder() {
openMailbox(Mailer.currentMailbox, true);
}
/* a model for a futur refactoring of the sortable table headers mechanism */
function configureMessageListEvents(table) {
if (table) {
table.multiselect = true;
// Each body row can load a message
table.observe("mousedown", onMessageSelectionChange);
function configureMessageListEvents(headerTable, dataTable) {
if (headerTable)
// Sortable columns
configureSortableTableHeaders(table);
}
}
function configureMessageListBodyEvents(table) {
if (table) {
// Page navigation
var cell = table.tHead.rows[1].cells[0];
if ($(cell).hasClassName("tbtv_navcell")) {
var anchors = $(cell).childNodesWithTag("a");
for (var i = 0; i < anchors.length; i++)
$(anchors[i]).observe("click", openMailboxAtIndex);
}
rows = table.tBodies[0].rows;
for (var i = 0; i < rows.length; i++) {
var row = $(rows[i]);
row.observe("mousedown", onRowClick);
row.observe("selectstart", listRowMouseDownHandler);
row.observe("contextmenu", onMessageContextMenu);
//row.dndTypes = function() { return new Array("mailRow"); };
//row.dndGhost = messageListGhost;
//row.dndDataForType = messageListData;
//document.DNDManager.registerSource(row);
// Correspondances index <> nom de la colonne
// 0 => Invisible
// 1 => Attachment
// 2 => Subject
// 3 => From
// 4 => Unread
// 5 => Date
// 6 => Priority
var columnsOrder = UserDefaults["SOGoMailListViewColumnsOrder"];
if ( typeof(columnsOrder) == "undefined" ) {
columnsOrder = defaultColumnsOrder;
}
for (var j = 0; j < row.cells.length; j++) {
var cell = $(row.cells[j]);
var cellType = columnsOrder[j];
cell.observe("mousedown", listRowMouseDownHandler);
if (cellType == "Subject" || cellType == "From" || cellType == "To" || cellType == "Date")
cell.observe("dblclick", onMessageDoubleClick.bindAsEventListener(cell));
else if (cellType == "Unread") {
var img = $(cell.childNodesWithTag("img")[0]);
if (img)
img.observe("click", mailListMarkMessage.bindAsEventListener(img));
}
}
}
configureSortableTableHeaders(headerTable);
if (dataTable) {
dataTable.multiselect = true;
// Each body row can load a message
dataTable.observe("mousedown",
onMessageSelectionChange.bindAsEventListener(dataTable));
}
}
@@ -1589,9 +1546,15 @@ function configureDragHandles() {
handle.addInterface(SOGoDragHandlesInterface);
handle.upperBlock=$("mailboxContent");
handle.lowerBlock=$("messageContent");
handle.upperBlock.observe("handle:resize", onMessageListResize);
}
}
function onMessageListResize(event) {
var h = $("mailboxContent").getHeight() - $("messageListHeader").getHeight();
$("mailboxList").setStyle({'height': h + 'px'});
}
function onWindowResize(event) {
var handle = $("verticalDragHandle");
if (handle)
@@ -1641,15 +1604,36 @@ function openInbox(node) {
mailboxTree.o(1);
}
function initFlagIcons () {
var icons = $$("TABLE#messageList TBODY TR.mailer_listcell_regular TD.messageFlag");
for (var i = 0; i < icons.length; i++)
icons[i].onclick = mailListFlagMessageToggle;
}
function initMailer(event) {
// Default sort options
sorting["attribute"] = "date";
sorting["ascending"] = false;
// Define columns order
if (typeof UserDefaults["SOGoMailListViewColumnsOrder"] == "undefined") {
var defaultColumnsOrder;
if (typeof textDefaultColumnsOrder != 'undefined') {
if (textDefaultColumnsOrder.length > 0)
defaultColumnsOrder = textDefaultColumnsOrder.evalJSON(true);
else
defaultColumnsOrder = new Array();
}
UserDefaults["SOGoMailListViewColumnsOrder"] = defaultColumnsOrder;
}
if (!$(document.body).hasClassName("popup")) {
//initDnd();
Mailer.dataTable = $("mailboxList");
Mailer.dataTable.addInterface(SOGoDataTableInterface);
Mailer.dataTable.setRowRenderCallback(messageListCallback);
Mailer.dataTable.observe("datatable:rendered", onMessageListRender);
var messageListHeader = $("messageListHeader");
messageListHeader.addInterface(SOGoResizableTableInterface);
configureMessageListEvents($("messageListHeader"), $("messageListBody"));
initMailboxTree();
initMessageCheckTimer();
@@ -1668,12 +1652,9 @@ function initMailer(event) {
Event.observe(window, "beforeunload", onUnload);
}
onMessageListResize();
onWindowResize.defer();
Event.observe(window, "resize", onWindowResize);
// Default sort options
sorting["attribute"] = "date";
sorting["ascending"] = false;
}
function initMessageCheckTimer() {
@@ -2188,8 +2169,17 @@ function folderRefreshCallback(http) {
&& isHttpStatus204(http.status)) {
var oldMailbox = http.callbackData.mailbox;
if (http.callbackData.refresh
&& oldMailbox == Mailer.currentMailbox)
refreshCurrentFolder();
&& oldMailbox == Mailer.currentMailbox) {
if (http.callbackData.id) {
var s = http.callbackData.id + "";
var uids = s.split(",");
for (var i = 0; i < uids.length; i++)
Mailer.dataTable.remove(uids[i]);
Mailer.dataTable.render();
}
else
refreshCurrentFolder();
}
}
else {
if (http.callbackData.id) {
@@ -2237,7 +2227,7 @@ function messageFlagCallback(http) {
}
function onLabelMenuPrepareVisibility() {
var messageList = $("messageList");
var messageList = $("messageListBody");
var flags = {};
if (messageList) {
@@ -2266,7 +2256,7 @@ function onLabelMenuPrepareVisibility() {
}
function saveAs(event) {
var messageList = $("messageList").down("TBODY");
var messageList = $("messageListBody").down("TBODY");
var rows = messageList.getSelectedNodes();
var uids = new Array(); // message IDs
var paths = new Array(); // row IDs
@@ -2434,7 +2424,7 @@ function configureDraggables () {
mainElement.hide();
new Draggable ("dragDropVisual",
{ handle: "messageList",
{ handle: "messageListBody",
onStart: startDragging,
onEnd: stopDragging,
onDrag: whileDragging,
@@ -2455,11 +2445,11 @@ function configureDroppables () {
function startDragging (itm, e) {
var target = Event.element(e);
if (target.up().up().tagName != "TBODY")
if (target.up('TBODY') == undefined)
return false;
var handle = $("dragDropVisual");
var count = $('messageList').getSelectedRowsId().length;
var count = $("messageListBody").getSelectedRowsId().length;
handle.update (count);
if (e.shiftKey)
+260
View File
@@ -0,0 +1,260 @@
/* -*- Mode: java; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* Data table interface to be added to a DIV (this!)
*
* Available events:
* datatable:rendered -- fired once the view rendering is completed
*
*/
var SOGoDataTableInterface = {
// Object variables initialized with "bind"
columnsCount: null,
rowModel: null,
rowHeight: 0,
body: null,
// Object variables
dataSource: null,
rowTop: null,
rowBottom: null,
renderedIndex: -1,
renderedCount: 0,
rowRenderCallback: null,
// Constants
overflow: 30, // must be lower than the overflow of the data source class
renderDelay: 0.2, // delay (in seconds) before which the table is rendered upon scrolling
bind: function() {
this.observe("scroll" , this.render.bind(this));
this.body = this.down("tbody");
this.rowModel = this.body.down("tr");
// Since we use the fixed table layout, the first row must have the
// proper CSS classes that will define the columns width.
this.rowTop = new Element('tr', {'id': 'rowTop'});//.update(new Element('td'));
this.body.insertBefore(this.rowTop, this.rowModel); // IE requires the element to be inside the DOM before appending new children
var cells = this.rowModel.select('TD');
for (var i = 0; i < cells.length; i++) {
var cell = cells[i];
var td = new Element('td', {'class': cell.className});
this.rowTop.appendChild(td);
}
this.rowBottom = new Element('tr', {'id': 'rowBottom'}).update(new Element('td'));
this.body.insertBefore(this.rowBottom, this.rowModel);
this.columnsCount = this.rowModel.select("td").length;
this.rowHeight = this.rowModel.getHeight();
},
setRowRenderCallback: function(callbackFunction) {
// Each time a row is created or updated with new data, this callback
// function will be called.
this.rowRenderCallback = callbackFunction;
},
setSource: function(dataSourceClass, url, params) {
// log ("DataTable.setSource() " + url);
if (this.dataSource) this.dataSource.destroy();
this._emptyTable();
this.dataSource = new window[dataSourceClass](this, url);
this.load(params);
},
load: function(urlParams) {
if (!this.dataSource) return;
// log ("DataTable.load() with parameters [" + urlParams.keys().join(' ') + "]");
if (Object.isHash(urlParams) && urlParams.keys().length > 0) this.dataSource.load(urlParams);
else this.dataSource.load(new Hash());
},
visibleRowCount: function() {
var divHeight = this.getHeight();
var visibleRowCount = Math.ceil(divHeight/this.rowHeight);
return visibleRowCount;
},
firstVisibleRowIndex: function() {
var firstRowIndex = Math.floor(this.scrollTop/this.rowHeight);
return firstRowIndex;
},
render: function(uid) {
var index = this.firstVisibleRowIndex();
var count = this.visibleRowCount();
// Overflow the query to the maximum defined in the class variable overflow
var start = index - (this.overflow/2);
if (start < 0) start = 0;
var end = index + count + this.overflow - (index - start);
// log ("DataTable.getData() from " + index + " to " + (index + count) + " boosted from " + start + " to " + end);
// Don't overflow above the maximum number of entries from the data source
if (this.dataSource.uids && this.dataSource.uids.length < end) end = this.dataSource.uids.length;
index = start;
count = end - start;
this.currentRenderID = index + "-" + count;
// Query the data source only if at least one row is not loaded
if (this.renderedIndex < 0 ||
this.renderedIndex > index ||
this.renderedCount < count ||
(index + count) > (this.renderedIndex + this.renderedCount)) {
this.dataSource.getData(this.currentRenderID,
index,
count,
this._render.bind(this),
this.renderDelay);
}
},
_render: function(renderID, start, max, data) {
if (this.currentRenderID != renderID) {
// log ("DataTable._render() ignore render for " + renderID + " (current is " + this.currentRenderID + ")");
return;
}
// log("DataTable._render() for " + data.length + " uids (from " + start + ")");
var h, i, j;
var rows = this.body.select("tr");
var scroll;
scroll = this.scrollTop;
lastClickedRow = -1; // defined in generic.js
h = start * this.rowHeight;
if (Prototype.Browser.IE)
this.rowTop.setStyle({ 'height': h + 'px', 'line-height': h + 'px' });
this.rowTop.firstChild.setStyle({ 'height': h + 'px', 'line-height': h + 'px' });
h = (max - start - data.length) * this.rowHeight;
if (Prototype.Browser.IE)
this.rowBottom.setStyle({ 'height': h + 'px', 'line-height': h + 'px' });
this.rowBottom.firstChild.setStyle({ 'height': h + 'px', 'line-height': h + 'px' });
if (this.renderedIndex < 0) {
this.renderedIndex = 0;
this.renderedCount = 0;
}
if (start > (this.renderedIndex + this.renderedCount) ||
start + data.length < this.renderedIndex) {
// No reusable row in the viewport;
// refresh the complete view port
for (i = 0, j = start;
i < this.renderedCount && i < data.length;
i++, j++) {
// Render all existing rows with new data
var row = rows[i+1]; // must skip the first row (this.rowTop)
row.removeClassName('_selected');
this.rowRenderCallback(row, data[i], false);
}
for (i = this.renderedCount;
i < data.length;
i++, j++) {
// Add new rows, if necessary
var row = this.rowModel.cloneNode(true);
this.rowRenderCallback(row, data[i], true);
row.show();
this.body.insertBefore(row, this.rowBottom);
}
for (i = this.renderedCount;
i > data.length;
i--) {
// Delete extra rows, if necessary
this.body.removeChild(rows[i]);
}
}
else if (start >= this.renderedIndex) {
// Scrolling down
// Delete top rows
for (i = start; i > this.renderedIndex; i--) {
this.body.removeChild(rows[i - this.renderedIndex]);
}
// Add bottom rows
for (j = this.renderedIndex + this.renderedCount - start, i = this.renderedIndex + this.renderedCount;
j < data.length;
j++, i++) {
var row = this.rowModel.cloneNode(true);
this.rowRenderCallback(row, data[j], true);
row.show();
this.body.insertBefore(row, this.rowBottom);
}
}
else {
// Scrolling up
// Delete bottom rows
for (i = this.renderedIndex + this.renderedCount, j = this.renderedCount;
i > (start + data.length);
i--, j--) {
this.body.removeChild(rows[j]);
}
// Add top rows
for (i = 0, j = start;
j < this.renderedIndex;
i++, j++) {
var row = this.rowModel.cloneNode(true);
this.rowRenderCallback(row, data[i], true);
row.show();
this.body.insertBefore(row, rows[1]);
}
}
this.body.refreshSelectionByIds();
// log ("DataTable._render() top gap/bottom gap/total rows = " + this.rowTop.getStyle('height') + "/" + this.rowBottom.getStyle('height') + "/" + this.body.select("tr").length + " (height = " + this.down("table").getHeight() + "px)");
// Save current rendered view index and count
this.renderedIndex = start;
this.renderedCount = data.length;
// Restore scroll position (necessary in certain cases)
this.scrollTop = scroll;
Event.fire(this, "datatable:rendered", max);
},
remove: function(uid) {
var rows = this.body.select("TR#row_" + uid);
if (rows.length == 1) {
var row = rows.first();
row.parentNode.removeChild(row);
var index = this.dataSource.invalidate(uid);
// log ("DataTable.remove(" + uid + ")");
if (this.renderedIndex < index &&
(this.renderedIndex + this.renderedCount) > index) {
this.renderedCount--;
}
}
},
_emptyTable: function() {
var rows = this.body.select("tr");
var currentCount = rows.length;
for (var i = currentCount - 1; i >= 0; i--) {
if (rows[i] != this.rowModel &&
rows[i] != this.rowTop &&
rows[i] != this.rowBottom)
this.body.removeChild(rows[i]);
}
this.renderedIndex = -1;
this.renderedCount = 0;
this.rowTop.firstChild.setStyle({ 'height': '0px', 'line-height': '0px' });
this.rowBottom.firstChild.setStyle({ 'height': '0px', 'line-height': '0px' });
}
};
+3 -2
View File
@@ -120,10 +120,11 @@ var SOGoDragHandlesInterface = {
deltaY = Math.floor(pointerY - this.origY - (this.offsetHeight / 2));
this.lowerBlock.setStyle({ top: (this.origLower + deltaY - this.delta) + 'px' });
this.upperBlock.setStyle({ height: (this.origUpper + deltaY - this.delta) + 'px' });
//this.lowerBlock.fire("handle:resize");
this.upperBlock.fire("handle:resize");
this.saveDragHandleState(this.dhType, parseInt(this.lowerBlock.getStyle("top")));
}
if (Prototype.Browser.IE)
if (Prototype.Browser.IE)
Event.stopObserving(document.body, "mouseup", this.stopHandleDraggingBound);
else
Event.stopObserving(window, "mouseup", this.stopHandleDraggingBound);
+167
View File
@@ -0,0 +1,167 @@
/* -*- Mode: java; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
SOGoMailDataSource = Class.create({
initialize: function(dataTable, url) {
// Instance variables
this.dataTable = dataTable;
this.url = url;
this.uids = new Array();
this.cache = new Hash();
this.loaded = false;
this.delayedGetData = false;
this.ajaxGetData = false;
// Constants
this.overflow = 60;
},
destroy: function() {
this.uids.clear();
var keys = this.cache.keys();
for (var i = 0; i < keys.length; i++)
this.cache.unset(keys[i]);
},
invalidate: function(uid) {
this.cache.unset(uid);
var index = this.uids.indexOf(parseInt(uid));
log ("MailDataSource.invalidate(" + uid + ") at index " + index);
if (index >= 0) {
this.uids.splice(index, 1);
}
return index;
},
load: function(urlParams) {
var params;
this.loaded = false;
if (urlParams.keys().length > 0) {
params = urlParams.keys().collect(function(key) { return key + "=" + urlParams.get(key); }).join("&");
}
else
params = "";
// log ("MailDataSource.load() " + params);
triggerAjaxRequest(this.url + "/uids",
this._loadCallback.bind(this),
null,
params,
{ "Content-type": "application/x-www-form-urlencoded" });
},
_loadCallback: function(http) {
if (http.status == 200) {
if (http.responseText.length > 0) {
this.uids = $A(http.responseText.evalJSON(true));
log ("MailDataSource._loadCallback() " + this.uids.length + " uids");
this.loaded = true;
}
}
else {
alert("SOGoMailDataSource._loadCallback Error " + http.status + ": " + http.responseText);
}
},
getData: function(id, index, count, callbackFunction, delay) {
if (this.loaded == false) {
// UIDs are not yet loaded -- delay the call to the current function
// log ("MailDataSource.getData() delaying data fetching while waiting for UIDs");
if (this.delayedGetData) window.clearTimeout(this.delayedGetData);
this.delayedGetData = this.getData.bind(this, id, index, count, callbackFunction, delay).delay(0.3);
return;
}
if (this.delayed_getData) window.clearTimeout(this.delayed_getData);
this.delayed_getData = this._getData.bind(this,
id,
index,
count,
callbackFunction
).delay(delay);
},
_getData: function(id, index, count, callbackFunction) {
var start, end;
var i, j;
var missingUids = new Array();
// Compute last index depending on number of UIDs
start = index - (this.overflow/2);
if (start < 0) start = 0;
end = index + count + this.overflow - (index - start);
if (end > this.uids.length) {
start -= end - this.uids.length;
end = this.uids.length;
if (start < 0) start = 0;
}
log ("MailDataSource._getData() from " + index + " to " + (index + count) + " boosted from " + start + " to " + end);
for (i = 0, j = start; j < end; j++) {
if (!this.cache.get(this.uids[j])) {
missingUids[i] = this.uids[j];
i++;
}
}
if (this.delayed_getRemoteData) window.clearTimeout(this.delayed_getRemoteData);
if (missingUids.length > 0) {
var params = "uids=" + missingUids.join(",");
this.delayed_getRemoteData = this._getRemoteData.bind(this,
{ callbackFunction: callbackFunction,
start: start, end: end,
id: id },
params).delay(0.5);
}
else
this._returnData(callbackFunction, id, start, end);
},
_getRemoteData: function(callbackData, urlParams) {
if (this.ajaxGetData) {
this.ajaxGetData.aborted = true;
this.ajaxGetData.abort();
// log ("MailDataSource._getData() aborted previous AJAX request");
}
// log ("MailDataSource._getData() fetching headers of " + urlParams);
this.ajaxGetData = triggerAjaxRequest(this.url + "/headers",
this._getRemoteDataCallback.bind(this),
callbackData,
urlParams,
{ "Content-type": "application/x-www-form-urlencoded" });
},
_getRemoteDataCallback: function(http) {
if (http.status == 200) {
if (http.responseText.length > 0) {
// We receives an array of hashes
var headers = $A(http.responseText.evalJSON(true));
var data = http.callbackData;
for (var i = 0; i < headers.length; i++) {
this.cache.set(headers[i]["uid"], headers[i]);
}
this._returnData(data["callbackFunction"], data["id"], data["start"], data["end"]);
}
}
else {
alert("SOGoMailDataSource._getRemoteDataCallback Error " + http.status + ": " + http.responseText);
}
},
_returnData: function(callbackFunction, id, start, end) {
var i, j;
var data = new Array();
for (i = start, j = 0; i < end; i++, j++) {
data[j] = this.cache.get(this.uids[i]);
}
callbackFunction(id, start, this.uids.length, data);
},
indexOf: function(uid) {
this.uids.indexOf(uid + "");
}
});
+237
View File
@@ -0,0 +1,237 @@
/* -*- Mode: java; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* Resizable table interface to be added to a TABLE (this!)
*
* Columns with the class resizable will be .. resizable.
*
*/
var SOGoResizableTableInterface = {
delayedResize: null,
bind: function() {
var i;
var cells = $(this).down('tr').childElements();
for (i = 0; i < cells.length; i++) {
var cell = cells[i];
if (Prototype.Browser.IE)
cell.observe("selectstart", Event.stop);
if (cell.hasClassName('resizable')) {
Event.observe(cell, 'mouseover', SOGoResizableTable.initDetect);
Event.observe(cell, 'mouseout', SOGoResizableTable.killDetect);
}
SOGoResizableTable._resize(this, $(cell), i, null, cell.getWidth());
}
Event.observe(window, "resize", this.restore.bind(this));
},
restore: function(e) {
// Only resize the columns after a certain delay, otherwise it slow
// down the interface.
if (this.delayedResize) window.clearTimeout(this.delayedResize);
this.delayedResize = this._restore.bind(this).delay(0.2);
},
_restore: function() {
if (Prototype.Browser.IE)
while (SOGoResizableTable._stylesheet.styleSheet.rules.length)
SOGoResizableTable._stylesheet.styleSheet.removeRule();
else
while (SOGoResizableTable._stylesheet.firstChild)
SOGoResizableTable._stylesheet.removeChild(SOGoResizableTable._stylesheet.firstChild);
// TODO : widths ratios should be computed and columns restored accordingly.
var cells = $(this).down('tr').childElements();
for (i = 0; i < cells.length; i++) {
var cell = cells[i];
SOGoResizableTable._resize(this, $(cell), i, null, cell.getWidth());
}
}
};
SOGoResizableTable = {
_onHandle: false,
_cell: null,
_tbl: null,
_handle: null,
_stylesheet: null,
resize: function(table, index, w) {
var cell;
if (typeof index === 'number') {
if (!table || (table.tagName && table.tagName !== "TABLE")) { return; }
table = $(table);
index = Math.min(table.rows[0].cells.length, index);
index = Math.max(1, index);
index -= 1;
cell = $(table.rows[0].cells[index]);
}
else {
cell = $(index);
table = table ? $(table) : cell.up('table');
index = SOGoResizableTable.getCellIndex(cell);
}
var cells = table.down('tr').childElements();
var nextResizableCell = null;
for (var i = index + 1; i < cells.length; i++) {
var c = cells[i];
if (c.hasClassName('resizable')) {
nextResizableCell = c;
break;
}
}
var delta = SOGoResizableTable._resize(table, cell, index, nextResizableCell, w, false);
if (delta != 0 && nextResizableCell != null) {
var w = nextResizableCell.getWidth() - delta;
SOGoResizableTable._resize(table, nextResizableCell, i, null, w, true);
}
},
_resize: function(table, cell, index, nextResizableCell, w, isAdjustment) {
var pad = 0;
if (!Prototype.Browser.WebKit) {
pad = parseInt(cell.getStyle('paddingLeft'),10) + parseInt(cell.getStyle('paddingRight'),10);
pad += parseInt(cell.getStyle('borderLeftWidth'),10) + parseInt(cell.getStyle('borderRightWidth'),10);
}
var cells = table.down('tr').childElements();
if ((index + 1) == cells.length) {
return 0;
}
if (!isAdjustment && cell.getWidth() < w) {
if (nextResizableCell == null && (index + 2) == cells.length)
// The next cell is the last cell; respect its minimum width
// event if it's not resizable.
nextResizableCell = cells[index + 1];
if (nextResizableCell != null) {
// Respect the minimum width of the next resizable cell.
var max = cells[index].getWidth()
+ nextResizableCell.getWidth()
- parseInt(nextResizableCell.getStyle('minWidth'))
- pad;
w = Math.min(max, w);
}
}
// Respect the minimum width of the cell.
w = Math.max(w - pad, parseInt(cell.getStyle('minWidth')));
var delta = w - cell.getWidth() + pad;
var cssSelector = ' TABLE.' + $w(table.className).first() + ' .' + $w(cell.className).first();
if (SOGoResizableTable._stylesheet == null) {
SOGoResizableTable._stylesheet = document.createElement("style");
SOGoResizableTable._stylesheet.type = "text/css";
document.getElementsByTagName("head")[0].appendChild(SOGoResizableTable._stylesheet);
}
if (SOGoResizableTable._stylesheet.styleSheet && SOGoResizableTable._stylesheet.styleSheet.addRule) {
// IE
SOGoResizableTable._stylesheet.styleSheet.addRule(cssSelector,
' { width: ' + w + 'px; max-width: ' + w + 'px; }');
}
else {
// Mozilla + Safari
SOGoResizableTable._stylesheet.appendChild(document.createTextNode(cssSelector +
' { width: ' + w + 'px; max-width: ' + w + 'px; }'));
}
return delta;
},
initDetect: function(e) {
var cell = Event.element(e);
if (cell.tagName != "TH") { return; }
Event.observe(cell, 'mousemove', SOGoResizableTable.detectHandle);
Event.observe(cell, 'mousedown', SOGoResizableTable.startResize);
},
detectHandle: function(e) {
var cell = Event.element(e);
if (SOGoResizableTable.pointerPos(cell, Event.pointerX(e), Event.pointerY(e))) {
cell.addClassName('resize-handle-active');
SOGoResizableTable._onHandle = true;
}
else {
cell.removeClassName('resize-handle-active');
SOGoResizableTable._onHandle = false;
}
},
killDetect: function(e) {
SOGoResizableTable._onHandle = false;
var cell = Event.element(e);
Event.stopObserving(cell, 'mousemove', SOGoResizableTable.detectHandle);
Event.stopObserving(cell, 'mousedown', SOGoResizableTable.startResize);
cell.removeClassName('resize-handle-active');
},
startResize: function(e) {
if (!SOGoResizableTable._onHandle) { return; }
var cell = Event.element(e);
Event.stopObserving(cell, 'mousemove', SOGoResizableTable.detectHandle);
Event.stopObserving(cell, 'mousedown', SOGoResizableTable.startResize);
Event.stopObserving(cell, 'mouseout', SOGoResizableTable.killDetect);
SOGoResizableTable._cell = cell;
var table = cell.up('table');
SOGoResizableTable._tbl = table;
SOGoResizableTable._handle = $(document.createElement('div')).addClassName('resize-handle').setStyle({
'top' : table.cumulativeOffset()[1] + 'px',
'left' : Event.pointerX(e) + 'px',
'height' : table.getHeight() + 'px',
'max-height' : table.getHeight() + 'px'
});
document.body.appendChild(SOGoResizableTable._handle);
Event.observe(document, 'mousemove', SOGoResizableTable.drag);
Event.observe(document, 'mouseup', SOGoResizableTable.endResize);
Event.stop(e);
},
endResize: function(e) {
var cell = SOGoResizableTable._cell;
if (!cell) { return; }
SOGoResizableTable.resize(null, cell, (Event.pointerX(e) - cell.cumulativeOffset()[0]));
Event.stopObserving(document, 'mousemove', SOGoResizableTable.drag);
Event.stopObserving(document, 'mouseup', SOGoResizableTable.endResize);
$$('div.resize-handle').each(function(elm){
document.body.removeChild(elm);
});
Event.observe(cell, 'mouseout', SOGoResizableTable.killDetect);
SOGoResizableTable._tbl = SOGoResizableTable._handle = SOGoResizableTable._cell = null;
Event.stop(e);
},
drag: function(e) {
e = $(e);
if (SOGoResizableTable._handle === null) {
try {
SOGoResizableTable.resize(SOGoResizableTable._tbl, SOGoResizableTable._cell, (Event.pointerX(e) - SOGoResizableTable._cell.cumulativeOffset()[0]));
}
catch(e) {}
}
else {
SOGoResizableTable._handle.setStyle({'left' : Event.pointerX(e) + 'px'});
}
return false;
},
pointerPos: function(element, x, y) {
var offset = $(element).cumulativeOffset();
return (y >= offset[1] &&
y < offset[1] + element.offsetHeight &&
x >= offset[0] + element.offsetWidth - 5 &&
x < offset[0] + element.offsetWidth);
},
getCellIndex : function(cell) {
return $A(cell.parentNode.cells).indexOf(cell);
}
};
+5 -5
View File
@@ -409,7 +409,7 @@ td img.tbtv_sortcell
height: 12px; }
TD.subjectCell,
td.tbtv_subject_headercell
TD.tbtv_subject_headercell
{ overflow: hidden; }
/* drag handles */
@@ -530,9 +530,10 @@ DIV.dTreeNode SPAN._dragOver
INPUT.checkBox
{ vertical-align: middle; }
/* tablekit resizable columns */
/* resizable columns */
TABLE TD.resize-handle-active
TABLE TD.resize-handle-active,
TABLE TH.resize-handle-active
{ cursor: e-resize; }
DIV.resize-handle
@@ -541,8 +542,7 @@ DIV.resize-handle
border-right: 1px solid #fff;
position: absolute;
top: 0px;
left: 0px;
max-height: 2em; } /* will be set in JavaScript when setting drag handles */
left: 0px; }
@media print
{
+4 -2
View File
@@ -466,7 +466,10 @@ function onRowClick(event) {
node = node.parentNode; // select TR
}
if (node.tagName == 'TR') {
rowIndex = node.rowIndex - $(node).up('table').down('thead').getElementsByTagName('tr').length;
var head = $(node).up('table').down('thead');
rowIndex = node.rowIndex;
if (head)
rowIndex -= head.getElementsByTagName('tr').length;
}
else if (node.tagName == 'LI') {
// Find index of clicked row
@@ -573,7 +576,6 @@ function popupMenu(event, menuId, target) {
$(document.body).observe("click", onBodyClickMenuHandler);
}
}
function getParentMenu(node) {
+3
View File
@@ -54,6 +54,9 @@ IMG.dragMessage
TD.mailer_fieldname
{ width: 8em; }
TABLE.messageList TD
{ white-space: pre; }
/* ContactsUI */
/*DIV#contactFoldersList SPAN.toolbarButton