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

1574 lines
45 KiB
JavaScript

/**
* Dynamic compose view.
*
* @author Michael Slusarz <slusarz@horde.org>
* @copyright 2005-2015 Horde LLC
* @license GPL-2 (http://www.horde.org/licenses/gpl)
*/
var DimpCompose = {
// Variables defaulting to empty/false:
// atc_context, auto_save_interval, compose_cursor, disabled,
// drafts_mbox, fwdattach, hash_hdrs, hash_msg,
// hash_msgOrig, hash_sig, hash_sigOrig, knl, last_identity,
// onload_show, old_action, old_identity, sc_submit,
// skip_spellcheck, spellcheck, tasks, upload_limit
ajax_atc_id: 0,
checkbox_context: $H({
ctx_atc: $H({
pgppubkey: 'pgp_attach_pubkey',
save: 'save_attachments_select',
vcard: 'vcard_attach'
}),
ctx_other: $H({
rr: 'request_read_receipt'
})
}),
knl: {},
getCacheElt: function()
{
var r = $('redirect');
return (r && r.visible())
? $('composeCacheRedirect')
: $('composeCache');
},
actionParams: function(p)
{
p.imp_compose = $F(this.getCacheElt());
return p;
},
confirmCancel: function(discard)
{
var base;
if (window.confirm(DimpCore.text.compose_cancel)) {
if (!DimpCore.conf.qreply &&
(base = DimpCore.baseAvailable())) {
base.focus();
}
DimpCore.doAction('cancelCompose', this.actionParams({
discard: ~~(!!discard)
}));
this.updateDraftsMailbox();
return this.closeCompose();
}
},
updateDraftsMailbox: function()
{
var base;
if ((base = DimpCore.baseAvailable()) &&
base.DimpBase.view == DimpCore.conf.drafts_mbox) {
base.DimpBase.poll();
}
},
closeCompose: function()
{
if (DimpCore.conf.qreply) {
this.closeQReply();
} else if (HordeCore.baseWindow() != window) {
// We are only checking whether window.close can be done, not the
// current status of the opening window.
window.close();
} else {
// Sanity checking: if popup cannot be manually closed, output
// information message without allowing further actions on the
// page.
$$('body')[0].update(DimpCore.text.compose_close);
}
},
closeQReply: function()
{
this.hash_hdrs = this.hash_msg = this.hash_msgOrig = this.hash_sig = this.hash_sigOrig = '';
this.upload_limit = false;
$('attach_list').hide().childElements().each(this.removeAttachRow.bind(this));
this.getCacheElt().clear();
$('qreply', 'sendcc', 'sendbcc').compact().invoke('hide');
$('noticerow').down('UL.notices').childElements().invoke('hide');
$('msgData', 'togglecc', 'togglebcc').compact().invoke('show');
if (ImpComposeBase.editor_on) {
this.toggleHtmlEditor();
}
$('compose').reset();
this.setDisabled(false);
// Disable auto-save-drafts now.
if (this.auto_save_interval) {
this.auto_save_interval.stop();
}
},
changeIdentity: function()
{
if (!Object.isUndefined(this.hash_sigOrig) &&
this.hash_sigOrig != this.sigHash() &&
!window.confirm(DimpCore.text.change_identity)) {
return false;
}
var identity = ImpComposeBase.identities[$F('identity')];
this.setPopdownLabel(
'sm',
identity.sm_name,
identity.sm_display,
identity.sm_title,
{
opts: {
input: 'save_sent_mail_mbox',
label: 'sent_mail_label'
}
}
);
if (identity.bcc) {
$('bcc').setValue(($F('bcc') ? $F('bcc') + ', ' : '') + identity.bcc)
.fire('AutoComplete:reset');
this.toggleCC('bcc');
}
this.setSaveSentMail(identity.sm_save);
this.setSignature(ImpComposeBase.editor_on, identity);
this.last_identity = $F('identity');
return true;
},
setSignature: function(rte, identity)
{
ImpComposeBase.setSignature(rte, identity);
this.setSignatureHash();
},
setSignatureHash: function()
{
if (ImpComposeBase.rte_sig && ImpComposeBase.rte_sig.busy()) {
this.setSignatureHash.bind(this).delay(0.1);
} else {
this.hash_sigOrig = this.sigHash();
}
},
setSaveSentMail: function(set)
{
var ssm = $('save_sent_mail');
if (ssm) {
ssm.setValue(set);
}
},
createPopdown: function(id, opts)
{
this.knl[id] = {
knl: new KeyNavList(opts.base, {
esc: true,
list: opts.data,
onChoose: this.setPopdownLabel.bind(this, id)
}),
opts: opts
};
$(opts.label).insert({ after:
new Element('SPAN', { className: 'iconImg horde-popdown' }).store('popdown_id', id)
});
},
setPopdownLabel: function(id, s, l, t, k)
{
var input;
if (!k) {
k = this.knl[id];
if (!k) {
return;
}
}
input = $(k.opts.input);
if (!input) {
return;
}
if (!l) {
l = (k.opts.data || []).find(function(f) {
return f.v == s;
});
if (!l) {
return;
}
l = (id == 'sm')
? (l.f || l.v)
: l.l;
}
input.setValue(s);
$(k.opts.label).writeAttribute('title', t).setText(l.truncate(15)).up(1).show();
if (k.knl) {
k.knl.setSelected(s);
}
},
retrySubmit: function(action)
{
if (this.old_action) {
this.uniqueSubmit(this.old_action);
delete this.old_action;
}
},
uniqueSubmit: function(action)
{
var c = (action == 'redirectMessage') ? $('redirect') : $('compose'),
sc = ImpComposeBase.getSpellChecker();
if (sc && sc.isActive()) {
sc.resume();
this.skip_spellcheck = true;
}
if (this.rte && this.rte.busy()) {
return this.uniqueSubmit.bind(this, action).delay(0.1);
}
switch (action) {
case 'sendMessage':
if (!this.skip_spellcheck &&
DimpCore.conf.spellcheck &&
sc &&
!sc.isActive()) {
this.sc_submit = action;
sc.spellCheck();
return;
}
if ($F('subject').empty() &&
!window.confirm(DimpCore.text.nosubject)) {
return;
}
// Fall-through
case 'saveDraft':
case 'saveTemplate':
// Don't send/save until uploading is completed.
if ($('upload_wait') && $('upload_wait').visible()) {
(function() { if (this.disabled) { this.uniqueSubmit(action); } }).bind(this).delay(0.25);
return;
}
// Fall-through
case 'redirectMessage':
$(document).fire('AutoComplete:update');
break;
}
this.skip_spellcheck = false;
if (action == 'addAttachment') {
// We need a submit action here because browser security models
// won't let us access files on user's filesystem otherwise.
HordeCore.submit(c);
} else {
// Move HTML text to textarea field for submission.
if (ImpComposeBase.editor_on) {
this.rte.updateElement();
if (ImpComposeBase.rte_sig) {
ImpComposeBase.rte_sig.updateElement();
}
}
DimpCore.doAction(
action,
ImpComposeBase.sendParams(c.serialize(true), action == 'sendMessage'),
{ callback: this.uniqueSubmitCallback.bind(this) }
);
// Can't disable until we send the message - or else nothing
// will get POST'ed.
if (action != 'autoSaveDraft') {
this.setDisabled(true);
}
}
},
uniqueSubmitCallback: function(d)
{
var base;
if (d.success || d.action == 'addAttachment') {
switch (d.action) {
case 'autoSaveDraft':
case 'saveDraft':
this.updateDraftsMailbox();
if (d.action == 'saveDraft') {
if (!DimpCore.conf.qreply &&
(base = DimpCore.baseAvailable())) {
HordeCore.notify_handler = base.HordeCore.showNotifications.bind(base.HordeCore);
}
if (DimpCore.conf.close_draft) {
$('attach_list').childElements().invoke('remove');
return this.closeCompose();
}
}
break;
case 'saveTemplate':
if ((base = DimpCore.baseAvailable()) &&
base.DimpBase.view == DimpCore.conf.templates_mbox) {
base.DimpBase.poll();
}
return this.closeCompose();
case 'sendMessage':
if ((base = DimpCore.baseAvailable())) {
if (d.draft_delete) {
base.DimpBase.poll();
}
if (!DimpCore.conf.qreply) {
HordeCore.notify_handler = base.HordeCore.showNotifications.bind(base.HordeCore);
}
}
$('attach_list').childElements().invoke('remove');
return this.closeCompose();
case 'redirectMessage':
if (!DimpCore.conf.qreply &&
(base = DimpCore.baseAvailable())) {
HordeCore.notify_handler = base.HordeCore.showNotifications.bind(base.HordeCore);
}
return this.closeCompose();
case 'addAttachment':
this.addAttachmentEnd();
break;
}
} else {
if (!Object.isUndefined(d.identity)) {
this.old_identity = $F('identity');
$('identity').setValue(d.identity);
this.changeIdentity();
$('noticerow', 'identitychecknotice').invoke('show');
this.resizeMsgArea();
}
if (!Object.isUndefined(d.encryptjs)) {
this.old_action = d.action;
eval(d.encryptjs.join(';'));
}
}
this.setDisabled(false);
},
setDisabled: function(disable)
{
var redirect = $('redirect'), sc;
this.disabled = disable;
if (redirect && redirect.visible()) {
HordeCore.loadingImg('sendingImg', 'redirect', disable);
DimpCore.toggleButtons(redirect.select('DIV.dimpActions A'), disable);
redirect.setStyle({ cursor: disable ? 'wait': null });
} else {
HordeCore.loadingImg('sendingImg', 'composeMessageParent', disable);
DimpCore.toggleButtons($('compose').select('DIV.dimpActions A'), disable);
[ $('compose') ].invoke(disable ? 'disable' : 'enable');
if ((sc = ImpComposeBase.getSpellChecker())) {
sc.disable(disable);
}
if (ImpComposeBase.editor_on) {
this.RTELoading(disable, true);
}
$('compose').setStyle({ cursor: disable ? 'wait' : null });
}
},
toggleHtmlEditor: function(noupdate)
{
var action, changed, sc, tmp,
active = ImpComposeBase.editor_on,
params = $H();
if (!DimpCore.conf.rte_avail) {
return;
}
noupdate = noupdate || false;
if ((sc = ImpComposeBase.getSpellChecker()) && sc.isActive()) {
sc.resume();
}
this.RTELoading(true);
if (this.rte && this.rte.busy()) {
return this.toggleHtmlEditor.bind(this, noupdate).delay(0.1);
}
if (active) {
action = 'html2Text',
changed = ~~(this.msgHash() != this.hash_msgOrig);
params.set('body', {
changed: changed,
text: this.rte.getData()
});
if ($('signature') && (this.sigHash() != this.hash_sigOrig)) {
params.set('sig', {
changed: 1,
text: ImpComposeBase.rte_sig.getData()
});
}
} else if (!noupdate) {
action = 'text2Html';
tmp = $F('composeMessage');
if (!tmp.blank()) {
changed = ~~(this.msgHash() != this.hash_msgOrig);
params.set('body', {
changed: changed,
text: tmp
});
}
if ($('signature')) {
tmp = $F('signature');
if (!tmp.blank() && (this.sigHash() != this.hash_sigOrig)) {
params.set('sig', {
changed: 1,
text: tmp
});
}
}
}
if (params.size()) {
DimpCore.doAction(action, this.actionParams({
data: Object.toJSON(params)
}), {
ajaxopts: { asynchronous: false },
callback: this.setMessageText.bind(this, {
changed: changed,
rte: !active
})
});
} else {
this.rteInit(!active);
this.setSignature(!active, ImpComposeBase.identities[$F('identity')]);
}
},
RTELoading: function(show, notxt)
{
var o;
if (!$('rteloading')) {
$(document.body).insert(
new Element('DIV', { id: 'rteloading' }).hide()
).insert(
new Element('SPAN', { id: 'rteloadingtxt' }).hide().insert(DimpCore.text.loading)
);
}
if (show) {
$('rteloading').clonePosition('composeMessageParent').show();
if (!notxt) {
o = $('rteloading').viewportOffset();
$('rteloadingtxt').setStyle({ top: (o.top + 15) + 'px', left: (o.left + 15) + 'px' }).show();
}
} else {
$('rteloading', 'rteloadingtxt').invoke('hide');
}
},
_onSpellCheckAfter: function()
{
if (ImpComposeBase.editor_on) {
this.setBodyText({ body: $F('composeMessage') });
$('composeMessage').next().show();
this.RTELoading(false);
}
this.sc_submit = false;
},
_onSpellCheckBefore: function()
{
ImpComposeBase.getSpellChecker().htmlAreaParent = ImpComposeBase.editor_on
? 'composeMessageParent'
: null;
if (ImpComposeBase.editor_on) {
this.rte.updateElement();
this.RTELoading(true, true);
$('composeMessage').next().hide();
}
},
_onSpellCheckError: function()
{
if (ImpComposeBase.editor_on) {
this.RTELoading(false);
}
},
_onSpellCheckNoError: function()
{
if (this.sc_submit) {
this.skip_spellcheck = true;
this.uniqueSubmit(this.sc_submit);
} else {
HordeCore.notify(DimpCore.text.spell_noerror, 'horde.message');
this._onSpellCheckAfter();
}
},
setMessageText: function(opts, r)
{
var ta = $('composeMessage');
if (!ta) {
$('composeMessageParent').insert(
new Element('TEXTAREA', {
id: 'composeMessage',
name: 'message',
style: 'width:100%'
})
);
}
this.rteInit(opts.rte);
if (this.rte && opts.rte) {
if (this.rte.busy()) {
this.setMessageText.bind(this, opts, r).delay(0.1);
return;
}
this.rte.setData(r.text.body);
} else {
ta.setValue(r.text.body);
}
this.RTELoading(false);
this.setSignature(opts.rte, r.text.sig ? r.text.sig : ImpComposeBase.identities[$F('identity')]);
this.resizeMsgArea();
if (!opts.changed) {
delete this.hash_msgOrig;
}
this.fillFormHash();
},
rteInit: function(rte)
{
var config;
if (rte && !this.rte) {
config = Object.clone(IMP.ckeditor_config);
config.extraPlugins = 'pasteattachment';
this.rte = new IMP_Editor('composeMessage', config);
this.rte.editor.on('getData', function(evt) {
var elt = new Element('SPAN'), elts;
/* Don't use prototype's insert() since we don't want any
* scripts that may exist in the text data to be eval'd. */
elt.innerHTML = evt.data.dataValue;
elts = elt.select('IMG[dropatc_id]');
if (elts.size()) {
elts.invoke('writeAttribute', 'dropatc_id', null);
elts.invoke('writeAttribute', 'src', null);
evt.data.dataValue = elt.innerHTML;
}
});
} else if (!rte && this.rte) {
this.rte.destroy();
delete this.rte;
}
ImpComposeBase.editor_on = rte;
$('htmlcheckbox').setValue(rte);
$('html').setValue(~~rte);
},
// ob = addr, body, format, identity, opts, subject, type
// ob.opts = auto, focus, fwd_list, noupdate, priority, readreceipt,
// reply_lang, reply_recip, reply_list_id, show_editor
fillForm: function(ob)
{
if (!document.loaded || $('dimpLoading').visible()) {
this.fillForm.bind(this, ob).delay(0.1);
return;
}
switch (ob.type) {
case 'forward_redirect':
return;
}
ob.opts = ob.opts || {};
if (ob.addr) {
$('to').setValue(ob.addr.to.join(', '))
.fire('AutoComplete:reset');
if (ob.addr.cc.size()) {
this.toggleCC('cc');
$('cc').setValue(ob.addr.cc.join(', '))
.fire('AutoComplete:reset');
}
if (ob.addr.bcc.size()) {
this.toggleCC('bcc');
$('bcc').setValue(ob.addr.bcc.join(', '))
.fire('AutoComplete:reset');
}
}
$('identity').setValue(ob.identity);
this.changeIdentity();
$('subject').setValue(ob.subject);
if (DimpCore.conf.priority && ob.opts.priority) {
this.setPopdownLabel('p', ob.opts.priority);
}
if (ob.opts.readreceipt && $('request_read_receipt')) {
$('request_read_receipt').setValue(true);
}
switch (ob.opts.auto) {
case 'forward_attach':
$('noticerow', 'fwdattachnotice').invoke('show');
this.fwdattach = true;
break;
case 'forward_body':
$('noticerow', 'fwdbodynotice').invoke('show');
break;
case 'reply_all':
$('replyallnotice').down('SPAN.replyAllNoticeCount').setText(DimpCore.text.replyall.sub('%d', ob.opts.reply_recip));
$('noticerow', 'replyallnotice').invoke('show');
break;
case 'reply_list':
$('replylistnotice').down('SPAN.replyListNoticeId').setText(ob.opts.reply_list_id ? (' (' + ob.opts.reply_list_id + ')') : '');
$('noticerow', 'replylistnotice').invoke('show');
break;
}
if (ob.opts.reply_lang) {
$('langnotice').down('SPAN.langNoticeList').setText(ob.opts.reply_lang.join(', '));
$('noticerow', 'langnotice').invoke('show');
}
this.setBodyText(ob);
this.resizeMsgArea();
ImpComposeBase.focus(ob.opts.focus || 'to');
this.fillFormHash();
},
fillFormHash: function()
{
if (this.rte && this.rte.busy()) {
this.fillFormHash.bind(this).delay(0.1);
return;
}
// This value is used to determine if the text has changed when
// swapping compose modes.
if (!this.hash_msgOrig) {
this.hash_msgOrig = this.msgHash();
}
// Set auto-save-drafts now if not already active. Only need if
// compose template is output on current page (redirect doesn't
// need autosave).
if (DimpCore.conf.auto_save_interval_val &&
!this.auto_save_interval &&
$('compose')) {
this.auto_save_interval = new PeriodicalExecuter(
this.autoSaveDraft.bind(this),
DimpCore.conf.auto_save_interval_val * 60
);
/* Immediately execute to get hash of headers. */
this.auto_save_interval.execute();
}
},
autoSaveDraft: function()
{
var hdrs, msg, sig;
if (!$('compose').visible()) {
return;
}
hdrs = IMP_JS.fnv_1a(
[$('to', 'cc', 'bcc', 'subject').compact().invoke('getValue'),
$('attach_list').select('SPAN.attachName').pluck('textContent')
].flatten().join('\0')
);
if (Object.isUndefined(this.hash_hdrs)) {
msg = this.hash_msgOrig;
sig = this.hash_sigOrig;
} else {
msg = this.msgHash();
sig = this.sigHash();
if (this.hash_hdrs != hdrs ||
this.hash_msg != msg ||
this.hash_sig != sig) {
this.uniqueSubmit('autoSaveDraft');
}
}
this.hash_hdrs = hdrs;
this.hash_msg = msg;
this.hash_sig = sig;
},
msgHash: function()
{
return IMP_JS.fnv_1a(
ImpComposeBase.editor_on ? this.rte.getData() : $F('composeMessage')
);
},
sigHash: function()
{
return $('signature')
? IMP_JS.fnv_1a(ImpComposeBase.rte_sig ? ImpComposeBase.rte_sig.getData() : $F('signature'))
: 0;
},
fadeNotice: function(elt)
{
elt = $(elt);
elt.fade({
afterFinish: function() {
if (!elt.siblings().any(Element.visible)) {
elt.up('TR').hide();
this.resizeMsgArea();
}
}.bind(this),
duration: 0.4
});
},
setBodyText: function(ob)
{
if (this.rte) {
this.rte.setData(ob.body);
} else {
$('composeMessage').setValue(ob.body);
ImpComposeBase.setCursorPosition('composeMessage', DimpCore.conf.compose_cursor);
}
if (ob.format == 'html') {
if (!ImpComposeBase.editor_on) {
this.toggleHtmlEditor(true);
}
if (ob.opts &&
ob.opts.focus &&
(ob.opts.focus == 'composeMessage')) {
this.rte.focus();
}
}
},
swapToAddressCallback: function(r)
{
if (r.addr) {
$('to').setValue(r.addr.to.join(', '))
.fire('AutoComplete:reset');
[ 'cc', 'bcc' ].each(function(t) {
if (r.addr[t].size() || $('send' + t).visible()) {
if (!$('send' + t).visible()) {
this.toggleCC(t);
}
$(t).setValue(r.addr[t].join(', '))
.fire('AutoComplete:reset');
}
}, this);
}
$('to_loading_img').hide();
},
// opts = (Object)
// icon: (string) Data url of icon data
// name: (string) Attachment name
// num: (integer) Attachment number
// size: (string) Size.
// type: (string) MIME type
// url: (string) Data view URL
// view: (boolean) Link to attachment preview page
addAttach: function(opts)
{
var canvas, img,
li = new Element('LI')
.store('atc_id', opts.num)
.store('atc_url', opts.url),
span = new Element('SPAN')
.addClassName(opts.view ? 'attachName' : 'attachNameNoview')
.insert(opts.name.escapeHTML());
if (opts.icon) {
canvas = new Element('CANVAS', { height: '16px', width: '16px' });
// IE8 doesn't support canvas
if (canvas.getContext) {
li.insert(canvas);
img = new Image();
img.onload = function() {
canvas.getContext('2d').drawImage(img, 0, 0, 16, 16);
};
img.src = opts.icon;
}
}
li.insert(span);
canvas.writeAttribute('title', opts.type);
li.insert(
new Element('SPAN')
.addClassName('attachSize')
.insert('(' + opts.size + ')')
);
$('attach_list').insert(li).show();
DimpCore.addPopdown(li.down(':last'), 'atcfile', {
no_offset: true
});
this.resizeMsgArea();
},
getAttach: function(id)
{
return $('attach_list').childElements().detect(function(e) {
return e.retrieve('atc_id') == id;
});
},
removeAttach: function(elt)
{
DimpCore.doAction('deleteAttach', this.actionParams({
atc_indices: Object.toJSON([ elt.retrieve('atc_id') ])
}), {
callback: this.removeAttachCallback.bind(this)
});
},
removeAttachCallback: function(r)
{
r.collect(this.getAttach.bind(this)).compact().each(function(elt) {
elt.fade({
afterFinish: function() {
this.removeAttachRow(elt);
this.initAttachList();
$('upload').value = '';
$('upload').removeAttribute('value');
$('upload').replace($('upload').cloneNode(true));
}.bind(this),
duration: 0.4
});
}, this);
},
removeAttachRow: function(elt)
{
DimpCore.DMenu.removeElement(elt.down('.horde-popdown').identify());
elt.remove();
},
initAttachList: function()
{
var al = $('attach_list'),
u = $('upload');
if (this.upload_limit) {
$('upload_limit').show();
u.up().hide();
} else {
$('upload_limit').hide();
u.up().show();
}
if (!al.childElements().size()) {
al.hide();
}
this.resizeMsgArea();
},
addAttachmentEnd: function()
{
var u = $('upload_wait');
if (u && u.visible()) {
u.hide();
this.initAttachList();
}
},
resizeMsgArea: function(e)
{
if (!document.loaded || $('dimpLoading').visible()) {
return;
}
// IE 7/8 Bug - can't resize TEXTAREA in the resize event (Bug #10075)
if (e && Prototype.Browser.IE && !document.addEventListener) {
this.resizeMsgArea.bind(this).delay(0.1);
return;
}
var mah,
cmp = $('composeMessageParent'),
sp = $('signatureParent'),
qreply = $('qreply');
if (!cmp || (qreply && !qreply.visible())) {
return;
}
cmp = cmp.getLayout();
try {
mah = document.viewport.getHeight() - cmp.get('top') - cmp.get('margin-box-height') + cmp.get('height');
} catch (ex) {
return;
}
if (sp) {
mah -= sp.getHeight();
}
if (this.rte) {
this.rte.resize('99%', mah - 1);
}
$('composeMessage').setStyle({ height: mah + 'px' });
if ($('rteloading') && $('rteloading').visible()) {
this.RTELoading(true);
}
},
uploadAttachmentWait: function(f)
{
var t;
$('upload').up().hide();
if (Object.isElement(f)) {
if (f.files) {
f = f.files;
} else {
t = $F(f).escapeHTML();
f = null;
}
}
if (f) {
t = (f.length > 1)
? DimpCore.text.multiple_atc.sub('%d', f.length)
: f[0].name.escapeHTML();
}
$('upload_wait').update(DimpCore.text.uploading + ' (' + t + ')')
.show();
},
uploadAttachmentAjax: function(data, params, callback)
{
var out = $H();
params = $H(params).update({
composeCache: $F(this.getCacheElt()),
json_return: 1
});
HordeCore.addRequestParams(params);
this.uploadAttachmentWait(data);
$A($R(0, data.length - 1)).each(function(i) {
var fd = new FormData();
params.merge({
file_id: ++this.ajax_atc_id,
file_upload: data[i]
}).each(function(p) {
fd.append(p.key, p.value);
});
HordeCore.doAction('addAttachment', {}, {
ajaxopts: {
postBody: fd,
requestHeaders: { "Content-type": null }
},
callback: function(r) {
if (callback) {
callback(r);
}
this.addAttachmentEnd();
}.bind(this)
});
out.set(this.ajax_atc_id, data[i]);
}, this);
return out;
},
toggleCC: function(type)
{
var t = $('toggle' + type),
s = t.siblings().first();
$('send' + type).show();
if (s && s.visible()) {
t.hide();
} else {
t.up('TR').hide();
}
this.resizeMsgArea();
ImpComposeBase.focus(type);
},
sentMailListCallback: function(r)
{
$('save_sent_mail_load').remove();
this.createPopdown('sm', {
base: 'save_sent_mail',
data: r.flist,
input: 'save_sent_mail_mbox',
label: 'sent_mail_label'
});
this.knl.sm.knl.setSelected($F('save_sent_mail_mbox'));
this.knl.sm.knl.show();
},
/* Open the addressbook window. */
openAddressbook: function(params)
{
var uri = DimpCore.conf.URI_ABOOK;
if (params) {
uri = HordeCore.addURLParam(uri, params);
}
window.open(uri, 'contacts', 'toolbar=no,location=no,status=no,scrollbars=yes,resizable=yes,width=800,height=350,left=100,top=100');
},
/* Click observe handler. */
clickHandler: function(e)
{
var elt = e.memo.element(), tmp;
/* Needed because reply/forward buttons need to be of type="submit"
* for FF to correctly size. */
if ((elt.readAttribute('type') == 'submit') &&
(elt.descendantOf('compose') || elt.descendantOf('redirect'))) {
e.memo.hordecore_stop = true;
return;
}
switch (e.element().readAttribute('id')) {
case 'togglebcc':
this.toggleCC('bcc');
this.resizeMsgArea();
break;
case 'togglecc':
this.toggleCC('cc');
this.resizeMsgArea();
break;
case 'signatureToggle':
if ($('signatureBorder').visible()) {
$('signatureToggle').removeClassName('signatureExpanded');
$('signatureBorder').hide();
HordeCore.doAction('setPrefValue', {
pref: 'signature_expanded',
value: 0
});
} else {
$('signatureToggle').addClassName('signatureExpanded');
$('signatureBorder').show();
HordeCore.doAction('setPrefValue', {
pref: 'signature_expanded',
value: 1
});
}
this.resizeMsgArea();
break;
case 'compose_close':
case 'redirect_close':
this.confirmCancel();
break;
case 'discard_button':
this.confirmCancel(true);
break;
case 'draft_button':
if (!this.disabled) {
this.uniqueSubmit('saveDraft');
}
break;
case 'template_button':
if (!this.disabled) {
this.uniqueSubmit('saveTemplate');
}
break;
case 'send_button':
if (!this.disabled) {
this.uniqueSubmit('sendMessage');
}
break;
case 'send_button_redirect':
if (!this.disabled) {
this.uniqueSubmit('redirectMessage');
}
break;
case 'htmlcheckbox':
e.memo.stop();
break;
case 'redirect_sendto':
if (elt.match('TD.label SPAN')) {
this.openAddressbook({
to_only: 1
});
}
break;
case 'sendcc':
case 'sendbcc':
case 'sendto':
if (DimpCore.conf.URI_ABOOK && elt.match('TD.label SPAN')) {
this.openAddressbook();
}
break;
case 'attach_list':
if (elt.match('SPAN.attachName')) {
HordeCore.popupWindow(elt.up('LI').retrieve('atc_url'));
}
break;
case 'save_sent_mail':
this.setSaveSentMail($F(e.element()));
break;
case 'compose_upload_add':
// This is no longer needed as of Firefox 22.
if (Prototype.Browser.Gecko && Object.isUndefined(Object.is)) {
$('upload').click();
}
break;
case 'fwdattachnotice':
this.fadeNotice(e.element());
DimpCore.doAction('getForwardData', this.actionParams({
dataonly: 1,
type: 'forward_body'
}), {
callback: this.setBodyText.bind(this)
});
this.fwdattach = false;
e.memo.stop();
break;
case 'fwdbodynotice':
this.fadeNotice(e.element());
DimpCore.doAction('getForwardData', this.actionParams({
dataonly: 1,
type: 'forward_attach'
}));
this.fwdattach = false;
e.memo.stop();
break;
case 'identitychecknotice':
this.fadeNotice(e.element());
$('identity').setValue(this.old_identity);
this.changeIdentity();
e.memo.stop();
break;
case 'replyall_revert':
case 'replylist_revert':
this.fadeNotice(e.element().up('LI'));
$('to_loading_img').show();
DimpCore.doAction('getReplyData', this.actionParams({
headeronly: 1,
type: 'reply'
}), {
callback: this.swapToAddressCallback.bind(this)
});
e.memo.stop();
break;
case 'writemsg':
if (!this.disabled && elt.hasClassName('horde-popdown')) {
tmp = elt.retrieve('popdown_id');
if (tmp && this.knl[tmp]) {
this.knl[tmp].knl.show();
this.knl[tmp].knl.ignoreClick(e.memo);
e.memo.stop();
}
}
break;
case 'save_sent_mail_load':
DimpCore.doAction('sentMailList', {}, {
callback: this.sentMailListCallback.bind(this)
});
break;
}
},
keydownHandler: function(e, fade)
{
switch (e.keyCode || e.charCode) {
case Event.KEY_ESC:
this.confirmCancel();
break;
case Event.KEY_RETURN:
if (!this.disabled && e.ctrlKey) {
this.uniqueSubmit('sendMessage');
}
break;
}
if (this.fwdattach &&
(fade || e.element() == $('composeMessage'))) {
this.fadeNotice('fwdattachnotice');
}
},
changeHandler: function(e)
{
switch (e.element().readAttribute('id')) {
case 'identity':
if (!this.changeIdentity()) {
$('identity').setValue(this.last_identity);
}
break;
case 'upload':
this.uniqueSubmit('addAttachment');
this.uploadAttachmentWait($('upload'));
break;
}
},
contextOnClick: function(e)
{
var id = e.memo.elt.identify();
switch (id) {
case 'ctx_atcfile_delete':
this.removeAttach(this.atc_context);
break;
default:
this.checkbox_context.each(function(pair) {
if (id.startsWith(pair.key + '_')) {
var t = pair.value.get(id.substring(pair.key.length + 1));
if (t) {
$(t).setValue(~~(!(~~$F(t))));
}
}
});
break;
}
},
contextOnShow: function(e)
{
var tmp = this.checkbox_context.get(e.memo);
if (tmp) {
tmp.each(function(pair) {
var t = $(e.memo + '_' + pair.key);
if (t) {
DimpCore.toggleCheck(t.down('SPAN'), ~~$F(pair.value));
}
});
}
if (e.element().up('#attach_list')) {
this.atc_context = e.element().up('LI');
} else {
delete this.atc_context;
}
},
onContactsUpdate: function(e)
{
switch (e.memo.field) {
case 'bcc':
case 'cc':
if (!$('send' + e.memo.field).visible()) {
this.toggleCC(e.memo.field);
}
break;
case 'to':
if (DimpCore.conf.redirect) {
e.memo.field = 'redirect_to';
}
break;
}
ImpComposeBase.updateAddressField(e);
},
tasksHandler: function(e)
{
var base = DimpCore.baseAvailable(),
t = e.tasks || {};
if (t['imp:compose']) {
this.getCacheElt().setValue(t['imp:compose'].cacheid);
if ($('composeCache')) {
$('composeHmac').setValue(t['imp:compose'].hmac);
}
this.upload_limit = t['imp:compose'].atclimit;
}
if (t['imp:compose-atc']) {
t['imp:compose-atc'].each(this.addAttach.bind(this));
}
if (base) {
if (t['imp:flag']) {
base.DimpBase.flagCallback(t['imp:flag']);
}
if (t['imp:mailbox']) {
base.DimpBase.mailboxCallback(t['imp:mailbox']);
}
if (t['imp:maillog']) {
base.DimpBase.maillogCallback(t['imp:maillog']);
}
}
},
onDomLoad: function()
{
var tmp;
/* Initialize redirect elements. */
if (DimpCore.conf.redirect) {
$('redirect').observe('submit', Event.stop);
if (DimpCore.conf.URI_ABOOK) {
$('redirect_sendto').down('TD.label SPAN').addClassName('composeAddrbook');
}
$('dimpLoading').hide();
$('composeContainer', 'redirect').invoke('show');
this.tasksHandler({ tasks: this.tasks });
if (this.onload_show) {
this.fillForm(this.onload_show);
delete this.onload_show;
}
ImpComposeBase.focus('redirect_to');
return;
}
/* Attach event handlers. */
if (Prototype.Browser.IE) {
// IE doesn't bubble change events.
$('identity', 'upload').compact().invoke(
'observe',
'change',
this.changeHandler.bindAsEventListener(this)
);
} else {
document.observe('change', this.changeHandler.bindAsEventListener(this));
}
$('compose').observe('submit', Event.stop);
$('htmlcheckbox').up('LABEL').observe('mouseup', function() {
if (!ImpComposeBase.editor_on ||
window.confirm(DimpCore.text.toggle_html)) {
this.toggleHtmlEditor();
}
}.bind(this));
HordeCore.initHandler('click');
HordeCore.handleSubmit($('compose'), {
callback: this.uniqueSubmitCallback.bind(this)
});
if ((tmp = $('atcdrop'))) {
tmp.observe('DragHandler:drop', function(e) {
this.uploadAttachmentAjax(e.memo);
}.bindAsEventListener(this));
DragHandler.dropelt = tmp;
DragHandler.droptarget = $('atcdiv');
DragHandler.hoverclass = 'atcdrop_over';
DimpCore.addPopdown($('upload'), 'atc', {
no_offset: true
});
}
if ($H(DimpCore.context.ctx_other).size()) {
DimpCore.addPopdown($('other_options').down('A'), 'other', {
trigger: true
});
} else {
$('other_options').hide();
}
/* Create sent-mail list. */
if ($('save_sent_mail_mbox')) {
this.changeIdentity();
}
/* Create priority list. */
if (DimpCore.conf.priority) {
this.createPopdown('p', {
base: 'priority_label',
data: DimpCore.conf.priority,
input: 'priority',
label: 'priority_label'
});
this.setPopdownLabel('p', $F('priority'));
}
/* Create encryption list. */
if (DimpCore.conf.encrypt) {
this.createPopdown('e', {
base: $('encrypt_label').up(),
data: DimpCore.conf.encrypt,
input: 'encrypt',
label: 'encrypt_label'
});
this.setPopdownLabel('e', $F('encrypt'));
}
/* Add addressbook link formatting. */
if (DimpCore.conf.URI_ABOOK) {
$('sendto', 'sendcc', 'sendbcc', 'redirect_sendto').compact().each(function(a) {
a.down('TD.label SPAN').addClassName('composeAddrbook');
});
}
$('dimpLoading').hide();
$('composeContainer', 'compose').compact().invoke('show');
this.tasksHandler({ tasks: this.tasks });
if (this.onload_show) {
this.fillForm(this.onload_show);
delete this.onload_show;
} else {
this.resizeMsgArea();
}
},
onAjaxFailure: function(e)
{
switch (e.memo[0].request.action) {
case 'redirectMessage':
case 'saveDraft':
case 'saveTemplate':
case 'sendMessage':
if (this.disabled) {
this.setDisabled(false);
}
break;
}
this.addAttachmentEnd();
this.RTELoading(false);
}
};
/* Attach event handlers. */
document.observe('dom:loaded', DimpCompose.onDomLoad.bind(DimpCompose));
document.observe('HordeCore:click', DimpCompose.clickHandler.bindAsEventListener(DimpCompose));
document.observe('keydown', DimpCompose.keydownHandler.bindAsEventListener(DimpCompose));
Event.observe(window, 'resize', DimpCompose.resizeMsgArea.bindAsEventListener(DimpCompose));
/* Other UI event handlers. */
document.observe('AutoComplete:resize', DimpCompose.resizeMsgArea.bind(DimpCompose));
document.observe('ImpContacts:update', DimpCompose.onContactsUpdate.bindAsEventListener(DimpCompose));
/* ContextSensitive functions. */
document.observe('ContextSensitive:click', DimpCompose.contextOnClick.bindAsEventListener(DimpCompose));
document.observe('ContextSensitive:show', DimpCompose.contextOnShow.bindAsEventListener(DimpCompose));
/* Initialize spellchecker. */
document.observe('SpellChecker:after', DimpCompose._onSpellCheckAfter.bind(DimpCompose));
document.observe('SpellChecker:before', DimpCompose._onSpellCheckBefore.bind(DimpCompose));
document.observe('SpellChecker:error', DimpCompose._onSpellCheckError.bind(DimpCompose));
document.observe('SpellChecker:noerror', DimpCompose._onSpellCheckNoError.bind(DimpCompose));
/* Catch dialog actions. */
document.observe('ImpPassphraseDialog:success', DimpCompose.retrySubmit.bind(DimpCompose));
/* Catch tasks. */
document.observe('HordeCore:runTasks', function(e) {
DimpCompose.tasksHandler(e.memo);
});
/* AJAX related events. */
document.observe('HordeCore:ajaxFailure', DimpCompose.onAjaxFailure.bindAsEventListener(DimpCompose));
/* IMP Editor events. */
document.observe('IMP_Editor:ready', function(e) {
if (e.memo.name == 'composeMessage') {
new CKEDITOR.dom.document(
e.memo.getThemeSpace('contents').$.down('IFRAME').contentWindow.document)
.on('keydown', function(evt) {
this.keydownHandler(Event.extend(evt.data.$), true);
}.bind(this));
}
}.bindAsEventListener(DimpCompose));
document.observe('IMP_Editor:dataReady', function(e) {
if (e.memo.name == 'composeMessage') {
this.RTELoading(false);
this.resizeMsgArea();
}
}.bindAsEventListener(DimpCompose));