Files
server/usr/share/psa-horde/imp/js/dimpbase.js
2026-01-07 20:52:11 +01:00

4594 lines
144 KiB
JavaScript

/**
* Base dynamic page.
*
* @author Michael Slusarz <slusarz@horde.org>
* @copyright 2005-2015 Horde LLC
* @license GPL-2 (http://www.horde.org/licenses/gpl)
*/
var DimpBase = {
// colorpicker,
flags: {},
flags_o: [],
// flist,
INBOX: 'SU5CT1g', // 'INBOX' base64url encoded
// init,
mboxDragConfig: {
classname: 'mboxdrag',
ghosting: true,
offset: { x: 15, y: 0 },
scroll: 'imp-normalmboxes',
threshold: 5
},
mboxDropConfig: (function() {
return {
caption: function(drop, drag, e) {
return DimpBase.mboxDropCaption(drop, drag, e);
},
keypress: true
};
})(),
msgDragConfig: (function() {
return {
caption: function() {
return DimpBase.messageCountText(DimpBase.selectedCount());
},
classname: 'msgdrag',
rightclick: true,
scroll: 'imp-normalmboxes',
threshold: 5
};
})(),
// pollPE,
// pp,
ppcache: {},
ppfifo: [],
// resize,
// rownum,
// search,
// searchbar_time,
// searchbar_time_mins,
// splitbar,
// sort_init,
// template,
// uid,
// unsub,
// view,
// viewaction,
// viewport,
// viewswitch,
// Preview pane cache size is 20 entries. Given that a reasonable guess
// of an average e-mail size is 10 KB (including headers), also make
// an estimate that the JSON data size will be approx. 10 KB. 200 KB
// should be a fairly safe caching value for any recent browser.
ppcachesize: 20,
// Message selection functions
// id = (string) DOM ID
// opts = (Object) Boolean options [ctrl, right, shift]
msgSelect: function(id, opts)
{
var bounds,
row = this.viewport.createSelection('domid', id),
sel = this.isSelected('domid', id),
selcount = this.selectedCount();
this.viewport.setMetaData({
curr_row: row,
last_row: (selcount ? this.viewport.getSelected() : null)
});
this.resetSelectAll();
if (opts.shift) {
if (selcount) {
if (!sel || selcount != 1) {
bounds = [ row.get('rownum').first(), this.viewport.getMetaData('pivot_row').get('rownum').first() ];
this.viewport.select($A($R(bounds.min(), bounds.max())));
}
return;
}
} else if (opts.ctrl) {
this.viewport.setMetaData({ pivot_row: row });
if (sel) {
this.viewport.deselect(row, { right: opts.right });
return;
} else if (opts.right || selcount) {
this.viewport.select(row, { add: true, right: opts.right });
return;
}
}
this.viewport.select(row, { right: opts.right });
},
selectAll: function()
{
var tmp = $('msglistHeaderContainer').select('DIV.msCheckAll');
if (tmp.first().hasClassName('msCheckOn')) {
this.resetSelected();
} else {
this.viewport.select($A($R(1, this.viewport.getMetaData('total_rows'))), { right: true });
DimpCore.toggleCheck(tmp, true);
}
},
isSelected: function(format, data)
{
return this.viewport.getSelected().contains(format, data);
},
selectedCount: function()
{
return (this.viewport) ? this.viewport.getSelected().size() : 0;
},
resetSelected: function(noviewport)
{
if (!noviewport && this.viewport) {
this.viewport.deselect(this.viewport.getSelected(), { clearall: true });
}
this.resetSelectAll();
this.toggleButtons();
this.clearPreviewPane();
},
resetSelectAll: function()
{
DimpCore.toggleCheck($('msglistHeaderContainer').select('DIV.msCheckAll'), false);
},
// num = (integer) See absolute.
// absolute = (boolean) Is num an absolute row number - from 1 ->
// page_size (true) - or a relative change from the current
// selected value (false)
// If no current selected value, the first message in the
// current viewport is selected.
// bottom = (boolean) Make selected appear at bottom?
moveSelected: function(num, absolute, bottom)
{
var curr, curr_row, row, row_data, sel;
if (absolute) {
if (!this.viewport.getMetaData('total_rows')) {
return;
}
curr = num;
} else {
if (num === 0) {
return;
}
sel = this.viewport.getSelected();
switch (sel.size()) {
case 0:
curr = this.viewport.currentOffset();
curr += (num > 0) ? 1 : this.viewport.getPageSize('current');
break;
case 1:
curr_row = sel.get('dataob').first();
curr = curr_row.VP_rownum + num;
break;
default:
sel = sel.get('rownum');
curr = (num > 0 ? sel.max() : sel.min()) + num;
break;
}
curr = (num > 0) ? Math.min(curr, this.viewport.getMetaData('total_rows')) : Math.max(curr, 1);
}
row = this.viewport.createSelection('rownum', curr);
if (row.size()) {
row_data = row.get('dataob').first();
if (!curr_row || row_data.VP_id != curr_row.VP_id) {
this.viewport.scrollTo(row_data.VP_rownum, { bottom: bottom });
this.viewport.select(row, { delay: 0.5 });
}
} else if (curr) {
this.rownum = curr;
this.viewport.requestContentRefresh(curr - 1);
}
},
// End message selection functions
// type = (string) app, compose, mbox, menu, msg, portal, prefs, search
// DEFAULT: View INBOX
// data = (mixed)
// 'app' - (object) [app, data]
// 'mbox' - (string) Mailbox to display
// 'menu' - (string) Menu item to display
// 'msg' - (string) Mailbox [;] Compressed UID string
// 'prefs' - (object) Extra parameters to add to prefs URL
// 'search' - (object)
// 'edit_query' = If 1, mailbox will be edited
// 'mailbox' = mailboxes to search
// 'subfolder' = do subfolder search
// If not set, loads search screen with current mailbox as
// default search mailbox
go: function(type, data)
{
var tmp;
if (!type) {
type = 'mbox';
}
if (type == 'compose') {
return;
}
if (type == 'msg') {
type = 'mbox';
tmp = data.split(';');
if (tmp[1]) {
data = tmp[0];
this.uid = tmp[1].parseViewportUidString().first();
// Fall through to the 'mbox' check below.
} else {
// Invalid formatted data.
data = '';
}
}
if (type == 'mbox' || Object.isUndefined(this.view)) {
if (Object.isUndefined(data) || data.empty()) {
data = Object.isUndefined(this.view)
? this.INBOX
: this.view;
}
if (this.view != data || !$('dimpmain_folder').visible()) {
this.highlightSidebar(data);
if ($('dimpmain_iframe').visible()) {
tmp = $('dimpmain_iframe').hide().down();
tmp.blur();
}
$('dimpmain_folder').show();
}
this.loadMailbox(data);
if (Object.isElement(tmp)) {
tmp.remove();
}
if (type == 'mbox') {
return;
}
}
$('dimpmain_folder').hide();
$('dimpmain_iframe').show();
switch (type) {
case 'search':
if (!data) {
data = { mailbox: this.view };
} else if (Object.isString(data) && data.isJSON()) {
data = data.evalJSON(true);
}
if (Object.isString(data)) {
data = { mailbox: data };
}
this.highlightSidebar();
this.setTitle(DimpCore.text.search);
$('dimpmain_iframe').insert(
new Element('IFRAME', {
src: HordeCore.addURLParam(DimpCore.conf.URI_SEARCH, data)
}).setStyle({
height: $('horde-page').getHeight() + 'px'
})
);
break;
}
},
setHash: function(type, data)
{
var h;
if (type) {
h = type;
if (data) {
h += ':' + data;
}
}
window.location.hash = h;
},
setMsgHash: function()
{
var vs = this.viewport.getSelection(),
view = vs.getBuffer().getView();
if (this.isQSearch() || this.isFSearch()) {
// Quicksearch/Filtering is not saved after page reload.
this.setHash('mbox', this.search.mbox);
} else if (vs.size()) {
this.setHash('msg', view + ';' + vs.get('uid').toViewportUidString());
} else {
this.setHash('mbox', view);
}
},
setTitle: function(title, unseen)
{
var opts = {};
document.title = DimpCore.conf.name + ' :: ' + title;
if (unseen !== null) {
if (unseen > 99 & unseen < 1000) {
opts.font = '8px Arial';
opts.offset = 1;
opts.width = 1;
}
Tinycon.setOptions(opts);
Tinycon.setBubble(unseen);
}
},
// id: (string) Either the ID of a sidebar element, or the name of a
// mailbox
highlightSidebar: function(id)
{
// Folder bar may not be fully loaded yet.
if ($('foldersLoading').visible()) {
this.highlightSidebar.bind(this, id).delay(0.1);
} else {
this.flist.highlight(id);
}
},
setSidebarWidth: function()
{
var tmp = $('horde-sidebar');
tmp.setStyle({
width: DimpCore.getPref('splitbar_side') + 'px'
});
this.splitbar.setStyle({
left: tmp.clientWidth + 'px'
});
$('horde-page').setStyle({
left: (tmp.clientWidth) + 'px'
});
},
// r = ViewPort row data
msgWindow: function(r)
{
HordeCore.popupWindow(DimpCore.conf.URI_MESSAGE, {
buid: r.VP_id,
mailbox: r.VP_view
}, {
name: 'msgview' + r.VP_view + r.VP_id
});
},
composeMailbox: function(type)
{
var sel = this.viewport.getSelected();
if (sel.size()) {
DimpCore.compose(type, {
buid: sel.get('uid').toViewportUidString(),
mailbox: this.view
});
}
},
loadMailbox: function(f)
{
var need_delete,
opts = {};
if (!this.viewport) {
this._createViewPort();
}
if (!this.isSearch(f)) {
this.quicksearchClear(true);
}
if (this.view != f) {
$('mailboxName').update(DimpCore.text.loading);
this.viewswitch = true;
/* Don't cache results of search mailboxes - since we will need to
* grab new copy if we ever return to it. */
if (this.isSearch()) {
need_delete = this.view;
}
if (!this.viewport.bufferLoaded(f)) {
this.resetSelected(true);
}
this.view = f;
}
if (this.uid) {
opts.search = { buid: this.uid };
}
this.viewport.loadView(f, opts);
if (need_delete) {
this.viewport.deleteView(need_delete);
}
},
_createViewPort: function()
{
var container = $('msgSplitPane');
this.template = {
horiz: new Template(DimpCore.conf.msglist_template_horiz),
vert: new Template(DimpCore.conf.msglist_template_vert)
};
this.viewport = new ViewPort({
// Mandatory config
ajax: function(params) {
/* Store the requestid locally, so we don't need to
* round-trip to the server. We'll re-add it later. */
var action, r_id = params.unset('requestid');
if (this.init) {
action = 'viewPort';
} else {
action = 'dynamicInit';
if (this.uid) {
params.set('msgload', this.uid);
}
this.init = true;
}
DimpCore.doAction(action, params, {
loading: 'viewport'
}).rid = r_id;
}.bind(this),
container: container,
onContent: function(r, mode) {
var bg, escapeAttr, highlight, u,
thread = $H(this.viewport.getMetaData('thread')),
tsort = this.isThreadSort();
escapeAttr = function(s) {
return s.escapeHTML().replace(/"/g, '&quot;');
};
r.status = r.subjectdata = '';
// Add thread graphics
if (tsort && mode != 'vert') {
u = thread.get(r.VP_id);
if (u) {
$R(0, u.length, true).each(function(i) {
r.subjectdata += '<span class="horde-tree-image horde-tree-image-' + u.charAt(i) + '"></span>';
});
}
}
/* Generate the subject/status flags. */
if (r.flag && this.flags_o.size()) {
r.flag.each(function(a) {
var ptr = this.flags[a];
if (ptr.u) {
if (!ptr.elt) {
ptr.elt = '<span class="' + escapeAttr(ptr.c) + '" title="' + escapeAttr(ptr.l) + '" style="' + ((ptr.b) ? ('background:' + escapeAttr(ptr.b) + ';') : '') + ';color:' + escapeAttr(ptr.f) + '">' + ptr.l.truncate(10).escapeHTML() + '</span>';
}
r.subjectdata += ptr.elt;
} else {
if (ptr.c) {
if (!ptr.elt) {
ptr.elt = '<div class="iconImg msgflags ' + escapeAttr(ptr.c) + '" title="' + escapeAttr(ptr.l) + '"></div>';
}
r.status += ptr.elt;
r.VP_bg.push(ptr.c);
}
if (ptr.b) {
bg = ptr.b;
}
}
}, this);
}
// Set bg
if (bg) {
r.style = 'background:' + bg;
}
[ 'date', 'from', 'size', 'subject' ].each(function(h) {
if (r[h] === null) {
// If these fields are null, invalid string was
// scrubbed by JSON encode.
switch (h) {
case 'from':
r.from = '[' + DimpCore.text.badaddr + ']';
break;
case 'subject':
r.subject = r.subjecttitle = '[' + DimpCore.text.badsubject + ']';
break;
}
} else if (!Object.isUndefined(r[h])) {
highlight = false;
switch (h) {
case 'from':
r.fromtitle = escapeAttr(r.fromaddr || r.from);
r.from = r.from.escapeHTML();
if (DimpCore.conf.from_link) {
r.from = '<a>' + r.from + '</a>';
}
switch (DimpCore.getPref('qsearch_field')) {
case 'all':
case 'from':
case 'recip':
highlight = true;
break;
}
break;
case 'subject':
r.subjecttitle = escapeAttr(r[h]);
r.subject = r.subject.escapeHTML();
switch (DimpCore.getPref('qsearch_field')) {
case 'all':
case 'subject':
highlight = true;
break;
}
break;
default:
r[h] = r[h].escapeHTML();
break;
}
if (highlight && this.isQSearch()) {
r[h] = r[h].gsub(
new RegExp("(" + RegExp.escape($F('horde-search-input').escapeHTML()) + ")", "i"),
'<span class="qsearchMatch">#{1}</span>'
);
}
}
}, this);
r.VP_bg.push('vpRow');
switch (mode) {
case 'vert':
r.VP_bg.unshift('vpRowVert');
r.className = r.VP_bg.join(' ');
return this.template.vert.evaluate(r);
}
r.VP_bg.unshift('vpRowHoriz');
r.className = r.VP_bg.join(' ');
return this.template.horiz.evaluate(r);
}.bind(this),
// Optional config
empty_msg: this.emptyMsg.bind(this),
list_class: 'msglist',
list_header: $('msglistHeaderContainer').remove(),
page_size: DimpCore.getPref('splitbar_horiz'),
pane_data: 'previewPane',
pane_mode: DimpCore.getPref('preview'),
pane_width: DimpCore.getPref('splitbar_vert'),
split_bar_class: {
horiz: 'horde-splitbar-horiz',
vert: 'horde-splitbar-vert'
},
split_bar_handle_class: {
horiz: 'horde-splitbar-horiz-handle',
vert: 'horde-splitbar-vert-handle'
},
// Callbacks
onAjaxRequest: function(params) {
var r_id = params.unset('requestid'),
view = params.get('view');
if (this.viewswitch &&
(this.isQSearch(view) || this.isFSearch(view))) {
params.update({
qsearchfield: DimpCore.getPref('qsearch_field'),
qsearchmbox: this.search.mbox
});
if (this.search.filter) {
params.set('qsearchfilter', this.search.filter);
} else if (this.search.flag) {
params.update({
qsearchflag: this.search.flag,
qsearchflagnot: ~~(!!this.search.not)
});
} else {
params.set('qsearch', $F('horde-search-input'));
}
}
params = $H({
viewport: Object.toJSON(params),
view: view
});
if (r_id) {
params.set('requestid', r_id);
}
HordeCore.addRequestParams(params);
return params;
}.bind(this),
onContentOffset: function(offset) {
if (this.uid) {
this.rownum = this.viewport.createSelectionBuffer().search({ VP_id: { equal: [ this.uid ] } }).get('rownum').first();
delete this.uid;
}
if (this.rownum) {
this.viewport.scrollTo(this.rownum, {
noupdate: true,
top: true
});
offset = this.viewport.currentOffset();
}
return offset;
}.bind(this)
});
/* Custom ViewPort events. */
container.observe('ViewPort:add', function(e) {
DimpCore.addContextMenu({
elt: e.memo,
type: 'message'
});
new Drag(e.memo, this.msgDragConfig);
}.bindAsEventListener(this));
container.observe('ViewPort:clear', function(e) {
$(e.memo).fire('DimpBase:removeElt');
}.bindAsEventListener(this));
container.observe('ViewPort:contentComplete', function() {
var ssc, tmp;
this.setMessageListTitle();
this.setMsgHash();
if (this.isSearch()) {
tmp = this.viewport.getMetaData('slabel');
if (this.viewport.getMetaData('vfolder')) {
$('search_close').hide();
if (tmp) {
tmp = DimpCore.text.vfolder.sub('%s', tmp);
}
} else {
$('search_close').show();
}
if (tmp) {
$('search_label').writeAttribute({ title: tmp });
if (tmp.length > 250) {
tmp = tmp.truncate(250);
}
$('search_label').update(tmp.escapeHTML());
}
[ $('search_edit') ].invoke(this.search || this.viewport.getMetaData('noedit') ? 'hide' : 'show');
this.showSearchbar(true);
} else {
this.setMboxLabel(this.view);
this.showSearchbar(false);
}
if (this.rownum) {
this.viewport.select([ this.rownum ]);
delete this.rownum;
}
this.updateTitle();
if (this.viewswitch) {
if (this.selectedCount()) {
if (DimpCore.getPref('preview')) {
this.initPreviewPane();
}
this.toggleButtons();
} else {
this.resetSelected();
}
tmp = $('filter');
if (this.isSearch()) {
tmp.hide();
if (!this.search || !this.search.qsearch) {
$('horde-search').hide();
}
} else if (tmp) {
tmp.show();
}
if (this.viewport.getMetaData('drafts')) {
$('button_resume').up().show();
$('button_template', 'button_reply', 'button_forward', 'button_spam', 'button_innocent').compact().invoke('up').invoke('hide');
} else if (this.viewport.getMetaData('templates')) {
$('button_template').up().show();
$('button_resume', 'button_reply', 'button_forward', 'button_spam', 'button_innocent').compact().invoke('up').invoke('hide');
} else {
$('button_resume', 'button_template').compact().invoke('up').invoke('hide');
$('button_reply', 'button_forward').compact().invoke('up').invoke('show');
[ $('button_innocent') ].compact().invoke('up').invoke(this.viewport.getMetaData('innocent_show') ? 'show' : 'hide');
[ $('button_spam') ].compact().invoke('up').invoke(this.viewport.getMetaData('spam_show') ? 'show' : 'hide');
}
/* Read-only changes. */
[ $('mailboxName').next('SPAN.readonlyImg') ].invoke(this.viewport.getMetaData('readonly') ? 'show' : 'hide');
/* ACL changes. */
if ((tmp = $('button_delete'))) {
[ tmp.up() ].invoke(this.viewport.getMetaData('nodelete') ? 'hide' : 'show');
}
// Reset variable at end of block, since other code may be
// conditional depending on whether we just switched to the
// mailbox.
this.viewswitch = false;
} else if (this.filtertoggle && this.isThreadSort()) {
ssc = DimpCore.conf.sort.get('date').v;
}
this.setSortColumns(ssc);
}.bindAsEventListener(this));
container.observe('ViewPort:deselect', function(e) {
var sel = this.viewport.getSelected(),
count = sel.size();
if (!count) {
this.viewport.setMetaData({
curr_row: null,
last_row: null,
pivot_row: null
});
}
this.toggleButtons();
if (e.memo.opts.right || !count) {
this.clearPreviewPane();
} else if ((count == 1) && DimpCore.getPref('preview')) {
this.loadPreview(sel.get('dataob').first());
}
this.resetSelectAll();
this.setMsgHash();
}.bindAsEventListener(this));
container.observe('ViewPort:fetch', function() {
if (!this.isSearch()) {
this.showSearchbar(false);
}
}.bind(this));
container.observe('ViewPort:remove', function(e) {
e.memo.get('dataob').each(function(d) {
this._expirePPCache([ this._getPPId(d.VP_id, d.VP_view) ]);
}, this);
}.bindAsEventListener(this));
container.observe('ViewPort:resize', function() {
switch (this.viewport.pane_mode) {
case 'vert':
$('msglistHeaderHoriz').hide();
$('msglistHeaderVert').show();
break;
case 'horiz':
default:
$('msglistHeaderVert').hide();
$('msglistHeaderHoriz').show();
break;
}
}.bind(this));
container.observe('ViewPort:select', function(e) {
var d = e.memo.vs.get('rownum');
if (d.size() == 1) {
this.viewport.setMetaData({
curr_row: e.memo.vs,
pivot_row: e.memo.vs
});
}
this.setMsgHash();
this.toggleButtons();
if (DimpCore.getPref('preview')) {
if (e.memo.opts.right) {
this.clearPreviewPane();
$('previewInfo').highlight({
duration: 2.0,
keepBackgroundImage: true,
queue: {
limit: 1,
scope: 'previewInfo'
}
});
} else if (e.memo.opts.delay) {
this.initPreviewPane.bind(this).delay(e.memo.opts.delay);
} else {
this.initPreviewPane();
}
}
}.bindAsEventListener(this));
container.observe('ViewPort:sliderEnd', function() {
$('slider_count').hide();
});
container.observe('ViewPort:sliderSlide', this.updateSliderCount.bind(this));
container.observe('ViewPort:sliderStart', function() {
var sc = $('slider_count'),
sb = $('msgSplitPane').down('.vpScroll'),
s = sb.viewportOffset();
if (!sc) {
sc = new Element('DIV', { id: 'slider_count' });
$(document.body).insert(sc);
}
this.updateSliderCount();
sc.setStyle({
top: (s.top + sb.getHeight() - sc.getHeight()) + 'px',
right: (document.viewport.getWidth() - s.left) + 'px'
}).show();
}.bind(this));
container.observe('ViewPort:splitBarChange', function(e) {
switch (e.memo) {
case 'horiz':
DimpCore.setPref('splitbar_horiz', this.viewport.getPageSize());
break;
case 'vert':
DimpCore.setPref('splitbar_vert', this.viewport.getVertWidth());
break;
}
}.bindAsEventListener(this));
container.observe('ViewPort:wait', function() {
if ($('dimpmain_folder').visible()) {
HordeCore.notify(DimpCore.text.listmsg_wait, 'horde.warning');
}
});
},
addViewportParams: function(vs)
{
return this.viewport.addRequestParams({}, {
view: (vs ? vs.getBuffer().getView() : null)
});
},
emptyMsg: function()
{
return (this.isQSearch() || this.isFSearch())
? DimpCore.text.vp_empty_search
: DimpCore.text.vp_empty;
},
contextOnClick: function(e)
{
var tmp,
elt = e.memo.elt,
id = elt.readAttribute('id'),
menu = e.memo.trigger;
switch (id) {
case 'ctx_container_create':
case 'ctx_mbox_create':
case 'ctx_remoteauth_create':
tmp = this.flist.getMbox(e);
RedBox.loading();
DimpCore.doAction('createMailboxPrepare', {
mbox: tmp.value()
},{
callback: this._mailboxPromptCallback.bind(this, 'create', tmp)
});
break;
case 'ctx_container_rename':
case 'ctx_mbox_rename':
tmp = this.flist.getMbox(e);
RedBox.loading();
DimpCore.doAction('deleteMailboxPrepare', {
mbox: tmp.value(),
type: 'rename'
},{
callback: this._mailboxPromptCallback.bind(this, 'rename', tmp)
});
break;
case 'ctx_mbox_empty':
tmp = this.flist.getMbox(e);
RedBox.loading();
DimpCore.doAction('emptyMailboxPrepare', {
mbox: tmp.value()
},{
callback: this._mailboxPromptCallback.bind(this, 'empty', tmp)
});
break;
case 'ctx_container_delete':
this._mailboxPromptCallback('delete', this.flist.getMbox(e), {
result: true
});
break;
case 'ctx_mbox_delete':
case 'ctx_vfolder_delete':
tmp = this.flist.getMbox(e);
RedBox.loading();
DimpCore.doAction('deleteMailboxPrepare', {
mbox: tmp.value(),
type: 'delete'
}, {
callback: this._mailboxPromptCallback.bind(this, 'delete', tmp)
});
break;
case 'ctx_mbox_export':
this.viewaction = function(e2, e) {
HordeCore.download('', {
actionID: 'download_mbox',
mbox_list: Object.toJSON([ this.flist.getMbox(e).value() ]),
type: e2.memo.findElement('FORM').down('[name=download_type]').getValue()
});
}.bindAsEventListener(this, e);
tmp = new Element('SELECT', { name: 'download_type' });
$H(DimpCore.conf.download_types).each(function(d) {
tmp.insert(new Element('OPTION', { value: d.key }).insert(d.value));
});
HordeDialog.display({
form: tmp,
form_id: 'dimpbase_confirm',
text: DimpCore.text.download_mbox
});
break;
case 'ctx_mbox_import':
HordeDialog.display({
form: new Element('DIV').insert(
new Element('INPUT', { name: 'import_file', type: 'file' })
).insert(
new Element('INPUT', { name: 'MAX_FILE_SIZE', value: DimpCore.conf.MAX_FILE_SIZE }).hide()
).insert(
new Element('INPUT', { name: 'import_mbox', value: this.flist.getMbox(e).value() }).hide()
),
form_id: 'mbox_import',
form_opts: {
action: HordeCore.conf.URI_AJAX + 'importMailbox',
className: 'RB_Form',
enctype: 'multipart/form-data',
method: 'post'
},
text: DimpCore.text.import_mbox
});
break;
case 'ctx_mbox_flag_seen':
case 'ctx_mbox_flag_unseen':
DimpCore.doAction('flagAll', {
add: ~~(id == 'ctx_mbox_flag_seen'),
flags: Object.toJSON([ DimpCore.conf.FLAG_SEEN ]),
mbox: this.flist.getMbox(e).value()
});
break;
case 'ctx_mbox_poll':
case 'ctx_mbox_nopoll':
this.modifyPoll(this.flist.getMbox(e).value(), id == 'ctx_mbox_poll');
break;
case 'ctx_mbox_sub':
this._mailboxPromptCallback('subscribe', this.flist.getMbox(e));
break;
case 'ctx_mbox_unsub':
this._mailboxPromptCallback('unsubscribe', this.flist.getMbox(e));
break;
case 'ctx_mbox_size':
tmp = this.flist.getMbox(e);
RedBox.loading();
DimpCore.doAction('mailboxSize', {
mbox: tmp.value()
}, {
callback: function(r) {
HordeDialog.display({
noform: true,
text: DimpCore.text.mboxsize.sub('%s', tmp.fullMboxDisplay()).sub('%s', r.size.escapeHTML())
});
}.bind(this)
});
break;
case 'ctx_mbox_acl':
HordeCore.redirect(HordeCore.addURLParam(
DimpCore.conf.URI_PREFS_IMP,
{
group: 'acl',
mbox: this.flist.getMbox(e).value()
}
));
break;
case 'ctx_folderopts_new':
this._createMboxForm('', 'create', DimpCore.text.create_prompt);
break;
case 'ctx_folderopts_sub':
case 'ctx_folderopts_unsub':
this.toggleSubscribed();
break;
case 'ctx_folderopts_expand':
case 'ctx_folderopts_collapse':
this._toggleSubFolder(
$('imp-normalmboxes'),
id == 'ctx_folderopts_expand' ? 'expall' : 'colall',
{ noeffect: true }
);
break;
case 'ctx_folderopts_reload':
this._reloadFolders();
break;
case 'ctx_container_expand':
case 'ctx_container_collapse':
case 'ctx_mbox_expand':
case 'ctx_mbox_collapse':
this._toggleSubFolder(
this.flist.getMbox(e).subElement(),
(id == 'ctx_container_expand' || id == 'ctx_mbox_expand') ? 'expall' : 'colall',
{ noeffect: true }
);
break;
case 'ctx_container_search':
case 'ctx_mbox_search':
this.go('search', {
mailbox: this.flist.getMbox(e).value()
});
break;
case 'ctx_message_innocent':
case 'ctx_message_spam':
this.reportSpam(id == 'ctx_message_spam');
break;
case 'ctx_message_blacklist':
case 'ctx_message_whitelist':
this.blacklist(id == 'ctx_message_blacklist');
break;
case 'ctx_message_delete':
this.deleteMsg();
break;
case 'ctx_message_forward':
case 'ctx_message_reply':
this.composeMailbox(id == 'ctx_message_forward' ? 'forward_auto' : 'reply_auto');
break;
case 'ctx_forward_editasnew':
case 'ctx_message_template':
case 'ctx_message_template_edit':
this.composeMailbox(id.substring(12));
break;
case 'ctx_message_source':
this.viewport.getSelected().get('dataob').each(function(v) {
HordeCore.popupWindow(DimpCore.conf.URI_VIEW, {
actionID: 'view_source',
buid: v.VP_id,
id: 0,
mailbox: v.VP_view
}, {
name: v.VP_id + '|' + v.VP_view
});
}, this);
break;
case 'ctx_message_resume':
this.composeMailbox('resume');
break;
case 'ctx_message_view':
this.viewport.getSelected().get('dataob').each(this.msgWindow.bind(this));
break;
case 'ctx_message_addfilter':
DimpCore.doAction('newFilter', {
mailbox: this.view
}, {
uids: this.viewport.getSelected()
});
break;
case 'ctx_reply_reply':
case 'ctx_reply_reply_all':
case 'ctx_reply_reply_list':
this.composeMailbox(id.substring(10));
break;
case 'ctx_forward_attach':
case 'ctx_forward_body':
case 'ctx_forward_both':
case 'ctx_forward_redirect':
this.composeMailbox(id.substring(4));
break;
case 'ctx_oa_preview_hide':
DimpCore.setPref('preview_old', DimpCore.getPref('preview', 'horiz'));
this.togglePreviewPane('');
break;
case 'ctx_oa_preview_show':
this.togglePreviewPane(DimpCore.getPref('preview_old'));
break;
case 'ctx_oa_layout_horiz':
case 'ctx_oa_layout_vert':
this.togglePreviewPane(id.substring(14));
break;
case 'ctx_oa_blacklist':
case 'ctx_oa_whitelist':
this.blacklist(id == 'ctx_oa_blacklist');
break;
case 'ctx_message_undelete':
case 'ctx_oa_undelete':
this.flag(DimpCore.conf.FLAG_DELETED, false);
break;
case 'ctx_oa_purge_deleted':
this.purgeDeleted();
break;
case 'ctx_oa_hide_deleted':
case 'ctx_oa_show_deleted':
this.viewport.reload({ delhide: ~~(id == 'ctx_oa_hide_deleted') });
break;
case 'ctx_oa_clear_sort':
this.sort(DimpCore.conf.sort.get('sequence').v);
break;
case 'ctx_sortopts_date':
case 'ctx_sortopts_from':
case 'ctx_sortopts_msgarrival':
case 'ctx_sortopts_msgdate':
case 'ctx_sortopts_to':
case 'ctx_sortopts_sequence':
case 'ctx_sortopts_size':
case 'ctx_sortopts_subject':
case 'ctx_sortopts_thread':
this.sort(DimpCore.conf.sort.get(id.substring(13)).v);
break;
case 'ctx_template_edit':
this.composeMailbox('template_edit');
break;
case 'ctx_template_new':
DimpCore.compose('template_new');
break;
case 'ctx_subjectsort_thread':
this.sort(DimpCore.conf.sort.get(this.isThreadSort() ? 'subject' : 'thread').v);
break;
case 'ctx_datesort_msgarrival':
case 'ctx_datesort_msgdate':
tmp = DimpCore.conf.sort.get(id.substring(13)).v;
if (tmp != this.viewport.getMetaData('sortby')) {
this.sort(tmp);
}
break;
case 'ctx_vfolder_edit':
this.go('search', {
edit_query: 1,
mailbox: this.flist.getMbox(e).value()
});
break;
case 'ctx_vcontainer_edit':
HordeCore.redirect(HordeCore.addURLParam(
DimpCore.conf.URI_PREFS_IMP,
{
group: 'searches'
}
));
break;
case 'ctx_qsearchopts_all':
case 'ctx_qsearchopts_body':
case 'ctx_qsearchopts_from':
case 'ctx_qsearchopts_recip':
case 'ctx_qsearchopts_subject':
DimpCore.setPref('qsearch_field', id.substring(16));
this._setQsearchText();
if (this.isQSearch()) {
this.viewswitch = true;
this.quicksearchRun();
} else {
$('horde-search-input').focus();
}
break;
case 'ctx_qsearchopts_advanced':
this.go('search', tmp);
break;
case 'ctx_filteropts_applyfilters':
if (this.viewport) {
this.viewport.reload({ applyfilter: 1 });
}
break;
case 'ctx_flag_new':
this.displayFlagNew();
break;
case 'ctx_flag_edit':
HordeCore.redirect(HordeCore.addURLParam(
DimpCore.conf.URI_PREFS_IMP,
{
group: 'flags'
}
));
break;
case 'ctx_rcontainer_prefs':
HordeCore.redirect(HordeCore.addURLParam(
DimpCore.conf.URI_PREFS_IMP,
{ group: 'remote' }
));
break;
case 'ctx_remoteauth_logout':
DimpCore.doAction('remoteLogout', {
remoteid: this.flist.getMbox(e).value()
});
break;
default:
if (menu == 'ctx_filteropts_filter') {
this.search = {
filter: elt.identify().substring('ctx_filter_'.length),
label: this.viewport.getMetaData('label'),
mbox: this.view
};
this.go('mbox', DimpCore.conf.fsearchid);
} else if (menu.endsWith('_setflag')) {
tmp = elt.down('DIV');
this.flag(elt.retrieve('flag'), !tmp.visible() || tmp.hasClassName('msCheck'));
} else if (menu.endsWith('_unsetflag')) {
this.flag(elt.retrieve('flag'), false);
} else if (menu.endsWith('_flag') || menu.endsWith('_flagnot')) {
this.search = {
flag: elt.retrieve('flag'),
label: this.viewport.getMetaData('label'),
mbox: this.view,
not: menu.endsWith('_flagnot')
};
this.go('mbox', DimpCore.conf.fsearchid);
}
break;
}
},
contextOnShow: function(e)
{
var baseelt, elts, flags, ob, sel, tmp,
ctx_id = e.memo;
switch (ctx_id) {
case 'ctx_mbox':
elts = $('ctx_mbox_create', 'ctx_mbox_rename', 'ctx_mbox_delete');
baseelt = this.flist.getMbox(e);
if (baseelt.value() == this.INBOX) {
elts.invoke('hide');
if ($('ctx_mbox_sub')) {
$('ctx_mbox_sub', 'ctx_mbox_unsub').invoke('hide');
}
} else {
if ($('ctx_mbox_sub')) {
tmp = baseelt.unsubscribed();
[ $('ctx_mbox_sub') ].invoke(tmp ? 'show' : 'hide');
[ $('ctx_mbox_unsub') ].invoke(tmp ? 'hide' : 'show');
}
if (Object.isUndefined(baseelt.fixed())) {
DimpCore.doAction('isFixedMbox', {
mbox: baseelt.value()
}, {
ajaxopts: {
asynchronous: false
},
callback: function(r) {
baseelt.fixed(r.fixed);
}
});
}
if (baseelt.fixed()) {
elts.shift();
elts.invoke('hide');
} else {
elts.invoke('show');
}
}
if (baseelt.nc()) {
$('ctx_mbox_create').hide();
}
if (DimpCore.conf.poll_alter) {
[ $('ctx_mbox_poll') ].compact().invoke(baseelt.polled() ? 'hide' : 'show');
[ $('ctx_mbox_nopoll') ].compact().invoke(baseelt.polled() ? 'show' : 'hide');
} else {
$('ctx_mbox_poll', 'ctx_mbox_nopoll').compact().invoke('hide');
}
[ $('ctx_mbox_expand').up() ].invoke(baseelt.subElement() ? 'show' : 'hide');
[ $('ctx_mbox_acl').up() ].invoke(DimpCore.conf.acl ? 'show' : 'hide');
// Fall-through
case 'ctx_container':
case 'ctx_noactions':
case 'ctx_remoteauth':
case 'ctx_vfolder':
$(ctx_id).down('DIV.mboxName').update(this.flist.getMbox(e).fullMboxDisplay());
break;
case 'ctx_reply':
sel = this.viewport.getSelected();
if (sel.size() == 1) {
ob = sel.get('dataob').first();
}
[ $('ctx_reply_reply_list') ].invoke(ob && ob.listmsg ? 'show' : 'hide');
break;
case 'ctx_oa':
switch (DimpCore.getPref('preview')) {
case 'vert':
$('ctx_oa_preview_hide', 'ctx_oa_layout_horiz').invoke('show');
$('ctx_oa_preview_show', 'ctx_oa_layout_vert').invoke('hide');
break;
case 'horiz':
$('ctx_oa_preview_hide', 'ctx_oa_layout_vert').invoke('show');
$('ctx_oa_preview_show', 'ctx_oa_layout_horiz').invoke('hide');
break;
default:
$('ctx_oa_preview_hide', 'ctx_oa_layout_horiz', 'ctx_oa_layout_vert').invoke('hide');
$('ctx_oa_preview_show').show();
break;
}
tmp = $('ctx_oa_undeleted', 'ctx_oa_blacklist', 'ctx_oa_whitelist');
sel = this.viewport.getSelected();
if ($('ctx_oa_setflag')) {
if (this.viewport.getMetaData('readonly') ||
this.viewport.getMetaData('pop3')) {
$('ctx_oa_setflag').up().hide();
} else {
tmp.push($('ctx_oa_setflag').up());
[ $('ctx_oa_unsetflag') ].invoke((sel.size() > 1) ? 'show' : 'hide');
}
}
tmp.compact().invoke(sel.size() ? 'show' : 'hide');
if ((tmp = $('ctx_oa_purge_deleted'))) {
if (this.viewport.getMetaData('pop3')) {
tmp.up().hide();
} else {
tmp.up().show();
if (this.viewport.getMetaData('noexpunge')) {
tmp.hide();
} else {
tmp.show();
[ tmp.up() ].invoke(tmp.up().select('> a').any(Element.visible) ? 'show' : 'hide');
}
}
}
if ((tmp = $('ctx_oa_hide_deleted'))) {
if (this.isThreadSort() || this.viewport.getMetaData('pop3')) {
$(tmp, 'ctx_oa_show_deleted').invoke('hide');
} else if (this.viewport.getMetaData('delhide')) {
tmp.hide();
$('ctx_oa_show_deleted').show();
} else {
tmp.show();
$('ctx_oa_show_deleted').hide();
}
}
if ((tmp = $('ctx_oa_clear_sort'))) {
[ tmp.up() ].invoke(this.viewport.getMetaData('sortby') == DimpCore.conf.sort.get('sequence').v ? 'hide' : 'show');
}
break;
case 'ctx_sortopts':
elts = $(ctx_id).select('a span.iconImg');
tmp = this.viewport.getMetaData('sortby');
elts.invoke('removeClassName', 'sortdown')
.invoke('removeClassName', 'sortup');
DimpCore.conf.sort.detect(function(s) {
if (s.value.v == tmp) {
$('ctx_sortopts_' + s.key).down('.iconImg').addClassName(this.viewport.getMetaData('sortdir') ? 'sortup' : 'sortdown');
return true;
}
}, this);
tmp = this.viewport.getMetaData('special');
[ $('ctx_sortopts_from') ].invoke(tmp ? 'hide' : 'show');
[ $('ctx_sortopts_to') ].invoke(tmp ? 'show' : 'hide');
break;
case 'ctx_qsearchopts':
$(ctx_id).descendants().invoke('removeClassName', 'contextSelected');
$(ctx_id + '_' + DimpCore.getPref('qsearch_field')).addClassName('contextSelected');
break;
case 'ctx_message':
[ $('ctx_message_source').up() ].invoke(DimpCore.getPref('preview') ? 'hide' : 'show');
[ $('ctx_message_delete') ].compact().invoke(this.viewport.getMetaData('nodelete') ? 'hide' : 'show');
[ $('ctx_message_undelete') ].compact().invoke(this.viewport.getMetaData('nodelete') || this.viewport.getMetaData('pop3') ? 'hide' : 'show');
[ $('ctx_message_setflag').up() ].invoke((!this.viewport.getMetaData('flags').size() && this.viewport.getMetaData('readonly')) || this.viewport.getMetaData('pop3') ? 'hide' : 'show');
if (this.viewport.getMetaData('drafts') ||
this.viewport.getMetaData('templates')) {
$('ctx_message_innocent', 'ctx_message_spam').compact().invoke('hide');
} else {
[ $('ctx_message_innocent') ].compact().invoke(this.viewport.getMetaData('innocent_show') ? 'show' : 'hide');
[ $('ctx_message_spam') ].compact().invoke(this.viewport.getMetaData('spam_show') ? 'show' : 'hide');
}
sel = this.viewport.getSelected();
if (sel.size() == 1) {
if (this.viewport.getMetaData('templates')) {
$('ctx_message_resume').hide().up().show();
$('ctx_message_template', 'ctx_message_template_edit').invoke('show');
} else if (this.isDraft(sel)) {
$('ctx_message_template', 'ctx_message_template_edit').invoke('hide');
$('ctx_message_resume').show().up('DIV').show();
} else {
$('ctx_message_resume').up('DIV').hide();
}
[ $('ctx_message_addfilter') ].compact().invoke('show');
[ $('ctx_message_unsetflag') ].compact().invoke('hide');
} else {
[ $('ctx_message_resume').up('DIV'), $('ctx_message_addfilter') ].compact().invoke('hide');
[ $('ctx_message_unsetflag') ].compact().invoke('show');
}
break;
case 'ctx_flag':
case 'ctx_flagunset':
flags = this.viewport.getMetaData('flags');
tmp = $(ctx_id).select('.ctxFlagRow');
if (flags.size()) {
tmp.each(function(c) {
[ c ].invoke(flags.include(c.retrieve('flag')) ? 'show' : 'hide');
});
} else {
tmp.invoke('show');
}
sel = this.viewport.getSelected();
flags = (sel.size() == 1)
? sel.get('dataob').first().flag
: null;
tmp.each(function(elt) {
DimpCore.toggleCheck(elt.down('DIV'), (flags === null) ? null : flags.include(elt.retrieve('flag')));
});
break;
case 'ctx_datesort':
tmp = this.viewport.getMetaData('sortby');
$(ctx_id).descendants().invoke('removeClassName', 'contextSelected').find(function(n) {
if (DimpCore.conf.sort.get(n.identify().substring(13)).v == tmp) {
n.addClassName('contextSelected');
return true;
}
});
break;
case 'ctx_subjectsort':
DimpCore.toggleCheck($('ctx_subjectsort_thread').down('.iconImg'), this.isThreadSort());
break;
case 'ctx_preview':
[ $('ctx_preview_allparts') ].invoke(this.pp.hide_all ? 'hide' : 'show');
[ $('ctx_preview_thread') ].invoke(this.viewport.getMetaData('nothread') ? 'hide' : 'show');
[ $('ctx_preview_listinfo') ].invoke(this.viewport.getSelected().get('dataob').first().listmsg ? 'show' : 'hide');
break;
case 'ctx_template':
[ $('ctx_template_edit') ].invoke(this.viewport.getSelected().size() == 1 ? 'show' : 'hide');
break;
case 'ctx_filteropts':
tmp = $('ctx_filteropts_applyfilters');
if (tmp) {
[ tmp.up('DIV') ].invoke(this.isSearch() || (!DimpCore.conf.filter_any && this.view != this.INBOX) ? 'hide' : 'show');
}
break;
}
},
contextOnTrigger: function(e)
{
switch (e.memo) {
case 'ctx_flag':
case 'ctx_flagunset':
this.flags_o.each(function(f) {
if (f.a) {
this.contextAddFlag(f.id, f, e.memo);
}
}, this);
if (e.memo == 'ctx_flag') {
$(e.memo).insert(new Element('DIV', { className: 'sep' }))
.insert(
new Element('A', { id: 'ctx_flag_new' }).insert(
new Element('DIV', { className: 'iconImg' })
) .insert(
DimpCore.text.newflag
)
).insert(
new Element('A', { id: 'ctx_flag_edit' }).insert(
new Element('DIV', { className: 'iconImg' })
) .insert(
DimpCore.text.editflag
)
);
}
break;
case 'ctx_flag_search':
this.flags_o.each(function(f) {
if (f.s) {
this.contextAddFlag(f.id, f, e.memo);
}
}, this);
break;
case 'ctx_folderopts':
[ $('ctx_folderopts_sub') ].compact().invoke('hide');
break;
}
},
contextAddFlag: function(flag, f, id)
{
var a = new Element('A', { className: 'ctxFlagRow' }),
style = {};
if (id == 'ctx_flag') {
a.insert(new Element('DIV', { className: 'iconImg' }));
}
if (f.b && f.u) {
style.backgroundColor = f.b.escapeHTML();
}
$(id).insert(
a.insert(
new Element('SPAN', { className: 'iconImg' }).addClassName(f.i ? f.i.escapeHTML() : f.c.escapeHTML()).setStyle(style)
).insert(
f.l.escapeHTML()
)
);
a.store('flag', flag);
},
updateTitle: function()
{
var elt, unseen,
label = this.viewport.getMetaData('label');
// 'label' will not be set if there has been an error retrieving data
// from the server.
if (!label || !$('dimpmain_folder').visible()) {
return;
}
if (this.isSearch()) {
if (this.isQSearch()) {
label += ' (' + this.search.label + ')';
}
unseen = 0;
} else if ((elt = this.flist.getMbox(this.view))) {
unseen = elt.unseen();
} else {
unseen = null;
}
this.setTitle(label, unseen);
},
sort: function(sortby)
{
var s;
if (Object.isUndefined(sortby)) {
return;
}
sortby = Number(sortby);
if (sortby == this.viewport.getMetaData('sortby')) {
if (this.viewport.getMetaData('sortdirlock')) {
return;
}
s = { sortdir: (this.viewport.getMetaData('sortdir') ? 0 : 1) };
this.viewport.setMetaData({ sortdir: s.sortdir });
} else {
if (this.viewport.getMetaData('sortbylock')) {
return;
}
s = { sortby: sortby };
this.viewport.setMetaData({ sortby: s.sortby });
}
this.setSortColumns(sortby);
this.viewport.reload(s);
},
setSortColumns: function(sortby)
{
var elt, tmp, tmp2,
ptr = DimpCore.conf.sort,
m = $('msglistHeaderHoriz');
if (Object.isUndefined(sortby)) {
sortby = this.viewport.getMetaData('sortby');
}
/* Init once per load. */
if (this.sort_init) {
[ m.down('.sortup') ].compact().invoke('removeClassName', 'sortup');
[ m.down('.sortdown') ].compact().invoke('removeClassName', 'sortdown');
} else {
ptr.each(function(s) {
if (s.value.t) {
var elt = new Element('A').insert(s.value.t);
if (s.value.ec) {
elt.addClassName(s.value.ec);
}
m.down('.' + s.value.c).store('sortby', s.value.v).insert({
top: elt
});
}
});
this.sort_init = true;
}
/* Toggle between From/To header. */
tmp = this.viewport.getMetaData('special');
tmp2 = m.down('a.msgFromTo');
[ tmp2 ].invoke(tmp ? 'show' : 'hide');
tmp2.adjacent('a').invoke(tmp ? 'hide' : 'show');
[ m.down('.msgSubject .horde-popdown'), m.down('.msgDate .horde-popdown') ].invoke(this.viewport.getMetaData('sortbylock') ? 'hide' : 'show');
ptr.find(function(s) {
if (sortby != s.value.v) {
return false;
}
if ((elt = m.down('.' + s.value.c))) {
elt.addClassName(this.viewport.getMetaData('sortdir') ? 'sortup' : 'sortdown').store('sortby', s.value.v);
}
return true;
}, this);
},
isThreadSort: function()
{
return (this.viewport.getMetaData('sortby') == DimpCore.conf.sort.get('thread').v);
},
// Preview pane functions
// mode = (string) Either 'horiz', 'vert', or empty
togglePreviewPane: function(mode)
{
var old = DimpCore.getPref('preview');
if (mode != old) {
DimpCore.setPref('preview', mode);
this.viewport.showSplitPane(mode);
if (!old) {
this.initPreviewPane();
}
}
},
loadPreview: function(data, params)
{
var curr, last, p, peek, pp_uid, rows, tmp,
msgload = {};
if (!DimpCore.getPref('preview')) {
return;
}
// If single message is loaded, and this mailbox is polled, try to
// preload next unseen message that exists in current buffer.
if (data &&
(tmp = this.flist.getMbox(data.VP_view)) &&
tmp.polled()) {
curr = this.viewport.getSelected().get('rownum').first();
rows = this.viewport.createSelectionBuffer().search({
flag: { notinclude: DimpCore.conf.FLAG_SEEN }
}).get('rownum').diff([ curr ]).numericSort();
if (rows.size()) {
p = rows.partition(function(r) {
return (r > curr);
});
last = this.viewport.getMetaData('last_row');
p[1].reverse();
/* Search for next cached message based on direction the
* selection row moved. */
this.viewport.createSelection('rownum', (last && last.get('rownum').first() > curr) ? p[1].concat(p[0]) : p[0].concat(p[1])).get('uid').detect(function(u) {
if (this.ppfifo.indexOf(this._getPPId(u, data.VP_view)) === -1) {
msgload = { msgload: u };
return true;
}
}, this);
}
}
peek = this.viewswitch && (this.viewport.bufferCount() > 1);
if (!params) {
if (!data ||
(this.pp &&
this.pp.VP_id == data.VP_id &&
this.pp.VP_view == data.VP_view)) {
return;
}
this.pp = {
VP_id: data.VP_id,
VP_view: data.VP_view
};
pp_uid = this._getPPId(data.VP_id, data.VP_view);
if (this.ppfifo.indexOf(pp_uid) !== -1) {
if (!peek) {
this.flag(DimpCore.conf.FLAG_SEEN, true, {
buid: data.VP_id,
mailbox: data.VP_view,
params: msgload
});
}
return this._loadPreview(data.VP_id, data.VP_view);
}
params = {};
}
params = Object.extend(params, msgload);
if (peek) {
params.peek = 1;
}
params.preview = 1;
DimpCore.doAction('showMessage', this.addViewportParams().merge(params), {
callback: function(r) {
if (!r) {
this.clearPreviewPane();
} else if (this.pp &&
this.pp.VP_id == r.buid &&
this.pp.VP_view == r.view) {
if (r.error) {
HordeCore.notify(r.error, r.errortype);
this.clearPreviewPane();
} else {
this._loadPreview(r.buid, r.view);
}
}
}.bind(this),
loading: 'msg',
uids: this.viewport.createSelection('dataob', this.pp)
});
},
_loadPreview: function(uid, mbox)
{
var tmp,
pm = $('previewMsg'),
r = this.ppcache[this._getPPId(uid, mbox)];
pm.down('.msgHeaders').select('.address').invoke('fire', 'DimpBase:removeElt');
// Add subject. Subject was already html encoded on server (subject
// may include links).
tmp = pm.select('.subject');
tmp.invoke('update', r.subject === null ? '[' + DimpCore.text.badsubject + ']' : (r.subjectlink || r.subject));
// Add date
[ $('msgHeaderDate') ].flatten().invoke(r.localdate ? 'show' : 'hide');
[ $('msgHeadersColl').select('.date'), $('msgHeaderDate').select('.date') ].flatten().invoke('update', r.localdate);
// Add from/to/cc/bcc headers
[ 'from', 'to', 'cc', 'bcc' ].each(function(h) {
if (r[h]) {
this.updateHeader(h, r[h], true);
$('msgHeader' + h.capitalize()).show();
} else {
$('msgHeader' + h.capitalize()).hide();
}
}, this);
[ 'msgloglist', 'partlist' ].each(function(a) {
if ($(a + '_exp').visible()) {
$(a, a + '_col', a + '_exp').invoke('toggle');
}
});
// Add attachment information
if (r.atc_label) {
$('msgAtc').show();
tmp = $('partlist');
tmp.previous().update(new Element('SPAN', { className: 'atcLabel' }).insert(r.atc_label)).insert(r.atc_download);
if (r.atc_list) {
tmp.update(new Element('TABLE'));
tmp = tmp.down();
r.atc_list.each(function(a) {
tmp.insert(
new Element('TR').insert(
new Element('TD').insert(a.icon)
).insert(
new Element('TD').insert(a.description + ' (' + a.size + ')')
).insert(
new Element('TD').insert(a.download)
)
);
if (a.download_zip) {
tmp.down('TD:last').insert(a.download_zip);
}
});
}
} else {
$('msgAtc').hide();
}
// Add message log information
if (r.log) {
this.updateMsgLog(r.log);
} else {
$('msgLogInfo').hide();
}
// Toggle resume link
if (this.viewport.getMetaData('templates')) {
$('msg_resume_draft').up().hide();
$('msg_template').up().show();
} else {
$('msg_template').up().hide();
[ $('msg_resume_draft').up() ].invoke(this.isDraft(this.viewport.getSelection()) ? 'show' : 'hide');
}
this.pp.hide_all = r.onepart;
this.pp.save_as = r.save_as;
$('messageBody').update(
(r.msgtext === null)
? $('messageBodyError').down().clone(true).show().writeAttribute('id', 'ppane_view_error')
: r.msgtext
);
$('previewInfo').hide();
$('previewPane').scrollTop = 0;
pm.show();
if (r.js) {
eval(r.js.join(';'));
}
},
messageCallback: function(r)
{
// Store messages in cache.
r.each(function(msg) {
var ppuid = this._getPPId(msg.buid, msg.mbox);
this._expirePPCache([ ppuid ]);
this.ppcache[ppuid] = msg.data;
this.ppfifo.push(ppuid);
}, this);
},
_dragAtc: function(e)
{
// As of now, only WebKit supports DownloadURL
if (!Prototype.Browser.Webkit) {
e.stop();
return;
}
var base = e.element().up();
e.dataTransfer.setData(
'DownloadURL',
base.down('IMG').readAttribute('title') + ':' +
// IE8 doesn't use this code so textContent is OK to use
base.down('SPAN.mimePartInfoDescrip A').textContent.gsub(':', '-') + ':' +
window.location.origin + e.element().readAttribute('href')
);
},
updateAddressHeader: function(e)
{
DimpCore.doAction('addressHeader', {
header: $w(e.element().className).first(),
view: this.view
}, {
callback: this._updateAddressHeaderCallback.bind(this),
loading: 'msg',
uids: this.viewport.createSelection('dataob', this.pp)
});
},
_updateAddressHeaderCallback: function(r)
{
$H(r.hdr_data).each(function(d) {
this.updateHeader(d.key, d.value);
}, this);
},
updateHeader: function(hdr, data, limit)
{
(hdr == 'from' ? $('previewMsg').select('.' + hdr) : [ $('msgHeaders').down('THEAD').down('.' + hdr) ]).each(function(elt) {
elt.replace(DimpCore.buildAddressLinks(data, elt.clone(false), limit));
});
},
updateMsgLog: function(log)
{
DimpCore.updateMsgLog(log);
$('msgLogInfo').show();
},
_mimeTreeCallback: function(r)
{
this.pp.hide_all = true;
$('partlist').update(r.tree).previous().update(new Element('SPAN', { className: 'atcLabel' }).insert(DimpCore.text.allparts_label));
$('partlist_col').show();
$('partlist_exp').hide();
$('msgAtc').show();
},
_sendMdnCallback: function(r)
{
this._expirePPCache([ this._getPPId(r.buid, r.view) ]);
if (r.mbox) {
this._expirePPCache([ this._getPPId(r.uid, r.mbox) ]);
}
if (this.pp &&
this.pp.VP_id == r.buid &&
this.pp.VP_view == r.view) {
$('sendMdnMessage').up(1).fade({ duration: 0.2 });
}
},
maillogCallback: function(r)
{
r.each(function(l) {
var tmp = this._getPPId(l.buid, l.mbox);
if (this.ppcache[tmp]) {
this.ppcache[tmp].log = l.log;
if (l.log &&
this.pp &&
this.pp.VP_id == l.buid &&
this.pp.VP_view == l.mbox) {
this.updateMsgLog(l.log);
}
}
}, this);
},
initPreviewPane: function()
{
var sel = this.viewport.getSelected();
if (sel.size() != 1) {
this.clearPreviewPane();
} else {
this.loadPreview(sel.get('dataob').first());
}
},
clearPreviewPane: function()
{
var pm = $('previewMsg');
if (pm.visible()) {
pm.hide().down('.msgHeaders').select('.address').invoke('fire', 'DimpBase:removeElt');
}
this.loadingImg('msg', false);
$('previewPane').scrollTop = 0;
$('previewInfo').update(DimpCore.text.selected.sub('%s', this.messageCountText(this.selectedCount()))).show();
delete this.pp;
},
_toggleHeaders: function(elt, update)
{
if (update) {
DimpCore.setPref('toggle_hdrs', ~~(!DimpCore.getPref('toggle_hdrs')));
}
[ $('msgHeadersColl', 'msgHeaders') ].flatten().invoke('toggle');
},
_expirePPCache: function(ids)
{
this.ppfifo = this.ppfifo.diff(ids);
ids.each(function(i) {
delete this.ppcache[i];
}, this);
if (this.ppfifo.size() > this.ppcachesize) {
delete this.ppcache[this.ppfifo.shift()];
}
},
_getPPId: function(uid, mailbox)
{
return uid + '|' + mailbox;
},
// mbox: (string) Mailbox name.
// unseen: (integer) The updated value.
updateUnseenStatus: function(mbox, unseen)
{
if (!(mbox = this.flist.getMbox(mbox))) {
return;
}
mbox.unseen(unseen);
this.setMboxLabel(mbox);
if (this.view == mbox.value()) {
this.updateTitle();
}
},
setMessageListTitle: function()
{
var rows = this.viewport.getMetaData('total_rows'),
text = this.viewport.getMetaData('label');
// 'label' will not be set if there has been an error retrieving data
// from the server.
if (text) {
if (rows) {
text += ' (' + this.messageCountText(rows) + ')';
}
$('mailboxName').update(text.escapeHTML());
}
},
// m = (string|Element) Mailbox element.
setMboxLabel: function(m)
{
var unseen;
if ((m = this.flist.getMbox(m))) {
unseen = m.unseen();
m.labelElement().update((unseen > 0) ?
new Element('STRONG').insert(m.label()).insert('&nbsp;').insert(new Element('SPAN', { className: 'count', dir: 'ltr' }).insert('(' + unseen + ')')) :
m.label());
}
},
/* Folder list updates. */
// search = (boolean) If true, update search results as well.
poll: function(search)
{
var args = $H(),
opts = { loading: 'viewport' };
// Reset poll counter.
this.setPoll();
// Check for label info - it is possible that the mailbox may be
// loading but not complete yet and sending this request will cause
// duplicate info to be returned.
if (this.view &&
$('dimpmain_folder').visible() &&
this.viewport.getMetaData('label')) {
args = this.addViewportParams();
// Possible further optimization: only poll VISIBLE mailboxes.
// Issue: it is quite expensive to determine this, since the
// mailbox elements themselves aren't hidden - it is one of the
// parent containers. Probably not worth the effort.
args.set('poll', Object.toJSON(Object.values(this.flist.mboxes).findAll(function(m) {
return m.polled();
}).invoke('value')));
} else {
args.set('poll', Object.toJSON([]));
}
if (search) {
args.set('forceUpdate', 1);
}
DimpCore.doAction('poll', args, opts);
},
pollCallback: function(r)
{
/* Don't update polled status until the sidebar is visible. Otherwise,
* preview callbacks may not correctly update unseen status. */
if (!$('foldersSidebar').visible()) {
return this.pollCallback.bind(this, r).delay(0.1);
}
$H(r).each(function(u) {
this.updateUnseenStatus(u.key, u.value);
}, this);
},
quotaCallback: function(r)
{
var quota = $('quota-text');
quota.removeClassName('quotaalert').
removeClassName('quotawarn').
setText(r.m);
switch (r.l) {
case 'alert':
case 'warn':
quota.addClassName('quota' + r.l);
break;
}
},
setPoll: function()
{
if (DimpCore.conf.refresh_time) {
if (this.pollPE) {
this.pollPE.stop();
}
// Run in anonymous function, or else PeriodicalExecuter passes
// in itself as first ('force') parameter to poll().
this.pollPE = new PeriodicalExecuter(function() { this.poll(); }.bind(this), DimpCore.conf.refresh_time);
}
},
/* Search functions. */
isSearch: function(id)
{
return this.viewport.getMetaData('search', id);
},
isFSearch: function(id)
{
return ((id ? id : this.view) == DimpCore.conf.fsearchid);
},
isQSearch: function(id)
{
return ((id ? id : this.view) == DimpCore.conf.qsearchid);
},
searchReset: function(e)
{
this.quicksearchClear();
},
searchSubmit: function(e)
{
if ($F('horde-search-input')) {
this.quicksearchRun();
} else {
this.quicksearchClear();
}
},
quicksearchRun: function()
{
var q = $('horde-search-input');
q.blur();
if (this.isSearch()) {
/* Search text has changed. */
if (this.search.query != $F(q)) {
this.viewswitch = true;
this.search.query = $F(q);
}
this.resetSelected();
this.viewport.reload();
} else {
this.search = {
label: this.viewport.getMetaData('label'),
mbox: this.view,
qsearch: true,
query: $F(q)
};
this.go('mbox', DimpCore.conf.qsearchid);
}
},
// 'noload' = (boolean) If true, don't load the mailbox
quicksearchClear: function(noload)
{
var qs = $('horde-search');
if (qs && this.isSearch()) {
$(qs, 'horde-search-dropdown', 'horde-search-input').invoke('show');
if (!noload) {
this.go('mbox', (this.search ? this.search.mbox : this.INBOX));
}
delete this.search;
$('horde-search-input').clear();
if (HordeTopbar.searchGhost) {
HordeTopbar.searchGhost.reset();
}
}
},
/* Set quicksearch text. */
_setQsearchText: function()
{
$('horde-search-input').writeAttribute('title', DimpCore.text.search_input.sub('%s', DimpCore.context.ctx_qsearchopts['*' + DimpCore.getPref('qsearch_field')]));
if (HordeTopbar.searchGhost) {
HordeTopbar.searchGhost.refresh();
}
},
/* Handle searchbar. */
showSearchbar: function(show)
{
if ($('searchbar').visible()) {
if (!show) {
$('searchbar').hide();
this.viewport.onResize(true);
}
this.searchbarTimeReset(show);
} else if (show) {
$('searchbar').show();
this.viewport.onResize(true);
this.searchbarTimeReset(true);
}
},
searchbarTimeReset: function(restart)
{
if (this.searchbar_time) {
this.searchbar_time.stop();
delete this.searchbar_time;
$('search_time_elapsed').hide();
}
if (restart) {
this.searchbar_time_mins = 0;
this.searchbar_time = new PeriodicalExecuter(function() {
if (++this.searchbar_time_mins > 5) {
$('search_time_elapsed').update(DimpCore.text.search_time.sub('%d', this.searchbar_time_mins).escapeHTML()).show();
}
}.bind(this), 60);
}
},
/* Enable/Disable action buttons as needed. */
toggleButtons: function()
{
var bf = $('button_forward'),
sc = this.selectedCount();
DimpCore.toggleButtons(
$('dimpmain_folder_top').select('DIV.horde-buttonbar A.noselectDisable'),
sc === 0
);
if (sc > 1) {
DimpCore.toggleButtons([ $('button_reply') ], true);
}
if (bf) {
[ bf.next('.horde-popdown') ].compact().invoke(sc > 1 ? 'hide' : 'show');
}
},
/* Drag/Drop handler. */
mboxDropHandler: function(e)
{
var dropbase, sel, uids,
drag = e.memo.element,
drag_m = this.flist.getMbox(drag),
drop = this.flist.getMbox(e.element());
if (drag_m) {
dropbase = this.isDropbase(e.element());
if (dropbase ||
(drop.ftype() != 'special' &&
!this.flist.isSubfolder(drag_m, drop))) {
DimpCore.doAction('renameMailbox', {
new_name: drag_m.label().unescapeHTML(),
new_parent: dropbase ? '' : drop.value(),
old_name: drag_m.value()
});
}
} else if (drop.ftype() != 'container') {
sel = this.viewport.getSelected();
if (sel.size()) {
// Dragging multiple selected messages.
uids = sel;
} else if (drag.retrieve('mbox') != drop.value()) {
// Dragging a single unselected message.
uids = this.viewport.createSelection('domid', drag.id);
}
if (uids.size()) {
if (e.memo.dragevent.ctrlKey) {
DimpCore.doAction('copyMessages', this.addViewportParams().merge({
mboxto: drop.value()
}), {
uids: uids
});
} else if (this.view != drop.value()) {
// Don't allow drag/drop to the current mailbox.
this.updateFlag(uids, DimpCore.conf.FLAG_DELETED, true);
DimpCore.doAction('moveMessages', this.addViewportParams().merge({
mboxto: drop.value()
}), {
uids: uids
});
}
}
}
},
dropbase: function()
{
var tmp = $('dropbase');
return tmp ? tmp.up('DIV') : null;
},
isDropbase: function(elt)
{
var tmp = this.dropbase();
return (tmp === elt || elt.descendantOf(tmp));
},
mboxDropCaption: function(drop, drag, e)
{
var m,
orig_drop = drop;
drag = this.flist.getMbox(drag);
drop = this.flist.getMbox(drop);
switch (e.type) {
case 'mousemove':
m = (e.ctrlKey) ? DimpCore.text.copyto : DimpCore.text.moveto;
break;
case 'keydown':
/* Can't use ctrlKey here since different browsers handle the
* ctrlKey in different ways when it comes to firing keyboard
* events. */
m = (e.keyCode == 17) ? DimpCore.text.copyto : DimpCore.text.moveto;
break;
case 'keyup':
m = (e.keyCode == 17)
? DimpCore.text.moveto
: (e.ctrlKey) ? DimpCore.text.copyto : DimpCore.text.moveto;
break;
}
if (drag) {
if (drop) {
return (drop.ftype() != 'special' && !this.flist.isSubfolder(drag, drop))
? m.sub('%s', drag.label()).sub('%s', drop.label())
: '';
}
return this.isDropbase(orig_drop)
? DimpCore.text.moveto.sub('%s', drag.label()).sub('%s', DimpCore.text.baselevel)
: '';
}
return (drop.ftype() != 'container')
? m.sub('%s', this.messageCountText(this.selectedCount())).sub('%s', drop.label())
: '';
},
messageCountText: function(cnt)
{
switch (cnt) {
case 0:
return DimpCore.text.message_0;
case 1:
return DimpCore.text.message_1;
default:
return DimpCore.text.message_2.sub('%d', cnt);
}
},
onDragMouseDown: function(e)
{
var args, tmp,
elt = e.element(),
id = elt.identify(),
d = DragDrop.Drags.getDrag(id);
if (elt.hasClassName('vpRow')) {
args = { right: e.memo.isRightClick() };
d.fromClick = d.selectIfNoDrag = false;
if (DimpCore.conf.from_link && e.memo.findElement('.msgFrom a')) {
d.fromClick = !args.right;
return;
}
// Handle selection first.
if (DimpCore.DMenu.operaCheck(e)) {
if (!this.isSelected('domid', id)) {
this.msgSelect(id, { right: true });
}
} else if (!args.right && (e.memo.ctrlKey || e.memo.metaKey)) {
this.msgSelect(id, $H({ ctrl: true }).merge(args).toObject());
} else if (e.memo.shiftKey) {
this.msgSelect(id, $H({ shift: true }).merge(args).toObject());
} else if (this.isSelected('domid', id)) {
if (!args.right) {
if (e.memo.element().hasClassName('msCheck')) {
this.msgSelect(id, { ctrl: true, right: true });
} else {
d.selectIfNoDrag = true;
}
}
} else if (e.memo.element().hasClassName('msCheck')) {
this.msgSelect(id, { ctrl: true, right: true });
} else {
this.msgSelect(id, args);
}
} else if ((tmp = this.flist.getMbox(elt)) && tmp.isMbox()) {
d.opera = DimpCore.DMenu.operaCheck(e);
}
},
onDragStart: function(e)
{
if (e.element().hasClassName('horde-subnavi')) {
var d = e.memo;
if (!d.opera && !d.wasDragged) {
$('folderopts_link').up().hide();
this.dropbase().show();
}
}
},
onDragEnd: function(e)
{
var elt = e.element(),
id = elt.identify(),
d = DragDrop.Drags.getDrag(id);
if (id == 'horde-slideleft') {
DimpCore.setPref('splitbar_side', d.lastCoord[0]);
this.setSidebarWidth();
} else if (elt.hasClassName('horde-subnavi')) {
if (!d.opera) {
$('folderopts_link').up().show();
this.dropbase().hide();
}
}
},
onDragMouseUp: function(e)
{
var elt = e.element(),
id = elt.identify();
if (elt.hasClassName('vpRow')) {
d = DragDrop.Drags.getDrag(id);
if (d.fromClick) {
DimpCore.compose('new_to', {
buid: this.viewport.createSelection('div', elt).get('uid').toViewportUidString(),
mailbox: this.view
});
} else if (d.selectIfNoDrag) {
this.msgSelect(id, { right: e.memo.isRightClick() });
}
}
},
/* Keydown event handler */
keydownHandler: function(e)
{
var all, cnt, co, h, need, pp, ps, r, row, rownum, rowoff, sel,
tmp, vsel, prev, noelt,
kc = e.keyCode || e.charCode;
// Only catch keyboard shortcuts in message list view.
if (!$('dimpmain_folder').visible()) {
return;
}
if (!Object.isFunction(e.element)) {
// Inside IFRAME. Wrap in prototypejs Event object.
// Ignore if IE 8
if (Prototype.Browser.IE && !document.addEventListener) {
return;
}
e = new Event(e);
e.preventDefault();
noelt = true;
// Allow ctrl-c (kc=67) and command-c (kc=91) to copy text from the
// message preview.
if (!(kc === 17 || kc === 67 || kc === 91)) {
$$('IFRAME').invoke('blur');
}
} else if (e.findElement('FORM')) {
// Inside form, so ignore.
return;
}
sel = this.viewport.getSelected();
switch (kc) {
case Event.KEY_DELETE:
case Event.KEY_BACKSPACE:
if (!this.viewport.getMetaData('nodelete')) {
r = sel.get('dataob');
if (e.shiftKey) {
this.moveSelected(
(r.last().VP_rownum == this.viewport.getMetaData('total_rows'))
? (r.first().VP_rownum - 1)
: (r.last().VP_rownum + 1),
true,
true
);
}
this.deleteMsg({ vs: sel });
}
e.stop();
break;
case Event.KEY_UP:
case Event.KEY_DOWN:
case Event.KEY_LEFT:
case Event.KEY_RIGHT:
prev = kc == Event.KEY_UP || kc == Event.KEY_LEFT;
tmp = this.viewport.getMetaData('curr_row');
if (e.altKey) {
pp = $('previewPane');
pp.scrollTop = prev
? Math.max(pp.scrollTop - 10, 0)
: Math.min(pp.scrollTop + 10, pp.scrollHeight - pp.getHeight() + 1);
} else if (e.shiftKey && tmp) {
row = this.viewport.createSelection('rownum', tmp.get('rownum').first() + ((prev) ? -1 : 1));
if (row.size()) {
row = row.get('dataob').first();
this.viewport.scrollTo(row.VP_rownum, { bottom: true });
this.msgSelect(row.VP_domid, { shift: true });
}
} else {
this.moveSelected(prev ? -1 : 1, false, !prev);
}
e.stop();
break;
case Event.KEY_PAGEUP:
case Event.KEY_PAGEDOWN:
if (e.altKey) {
pp = $('previewPane');
h = pp.getHeight();
if (h != pp.scrollHeight) {
switch (kc) {
case Event.KEY_PAGEUP:
pp.scrollTop = Math.max(pp.scrollTop - h + 20, 0);
break;
case Event.KEY_PAGEDOWN:
pp.scrollTop = Math.min(pp.scrollTop + h - 20, pp.scrollHeight - h + 1);
break;
}
}
e.stop();
} else if (!e.ctrlKey && !e.shiftKey && !e.metaKey) {
ps = this.viewport.getPageSize() - 1;
move = ps * (kc == Event.KEY_PAGEUP ? -1 : 1);
if (sel.size() == 1) {
co = this.viewport.currentOffset();
rowoff = sel.get('rownum').first() - 1;
switch (kc) {
case Event.KEY_PAGEUP:
if (co != rowoff) {
move = co - rowoff;
}
break;
case Event.KEY_PAGEDOWN:
if ((co + ps) != rowoff) {
move = co + ps - rowoff;
}
break;
}
}
this.moveSelected(move, false, kc == Event.KEY_PAGEDOWN);
e.stop();
}
break;
case Event.KEY_HOME:
case Event.KEY_END:
this.moveSelected(kc == Event.KEY_HOME ? 1 : this.viewport.getMetaData('total_rows'), true);
e.stop();
break;
case Event.KEY_RETURN:
if ((noelt || !e.element().match('INPUT')) && sel.size() == 1) {
// Popup message window if single message is selected.
this.msgWindow(sel.get('dataob').first());
}
e.stop();
break;
case 65: // A
case 97: // a
if (e.ctrlKey) {
this.selectAll();
e.stop();
}
break;
case 78: // N
case 110: // n
if (e.shiftKey && !this.isSearch()) {
tmp = this.flist.getMbox(this.view);
cnt = tmp.unseen();
if (cnt || !tmp.polled()) {
vsel = this.viewport.createSelectionBuffer();
row = vsel.search({ flag: { notinclude: DimpCore.conf.FLAG_SEEN } }).get('rownum');
all = (vsel.size() == this.viewport.getMetaData('total_rows'));
if (all || ((row.size() == cnt) && tmp.polled())) {
// Here we either have the entire mailbox in buffer,
// or all unseen messages are in the buffer.
if (sel.size()) {
tmp = sel.get('rownum').last();
if (tmp) {
rownum = row.detect(function(r) {
return tmp < r;
});
}
} else {
rownum = tmp = row.first();
}
} else {
// Here there is no guarantee that the next unseen
// message will appear in the current buffer. Need to
// determine if any gaps are between last selected
// message and next unseen message in buffer.
vsel = vsel.get('rownum');
if (sel.size()) {
// We know that the selected rows are in the
// buffer.
tmp = sel.get('rownum').last();
} else if (vsel.include(1)) {
// If no selected rows, start searching from the
// first entry.
tmp = 0;
} else {
// First message is not in current buffer.
need = true;
}
if (!need) {
rownum = vsel.detect(function(r) {
if (r > tmp) {
if (++tmp != r) {
// We have found a gap.
need = true;
throw $break;
}
return row.include(tmp);
}
});
if (!need && !rownum) {
need = (tmp !== this.viewport.getMetaData('total_rows'));
}
}
if (need) {
this.viewport.select(null, { search: { unseen: 1 } });
}
}
if (rownum) {
this.moveSelected(rownum, true);
}
}
e.stop();
}
break;
}
},
dblclickHandler: function(e)
{
var elt = e.element(),
tmp;
if (elt.hasClassName('splitBarVertSidebar')) {
DimpCore.setPref('splitbar_side', null);
this.setSidebarWidth();
e.memo.stop();
return;
} else if (elt.hasClassName('vpRow')) {
tmp = this.viewport.createSelection('domid', elt.identify());
if (this.viewport.getMetaData('templates')) {
DimpCore.compose('template', {
buid: tmp.get('uid').toViewportUidString(),
mailbox: this.view
});
} else if (this.isDraft(tmp)) {
DimpCore.compose('resume', {
buid: tmp.get('uid').toViewportUidString(),
mailbox: this.view
});
} else {
this.msgWindow(tmp.get('dataob').first());
}
e.memo.stop();
}
},
clickHandler: function(e)
{
var tmp,
elt = e.element(),
id = elt.readAttribute('id');
if (DimpCore.DMenu.operaCheck(e.memo)) {
return;
}
switch (id) {
case 'imp-normalmboxes':
case 'imp-specialmboxes':
this._handleMboxMouseClick(e.memo);
break;
case 'appportal':
case 'hometab':
case 'logolink':
this.go('portal');
e.memo.stop();
break;
case 'button_compose':
case 'composelink':
DimpCore.compose('new');
e.memo.stop();
break;
case 'search_refresh':
this.searchbarTimeReset(true);
this.poll(true);
e.memo.stop();
break;
case 'checkmaillink':
this.poll(false);
e.memo.stop();
break;
case 'search_edit':
this.go('search', {
edit_query: 1,
mailbox: this.view
});
e.memo.stop();
break;
case 'appprefs':
this.go('prefs');
e.memo.stop();
break;
case 'applogout':
elt.down('A').update('[' + DimpCore.text.onlogout + ']');
HordeCore.logout();
e.memo.stop();
break;
case 'button_forward':
this.composeMailbox('forward_auto');
break;
case 'button_reply':
this.composeMailbox('reply_auto');
break;
case 'button_resume':
this.composeMailbox('resume');
e.memo.stop();
break;
case 'button_template':
if (this.viewport.getSelection().size()) {
this.composeMailbox('template');
}
e.memo.stop();
break;
case 'button_innocent':
this.reportSpam(false);
e.memo.stop();
break;
case 'button_spam':
this.reportSpam(true);
e.memo.stop();
break;
case 'button_delete':
this.deleteMsg();
e.memo.stop();
break;
case 'msglistHeaderHoriz':
tmp = e.memo.findElement('DIV');
if (tmp.hasClassName('msCheckAll')) {
this.selectAll();
} else if (!e.memo.element().hasClassName('horde-popdown')) {
this.sort(tmp.retrieve('sortby'));
}
e.memo.stop();
break;
case 'msglistHeaderVert':
tmp = e.memo.element();
if (tmp.hasClassName('msCheckAll')) {
this.selectAll();
}
e.memo.stop();
break;
case 'th_expand':
case 'th_collapse':
this._toggleHeaders(elt, true);
break;
case 'msgloglist_toggle':
case 'partlist_toggle':
tmp = (id == 'partlist_toggle') ? 'partlist' : 'msgloglist';
$(tmp + '_col', tmp + '_exp').invoke('toggle');
Effect.toggle(tmp, 'blind', {
duration: 0.2,
queue: {
position: 'end',
scope: tmp,
limit: 2
}
});
break;
case 'msg_newwin_options':
case 'ppane_view_error':
this.msgWindow(this.viewport.getSelection(this.pp.VP_view).search({
VP_id: {
equal: [ this.pp.VP_id ]
}
}).get('dataob').first());
e.memo.stop();
break;
case 'ctx_preview_save':
HordeCore.redirect(this.pp.save_as);
break;
case 'ctx_preview_viewsource':
HordeCore.popupWindow(DimpCore.conf.URI_VIEW, {
actionID: 'view_source',
buid: this.pp.VP_id,
id: 0,
mailbox: this.pp.VP_view
}, {
name: this.pp.VP_id + '|' + this.pp.VP_view
});
break;
case 'ctx_preview_listinfo':
case 'ctx_preview_thread':
HordeCore.popupWindow((id == 'ctx_preview_listinfo') ? DimpCore.conf.URI_LISTINFO : DimpCore.conf.URI_THREAD, {
buid: this.pp.VP_id,
mailbox: this.pp.VP_view
}, {
name: this.pp.VP_id + '|' + this.pp.VP_view
});
break;
case 'ctx_preview_allparts':
DimpCore.doAction('messageMimeTree', {
preview: 1,
view: this.pp.VP_view
}, {
callback: this._mimeTreeCallback.bind(this),
loading: 'msg',
uids: [ this.pp.VP_id ]
});
break;
case 'msg_resume_draft':
this.composeMailbox('resume');
break;
case 'msg_template':
this.composeMailbox('template');
break;
case 'search_close':
this.quicksearchClear();
e.memo.stop();
break;
case 'send_mdn_link':
DimpCore.doAction('sendMDN', {
view: this.pp.VP_view
}, {
callback: this._sendMdnCallback.bind(this),
uids: [ this.pp.VP_id ]
});
e.memo.stop();
break;
default:
if (elt.hasClassName('printAtc')) {
HordeCore.popupWindow(DimpCore.conf.URI_VIEW, {
actionID: 'print_attach',
buid: this.pp.VP_id,
id: elt.readAttribute('mimeid'),
mailbox: this.pp.VP_view
}, {
name: this.pp.VP_id + '|' + this.pp.VP_view + '|print',
onload: IMP_JS.printWindow
});
e.memo.stop();
} else if (elt.hasClassName('stripAtc')) {
if (window.confirm(DimpCore.text.strip_warn)) {
DimpCore.doAction('stripAttachment', this.addViewportParams().merge({
id: elt.readAttribute('mimeid')
}), {
callback: function(r) {
if (!this.pp) {
this.viewport.select(this.viewport.createSelectionBuffer(r.newmbox).search({
VP_id: {
equal: [ r.newbuid ]
}
}).get('rownum'));
}
}.bind(this),
loading: 'msg',
uids: [ this.pp.VP_id ]
});
}
e.memo.stop();
} else if (elt.hasClassName('flagcolorpicker')) {
tmp = elt.previous('INPUT');
this.colorpicker = new ColorPicker({
color: $F(tmp) || '#fff',
draggable: true,
offsetParent: elt,
resizable: true,
update: [
[ tmp, 'value' ],
[ tmp, 'background' ]
]
});
e.memo.stop();
} else if (elt.hasClassName('imp-sidebar-remote')) {
elt = this.flist.getMbox(elt);
HordeDialog.display({
form: new Element('DIV').insert(
new Element('INPUT', { name: 'remote_password', type: 'password' })
).insert(
new Element('INPUT', { name: 'remote_id', value: elt.value() }).hide()
),
form_id: 'remote_login',
text: DimpCore.text.remote_password.sub('%s', elt.fullMboxDisplay())
});
e.memo.stop();
}
break;
}
},
loadingStartHandler: function(e)
{
this.loadingImg(e.memo, true);
},
loadingEndHandler: function(e)
{
this.loadingImg(e.memo, false);
},
dialogClickHandler: function(e)
{
var elt = e.element();
switch (elt.identify()) {
case 'dimpbase_confirm':
this.viewaction(e);
HordeDialog.close();
break;
case 'flag_new':
DimpCore.doAction('createFlag', this.addViewportParams().merge({
flagcolor: $F(elt.down('INPUT[name="flagcolor"]')),
flagname: $F(elt.down('INPUT[name="flagname"]'))
}), {
callback: function(r) {
if (r.success) {
HordeDialog.close();
} else {
this.displayFlagNew();
}
}.bind(this),
uids: this.viewport.getSelected()
});
elt.update(DimpCore.text.newflag_wait);
break;
case 'mbox_import':
HordeCore.submit(elt, {
callback: function(r) {
HordeDialog.close();
if (r.action == 'importMailbox' &&
r.mbox == this.view) {
this.viewport.reload();
}
}.bind(this)
});
elt.update(DimpCore.text.import_mbox_loading);
break;
case 'remote_login':
DimpCore.doAction('remoteLogin', {
// Base64 encode just to keep password data from being
// plaintext. A trivial obfuscation, but will prevent
// passwords from leaking in the event of some sort of data
// dump.
password: Base64.encode($F(elt.down('INPUT[name="remote_password"]'))),
password_base64: true,
remoteid: $F(elt.down('INPUT[name="remote_id"]')),
unsub: this.showUnsub()
}, {
callback: function(r) {
if (r.success) {
this.flist.getMbox($F(elt.down('INPUT[name="remote_id"]'))).element()
.removeClassName('imp-sidebar-remote')
.addClassName('imp-sidebar-container');
HordeDialog.close();
} else {
elt.enable().down('INPUT[name="remote_password"]').clear().focus();
}
}.bind(this)
});
elt.disable();
break;
}
},
dialogCloseHandler: function()
{
if (this.colorpicker) {
this.colorpicker.hide();
}
delete this.colorpicker;
},
removeEltHandler: function(e)
{
var id = e.element().readAttribute('id');
if (id) {
[ DragDrop.Drags.getDrag(id), DragDrop.Drops.getDrop(id) ].compact().invoke('destroy');
DimpCore.DMenu.removeElement(id);
}
},
updateSliderCount: function()
{
var range = this.viewport.currentViewableRange();
$('slider_count').update(DimpCore.text.slidertext.sub('%d', range.first).sub('%d', range.last));
},
// elt: [Object:IMP_Flist_Mbox]
_mailboxPromptCallback: function(type, elt, r)
{
switch (type) {
case 'create':
if (r.result) {
this._createMboxForm(elt, 'createsub', DimpCore.text.createsub_prompt.sub('%s', elt.fullMboxDisplay()));
} else {
RedBox.close();
}
break;
case 'delete':
if (r.result) {
this.viewaction = function(e) {
DimpCore.doAction('deleteMailbox', {
container: ~~elt.isContainer(),
mbox: elt.value(),
subfolders: e.element().down('[name=delete_subfolders]').getValue()
});
};
HordeDialog.display({
form: new Element('DIV').insert(
new Element('INPUT', { name: 'delete_subfolders', type: 'checkbox' })
).insert(
DimpCore.text.delete_mbox_subfolders.sub('%s', elt.fullMboxDisplay())
),
form_id: 'dimpbase_confirm',
text: elt.isContainer() ? null : DimpCore.text.delete_mbox.sub('%s', elt.fullMboxDisplay())
});
} else {
RedBox.close();
}
break;
case 'empty':
if (r.result) {
this.viewaction = function() {
DimpCore.doAction('emptyMailbox', {
mbox: elt.value()
});
};
HordeDialog.display({
form_id: 'dimpbase_confirm',
noinput: true,
text: DimpCore.text.empty_mbox.sub('%s', elt.fullMboxDisplay()).sub('%d', r.result)
});
} else {
RedBox.close();
}
break;
case 'rename':
if (r.result) {
this._createMboxForm(elt, 'rename', DimpCore.text.rename_prompt.sub('%s', elt.fullMboxDisplay()), elt.label().unescapeHTML());
} else {
RedBox.close();
}
break;
case 'subscribe':
this.viewaction = function(e) {
DimpCore.doAction('subscribe', {
mbox: elt.value(),
sub: 1,
subfolders: e.element().down('[name=subscribe_subfolders]').getValue()
});
};
HordeDialog.display({
form: new Element('DIV').insert(
new Element('INPUT', { name: 'subscribe_subfolders', type: 'checkbox' })
).insert(
DimpCore.text.subscribe_mbox_subfolders.sub('%s', elt.fullMboxDisplay())
),
form_id: 'dimpbase_confirm',
text: elt.isContainer() ? null : DimpCore.text.subscribe_mbox.sub('%s', elt.fullMboxDisplay())
});
break;
case 'unsubscribe':
this.viewaction = function(e) {
DimpCore.doAction('subscribe', {
mbox: elt.value(),
sub: 0,
subfolders: e.element().down('[name=unsubscribe_subfolders]').getValue()
});
};
HordeDialog.display({
form: new Element('DIV').insert(
new Element('INPUT', { name: 'unsubscribe_subfolders', type: 'checkbox' })
).insert(
DimpCore.text.unsubscribe_mbox_subfolders.sub('%s', elt.fullMboxDisplay())
),
form_id: 'dimpbase_confirm',
text: elt.isContainer() ? null : DimpCore.text.unsubscribe_mbox.sub('%s', elt.fullMboxDisplay())
});
break;
}
},
/* Handle create mailbox actions. */
_createMboxForm: function(mbox, mode, text, val)
{
this.viewaction = function(e) {
this._mboxAction(e, mbox, mode);
}.bind(this);
HordeDialog.display({
form_id: 'dimpbase_confirm',
input_val: val,
text: text
});
},
// mbox: (Object:IMP_Flist_Mbox)
_mboxAction: function(e, mbox, mode)
{
var action, params, val,
form = e.findElement('form');
val = $F(form.down('input'));
if (val) {
switch (mode) {
case 'rename':
if (mbox.label() != val) {
action = 'renameMailbox';
params = {
old_name: mbox.value(),
new_name: val
};
}
break;
case 'create':
case 'createsub':
action = 'createMailbox';
params = { mbox: val };
if (mode == 'createsub') {
params.parent = mbox.value();
}
break;
}
if (action) {
DimpCore.doAction(action, params);
}
}
},
/* Mailbox action callback functions. */
mailboxCallback: function(r)
{
var nm = $('imp-normalmboxes');
if (r.d) {
r.d.each(function(m) {
if (this.view == m) {
this.go('mbox', r['switch'] || this.INBOX);
}
this.flist.deleteMbox(m, { sub: true });
this.viewport.deleteView(m);
}, this);
}
if (r.c) {
r.c.each(function(m) {
if (m.un && !this.showUnsub()) {
this.flist.deleteMbox(m.m);
this.viewport.deleteView(m.m);
} else {
this.flist.changeMbox(m);
}
}, this);
}
if (r.a) {
r.a.each(this.flist.createMbox.bind(this.flist));
}
if (r.expand) {
this.flist.subElements(r.base).findAll(function(e) { return e.down(); }).each(function(sub) {
this._toggleSubFolder(sub, 'exp', {
noeffect: true,
noexpand: true,
noparents: r.base
});
}, this);
}
if (r.all) {
this._toggleSubFolder(nm, 'expall', {
noeffect: true,
noexpand: true
});
}
if ($('foldersLoading').visible()) {
$('foldersLoading').hide();
$('foldersSidebar').show();
}
if (this.view) {
this.highlightSidebar(this.view);
}
if (nm && nm.getStyle('max-height') !== null) {
this._sizeFolderlist();
}
},
flagConfigCallback: function(r)
{
$('ctx_flag', 'ctx_flagunset', 'ctx_flag_search').compact().invoke('remove');
this.flags = {};
this.flags_o = r;
r.each(function(f) {
this.flags[f.id] = f;
}, this);
},
flagCallback: function(r)
{
Object.values(r).each(function(entry) {
$H(entry.buids).each(function(m) {
var s = this.viewport.createSelectionBuffer(m.key).search({
VP_id: { equal: m.value.parseViewportUidString() }
});
if (entry.replace) {
s.get('dataob').each(function(d) {
d.flag = [];
this.viewport.updateRow(d);
}, this);
entry.add = entry.replace;
}
if (entry.add) {
entry.add.each(function(f) {
this.updateFlag(s, f, true);
}, this);
}
if (entry.remove) {
entry.remove.each(function(f) {
this.updateFlag(s, f, false);
}, this);
}
}, this);
}, this);
},
displayFlagNew: function()
{
HordeDialog.display({
form: $('flagnewContainer').down().clone(true),
form_id: 'flag_new',
text: DimpCore.text.newflag_name
});
},
_handleMboxMouseClick: function(e)
{
var mbox = this.flist.getMbox(e);
if (!mbox) {
return;
}
if ((mbox.expand() !== null) && (e.element() == mbox.iconElement())) {
this._toggleSubFolder(mbox.element(), 'tog');
} else {
switch (mbox.ftype()) {
case 'container':
case 'rcontainer':
case 'remote':
case 'remoteauth':
case 'scontainer':
case 'vcontainer':
e.stop();
break;
case 'mbox':
case 'special':
case 'vfolder':
e.stop();
if (mbox.value() != this.view ||
!$('dimpmain_folder').visible()) {
this.go('mbox', mbox.value());
}
break;
}
}
},
_toggleSubFolder: function(base, mode, opts)
{
var collapse = [], expand = [], subs = [],
need = $H();
opts = opts || {};
if (mode == 'expall' || mode == 'colall') {
if (base.hasClassName('horde-subnavi-sub')) {
subs.push(base);
}
subs = subs.concat(base.select('.horde-subnavi-sub'));
} else if (mode == 'exp') {
// If we are explicitly expanding ('exp'), make sure all parent
// subfolders are expanded.
// The last 2 elements of ancestors() are the BODY and HTML tags -
// don't need to parse through them.
subs = opts.noparents
? [ base ]
: [ base, base.ancestors() ].flatten().slice(0, -2).reverse().findAll(function(n) { return n.hasClassName('horde-subnavi-sub'); });
} else {
if (!base.hasClassName('horde-subnavi')) {
base = base.up();
}
subs = [ base.next('.horde-subnavi-sub') ];
}
subs = subs.compact();
if (!subs) {
return;
}
if (!opts.noexpand && (mode == 'tog' || mode == 'expall')) {
subs.invoke('previous').each(function(s) {
var s2 = this.flist.getMbox(s);
if (!s2.loaded()) {
need.set(s2.value(), 1);
}
}, this);
if (need.size() && mode == 'expall') {
this._listMboxes({
all: 1,
base: base,
expall: 1,
mboxes: need.keys()
});
return;
}
}
subs.each(function(s) {
if (mode == 'tog' ||
((mode == 'exp' || mode == 'expall') && !s.visible()) ||
((mode == 'col' || mode == 'colall') && s.visible())) {
var mbox = this.flist.getMbox(s.previous());
if (mode == 'col' ||
((mode == 'tog') && s.visible())) {
collapse.push(mbox.value());
} else if (!opts.noexpand &&
!need.get(mbox.value()) &&
(mode == 'exp' ||
((mode == 'tog') && !s.visible()))) {
expand.push(mbox.value());
}
if (opts.noeffect && !need.get(mbox.value())) {
s.toggle();
mbox.expand(!mbox.expand());
} else {
Effect.toggle(s, 'blind', {
beforeStart: (need.get(mbox.value()) ? this._loadMboxes.bind(this, mbox, base) : Prototype.emptyFunction),
afterFinish: function() {
if (!mbox.expand()) {
mbox.expand(true);
} else if (mbox.hasChildren()) {
mbox.expand(false);
} else {
s.hide();
}
}.bind(this),
duration: opts.noeffect ? 0 : 0.2,
queue: {
limit: 1,
scope: 'subfolder' + mbox.value()
}
});
}
}
}, this);
if (DimpCore.conf.mbox_expand) {
if (collapse.size()) {
DimpCore.doAction('toggleMailboxes', {
action: 'collapse',
mboxes: Object.toJSON(collapse)
});
} else if (expand.size()) {
DimpCore.doAction('toggleMailboxes', {
action: 'expand',
mboxes: Object.toJSON(expand)
});
} else if (mode == 'colall' ||
(!opts.noexpand && mode == 'expall')) {
DimpCore.doAction('toggleMailboxes', {
action: (mode == 'colall' ? 'collapse' : 'expand'),
all: 1
});
}
}
},
_loadMboxes: function(m, base, e)
{
var ed;
m.labelElement().update(
new Element('SPAN')
.addClassName('imp-sidebar-mbox-loading')
.update('[' + DimpCore.text.loading + ']')
);
this._listMboxes({
base: base,
mboxes: [ m.value() ]
}, true);
this.setMboxLabel(m);
/* Need to update sizing since it is calculated at instantiation
* before the submailbox DIV contained anything. */
ed = m.subElement().getDimensions();
e.options.scaleMode = {
originalHeight: ed.height,
originalWidth: ed.width
};
},
_listMboxes: function(params, sync)
{
var m;
params = params || {};
params.unsub = this.showUnsub();
if (!Object.isArray(params.mboxes)) {
params.mboxes = [ params.mboxes ];
}
if ((m = this.flist.getMbox(params.base))) {
params.base = m.value();
}
params.mboxes = Object.toJSON(params.mboxes);
DimpCore.doAction('listMailboxes', params, {
ajaxopts: { asynchronous: !sync }
});
},
createMboxHandler: function(e)
{
var ftype = e.memo.ftype();
// Make the new mailbox a drop target.
if (!e.memo.virtual()) {
new Drop(e.memo.element(), this.mboxDropConfig);
}
if (DimpCore.conf.subscribe && e.memo.unsubscribed()) {
e.memo.element().addClassName('imp-sidebar-unsubmbox');
}
switch (ftype) {
case 'special':
// For purposes of the contextmenu, treat special mailboxes
// like regular mailboxes.
ftype = 'mbox';
// Fall through.
case 'container':
case 'mbox':
new Drag(e.memo.element(), this.mboxDragConfig);
break;
case 'remote':
case 'scontainer':
ftype = 'noactions';
break;
case 'remoteauth':
ftype = 'remoteauth';
break;
case 'vfolder':
if (e.memo.virtual()) {
ftype = 'noactions';
}
break;
}
DimpCore.addContextMenu({
elt: e.memo.element(),
type: ftype
});
},
_sizeFolderlist: function()
{
var nf = $('imp-normalmboxes');
if (nf) {
nf.setStyle({ height: Math.max(document.viewport.getHeight() - nf.cumulativeOffset()[1], 0) + 'px' });
}
},
toggleSubscribed: function()
{
this.unsub = !this.unsub;
$('ctx_folderopts_sub', 'ctx_folderopts_unsub').invoke('toggle');
this._reloadFolders();
},
showUnsub: function()
{
return (!DimpCore.conf.subscribe || ~~(!!this.unsub));
},
_reloadFolders: function()
{
$('foldersLoading').show();
$('foldersSidebar').hide();
this.flist.reload();
this._listMboxes({ reload: 1, mboxes: this.view });
},
_getSelection: function(opts)
{
var vs;
if (opts.vs) {
vs = opts.vs;
} else if (opts.uid) {
vs = this.viewport.createSelection('uid', [ opts.uid ], opts.mailbox ? opts.mailbox : this.view);
} else {
vs = this.viewport.getSelected();
}
return vs;
},
// type = (string) AJAX action type
// opts = (Object) loading, mailbox, uid
// args = (Object) Parameters to pass to AJAX call
_doMsgAction: function(type, opts, args)
{
var vs = this._getSelection(opts);
if (vs.size()) {
// This needs to be synchronous Ajax if we are calling from a
// popup window because Mozilla will not correctly call the
// callback function if the calling window has been closed.
DimpCore.doAction(type, this.addViewportParams(vs).merge(args), {
ajaxopts: { asynchronous: !(opts.uid && opts.mailbox) },
loading: opts,
uids: vs
});
return vs;
}
return false;
},
// spam = (boolean) True for spam, false for innocent
// opts = 'mailbox', 'uid'
reportSpam: function(spam, opts)
{
opts = opts || {};
opts.loading = 'viewport';
opts.vs = this._getSelection(opts);
if (this._doMsgAction('reportSpam', opts, { spam: ~~(!!spam) })) {
this.updateFlag(opts.vs, spam ? DimpCore.conf.FLAG_SPAM : DimpCore.conf.FLAG_INNOCENT, true);
}
},
// blacklist = (boolean) True for blacklist, false for whitelist
// opts = 'mailbox', 'uid'
blacklist: function(blacklist, opts)
{
this._doMsgAction('blacklist', opts || {}, { blacklist: ~~(!!blacklist) });
},
// opts = 'mailbox', 'uid'
deleteMsg: function(opts)
{
opts = opts || {};
opts.vs = this._getSelection(opts);
if (this._doMsgAction('deleteMessages', opts, {})) {
this.updateFlag(opts.vs, DimpCore.conf.FLAG_DELETED, true);
}
},
// flag = (string) IMAP flag name
// add = (boolean) True to add flag
// opts = (Object) 'mailbox', 'params', 'uid'
flag: function(flag, add, opts)
{
opts = opts || {};
var need,
vs = this._getSelection(opts);
need = !vs.getBuffer().getMetaData('readonly') &&
vs.get('dataob').any(function(ob) {
return add
? (!ob.flag || !ob.flag.include(flag))
: (ob.flag && ob.flag.include(flag));
});
if (need) {
DimpCore.doAction('flagMessages', this.addViewportParams(vs).merge(opts.params).merge({
add: ~~(!!add),
flags: Object.toJSON([ flag ])
}), {
uids: vs
});
}
},
updateFlag: function(vs, flag, add)
{
vs.get('dataob').each(function(ob) {
var hasflag;
if (!ob.flag) {
ob.flag = [];
} else {
hasflag = ob.flag.include(flag);
}
if (add && !hasflag) {
ob.flag.push(flag);
this.viewport.updateRow(ob);
} else if (!add && hasflag) {
ob.flag = ob.flag.without(flag);
this.viewport.updateRow(ob);
}
}, this);
},
isDraft: function(vs)
{
var d;
return this.viewport.getMetaData('drafts') ||
((d = vs.get('dataob').first()) &&
d.flag.include(DimpCore.conf.FLAG_DRAFT));
},
/* Miscellaneous mailbox actions. */
purgeDeleted: function()
{
DimpCore.doAction('purgeDeleted', this.addViewportParams());
},
modifyPoll: function(mbox, add)
{
DimpCore.doAction('modifyPoll', {
add: ~~(!!add),
mbox: mbox
}, {
callback: this._modifyPollCallback.bind(this)
});
},
_modifyPollCallback: function(r)
{
this.flist.getMbox(r.mbox).polled(r.add);
if (!r.add) {
this.updateUnseenStatus(r.mbox, 0);
}
},
loadingImg: function(id, show)
{
if (id == 'viewport') {
if (show) {
$('checkmaillink').addClassName('imp-loading');
} else {
$('checkmaillink').removeClassName('imp-loading');
}
return;
}
HordeCore.loadingImg(id + 'Loading', 'previewPane', show);
},
/* AJAX tasks handler. */
tasksHandler: function(e)
{
var t = e.tasks || {};
if (t['imp:flag-config']) {
this.flagConfigCallback(t['imp:flag-config']);
}
if (t['imp:message']) {
this.messageCallback(t['imp:message']);
}
if (this.viewport && t['imp:viewport']) {
t['imp:viewport'].requestid = e.response.request.rid;
this.viewport.parseJSONResponse(t['imp:viewport']);
}
if (t['imp:mailbox']) {
this.mailboxCallback(t['imp:mailbox']);
}
if (t['imp:flag']) {
this.flagCallback(t['imp:flag']);
}
if (t['imp:maillog']) {
this.maillogCallback(t['imp:maillog']);
}
if (t['imp:poll']) {
this.pollCallback(t['imp:poll']);
}
if (t['imp:quota']) {
this.quotaCallback(t['imp:quota']);
}
},
/* Onload function. */
onDomLoad: function()
{
var DM = DimpCore.DMenu, tmp, tmp2;
/* Register global handlers now. */
HordeCore.initHandler('click');
HordeCore.initHandler('dblclick');
/* Initialize variables. */
DimpCore.conf.sort = $H(DimpCore.conf.sort);
this.flist = new IMP_Flist();
/* Limit to folders sidebar only. */
$('foldersSidebar').on('mouseover', '.exp', function(e, elt) {
if (DragDrop.Drags.drag) {
this._toggleSubFolder(elt.up(), 'tog');
}
}.bind(this));
/* Create splitbar for sidebar. */
this.splitbar = $('horde-slideleft');
new Drag(this.splitbar, {
constraint: 'horizontal',
ghosting: true,
nodrop: true
});
/* Show page now. */
$('dimpLoading').hide();
$('horde-page').show();
this.setSidebarWidth();
/* Init quicksearch. These needs to occur before loading the message
* list since it may be disabled if we are in a search mailbox. */
if ($('horde-search')) {
this._setQsearchText();
DimpCore.addContextMenu({
elt: $('horde-search-dropdown'),
left: true,
offset: $$('#horde-search .horde-fake-input')[0],
type: 'qsearchopts'
});
DimpCore.addContextMenu({
elt: $('horde-search-dropdown'),
left: false,
offset: $$('#horde-search .horde-fake-input')[0],
type: 'qsearchopts'
});
DimpCore.addPopdown('button_filter', 'filteropts', {
trigger: true
});
DM.addSubMenu('ctx_filteropts_filter', 'ctx_filter');
DM.addSubMenu('ctx_filteropts_flag', 'ctx_flag_search');
DM.addSubMenu('ctx_filteropts_flagnot', 'ctx_flag_search');
/* Don't submit FORM. Really only needed for Opera (Bug #9730)
* but shouldn't hurt otherwise. */
$('horde-search-input').up('FORM').observe('submit', Event.stop);
}
/* Initialize the starting page. The initial call to viewPort will
* return the mailbox list and pending notifications. */
tmp = decodeURIComponent(location.hash);
if (!tmp.empty() && tmp.startsWith('#')) {
tmp = (tmp.length == 1) ? "" : tmp.substring(1);
}
if (!tmp.empty()) {
tmp2 = tmp.indexOf(':');
if (tmp2 == -1) {
this.go(tmp);
} else {
this.go(tmp.substring(0, tmp2), tmp.substring(tmp2 + 1));
}
} else if (DimpCore.conf.initial_page) {
this.go('mbox', DimpCore.conf.initial_page);
} else {
this.go();
}
/* Add popdown menus. */
DimpCore.addPopdown('button_template', 'template');
DimpCore.addPopdown('button_other', 'oa', {
trigger: true
});
DimpCore.addPopdown('folderopts_link', 'folderopts', {
trigger: true
});
DimpCore.addPopdown('vertical_sort', 'sortopts', {
trigger: true
});
DM.addSubMenu('ctx_message_reply', 'ctx_reply');
DM.addSubMenu('ctx_message_forward', 'ctx_forward');
DM.addSubMenu('ctx_message_setflag', 'ctx_flag');
DM.addSubMenu('ctx_message_unsetflag', 'ctx_flagunset');
DM.addSubMenu('ctx_oa_setflag', 'ctx_flag');
DM.addSubMenu('ctx_oa_unsetflag', 'ctx_flagunset');
DM.addSubMenu('ctx_mbox_setflag', 'ctx_mbox_flag');
DimpCore.addPopdown($('msglistHeaderHoriz').down('.msgSubject').identify(), 'subjectsort', {
insert: 'bottom'
});
DimpCore.addPopdown($('msglistHeaderHoriz').down('.msgDate').identify(), 'datesort', {
insert: 'bottom'
});
DimpCore.addPopdown($('preview_other_opts').down('A'), 'preview', {
trigger: true
});
DimpCore.addContextMenu({
elt: $('preview_other'),
left: true,
offset: $('preview_other').down('SPAN'),
type: 'preview'
});
if (DimpCore.conf.disable_compose) {
$('button_reply', 'button_forward').compact().invoke('up').concat($('button_compose', 'horde-new-link', 'ctx_contacts_new')).compact().invoke('remove');
} else {
DimpCore.addPopdown('button_reply', 'reply');
DimpCore.addPopdown('button_forward', 'forward');
}
if (tmp = this.dropbase()) {
new Drop(tmp, this.mboxDropConfig);
}
// See: http://www.thecssninja.com/javascript/gmail-dragout
$('messageBody').on('dragstart', 'DIV.mimePartInfo A.downloadAtc', this._dragAtc.bind(this));
if (DimpCore.getPref('toggle_hdrs')) {
this._toggleHeaders($('th_expand'));
}
/* Check for new mail. */
this.setPoll();
},
/* Resize function. */
onResize: function()
{
if (this.resize) {
clearTimeout(this.resize);
}
this.resize = this._onResize.bind(this).delay(0.1);
},
_onResize: function()
{
if (!$('dimpLoading').visible()) {
this._sizeFolderlist();
this.splitbar.setStyle({
height: document.viewport.getHeight() + 'px'
});
if ($('dimpmain_iframe').visible()) {
$('dimpmain_iframe').down('IFRAME').setStyle({
height: $('horde-page').getHeight() + 'px'
});
}
}
},
/* AJAX exception handling. */
onAjaxException: function()
{
HordeCore.notify(HordeCore.text.ajax_error, 'horde.error');
},
onAjaxFailure: function(r)
{
if (r.memo[0].request) {
switch (r.memo[0].request.action) {
case 'createMailboxPrepare':
case 'deleteMailboxPrepare':
case 'emptyMailboxPrepare':
case 'mailboxSize':
RedBox.close();
break;
}
}
}
};
var IMP_Flist = Class.create({
initialize: function()
{
this.active = null;
this.mboxes = {};
},
getMbox: function(id)
{
var ob;
if (Object.isUndefined(id)) {
return null;
} else if (Object.isString(id)) {
return this.mboxes[id];
} else if (Object.isElement(id)) {
ob = this.mboxes[id.retrieve('mbox')];
if (ob) {
if (ob.element() == id) {
return ob;
}
ob = ob.fake();
if (ob && ob.element() == id) {
return ob;
}
}
} else if (Object.isFunction(id.value)) {
return id;
} else if (Object.isFunction(id.findElement)) {
return this.getMbox(id.findElement('DIV.horde-subnavi'));
}
return null;
},
// m: (string) Mailbox ID
// opts: (object) [sub]
deleteMbox: function(m, opts)
{
if ((m = this.getMbox(m))) {
m.remove(opts && opts.sub);
delete this.mboxes[m.value()];
}
},
changeMbox: function(ob)
{
if (this.mboxes[ob.m]) {
this.mboxes[ob.m].build(this, ob);
} else {
this.createMbox(ob);
}
},
createMbox: function(ob)
{
var f;
if (!this.mboxes[ob.m]) {
f = new IMP_Flist_Mbox(this, ob);
if (f.element()) {
this.mboxes[ob.m] = f;
}
}
},
// p = (IMP_Flist_Mbox) Parent
// c = (IMP_Flist_Mbox) Child
isSubfolder: function(p, c)
{
var sf = p.subElement();
return sf && c.element().descendantOf(sf);
},
reload: function()
{
Object.values(this.mboxes).each(function(elt) {
this.deleteMbox(elt, { sub: true });
}, this);
},
highlight: function(id)
{
var elt = this.getMbox(id);
if (this.active === elt) {
return;
}
if (this.active) {
this.active.element().removeClassName('horde-subnavi-active');
}
if (elt) {
elt.element().addClassName('horde-subnavi-active');
this.active = elt;
}
},
subElements: function(base)
{
if (base) {
base = this.getMbox(base);
if (base) {
base = base.subElement();
if (base) {
return base.select('DIV.horde-subnavi-sub').compact();
}
}
return [];
}
return Object.values(this.mboxes).invoke('subElement').compact();
}
});
var IMP_Flist_Mbox = Class.create({
// For format of the ob object, see IMP_Queue#_ftreeElt().
// Extra fields: fake, elt, fixed, unseen
initialize: function(flist, ob)
{
this.build(flist, ob);
},
build: function(flist, ob)
{
var div, f_node, ll, parent_c, parent_e, tmp,
cname = 'imp-sidebar-container',
mbox = (!ob.isfake && flist.getMbox(ob.m)),
title = ob.t || ob.l;
if (ob.s) {
/* Create a "fake" container element in normal mailboxes section
* if special mailbox has children. */
if (ob.ch) {
ob.fake = new IMP_Flist_Mbox(flist, Object.extend(Object.clone(ob), {
co: true,
isfake: true,
l: title,
ns: false,
s: false
}));
} else if (mbox && mbox.fake()) {
mbox.fake().remove();
}
}
if (ob.v) {
if (!ob.co) {
cname = 'imp-sidebar-mbox';
}
} else if (ob.r) {
if (ob.r == 2) {
cname = 'imp-sidebar-remote';
}
} else if (ob.co) {
if (ob.n) {
title = ob.l;
}
} else {
cname = 'imp-sidebar-mbox';
}
div = new Element('DIV', { className: 'horde-subnavi-icon' });
if (ob.ch && !ob.s) {
ob.expand = true;
div.addClassName('exp');
} else {
ob.expand = null;
div.addClassName(ob.cl || 'folderImg');
}
if (ob.i) {
div.setStyle({ backgroundImage: 'url("' + ob.i + '")' });
}
ob.elt = new Element('DIV', { className: 'horde-subnavi', title: title })
.addClassName(cname)
.store('mbox', ob.m)
.insert(div)
.insert(new Element('DIV', { className: 'horde-subnavi-point' })
.insert(new Element('A').insert(ob.l)));
if (mbox) {
mbox.element().fire('IMP_Flist_Mbox:delete', mbox);
mbox.element().replace(ob.elt);
} else {
if (ob.s) {
parent_e = $('imp-specialmboxes');
} else if (ob.pa) {
/* Check for existence of parent object. May not exist if,
* e.g., mailbox is created in collapsed subfolder. */
if (!(tmp = flist.getMbox(ob.pa))) {
return;
}
parent_e = tmp.subElement();
}
if (!parent_e) {
parent_e = $('imp-normalmboxes');
}
/* Insert into correct place in level. */
parent_c = parent_e.childElements();
if (!ob.ns) {
ll = ob.l.toLowerCase();
f_node = parent_c.find(function(node) {
var m = flist.getMbox(node);
return (m && !m.fs() && (ll < m.label().toLowerCase()));
});
}
tmp = f_node
? f_node.previous()
: parent_c.last();
if (tmp &&
tmp.hasClassName('horde-subnavi-sub') &&
tmp.retrieve('m') == ob.m) {
tmp.insert({ before: ob.elt });
} else if (f_node) {
f_node.insert({ before: ob.elt });
} else {
parent_e.insert(ob.elt);
}
}
this.data = ob;
if (!ob.s && ob.ch && !this.subElement()) {
ob.elt.insert({
after: new Element('DIV', { className: 'horde-subnavi-sub' }).store('m', ob.m).hide()
});
}
ob.elt.fire('IMP_Flist_Mbox:create', this);
},
remove: function(sub)
{
var smbox;
if (sub && (smbox = this.subElement())) {
smbox.remove();
}
if (this.data.fake) {
this.data.fake.remove(sub);
}
this.data.elt.fire('IMP_Flist_Mbox:delete', this);
this.data.elt.remove();
},
/* Read/write. */
fixed: function(f)
{
if (!Object.isUndefined(f)) {
this.data.fixed = !!f;
}
return this.data.fixed;
},
polled: function(p)
{
if (!Object.isUndefined(p)) {
this.data.po = p;
}
return !!this.data.po;
},
unseen: function(u)
{
if (!Object.isUndefined(u)) {
this.data.unseen = u;
}
return ~~this.data.unseen;
},
expand: function(e)
{
var elt;
if (this.data.fake) {
return this.data.fake.expand(e);
} else if (!Object.isUndefined(e)) {
elt = this.iconElement();
[ 'col', 'exp', 'folderImg' ].each(elt.removeClassName.bind(elt));
if (e === null) {
elt.addClassName('folderImg');
} else {
e = !!e;
[ elt ].invoke('addClassName', e ? 'exp' : 'col');
if (!e) {
this.data.load = true;
}
}
this.data.expand = e;
}
return this.data.expand;
},
/* Read-only. */
element: function()
{
return this.data.elt;
},
labelElement: function()
{
return this.data.elt.down('A');
},
subElement: function()
{
var m_elt;
if (this.data && this.data.fake && this.data.fake.data) {
return this.data.fake.subElement();
}
m_elt = this.data.elt.next();
return (m_elt && m_elt.hasClassName('horde-subnavi-sub'))
? m_elt
: null;
},
hasChildren: function()
{
var sub = this.subElement();
return (sub && sub.childElements().size());
},
parentElement: function()
{
var elt = this.data.elt.up('DIV.horde-subnavi-sub');
return elt ? elt.previous() : null;
},
iconElement: function()
{
return this.data.elt.down('DIV.horde-subnavi-icon');
},
value: function()
{
return this.data.m;
},
fake: function()
{
return this.data.fake;
},
isContainer: function()
{
return this.data.elt.hasClassName('imp-sidebar-container');
},
isMbox: function()
{
return this.data.elt.hasClassName('imp-sidebar-mbox');
},
ftype: function()
{
if (this.data.v) {
return this.data.co ? 'vcontainer' : 'vfolder';
} else if (this.data.r) {
switch (this.data.r) {
case 1:
return 'rcontainer';
case 2:
return 'remote';
case 3:
return 'remoteauth';
}
} else if (this.data.co) {
return this.data.n ? 'scontainer' : 'container';
} else if (this.data.s) {
return 'special';
}
return 'mbox';
},
loaded: function()
{
return !!this.data.load;
},
nc: function()
{
return !!this.data.nc;
},
label: function()
{
return this.data.l;
},
fs: function()
{
return !!this.data.fs;
},
virtual: function()
{
return !!(~~this.data.v);
},
unsubscribed: function()
{
return !!this.data.un;
},
fullMboxDisplay: function()
{
return this.data.elt.readAttribute('title').escapeHTML();
}
});
/* Initialize onload handler. */
document.observe('dom:loaded', function() {
if (Prototype.Browser.IE && !document.addEventListener) {
// For IE 8
DimpBase.onDomLoad.bind(DimpBase).delay(0.1);
} else {
DimpBase.onDomLoad();
}
});
/* Basic event handlers. */
document.observe('keydown', DimpBase.keydownHandler.bindAsEventListener(DimpBase));
Event.observe(window, 'resize', DimpBase.onResize.bind(DimpBase));
/* Drag/drop listeners. */
document.observe('DragDrop2:start', DimpBase.onDragStart.bindAsEventListener(DimpBase));
document.observe('DragDrop2:drop', DimpBase.mboxDropHandler.bindAsEventListener(DimpBase));
document.observe('DragDrop2:end', DimpBase.onDragEnd.bindAsEventListener(DimpBase));
document.observe('DragDrop2:mousedown', DimpBase.onDragMouseDown.bindAsEventListener(DimpBase));
document.observe('DragDrop2:mouseup', DimpBase.onDragMouseUp.bindAsEventListener(DimpBase));
/* HordeDialog listener. */
document.observe('HordeDialog:onClick', DimpBase.dialogClickHandler.bindAsEventListener(DimpBase));
document.observe('HordeDialog:close', DimpBase.dialogCloseHandler.bind(DimpBase));
/* AJAX related events. */
document.observe('HordeCore:ajaxException', DimpBase.onAjaxException.bind(DimpBase));
document.observe('HordeCore:ajaxFailure', DimpBase.onAjaxFailure.bind(DimpBase));
document.observe('HordeCore:runTasks', function(e) {
DimpBase.tasksHandler(e.memo);
});
/* Click handlers. */
document.observe('HordeCore:click', DimpBase.clickHandler.bindAsEventListener(DimpBase));
document.observe('HordeCore:dblclick', DimpBase.dblclickHandler.bindAsEventListener(DimpBase));
/* AJAX loading handlers. */
document.observe('HordeCore:loadingStart', DimpBase.loadingStartHandler.bindAsEventListener(DimpBase));
document.observe('HordeCore:loadingEnd', DimpBase.loadingEndHandler.bindAsEventListener(DimpBase));
/* ContextSensitive handlers. */
document.observe('ContextSensitive:click', DimpBase.contextOnClick.bindAsEventListener(DimpBase));
document.observe('ContextSensitive:show', DimpBase.contextOnShow.bindAsEventListener(DimpBase));
document.observe('ContextSensitive:trigger', DimpBase.contextOnTrigger.bindAsEventListener(DimpBase));
/* Search handlers. */
document.observe('FormGhost:reset', DimpBase.searchReset.bindAsEventListener(DimpBase));
document.observe('FormGhost:submit', DimpBase.searchSubmit.bindAsEventListener(DimpBase));
/* DimpBase handlers. */
document.observe('DimpBase:removeElt', DimpBase.removeEltHandler.bindAsEventListener(DimpBase));
/* DimpCore handlers. */
document.observe('DimpCore:updateAddressHeader', DimpBase.updateAddressHeader.bindAsEventListener(DimpBase));
/* Folder list element handlers. */
document.observe('IMP_Flist_Mbox:create', DimpBase.createMboxHandler.bind(DimpBase));
document.observe('IMP_Flist_Mbox:delete', function(e) {
e.memo.element().fire('DimpBase:removeElt');
});
/* HTML IFRAME handlers. */
document.observe('IMP_JS:htmliframe_keydown', function(e) {
DimpBase.keydownHandler(e.memo);
});
/* Define reloadMessage() method for this page. */
DimpCore.reloadMessage = function(params) {
DimpBase.loadPreview(null, params);
};