commit fe063faf0051520fcd784ee5b8be23f23df2d4c8
parent 55e9a0ee3508b1c0099c92f15f8b540d2768d05e
Author: Dan Stillman <dstillman@zotero.org>
Date: Fri, 3 Feb 2017 15:31:37 -0500
Add text color buttons to notes, and move direction to context menu
And reduce button spacing slightly to accommodate
Closes #1151
Diffstat:
4 files changed, 316 insertions(+), 13 deletions(-)
diff --git a/resource/tinymce/css/note-ui.css b/resource/tinymce/css/note-ui.css
@@ -26,8 +26,8 @@ html, body {
/* Shrink the buttons a bit */
.mce-btn-small button {
- padding-left: 4px !important;
- padding-right: 4px !important;
+ padding-left: 3px !important;
+ padding-right: 3px !important;
}
.mce-listbox button {
diff --git a/resource/tinymce/note.html b/resource/tinymce/note.html
@@ -15,16 +15,16 @@
entity_encoding: 'raw',
fix_list_elements: true,
- plugins: "autolink,code,contextmenu,directionality,link,lists,paste,searchreplace",
+ plugins: "autolink,code,contextmenu,directionality,link,lists,paste,searchreplace,textcolor",
- toolbar1: "bold italic underline strikethrough | subscript superscript | forecolor backcolor | blockquote link | %DIR% | removeformat",
- toolbar2: "formatselect | alignleft aligncenter alignright | bullist numlist outdent indent | searchreplace",
+ toolbar1: "bold italic underline strikethrough | subscript superscript | forecolor backcolor | blockquote link | removeformat",
+ toolbar2: "formatselect | alignleft aligncenter alignright | bullist numlist outdent indent | %DIR% | searchreplace",
toolbar_items_size: 'small',
menubar: false,
resize: false,
statusbar: false,
- contextmenu: "link | code",
+ contextmenu: "link | dir | code",
link_context_toolbar: true,
link_assume_external_targets: true,
@@ -36,12 +36,18 @@
// Set text direction
var dir = window.location.href.match(/dir=(ltr|rtl)/)[1];
+ var opDir = dir.split("").reverse().join("");
ed.settings.directionality = dir;
- // Include button for opposite direction, to function as a toggle
- ed.settings.toolbar1 = ed.settings.toolbar1.replace(
- "%DIR%",
- dir.split("").reverse().join("")
- );
+ ed.addMenuItem('dir', {
+ icon: opDir,
+ // TODO: Show correct label based on current line
+ text: opDir == 'rtl' ? "Right to left" : "Left to right",
+ onclick: function () {
+ ed.execCommand('mceDirection' + opDir.toUpperCase());
+ },
+ context: 'insert',
+ prependToContext: true
+ });
},
init_instance_callback: function (ed) {
diff --git a/resource/tinymce/plugins/link/plugin.js b/resource/tinymce/plugins/link/plugin.js
@@ -64,7 +64,7 @@ tinymce.PluginManager.add('link', function(editor) {
document.body.removeChild(link);
}
- function openDetachedWindow(url) { /* Added by Zotero */ editor.execCommand("ZoteroLinkClick", false, url); return;
+ function openDetachedWindow(url) { /* Added by Zotero */ editor.execCommand("ZoteroLinkClick", false, url); } /*
// Chrome and Webkit has implemented noopener and works correctly with/without popup blocker
// Firefox has it implemented noopener but when the popup blocker is activated it doesn't work
// Edge has only implemented noreferrer and it seems to remove opener as well
@@ -91,7 +91,7 @@ tinymce.PluginManager.add('link', function(editor) {
}
}
- function gotoLink(a) {
+ */function gotoLink(a) {
if (a) {
var href = getHref(a);
if (/^#/.test(href)) {
diff --git a/resource/tinymce/plugins/textcolor/plugin.js b/resource/tinymce/plugins/textcolor/plugin.js
@@ -0,0 +1,297 @@
+/**
+ * plugin.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
+
+/*global tinymce:true */
+/*eslint consistent-this:0 */
+
+tinymce.PluginManager.add('textcolor', function(editor) {
+ var cols, rows;
+
+ rows = {
+ forecolor: editor.settings.forecolor_rows || editor.settings.textcolor_rows || 5,
+ backcolor: editor.settings.backcolor_rows || editor.settings.textcolor_rows || 5
+ };
+ cols = {
+ forecolor: editor.settings.forecolor_cols || editor.settings.textcolor_cols || 8,
+ backcolor: editor.settings.backcolor_cols || editor.settings.textcolor_cols || 8
+ };
+
+ function getCurrentColor(format) {
+ var color;
+
+ editor.dom.getParents(editor.selection.getStart(), function(elm) {
+ var value;
+
+ if ((value = elm.style[format == 'forecolor' ? 'color' : 'background-color'])) {
+ color = value;
+ }
+ });
+
+ return color;
+ }
+
+ function mapColors(type) {
+ var i, colors = [], colorMap;
+
+ colorMap = [
+ "000000", "Black",
+ "993300", "Burnt orange",
+ "333300", "Dark olive",
+ "003300", "Dark green",
+ "003366", "Dark azure",
+ "000080", "Navy Blue",
+ "333399", "Indigo",
+ "333333", "Very dark gray",
+ "800000", "Maroon",
+ "FF6600", "Orange",
+ "808000", "Olive",
+ "008000", "Green",
+ "008080", "Teal",
+ "0000FF", "Blue",
+ "666699", "Grayish blue",
+ "808080", "Gray",
+ "FF0000", "Red",
+ "FF9900", "Amber",
+ "99CC00", "Yellow green",
+ "339966", "Sea green",
+ "33CCCC", "Turquoise",
+ "3366FF", "Royal blue",
+ "800080", "Purple",
+ "999999", "Medium gray",
+ "FF00FF", "Magenta",
+ "FFCC00", "Gold",
+ "FFFF00", "Yellow",
+ "00FF00", "Lime",
+ "00FFFF", "Aqua",
+ "00CCFF", "Sky blue",
+ "993366", "Red violet",
+ "FFFFFF", "White",
+ "FF99CC", "Pink",
+ "FFCC99", "Peach",
+ "FFFF99", "Light yellow",
+ "CCFFCC", "Pale green",
+ "CCFFFF", "Pale cyan",
+ "99CCFF", "Light sky blue",
+ "CC99FF", "Plum"
+ ];
+
+ colorMap = editor.settings.textcolor_map || colorMap;
+ colorMap = editor.settings[type + '_map'] || colorMap;
+
+ for (i = 0; i < colorMap.length; i += 2) {
+ colors.push({
+ text: colorMap[i + 1],
+ color: '#' + colorMap[i]
+ });
+ }
+
+ return colors;
+ }
+
+ function renderColorPicker() {
+ var ctrl = this, colors, color, html, last, x, y, i, id = ctrl._id, count = 0, type;
+
+ type = ctrl.settings.origin;
+
+ function getColorCellHtml(color, title) {
+ var isNoColor = color == 'transparent';
+
+ return (
+ '<td class="mce-grid-cell' + (isNoColor ? ' mce-colorbtn-trans' : '') + '">' +
+ '<div id="' + id + '-' + (count++) + '"' +
+ ' data-mce-color="' + (color ? color : '') + '"' +
+ ' role="option"' +
+ ' tabIndex="-1"' +
+ ' style="' + (color ? 'background-color: ' + color : '') + '"' +
+ ' title="' + tinymce.translate(title) + '">' +
+ (isNoColor ? '×' : '') +
+ '</div>' +
+ '</td>'
+ );
+ }
+
+ colors = mapColors(type);
+ colors.push({
+ text: tinymce.translate("No color"),
+ color: "transparent"
+ });
+
+ html = '<table class="mce-grid mce-grid-border mce-colorbutton-grid" role="list" cellspacing="0"><tbody>';
+ last = colors.length - 1;
+
+ for (y = 0; y < rows[type]; y++) {
+ html += '<tr>';
+
+ for (x = 0; x < cols[type]; x++) {
+ i = y * cols[type] + x;
+
+ if (i > last) {
+ html += '<td></td>';
+ } else {
+ color = colors[i];
+ html += getColorCellHtml(color.color, color.text);
+ }
+ }
+
+ html += '</tr>';
+ }
+
+ if (editor.settings.color_picker_callback) {
+ html += (
+ '<tr>' +
+ '<td colspan="' + cols[type] + '" class="mce-custom-color-btn">' +
+ '<div id="' + id + '-c" class="mce-widget mce-btn mce-btn-small mce-btn-flat" ' +
+ 'role="button" tabindex="-1" aria-labelledby="' + id + '-c" style="width: 100%">' +
+ '<button type="button" role="presentation" tabindex="-1">' + tinymce.translate('Custom...') + '</button>' +
+ '</div>' +
+ '</td>' +
+ '</tr>'
+ );
+
+ html += '<tr>';
+
+ for (x = 0; x < cols[type]; x++) {
+ html += getColorCellHtml('', 'Custom color');
+ }
+
+ html += '</tr>';
+ }
+
+ html += '</tbody></table>';
+
+ return html;
+ }
+
+ function applyFormat(format, value) {
+ editor.undoManager.transact(function() {
+ editor.focus();
+ editor.formatter.apply(format, {value: value});
+ editor.nodeChanged();
+ });
+ }
+
+ function removeFormat(format) {
+ editor.undoManager.transact(function() {
+ editor.focus();
+ editor.formatter.remove(format, {value: null}, null, true);
+ editor.nodeChanged();
+ });
+ }
+
+ function onPanelClick(e) {
+ var buttonCtrl = this.parent(), value, type;
+
+ type = buttonCtrl.settings.origin;
+
+ function selectColor(value) {
+ buttonCtrl.hidePanel();
+ buttonCtrl.color(value);
+ applyFormat(buttonCtrl.settings.format, value);
+ }
+
+ function resetColor() {
+ buttonCtrl.hidePanel();
+ buttonCtrl.resetColor();
+ removeFormat(buttonCtrl.settings.format);
+ }
+
+ function setDivColor(div, value) {
+ div.style.background = value;
+ div.setAttribute('data-mce-color', value);
+ }
+
+ if (tinymce.DOM.getParent(e.target, '.mce-custom-color-btn')) {
+ buttonCtrl.hidePanel();
+
+ editor.settings.color_picker_callback.call(editor, function(value) {
+ var tableElm = buttonCtrl.panel.getEl().getElementsByTagName('table')[0];
+ var customColorCells, div, i;
+
+ customColorCells = tinymce.map(tableElm.rows[tableElm.rows.length - 1].childNodes, function(elm) {
+ return elm.firstChild;
+ });
+
+ for (i = 0; i < customColorCells.length; i++) {
+ div = customColorCells[i];
+ if (!div.getAttribute('data-mce-color')) {
+ break;
+ }
+ }
+
+ // Shift colors to the right
+ // TODO: Might need to be the left on RTL
+ if (i == cols[type]) {
+ for (i = 0; i < cols[type] - 1; i++) {
+ setDivColor(customColorCells[i], customColorCells[i + 1].getAttribute('data-mce-color'));
+ }
+ }
+
+ setDivColor(div, value);
+ selectColor(value);
+ }, getCurrentColor(buttonCtrl.settings.format));
+ }
+
+ value = e.target.getAttribute('data-mce-color');
+ if (value) {
+ if (this.lastId) {
+ document.getElementById(this.lastId).setAttribute('aria-selected', false);
+ }
+
+ e.target.setAttribute('aria-selected', true);
+ this.lastId = e.target.id;
+
+ if (value == 'transparent') {
+ resetColor();
+ } else {
+ selectColor(value);
+ }
+ } else if (value !== null) {
+ buttonCtrl.hidePanel();
+ }
+ }
+
+ function onButtonClick() {
+ var self = this;
+
+ if (self._color) {
+ applyFormat(self.settings.format, self._color);
+ } else {
+ removeFormat(self.settings.format);
+ }
+ }
+
+ editor.addButton('forecolor', {
+ type: 'colorbutton',
+ tooltip: 'Text color',
+ format: 'forecolor',
+ panel: {
+ origin: 'forecolor',
+ role: 'application',
+ ariaRemember: true,
+ html: renderColorPicker,
+ onclick: onPanelClick
+ },
+ onclick: onButtonClick
+ });
+
+ editor.addButton('backcolor', {
+ type: 'colorbutton',
+ tooltip: 'Background color',
+ format: 'hilitecolor',
+ panel: {
+ origin: 'backcolor',
+ role: 'application',
+ ariaRemember: true,
+ html: renderColorPicker,
+ onclick: onPanelClick
+ },
+ onclick: onButtonClick
+ });
+});