/**
- * Provides the javascript for the compose.php script.
+ * Provides the javascript for the compose.php script (standard view).
*
* See the enclosed file COPYING for license information (GPL). If you
* did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
*/
-/*
- * Variables defined in compose.php:
- * cancel_url, compose_spellcheck, cursor_pos, identities, max_attachments,
- * popup, redirect, rtemode, smf_check
- */
-
-var display_unload_warning = true,
- textarea_ready = true;
-
-function confirmCancel(event)
-{
- if (window.confirm(IMP.text.compose_cancel)) {
- display_unload_warning = false;
- if (popup) {
- if (cancel_url) {
- self.location = cancel_url;
+var ImpCompose = {
+ /* Variables defined in compose.php:
+ * cancel_url, spellcheck, cursor_pos, identities, max_attachments,
+ * popup, redirect, reloaded, rtemode, smf_check */
+ display_unload_warning: true,
+ textarea_ready: true,
+
+ confirmCancel: function(e)
+ {
+ if (window.confirm(IMP.text.compose_cancel)) {
+ this.display_unload_warning = false;
+ if (this.popup) {
+ if (this.cancel_url) {
+ self.location = this.cancel_url;
+ } else {
+ self.close();
+ }
} else {
- self.close();
+ window.location = this.cancel_url;
}
} else {
- window.location = cancel_url;
+ e.stop();
}
- return true;
- } else {
- Event.extend(event);
- event.stop();
- return false;
- }
-}
-
-/**
- * Sets the cursor to the given position.
- */
-function setCursorPosition(input, position)
-{
- if (input.setSelectionRange) {
- /* This works in Mozilla */
- Field.focus(input);
- input.setSelectionRange(position, position);
- } else if (input.createTextRange) {
- /* This works in IE */
- var range = input.createTextRange();
- range.collapse(true);
- range.moveStart('character', position);
- range.moveEnd('character', 0);
- Field.select(range);
- range.scrollIntoView(true);
- }
-}
-
-function redirectSubmit(event)
-{
- if ($F('to') == '') {
- alert(IMP.text.compose_recipient);
- $('to').focus();
- Event.extend(event);
- event.stop();
- return false;
- }
-
- $('redirect').setStyle({ cursor: 'wait' });
- display_unload_warning = false;
-
- return true;
-}
-
-function change_identity(id)
-{
- var last = identities[$F('last_identity')],
- next = identities[id],
- msg, ed, lastSignature, nextSignature;
-
- // If the rich text editor is on, we'll use a regexp to find the
- // signature comment and replace its contents.
- if (rtemode) {
- ed = FCKeditorAPI.GetInstance('message');
-
- msg = ed.GetHTML.replace(/\r\n/g, '\n');
+ },
+
+ /**
+ * Sets the cursor to the given position.
+ */
+ setCursorPosition: function(input, position)
+ {
+ if (input.setSelectionRange) {
+ /* This works in Mozilla */
+ Field.focus(input);
+ input.setSelectionRange(position, position);
+ } else if (input.createTextRange) {
+ /* This works in IE */
+ var range = input.createTextRange();
+ range.collapse(true);
+ range.moveStart('character', position);
+ range.moveEnd('character', 0);
+ Field.select(range);
+ range.scrollIntoView(true);
+ }
+ },
+
+ changeIdentity: function(elt)
+ {
+ var id = $F(elt),
+ last = this.identities[$F('last_identity')],
+ next = this.identities[id],
+ i = 0,
+ bcc = $('bcc'),
+ save = $('ssm'),
+ smf = $('sent_mail_folder'),
+ ed, lastSignature, msg, nextSignature, pos, re;
+
+ // If the rich text editor is on, we'll use a regexp to find the
+ // signature comment and replace its contents.
+ if (this.rtemode) {
+ ed = FCKeditorAPI.GetInstance('message');
+
+ msg = ed.GetHTML.replace(/\r\n/g, '\n');
+
+ lastSignature = '<p><!--begin_signature--><!--end_signature--></p>';
+ nextSignature = '<p><!--begin_signature-->' + next[0].replace(/^ ?<br \/>\n/, '').replace(/ +/g, ' ') + '<!--end_signature--></p>';
+
+ // Dot-all functionality achieved with [\s\S], see:
+ // http://simonwillison.net/2004/Sep/20/newlines/
+ msg = msg.replace(/<p class="imp-signature">\s*<!--begin_signature-->[\s\S]*?<!--end_signature-->\s*<\/p>/, lastSignature);
+ } else {
+ msg = $F('message').replace(/\r\n/g, '\n');
- lastSignature = '<p><!--begin_signature--><!--end_signature--></p>';
- nextSignature = '<p><!--begin_signature-->' + next[0].replace(/^ ?<br \/>\n/, '').replace(/ +/g, ' ') + '<!--end_signature--></p>';
+ lastSignature = last[0].replace(/^\n/, '');
+ nextSignature = next[0].replace(/^\n/, '');
+ }
- // Dot-all functionality achieved with [\s\S], see:
- // http://simonwillison.net/2004/Sep/20/newlines/
- msg = msg.replace(/<p class="imp-signature">\s*<!--begin_signature-->[\s\S]*?<!--end_signature-->\s*<\/p>/, lastSignature);
- } else {
- msg = $F('message').replace(/\r\n/g, '\n');
+ pos = (last[1]) ? msg.indexOf(lastSignature) : msg.lastIndexOf(lastSignature);
+ if (pos != -1) {
+ if (next[1] == last[1]) {
+ msg = msg.substring(0, pos) + nextSignature + msg.substring(pos + lastSignature.length, msg.length);
+ } else if (next[1]) {
+ msg = nextSignature + msg.substring(0, pos) + msg.substring(pos + lastSignature.length, msg.length);
+ } else {
+ msg = msg.substring(0, pos) + msg.substring(pos + lastSignature.length, msg.length) + nextSignature;
+ }
- lastSignature = last[0].replace(/^\n/, '');
- nextSignature = next[0].replace(/^\n/, '');
- }
+ msg = msg.replace(/\r\n/g, '\n').replace(/\n/g, '\r\n');
- var pos = (last[1]) ? msg.indexOf(lastSignature) : msg.lastIndexOf(lastSignature);
- if (pos != -1) {
- if (next[1] == last[1]) {
- msg = msg.substring(0, pos) + nextSignature + msg.substring(pos + lastSignature.length, msg.length);
- } else if (next[1]) {
- msg = nextSignature + msg.substring(0, pos) + msg.substring(pos + lastSignature.length, msg.length);
+ $('last_identity').setValue(id);
+ window.status = IMP.text.compose_sigreplace;
} else {
- msg = msg.substring(0, pos) + msg.substring(pos + lastSignature.length, msg.length) + nextSignature;
+ window.status = IMP.text.compose_signotreplace;
}
- msg = msg.replace(/\r\n/g, '\n').replace(/\n/g, '\r\n');
-
- $('last_identity').setValue(id);
- window.status = IMP.text.compose_sigreplace;
- } else {
- window.status = IMP.text.compose_signotreplace;
- }
+ if (this.rtemode) {
+ ed.SetHTML(msg);
+ } else {
+ $('message').setValue(msg);
+ }
- if (rtemode) {
- ed.SetHTML(msg);
- } else {
- $('message').setValue(msg);
- }
- var smf = $('sent_mail_folder');
- if (smf_check) {
- var i = 0;
- $A(smf.options).detect(function(f) {
- if (f.value == next[2]) {
- smf.selectedIndex = i;
- return true;
- }
- ++i;
- });
- } else {
- if (smf.firstChild) {
- smf.replaceChild(document.createTextNode(next[2]), smf.firstChild);
+ if (this.smf_check) {
+ $A(smf.options).detect(function(f) {
+ if (f.value == next[2]) {
+ smf.selectedIndex = i;
+ return true;
+ }
+ ++i;
+ });
} else {
- smf.appendChild(document.createTextNode(next[2]));
+ if (smf.firstChild) {
+ smf.replaceChild(document.createTextNode(next[2]), smf.firstChild);
+ } else {
+ smf.appendChild(document.createTextNode(next[2]));
+ }
}
- }
- var save = $('ssm');
- if (save) {
- save.checked = next[3];
- }
- var bcc = $('bcc');
- if (bcc) {
- bccval = bcc.value;
-
- if (last[4]) {
- var re = new RegExp(last[4] + ",? ?", 'gi');
- bccval = bccval.replace(re, "");
- if (bccval) {
- bccval = bccval.replace(/, ?$/, "");
- }
+ if (save) {
+ save.checked = next[3];
}
+ if (bcc) {
+ bccval = bcc.value;
+
+ if (last[4]) {
+ re = new RegExp(last[4] + ",? ?", 'gi');
+ bccval = bccval.replace(re, "");
+ if (bccval) {
+ bccval = bccval.replace(/, ?$/, "");
+ }
+ }
- if (next[4]) {
- if (bccval) {
- bccval += ', ';
+ if (next[4]) {
+ if (bccval) {
+ bccval += ', ';
+ }
+ bccval += next[4];
}
- bccval += next[4];
+
+ bcc.setValue(bccval);
}
+ },
- bcc.setValue(bccval);
- }
-}
+ uniqSubmit: function(actionID, e)
+ {
+ e.stop();
-function uniqSubmit(actionID, event)
-{
- if (event) {
- Event.extend(event);
- event.stop();
- }
+ if (actionID == 'redirect') {
+ if ($F('to') == '') {
+ alert(IMP.text.compose_recipient);
+ $('to').focus();
+ } else {
+ // Ticket #6727; this breaks on WebKit w/FCKeditor.
+ if (!Prototype.Browser.WebKit) {
+ $('redirect').setStyle({ cursor: 'wait' });
+ }
+ this.display_unload_warning = false;
+ }
- if (actionID == 'send_message') {
- if (($F('subject') == '') &&
- !window.confirm(IMP.text.compose_nosubject)) {
return;
}
- if (compose_spellcheck &&
- IMP.SpellCheckerObject &&
- !IMP.SpellCheckerObject.isActive()) {
- IMP.SpellCheckerObject.spellCheck();
- return;
+ if (actionID == 'send_message') {
+ if (($F('subject') == '') &&
+ !window.confirm(IMP.text.compose_nosubject)) {
+ return;
+ }
+
+ if (this.spellcheck &&
+ IMP.SpellCheckerObject &&
+ !IMP.SpellCheckerObject.isActive()) {
+ IMP.SpellCheckerObject.spellCheck();
+ return;
+ }
}
- }
- if (IMP.SpellCheckerObject) {
- IMP.SpellCheckerObject.resume();
- }
+ if (IMP.SpellCheckerObject) {
+ IMP.SpellCheckerObject.resume();
+ }
- // Ticket #6727; this breaks on WebKit w/FCKeditor.
- if (!Prototype.Browser.WebKit) {
- $('compose').setStyle({ cursor: 'wait' });
- }
- display_unload_warning = false;
- $('actionID').setValue(actionID);
- _uniqSubmit();
-}
-
-function _uniqSubmit()
-{
- if (textarea_ready) {
- $('compose').submit();
- } else {
- _uniqSubmit.defer();
- }
-}
+ // Ticket #6727; this breaks on WebKit w/FCKeditor.
+ if (!Prototype.Browser.WebKit) {
+ $('compose').setStyle({ cursor: 'wait' });
+ }
-function attachmentChanged()
-{
- var fields = [], usedFields = 0;
+ this.display_unload_warning = false;
+ $('actionID').setValue(actionID);
+ this._uniqSubmit();
+ },
- $('upload_atc').select('input[type="file"]').each(function(i) {
- fields[fields.length] = i;
- });
+ _uniqSubmit: function()
+ {
+ if (this.textarea_ready) {
+ $('compose').submit();
+ } else {
+ this._uniqSubmit.defer();
+ }
+ },
- if (max_attachments !== null &&
- fields.length == max_attachments) {
- return;
- }
+ attachmentChanged: function()
+ {
+ var fields = [],
+ usedFields = 0,
+ lastRow, newRow, td;
- fields.each(function(i) {
- if (i.value.length > 0) {
- usedFields++;
+ $('upload_atc').select('input[type="file"]').each(function(i) {
+ fields[fields.length] = i;
+ });
+
+ if (this.max_attachments !== null &&
+ fields.length == this.max_attachments) {
+ return;
}
- });
- if (usedFields == fields.length) {
- var lastRow = $('attachment_row_' + usedFields);
- if (lastRow) {
- var td = new Element('TD', { align: 'left' }).insert(new Element('STRONG').insert(IMP.text.compose_file + ' ' + (usedFields + 1) + ':')).insert(' ')
+ fields.each(function(i) {
+ if (i.value.length > 0) {
+ usedFields++;
+ }
+ });
- var file = new Element('INPUT', { type: 'file', name: 'upload_' + (usedFields + 1), size: 25 });
- file.observe('change', attachmentChanged);
- td.insert(file);
+ if (usedFields == fields.length) {
+ lastRow = $('attachment_row_' + usedFields);
+ if (lastRow) {
+ td = new Element('TD', { align: 'left' }).insert(new Element('STRONG').insert(IMP.text.compose_file + ' ' + (usedFields + 1) + ':')).insert(' ')
- var newRow = new Element('TR', { id: 'attachment_row_' + (usedFields + 1) }).insert(td);
+ td.insert(new Element('INPUT', { type: 'file', name: 'upload_' + (usedFields + 1), size: 25 }));
- lastRow.parentNode.insertBefore(newRow, lastRow.nextSibling);
+ newRow = new Element('TR', { id: 'attachment_row_' + (usedFields + 1) }).insert(td);
+
+ lastRow.parentNode.insertBefore(newRow, lastRow.nextSibling);
+ }
}
- }
-}
-
-function initializeSpellChecker()
-{
- if (typeof IMP.SpellCheckerObject != 'object') {
- // If we fired before the onload that initializes the
- // spellcheck, wait.
- initializeSpellChecker.defer();
- return;
- }
+ },
+
+ initializeSpellChecker: function()
+ {
+ if (typeof IMP.SpellCheckerObject != 'object') {
+ // If we fired before the onload that initializes the spellcheck,
+ // wait.
+ this.initializeSpellChecker.defer();
+ return;
+ }
+
+ IMP.SpellCheckerObject.onBeforeSpellCheck = this._beforeSpellCheck.bind(this);
+ IMP.SpellCheckerObject.onAfterSpellCheck = this._afterSpellCheck.bind(this);
+ },
- IMP.SpellCheckerObject.onBeforeSpellCheck = function() {
+ _beforeSpellCheck: function()
+ {
IMP.SpellCheckerObject.htmlAreaParent = 'messageParent';
IMP.SpellCheckerObject.htmlArea = $('message').adjacent('iframe[id*=message]').first();
$('message').setValue(FCKeditorAPI.GetInstance('message').GetHTML());
- textarea_ready = false;
- }
- IMP.SpellCheckerObject.onAfterSpellCheck = function() {
+ this.textarea_ready = false;
+ },
+
+ _afterSpellCheck: function()
+ {
IMP.SpellCheckerObject.htmlArea = IMP.SpellCheckerObject.htmlAreaParent = null;
var ed = FCKeditorAPI.GetInstance('message');
ed.SetHTML($('message').value);
- ed.Events.AttachEvent('OnAfterSetHTML', function() { textarea_ready = true; });
- }
-}
+ ed.Events.AttachEvent('OnAfterSetHTML', this._afterSetHTML.bind(this));
+ },
+
+ _afterSetHTML: function()
+ {
+ this.textarea_ready = true;
+ },
+
+ clickHandler: function(e)
+ {
+ var elt = e.element(), name;
+
+ if (elt.hasClassName('button')) {
+ name = elt.readAttribute('name');
+ switch (name) {
+ case 'btn_add_attachment':
+ case 'btn_redirect':
+ case 'btn_save_draft':
+ case 'btn_send_message':
+ this.uniqSubmit(name.substring(4), e);
+ break;
+
+ case 'btn_cancel_compose':
+ this.confirmCancel(e);
+ break;
+ }
+ }
+ },
-/**
- * Code to run on window load.
- */
-document.observe('dom:loaded', function() {
- /* Prevent Return from sending messages - it should bring us out of
- * autocomplete, not submit the whole form. */
- $$('INPUT').each(function(i) {
- /* Attach to everything but button and submit elements. */
- if (i.type != 'submit' && i.type != 'button') {
- i.observe('keydown', function(e) {
- if (e.keyCode == 10 || e.keyCode == Event.KEY_RETURN) {
- e.stop();
- return false;
- }
- });
+ changeHandler: function(e)
+ {
+ var elt = e.element(),
+ id = elt.readAttribute('id');
+
+ switch (id) {
+ case 'identity':
+ this.changeIdentity(elt);
+ break;
+
+ case 'stationery':
+ this.uniqSubmit('change_stationery', e);
+ break;
+
+ case 'sent_mail_folder':
+ $('ssm').writeAttribute('checked', 'checked');
+ break;
+
+ default:
+ if (id.substring(0, 7) == 'upload_') {
+ this.attachmentChanged();
+ }
+ break;
}
- });
+ },
+
+ onDomLoad: function()
+ {
+ /* Prevent Return from sending messages - it should bring us out of
+ * autocomplete, not submit the whole form. */
+ $$('INPUT').each(function(i) {
+ /* Attach to everything but button and submit elements. */
+ if (i.type != 'submit' && i.type != 'button') {
+ i.observe('keydown', function(e) {
+ if (e.keyCode == 10 || e.keyCode == Event.KEY_RETURN) {
+ e.stop();
+ return false;
+ }
+ });
+ }
+ });
- if (cursor_pos !== null && $('message')) {
- setCursorPosition($('message'), cursor_pos);
- }
+ if (this.cursor_pos !== null && $('message')) {
+ this.setCursorPosition($('message'), this.cursor_pos);
+ }
+
+ if (this.redirect) {
+ $('to').focus();
+ } else {
+ if (Prototype.Browser.IE) {
+ $('subject').observe('keydown', function(e) {
+ if (e.keyCode == Event.KEY_TAB && !e.shiftKey) {
+ e.stop();
+ $('message').focus();
+ }
+ });
+ }
+
+ if (this.rtemode) {
+ this.initializeSpellChecker();
+ }
- if (redirect) {
- $('to').focus();
- } else {
- if (Prototype.Browser.IE) {
- $('subject').observe('keydown', function(e) {
- if (e.keyCode == Event.KEY_TAB && !e.shiftKey) {
- e.stop();
+ if ($('to') && !$F('to')) {
+ $('to').focus();
+ } else if (!$F('subject')) {
+ if (this.rtemode) {
+ $('subject').focus();
+ } else {
$('message').focus();
}
- });
+ }
}
+ },
- if (rtemode) {
- initializeSpellChecker();
- }
+ onLoad: function()
+ {
+ var d, e = this.redirect ? $('redirect') : $('compose');
- if ($('to') && !$F('to')) {
- $('to').focus();
- } else if (!$F('subject')) {
- if (rtemode) {
- $('subject').focus();
- } else {
- $('message').focus();
+ if (this.popup && !this.reloaded) {
+ d = Math.min(e.getHeight(), screen.height - 100) - document.viewport.getHeight();
+ if (d > 0) {
+ window.resizeBy(0, d);
}
}
- }
-});
-
-Event.observe(window, 'load', function() {
- if (compose_popup && !reloaded) {
- var d, e = redirect ? $('redirect') : $('compose');
- d = Math.min(e.getHeight(), screen.height - 100) - document.viewport.getHeight();
- if (d > 0) {
- window.resizeBy(0, d);
+
+ document.observe('click', this.clickHandler.bindAsEventListener(this));
+ document.observe('change', this.changeHandler.bindAsEventListener(this));
+ },
+
+ onBeforeUnload: function()
+ {
+ if (this.display_unload_warning) {
+ return IMP.text.compose_discard;
}
}
-});
-/**
- * Warn before closing the window.
- */
-Event.observe(window, 'beforeunload', function() {
- if (display_unload_warning) {
- return IMP.text.compose_discard;
- }
-});
+};
+
+/* Code to run on window load. */
+document.observe('dom:loaded', ImpCompose.onDomLoad.bind(ImpCompose));
+Event.observe(window, 'load', ImpCompose.onLoad.bind(ImpCompose));
+
+/* Warn before closing the window. */
+Event.observe(window, 'beforeunload', ImpCompose.onBeforeUnload.bind(ImpCompose));