HTML editor with integrated mode switch (#41)

pull/5742/merge
Aleksander Machniak 7 years ago
parent 5e14533422
commit 2c53d903df

@ -102,7 +102,8 @@
// Forms // Forms
@color-input-border: @color-border; @color-input-border: rgba(0, 0, 0, 0.15); /* from Bootstrap's .form-control */
@color-input-addon-background: #e9ecef; /* from Bootstrap's .input-group-addon */
@color-recipient-input-border: @color-input-border; @color-recipient-input-border: @color-input-border;
@color-recipient-input-background: #f4f4f4; @color-recipient-input-background: #f4f4f4;

@ -380,9 +380,54 @@ html.touch input.icon-checkbox + label {
} }
/*** TinyMCE editor ***/ /*** HTML editor widget (and TinyMCE editor) ***/
.mce-tinymce.mce-container.mce-panel { .mce-tinymce {
&.mce-container.mce-panel {
border-radius: .25rem; border-radius: .25rem;
border-color: @color-input-border;
overflow: hidden; overflow: hidden;
} }
.mce-btn,
.mce-panel {
background-color: @color-input-addon-background;
}
}
.html-editor {
position: relative;
display: flex;
& > .nav {
border-color: transparent;
z-index: 1;
position: absolute;
top: 1px;
right: 1rem;
a.active {
border-color: @color-input-border !important;
&.mode-html {
background-color: @color-input-addon-background;
border-bottom-color: @color-input-addon-background !important;
}
&.mode-plain {
border-bottom-color: #fff !important;
}
}
a:hover {
border-bottom-color: transparent;
}
}
& > .mce-tinymce,
& > textarea {
margin-top: 2.55rem;
font-family: monospace;
width: 100%;
}
}

@ -71,7 +71,7 @@
<roundcube:endif /> <roundcube:endif />
<roundcube:container name="composeoptions" id="compose-options" /> <roundcube:container name="composeoptions" id="compose-options" />
<roundcube:if condition="!in_array('htmleditor', (array)config:dont_override)" /> <roundcube:if condition="!in_array('htmleditor', (array)config:dont_override)" />
<div class="form-group row"> <div class="form-group row hidden">
<label for="editor-selector" class="col-form-label col-6"><roundcube:label name="editortype" /></label> <label for="editor-selector" class="col-form-label col-6"><roundcube:label name="editortype" /></label>
<div class="col-6"> <div class="col-6">
<roundcube:object name="editorSelector" id="editor-selector" editorid="composebody" noform="true" tabindex="2" class="form-control" /> <roundcube:object name="editorSelector" id="editor-selector" editorid="composebody" noform="true" tabindex="2" class="form-control" />

@ -1,6 +1,8 @@
<roundcube:add_label name="back" /> <roundcube:add_label name="back" />
<roundcube:add_label name="errortitle" /> <roundcube:add_label name="errortitle" />
<roundcube:add_label name="options" /> <roundcube:add_label name="options" />
<roundcube:add_label name="plaintoggle" />
<roundcube:add_label name="htmltoggle" />
<roundcube:object name="doctype" value="html5" /> <roundcube:object name="doctype" value="html5" />
<roundcube:if condition="!env:framed || env:extwin" /> <roundcube:if condition="!env:framed || env:extwin" />
<html> <html>

@ -210,6 +210,9 @@ function rcube_elastic_ui()
}).change(); }).change();
}); });
// Add HTML/Plain tabs (switch) on top of textarea with TinyMCE editor
$('textarea[data-html-editor]').each(function() { html_editor_init(this); });
$('#dragmessage-menu,#dragcontact-menu').each(function() { $('#dragmessage-menu,#dragcontact-menu').each(function() {
rcmail.gui_object('dragmenu', this.id); rcmail.gui_object('dragmenu', this.id);
}); });
@ -2140,6 +2143,75 @@ function rcube_elastic_ui()
); );
}; };
/**
* HTML editor textarea wrapper with nice looking tabs-like switch
*/
function html_editor_init(obj)
{
// Here we support two structures
// 1. <div><textarea></textarea><select name="editorSelector"></div>
// 2. <tr><td><td><td><textarea></textarea></td></tr>
// <tr><td><td><td><input type="checkbox"></td></tr>
var sw, is_table = false,
editor = $(obj),
parent = editor.parent(),
mode = function() {
if (is_table) {
return sw.is(':checked') ? 'html' : 'plain';
}
return sw.val();
},
tabs = $('<ul class="nav nav-tabs">')
.append($('<li class="nav-item">')
.append($('<a class="nav-link mode-html" href="#">')
.text(rcmail.gettext('htmltoggle'))))
.append($('<li class="nav-item">')
.append($('<a class="nav-link mode-plain" href="#">')
.text(rcmail.gettext('plaintoggle'))));
if (parent.is('td')) {
sw = $('input[type="checkbox"]', parent.parent().next());
is_table = true;
}
else {
sw = $('[name="editorSelector"]', obj.form);
}
// sanity check
if (sw.length != 1) {
return;
}
parent.addClass('html-editor');
editor.before(tabs);
$('a', tabs).attr('tabindex', editor.attr('tabindex'))
.on('click', function(e) {
var id = editor.attr('id'), is_html = $(this).is('.mode-html');
e.preventDefault();
if (rcmail.command('toggle-editor', {id: id, html: is_html}, '', e.originalEvent)) {
$(this).tab('show');
if (is_table) {
console.log(sw[0]);
sw.prop('checked', is_html);
}
}
})
.filter('.mode-' + mode()).tab('show');
if (is_table) {
// Hide unwanted table cells
sw.parent().parent().hide();
parent.prev().hide();
// Modify the textarea cell to use 100% width
parent.addClass('col-sm-12');
}
};
/** /**
* Wrapper for rcmail.open_window to intercept window opening * Wrapper for rcmail.open_window to intercept window opening
* and display a dialog with an iframe instead of a real window. * and display a dialog with an iframe instead of a real window.

Loading…
Cancel
Save