|
1 /** |
|
2 * plugin.js |
|
3 * |
|
4 * Copyright, Moxiecode Systems AB |
|
5 * Released under LGPL License. |
|
6 * |
|
7 * License: http://www.tinymce.com/license |
|
8 * Contributing: http://www.tinymce.com/contributing |
|
9 */ |
|
10 |
|
11 /*global tinymce:true */ |
|
12 /*eslint consistent-this:0 */ |
|
13 |
|
14 tinymce.PluginManager.add('textcolor', function(editor) { |
|
15 var cols, rows; |
|
16 |
|
17 rows = editor.settings.textcolor_rows || 5; |
|
18 cols = editor.settings.textcolor_cols || 8; |
|
19 |
|
20 function getCurrentColor(format) { |
|
21 var color; |
|
22 |
|
23 editor.dom.getParents(editor.selection.getStart(), function(elm) { |
|
24 var value; |
|
25 |
|
26 if ((value = elm.style[format == 'forecolor' ? 'color' : 'background-color'])) { |
|
27 color = value; |
|
28 } |
|
29 }); |
|
30 |
|
31 return color; |
|
32 } |
|
33 |
|
34 function mapColors() { |
|
35 var i, colors = [], colorMap; |
|
36 |
|
37 colorMap = editor.settings.textcolor_map || [ |
|
38 "000000", "Black", |
|
39 "993300", "Burnt orange", |
|
40 "333300", "Dark olive", |
|
41 "003300", "Dark green", |
|
42 "003366", "Dark azure", |
|
43 "000080", "Navy Blue", |
|
44 "333399", "Indigo", |
|
45 "333333", "Very dark gray", |
|
46 "800000", "Maroon", |
|
47 "FF6600", "Orange", |
|
48 "808000", "Olive", |
|
49 "008000", "Green", |
|
50 "008080", "Teal", |
|
51 "0000FF", "Blue", |
|
52 "666699", "Grayish blue", |
|
53 "808080", "Gray", |
|
54 "FF0000", "Red", |
|
55 "FF9900", "Amber", |
|
56 "99CC00", "Yellow green", |
|
57 "339966", "Sea green", |
|
58 "33CCCC", "Turquoise", |
|
59 "3366FF", "Royal blue", |
|
60 "800080", "Purple", |
|
61 "999999", "Medium gray", |
|
62 "FF00FF", "Magenta", |
|
63 "FFCC00", "Gold", |
|
64 "FFFF00", "Yellow", |
|
65 "00FF00", "Lime", |
|
66 "00FFFF", "Aqua", |
|
67 "00CCFF", "Sky blue", |
|
68 "993366", "Red violet", |
|
69 "FFFFFF", "White", |
|
70 "FF99CC", "Pink", |
|
71 "FFCC99", "Peach", |
|
72 "FFFF99", "Light yellow", |
|
73 "CCFFCC", "Pale green", |
|
74 "CCFFFF", "Pale cyan", |
|
75 "99CCFF", "Light sky blue", |
|
76 "CC99FF", "Plum" |
|
77 ]; |
|
78 |
|
79 for (i = 0; i < colorMap.length; i += 2) { |
|
80 colors.push({ |
|
81 text: colorMap[i + 1], |
|
82 color: '#' + colorMap[i] |
|
83 }); |
|
84 } |
|
85 |
|
86 return colors; |
|
87 } |
|
88 |
|
89 function renderColorPicker() { |
|
90 var ctrl = this, colors, color, html, last, x, y, i, id = ctrl._id, count = 0; |
|
91 |
|
92 function getColorCellHtml(color, title) { |
|
93 var isNoColor = color == 'transparent'; |
|
94 |
|
95 return ( |
|
96 '<td class="mce-grid-cell' + (isNoColor ? ' mce-colorbtn-trans' : '') + '">' + |
|
97 '<div id="' + id + '-' + (count++) + '"' + |
|
98 ' data-mce-color="' + (color ? color : '') + '"' + |
|
99 ' role="option"' + |
|
100 ' tabIndex="-1"' + |
|
101 ' style="' + (color ? 'background-color: ' + color : '') + '"' + |
|
102 ' title="' + tinymce.translate(title) + '">' + |
|
103 (isNoColor ? '×' : '') + |
|
104 '</div>' + |
|
105 '</td>' |
|
106 ); |
|
107 } |
|
108 |
|
109 colors = mapColors(); |
|
110 colors.push({ |
|
111 text: tinymce.translate("No color"), |
|
112 color: "transparent" |
|
113 }); |
|
114 |
|
115 html = '<table class="mce-grid mce-grid-border mce-colorbutton-grid" role="list" cellspacing="0"><tbody>'; |
|
116 last = colors.length - 1; |
|
117 |
|
118 for (y = 0; y < rows; y++) { |
|
119 html += '<tr>'; |
|
120 |
|
121 for (x = 0; x < cols; x++) { |
|
122 i = y * cols + x; |
|
123 |
|
124 if (i > last) { |
|
125 html += '<td></td>'; |
|
126 } else { |
|
127 color = colors[i]; |
|
128 html += getColorCellHtml(color.color, color.text); |
|
129 } |
|
130 } |
|
131 |
|
132 html += '</tr>'; |
|
133 } |
|
134 |
|
135 if (editor.settings.color_picker_callback) { |
|
136 html += ( |
|
137 '<tr>' + |
|
138 '<td colspan="' + cols + '" class="mce-custom-color-btn">' + |
|
139 '<div id="' + id + '-c" class="mce-widget mce-btn mce-btn-small mce-btn-flat" ' + |
|
140 'role="button" tabindex="-1" aria-labelledby="' + id + '-c" style="width: 100%">' + |
|
141 '<button type="button" role="presentation" tabindex="-1">' + tinymce.translate('Custom...') + '</button>' + |
|
142 '</div>' + |
|
143 '</td>' + |
|
144 '</tr>' |
|
145 ); |
|
146 |
|
147 html += '<tr>'; |
|
148 |
|
149 for (x = 0; x < cols; x++) { |
|
150 html += getColorCellHtml('', 'Custom color'); |
|
151 } |
|
152 |
|
153 html += '</tr>'; |
|
154 } |
|
155 |
|
156 html += '</tbody></table>'; |
|
157 |
|
158 return html; |
|
159 } |
|
160 |
|
161 function applyFormat(format, value) { |
|
162 editor.undoManager.transact(function() { |
|
163 editor.focus(); |
|
164 editor.formatter.apply(format, {value: value}); |
|
165 editor.nodeChanged(); |
|
166 }); |
|
167 } |
|
168 |
|
169 function removeFormat(format) { |
|
170 editor.undoManager.transact(function() { |
|
171 editor.focus(); |
|
172 editor.formatter.remove(format, {value: null}, null, true); |
|
173 editor.nodeChanged(); |
|
174 }); |
|
175 } |
|
176 |
|
177 function onPanelClick(e) { |
|
178 var buttonCtrl = this.parent(), value; |
|
179 |
|
180 function selectColor(value) { |
|
181 buttonCtrl.hidePanel(); |
|
182 buttonCtrl.color(value); |
|
183 applyFormat(buttonCtrl.settings.format, value); |
|
184 } |
|
185 |
|
186 function resetColor() { |
|
187 buttonCtrl.hidePanel(); |
|
188 buttonCtrl.resetColor(); |
|
189 removeFormat(buttonCtrl.settings.format); |
|
190 } |
|
191 |
|
192 function setDivColor(div, value) { |
|
193 div.style.background = value; |
|
194 div.setAttribute('data-mce-color', value); |
|
195 } |
|
196 |
|
197 if (tinymce.DOM.getParent(e.target, '.mce-custom-color-btn')) { |
|
198 buttonCtrl.hidePanel(); |
|
199 |
|
200 editor.settings.color_picker_callback.call(editor, function(value) { |
|
201 var tableElm = buttonCtrl.panel.getEl().getElementsByTagName('table')[0]; |
|
202 var customColorCells, div, i; |
|
203 |
|
204 customColorCells = tinymce.map(tableElm.rows[tableElm.rows.length - 1].childNodes, function(elm) { |
|
205 return elm.firstChild; |
|
206 }); |
|
207 |
|
208 for (i = 0; i < customColorCells.length; i++) { |
|
209 div = customColorCells[i]; |
|
210 if (!div.getAttribute('data-mce-color')) { |
|
211 break; |
|
212 } |
|
213 } |
|
214 |
|
215 // Shift colors to the right |
|
216 // TODO: Might need to be the left on RTL |
|
217 if (i == cols) { |
|
218 for (i = 0; i < cols - 1; i++) { |
|
219 setDivColor(customColorCells[i], customColorCells[i + 1].getAttribute('data-mce-color')); |
|
220 } |
|
221 } |
|
222 |
|
223 setDivColor(div, value); |
|
224 selectColor(value); |
|
225 }, getCurrentColor(buttonCtrl.settings.format)); |
|
226 } |
|
227 |
|
228 value = e.target.getAttribute('data-mce-color'); |
|
229 if (value) { |
|
230 if (this.lastId) { |
|
231 document.getElementById(this.lastId).setAttribute('aria-selected', false); |
|
232 } |
|
233 |
|
234 e.target.setAttribute('aria-selected', true); |
|
235 this.lastId = e.target.id; |
|
236 |
|
237 if (value == 'transparent') { |
|
238 resetColor(); |
|
239 } else { |
|
240 selectColor(value); |
|
241 } |
|
242 } else if (value !== null) { |
|
243 buttonCtrl.hidePanel(); |
|
244 } |
|
245 } |
|
246 |
|
247 function onButtonClick() { |
|
248 var self = this; |
|
249 |
|
250 if (self._color) { |
|
251 applyFormat(self.settings.format, self._color); |
|
252 } else { |
|
253 removeFormat(self.settings.format); |
|
254 } |
|
255 } |
|
256 |
|
257 editor.addButton('forecolor', { |
|
258 type: 'colorbutton', |
|
259 tooltip: 'Text color', |
|
260 format: 'forecolor', |
|
261 panel: { |
|
262 role: 'application', |
|
263 ariaRemember: true, |
|
264 html: renderColorPicker, |
|
265 onclick: onPanelClick |
|
266 }, |
|
267 onclick: onButtonClick |
|
268 }); |
|
269 |
|
270 editor.addButton('backcolor', { |
|
271 type: 'colorbutton', |
|
272 tooltip: 'Background color', |
|
273 format: 'hilitecolor', |
|
274 panel: { |
|
275 role: 'application', |
|
276 ariaRemember: true, |
|
277 html: renderColorPicker, |
|
278 onclick: onPanelClick |
|
279 }, |
|
280 onclick: onButtonClick |
|
281 }); |
|
282 }); |