Adds the ability to switch between HTML and text-based composition.
Three notes: all the HTML buttons are still available when you're in plain-text mode; we don't check your prefs as to what default composer mode you'd like; and line breaks are a bit whacky when you switch modes (I think :). Please expect and report breakage.
This commit is contained in:
@@ -35,8 +35,8 @@ class ConversationsHandler(ResourceHandler):
|
||||
|
||||
if jsob.has_key("body") :
|
||||
composer.SetBody(jsob.get("body"))
|
||||
if jsob.has_key("bodyHtml") :
|
||||
composer.SetBody(jsob.get("bodyHtml"), "text/html")
|
||||
if jsob.has_key("isHtml") and (jsob.get("isHtml") == True or jsob.get("isHtml") == 'true') :
|
||||
composer.SetBody(jsob.get("body"), "text/html")
|
||||
|
||||
composer.SetDate(time.time())
|
||||
|
||||
|
||||
+32
-16
@@ -53,7 +53,7 @@ Dragonfly.Mail.Composer.parseMailto = function (mailto)
|
||||
to: '',
|
||||
cc: '',
|
||||
bcc: p.getAutoBcc() || '',
|
||||
bodyHtml: defaultbodyHtml
|
||||
body: defaultbodyHtml
|
||||
};
|
||||
if (mailto.substr (0, 7) != 'mailto:') {
|
||||
return null;
|
||||
@@ -75,7 +75,7 @@ Dragonfly.Mail.Composer.parseMailto = function (mailto)
|
||||
case 'subject':
|
||||
case 'inreplyto':
|
||||
case 'forward':
|
||||
case 'bodyHtml':
|
||||
case 'body':
|
||||
case 'conversation':
|
||||
msg[field] = decodeURIComponent (arg[1]);
|
||||
break;
|
||||
@@ -104,9 +104,9 @@ Dragonfly.Mail.Composer.prototype.buildHtml = function (html)
|
||||
this.addAttachment = d.nextId ('add-attachment');
|
||||
|
||||
this.subject = d.nextId ('subject');
|
||||
this.bodyHtml = d.nextId ('bodyHtml');
|
||||
|
||||
this.toolbar = d.nextId ('toolbar');
|
||||
this.body = d.nextId ('body');
|
||||
|
||||
this.toolbar = $('toolbar');
|
||||
this.discard = d.nextId ('discard');
|
||||
this.save = d.nextId ('save');
|
||||
this.send = d.nextId ('send');
|
||||
@@ -137,9 +137,9 @@ Dragonfly.Mail.Composer.prototype.buildHtml = function (html)
|
||||
if (this.msg.contents) {
|
||||
switch (this.msg.contents.contenttype) {
|
||||
case 'multipart/mixed':
|
||||
var bodyHtml = this.msg.contents.children[0];
|
||||
if (bodyHtml.contenttype == 'text/plain') {
|
||||
this.msg.bodyHtml = bodyHtml.content;
|
||||
var body = this.msg.contents.children[0];
|
||||
if (body.contenttype == 'text/plain') {
|
||||
this.msg.body = body.content;
|
||||
}
|
||||
for (var i = 1; i < this.msg.contents.children.length; i++) {
|
||||
var attachment = this.msg.contents.children[i];
|
||||
@@ -149,13 +149,18 @@ Dragonfly.Mail.Composer.prototype.buildHtml = function (html)
|
||||
}
|
||||
break;
|
||||
case 'text/plain':
|
||||
this.msg.bodyHtml = this.msg.contents.content;
|
||||
this.msg.body = this.msg.contents.content;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
m.defaultComposerStyle = "font-family: lucida grande,myriad,myriad pro,verdana,luxi sans,bitstream vera sans,sans-serif;font-size:0.9em;"
|
||||
m.isHtml = true;
|
||||
|
||||
var composerToolbar = "[bold][italic][underlined] sep [align-left][justify][align-center][align-right] sep [undo][redo][select-all] sep [insert-image][insert-link] sep [switch-mode]</div>[edit-area]";
|
||||
|
||||
html.push ('<li><a id="', this.addAttachment, '">', _('Attach file...'), '</a></li></ul>',
|
||||
'<tr><td colspan="2"><div class="toolbar">', insertEditableArea(this.bodyHtml, '99%', '250px', "[bold][italic][underlined] sep [align-left][justify][align-center][align-right] sep [undo][redo][select-all] sep [insert-image][insert-link]</div>[edit-area]", "font-family: lucida grande,myriad,myriad pro,verdana,luxi sans,bitstream vera sans,sans-serif;font-size:0.9em;"), '</td></tr>',
|
||||
'<tr><td colspan="2"><div class="toolbar">', insertEditableArea(this.body, '99%', '250px', composerToolbar, m.defaultComposerStyle), '</td></tr>',
|
||||
'<tr class="action"><td id="', this.toolbar, '" colspan="2">',
|
||||
'<input id="', this.discard, '" class="discard" type="button" value="', _('Discard'), '">',
|
||||
'<input id="', this.save, '" class="save" type="button" value="', _('Save Draft'), '">',
|
||||
@@ -184,8 +189,8 @@ Dragonfly.Mail.Composer.prototype.connectHtml = function (elem)
|
||||
this.bcc = $(this.bcc);
|
||||
this.from = $(this.from);
|
||||
this.subject = $(this.subject);
|
||||
//d.bodyHtmlname = this.bodyHtml;
|
||||
//this.bodyHtml = $(this.bodyHtml);
|
||||
//d.bodyname = this.body;
|
||||
//this.body = $(this.body);
|
||||
this.addAttachment = $(this.addAttachment);
|
||||
this.discard = $(this.discard);
|
||||
this.send = $(this.send);
|
||||
@@ -244,7 +249,8 @@ Dragonfly.Mail.Composer.prototype.getCurrentMessage = function ()
|
||||
cc: this.cc.value,
|
||||
bcc: this.bcc.value,
|
||||
subject: this.subject.value,
|
||||
bodyHtml: editableAreaContents(this.bodyHtml)
|
||||
body: editableAreaContents(this.body),
|
||||
isHtml: Dragonfly.Mail.isHtml
|
||||
};
|
||||
};
|
||||
|
||||
@@ -425,12 +431,22 @@ Dragonfly.Mail.Composer.prototype.sendMessage = function (evt)
|
||||
{
|
||||
this.saveDraft(this);
|
||||
this.draftSaveCalled = true;
|
||||
this.callCount = 1;
|
||||
callLater(1, bind('sendMessage', this));
|
||||
}
|
||||
else if (this.callCount > 10)
|
||||
{
|
||||
logDebug('Save took more than 10sec, giving up.');
|
||||
d.notifyError (_('Error sending message: Gave up while trying to send. Check logs.'));
|
||||
this.callCount = 0; // Reset counter.
|
||||
this.draftSaveCalled = false;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Still waiting for draft to save...
|
||||
logDebug('Save not finished yet - checking again in 1sec.');
|
||||
this.callCount++;
|
||||
callLater(1, bind('sendMessage', this));
|
||||
}
|
||||
|
||||
@@ -610,8 +626,8 @@ Dragonfly.Mail.Composer.composeNew = function (msg)
|
||||
|
||||
html.set ('conv-msg-list');
|
||||
|
||||
setEditableAreaContents(composer.bodyHtml, d.escapeHTML (msg.bodyHtml));
|
||||
ititButtons(composer.bodyHtml);
|
||||
setEditableAreaContents(composer.body, d.escapeHTML (msg.body));
|
||||
ititButtons(composer.body);
|
||||
|
||||
d.resizeScrolledView();
|
||||
|
||||
@@ -880,7 +896,7 @@ Dragonfly.Mail.AttachmentForm.prototype.frameLoad = function (evt)
|
||||
var doc = d.getIFrameDocument (this.iframeId);
|
||||
var jsob;
|
||||
try {
|
||||
jsob = d.eval (Element.getText (doc.bodyHtml));
|
||||
jsob = d.eval (Element.getText (doc.body));
|
||||
} catch (e) {
|
||||
showError.call (this, 'server response was not understood');
|
||||
return;
|
||||
|
||||
@@ -29,7 +29,8 @@ function insertEditableArea(editableAreaName, editableAreaWidth, editableAreaHei
|
||||
var redoButton = '<input type="image" src="/js/eArea/icons/edit-redo.png" value="Redo" alt="Redo" name="' + editableAreaName + '" id="redo" class="icon" style="width:24px;height:24px;">';
|
||||
var selectAllButton = '<input type="image" src="/js/eArea/icons/edit-select-all.png" value="Select all" alt="Select all" name="' + editableAreaName + '" id="selectall" class="icon" style="width:24px;height:24px;">';
|
||||
var insertImageButton = '<input type="image" src="/js/eArea/icons/insert-image.png" value="Insert image" alt="Insert image" name="' + editableAreaName + '" id="insertimage" class="icon" style="width:24px;height:24px;">';
|
||||
var insertLinkButton = '<input type="image" src="/js/eArea/icons/insert-link.png" value="Insert link" alt="Insert link" name="' + editableAreaName + '" id="insertlink" class="icon" style="width:24px;height:24px;">';
|
||||
var insertLinkButton = '<input type="image" src="/js/eArea/icons/insert-link.png" value="Insert link" alt="Insert link" name="' + editableAreaName + '" id="insertlink" class="icon" style="width:24px;height:24px;">';
|
||||
var switchModeButton = '<input type="image" src="/js/eArea/icons/switch-mode.png" value="Switch mode" alt="Switch mode" name="' + editableAreaName + '" id="switchmode" class="icon" style="width:24px;height:24px;">';
|
||||
var editableArea = '<iframe src="/js/eArea/blank.html?style=' + editableAreaStyle + '" id="' + editableAreaName + '" \n style="width:' + editableAreaWidth + '; min-height:' + editableAreaHeight + '; border-style:solid; border: 1px solid #DDDDDD;" frameborder="0px"></iframe>'
|
||||
|
||||
var editableAreaHTML = editableAreaLayout;
|
||||
@@ -48,6 +49,7 @@ function insertEditableArea(editableAreaName, editableAreaWidth, editableAreaHei
|
||||
editableAreaHTML = editableAreaHTML.replace("[select-all]", selectAllButton);
|
||||
editableAreaHTML = editableAreaHTML.replace("[insert-image]", insertImageButton);
|
||||
editableAreaHTML = editableAreaHTML.replace("[insert-link]", insertLinkButton);
|
||||
editableAreaHTML = editableAreaHTML.replace("[switch-mode]", switchModeButton);
|
||||
|
||||
editableAreaHTML = editableAreaHTML.replace(/sep/g, '<span class="split"></span>');
|
||||
editableAreaHTML = editableAreaHTML.replace("[edit-area]", editableArea);
|
||||
@@ -65,9 +67,24 @@ function insertEditableArea(editableAreaName, editableAreaWidth, editableAreaHei
|
||||
return retHTML;
|
||||
}
|
||||
|
||||
// TODO!
|
||||
function stripHTML(d)
|
||||
{
|
||||
d = d.replace(/(<([^>]+)>)/ig, ""); // Remove the other tags we can't handle.
|
||||
/*
|
||||
foreach ($tags as $tag){
|
||||
while(preg_match('/<'.$tag.'(|\W[^>]*)>(.*)<\/'. $tag .'>/iusU', $text, $found)){
|
||||
$text = str_replace($found[0],$found[2],$text);
|
||||
}
|
||||
}
|
||||
|
||||
return preg_replace('/(<('.join('|',$tags).')(|\W.*)\/>)/iusU', '', $text);
|
||||
*/
|
||||
|
||||
d = d.replace(/<a[^href]+href=\"([^\"]*)\"[^>]*>/ig,"$1"); // Linkies
|
||||
d = d.replace("<b>", "*"); // Vold (that's bold with an accent ;)
|
||||
d = d.replace("<strong>", "*");
|
||||
//d = d.replace("<br />"
|
||||
//d = d.replace(/(<([^>]+)>)/ig, ""); // Remove the other tags we can't handle.
|
||||
|
||||
return d;
|
||||
}
|
||||
@@ -84,6 +101,21 @@ function editableAreaContents(editableAreaName) {
|
||||
}
|
||||
}
|
||||
|
||||
// Enable/disable HTML buttons
|
||||
// TODO!!!
|
||||
function setHTMLbuttons(value)
|
||||
{
|
||||
var obj = $('toolbar').childNodes;
|
||||
for (var i=0; i < obj.length; i++)
|
||||
{
|
||||
var btn = obj[i];
|
||||
if (btn.attributes.getNamedItem('isHtml').value == "true")
|
||||
{
|
||||
btn.style.class = "icon selected";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function setEditableAreaContents(editableAreaName, value)
|
||||
{
|
||||
if (document.designMode) {
|
||||
@@ -260,6 +292,61 @@ function buttonOnClick() {
|
||||
//runCmd(this.name, this.id, null, path);
|
||||
}
|
||||
}
|
||||
else if (this.id == "switchmode")
|
||||
{
|
||||
// Dragonfly must be included here; otherwise you'll get script errors!
|
||||
if (Dragonfly)
|
||||
{
|
||||
var m = Dragonfly.Mail;
|
||||
if (m.isHtml)
|
||||
{
|
||||
// Grab the contents to put in the normal textarea.
|
||||
var style = "'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Monaco', 'Courier', monospace";
|
||||
|
||||
// Disable HTML-styling buttons / change onclick events.
|
||||
|
||||
// Set the style for the inner iframe thing (only on browsers that support designMode, since textarea is already ok)
|
||||
if (window[this.name])
|
||||
{
|
||||
window[this.name].document.body.style.fontFamily = style;
|
||||
window[this.name].document.body.style.width = "47em";
|
||||
}
|
||||
else
|
||||
{
|
||||
document.getElementById(this.name).contentWindow.document.body.style.fontFamily = style;
|
||||
document.getElementById(this.name).contentWindow.document.body.style.width = "47em";
|
||||
}
|
||||
|
||||
setEditableAreaContents(this.name, stripHTML(editableAreaContents(this.name)));
|
||||
|
||||
m.isHtml = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
var style = m.defaultComposerStyle;
|
||||
|
||||
// Re-enable HTML-styling buttons / change onclick events.
|
||||
|
||||
// Set the style for the inner iframe thing (only on browsers that support designMode, since textarea is already ok)
|
||||
if (window[this.name])
|
||||
{
|
||||
window[this.name].document.body.setAttribute('style', style);
|
||||
}
|
||||
else
|
||||
{
|
||||
document.getElementById(this.name).contentWindow.document.body.setAttribute('style', style);
|
||||
}
|
||||
|
||||
m.isHtml = true;
|
||||
}
|
||||
|
||||
//alert('isHtml? ' + m.isHtml);
|
||||
}
|
||||
else
|
||||
{
|
||||
alert('Dragonfly not loaded - can\'t switch composition modes.');
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
runCmd(this.name, this.id, false, null);
|
||||
|
||||
Reference in New Issue
Block a user