4 * Released under LGPL License.
5 * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
7 * License: http://www.tinymce.com/license
8 * Contributing: http://www.tinymce.com/contributing
11 /*global tinymce:true */
12 /*eslint consistent-this:0 */
14 tinymce.PluginManager.add('textcolor', function(editor) {
18 forecolor: editor.settings.forecolor_rows || editor.settings.textcolor_rows || 5,
19 backcolor: editor.settings.backcolor_rows || editor.settings.textcolor_rows || 5
22 forecolor: editor.settings.forecolor_cols || editor.settings.textcolor_cols || 8,
23 backcolor: editor.settings.backcolor_cols || editor.settings.textcolor_cols || 8
26 function getCurrentColor(format) {
29 editor.dom.getParents(editor.selection.getStart(), function(elm) {
32 if ((value = elm.style[format == 'forecolor' ? 'color' : 'background-color'])) {
40 function mapColors(type) {
41 var i, colors = [], colorMap;
45 "993300", "Burnt orange",
46 "333300", "Dark olive",
47 "003300", "Dark green",
48 "003366", "Dark azure",
49 "000080", "Navy Blue",
51 "333333", "Very dark gray",
58 "666699", "Grayish blue",
62 "99CC00", "Yellow green",
63 "339966", "Sea green",
64 "33CCCC", "Turquoise",
65 "3366FF", "Royal blue",
67 "999999", "Medium gray",
74 "993366", "Red violet",
78 "FFFF99", "Light yellow",
79 "CCFFCC", "Pale green",
80 "CCFFFF", "Pale cyan",
81 "99CCFF", "Light sky blue",
85 colorMap = editor.settings.textcolor_map || colorMap;
86 colorMap = editor.settings[type + '_map'] || colorMap;
88 for (i = 0; i < colorMap.length; i += 2) {
90 text: colorMap[i + 1],
91 color: '#' + colorMap[i]
98 function renderColorPicker() {
99 var ctrl = this, colors, color, html, last, x, y, i, id = ctrl._id, count = 0, type;
101 type = ctrl.settings.origin;
103 function getColorCellHtml(color, title) {
104 var isNoColor = color == 'transparent';
107 '<td class="mce-grid-cell' + (isNoColor ? ' mce-colorbtn-trans' : '') + '">' +
108 '<div id="' + id + '-' + (count++) + '"' +
109 ' data-mce-color="' + (color ? color : '') + '"' +
112 ' style="' + (color ? 'background-color: ' + color : '') + '"' +
113 ' title="' + tinymce.translate(title) + '">' +
114 (isNoColor ? '×' : '') +
120 colors = mapColors(type);
122 text: tinymce.translate("No color"),
126 html = '<table class="mce-grid mce-grid-border mce-colorbutton-grid" role="list" cellspacing="0"><tbody>';
127 last = colors.length - 1;
129 for (y = 0; y < rows[type]; y++) {
132 for (x = 0; x < cols[type]; x++) {
133 i = y * cols[type] + x;
139 html += getColorCellHtml(color.color, color.text);
146 if (editor.settings.color_picker_callback) {
149 '<td colspan="' + cols[type] + '" class="mce-custom-color-btn">' +
150 '<div id="' + id + '-c" class="mce-widget mce-btn mce-btn-small mce-btn-flat" ' +
151 'role="button" tabindex="-1" aria-labelledby="' + id + '-c" style="width: 100%">' +
152 '<button type="button" role="presentation" tabindex="-1">' + tinymce.translate('Custom...') + '</button>' +
160 for (x = 0; x < cols[type]; x++) {
161 html += getColorCellHtml('', 'Custom color');
167 html += '</tbody></table>';
172 function applyFormat(format, value) {
173 editor.undoManager.transact(function() {
175 editor.formatter.apply(format, {value: value});
176 editor.nodeChanged();
180 function removeFormat(format) {
181 editor.undoManager.transact(function() {
183 editor.formatter.remove(format, {value: null}, null, true);
184 editor.nodeChanged();
188 function onPanelClick(e) {
189 var buttonCtrl = this.parent(), value, type;
191 type = buttonCtrl.settings.origin;
193 function selectColor(value) {
194 buttonCtrl.hidePanel();
195 buttonCtrl.color(value);
196 applyFormat(buttonCtrl.settings.format, value);
199 function resetColor() {
200 buttonCtrl.hidePanel();
201 buttonCtrl.resetColor();
202 removeFormat(buttonCtrl.settings.format);
205 function setDivColor(div, value) {
206 div.style.background = value;
207 div.setAttribute('data-mce-color', value);
210 if (tinymce.DOM.getParent(e.target, '.mce-custom-color-btn')) {
211 buttonCtrl.hidePanel();
213 editor.settings.color_picker_callback.call(editor, function(value) {
214 var tableElm = buttonCtrl.panel.getEl().getElementsByTagName('table')[0];
215 var customColorCells, div, i;
217 customColorCells = tinymce.map(tableElm.rows[tableElm.rows.length - 1].childNodes, function(elm) {
218 return elm.firstChild;
221 for (i = 0; i < customColorCells.length; i++) {
222 div = customColorCells[i];
223 if (!div.getAttribute('data-mce-color')) {
228 // Shift colors to the right
229 // TODO: Might need to be the left on RTL
230 if (i == cols[type]) {
231 for (i = 0; i < cols[type] - 1; i++) {
232 setDivColor(customColorCells[i], customColorCells[i + 1].getAttribute('data-mce-color'));
236 setDivColor(div, value);
238 }, getCurrentColor(buttonCtrl.settings.format));
241 value = e.target.getAttribute('data-mce-color');
244 document.getElementById(this.lastId).setAttribute('aria-selected', false);
247 e.target.setAttribute('aria-selected', true);
248 this.lastId = e.target.id;
250 if (value == 'transparent') {
255 } else if (value !== null) {
256 buttonCtrl.hidePanel();
260 function onButtonClick() {
264 applyFormat(self.settings.format, self._color);
266 removeFormat(self.settings.format);
270 editor.addButton('forecolor', {
272 tooltip: 'Text color',
278 html: renderColorPicker,
279 onclick: onPanelClick
281 onclick: onButtonClick
284 editor.addButton('backcolor', {
286 tooltip: 'Background color',
287 format: 'hilitecolor',
292 html: renderColorPicker,
293 onclick: onPanelClick
295 onclick: onButtonClick