61d411be40101bdc047441e68c0315205dbe0e59
[ckeditor.git] / _source / plugins / colordialog / dialogs / colordialog.js
1 /*
2 Copyright (c) 2003-2011, CKSource - Frederico Knabben. All rights reserved.
3 For licensing, see LICENSE.html or http://ckeditor.com/license
4 */
5
6 CKEDITOR.dialog.add( 'colordialog', function( editor )
7 {
8 // Define some shorthands.
9 var $el = CKEDITOR.dom.element,
10 $doc = CKEDITOR.document,
11 $tools = CKEDITOR.tools,
12 lang = editor.lang.colordialog;
13
14 // Reference the dialog.
15 var dialog;
16
17 var spacer =
18 {
19 type : 'html',
20 html : ' '
21 };
22
23 function clearSelected()
24 {
25 $doc.getById( selHiColorId ).removeStyle( 'background-color' );
26 dialog.getContentElement( 'picker', 'selectedColor' ).setValue( '' );
27 }
28
29 function updateSelected( evt )
30 {
31 if ( ! ( evt instanceof CKEDITOR.dom.event ) )
32 evt = new CKEDITOR.dom.event( evt );
33
34 var target = evt.getTarget(),
35 color;
36
37 if ( target.getName() == 'a' && ( color = target.getChild( 0 ).getHtml() ) )
38 dialog.getContentElement( 'picker', 'selectedColor' ).setValue( color );
39 }
40
41 function updateHighlight( event )
42 {
43 if ( ! ( event instanceof CKEDITOR.dom.event ) )
44 event = event.data;
45
46 var target = event.getTarget(),
47 color;
48
49 if ( target.getName() == 'a' && ( color = target.getChild( 0 ).getHtml() ) )
50 {
51 $doc.getById( hicolorId ).setStyle( 'background-color', color );
52 $doc.getById( hicolorTextId ).setHtml( color );
53 }
54 }
55
56 function clearHighlight()
57 {
58 $doc.getById( hicolorId ).removeStyle( 'background-color' );
59 $doc.getById( hicolorTextId ).setHtml( ' ' );
60 }
61
62 var onMouseout = $tools.addFunction( clearHighlight ),
63 onClick = updateSelected,
64 onClickHandler = CKEDITOR.tools.addFunction( onClick ),
65 onFocus = updateHighlight,
66 onBlur = clearHighlight;
67
68 var onKeydownHandler = CKEDITOR.tools.addFunction( function( ev )
69 {
70 ev = new CKEDITOR.dom.event( ev );
71 var element = ev.getTarget();
72 var relative, nodeToMove;
73 var keystroke = ev.getKeystroke(),
74 rtl = editor.lang.dir == 'rtl';
75
76 switch ( keystroke )
77 {
78 // UP-ARROW
79 case 38 :
80 // relative is TR
81 if ( ( relative = element.getParent().getParent().getPrevious() ) )
82 {
83 nodeToMove = relative.getChild( [element.getParent().getIndex(), 0] );
84 nodeToMove.focus();
85 onBlur( ev, element );
86 onFocus( ev, nodeToMove );
87 }
88 ev.preventDefault();
89 break;
90 // DOWN-ARROW
91 case 40 :
92 // relative is TR
93 if ( ( relative = element.getParent().getParent().getNext() ) )
94 {
95 nodeToMove = relative.getChild( [ element.getParent().getIndex(), 0 ] );
96 if ( nodeToMove && nodeToMove.type == 1 )
97 {
98 nodeToMove.focus();
99 onBlur( ev, element );
100 onFocus( ev, nodeToMove );
101 }
102 }
103 ev.preventDefault();
104 break;
105 // SPACE
106 // ENTER is already handled as onClick
107 case 32 :
108 onClick( ev );
109 ev.preventDefault();
110 break;
111
112 // RIGHT-ARROW
113 case rtl ? 37 : 39 :
114 // relative is TD
115 if ( ( relative = element.getParent().getNext() ) )
116 {
117 nodeToMove = relative.getChild( 0 );
118 if ( nodeToMove.type == 1 )
119 {
120 nodeToMove.focus();
121 onBlur( ev, element );
122 onFocus( ev, nodeToMove );
123 ev.preventDefault( true );
124 }
125 else
126 onBlur( null, element );
127 }
128 // relative is TR
129 else if ( ( relative = element.getParent().getParent().getNext() ) )
130 {
131 nodeToMove = relative.getChild( [ 0, 0 ] );
132 if ( nodeToMove && nodeToMove.type == 1 )
133 {
134 nodeToMove.focus();
135 onBlur( ev, element );
136 onFocus( ev, nodeToMove );
137 ev.preventDefault( true );
138 }
139 else
140 onBlur( null, element );
141 }
142 break;
143
144 // LEFT-ARROW
145 case rtl ? 39 : 37 :
146 // relative is TD
147 if ( ( relative = element.getParent().getPrevious() ) )
148 {
149 nodeToMove = relative.getChild( 0 );
150 nodeToMove.focus();
151 onBlur( ev, element );
152 onFocus( ev, nodeToMove );
153 ev.preventDefault( true );
154 }
155 // relative is TR
156 else if ( ( relative = element.getParent().getParent().getPrevious() ) )
157 {
158 nodeToMove = relative.getLast().getChild( 0 );
159 nodeToMove.focus();
160 onBlur( ev, element );
161 onFocus( ev, nodeToMove );
162 ev.preventDefault( true );
163 }
164 else
165 onBlur( null, element );
166 break;
167 default :
168 // Do not stop not handled events.
169 return;
170 }
171 });
172
173 function createColorTable()
174 {
175 // Create the base colors array.
176 var aColors = [ '00', '33', '66', '99', 'cc', 'ff' ];
177
178 // This function combines two ranges of three values from the color array into a row.
179 function appendColorRow( rangeA, rangeB )
180 {
181 for ( var i = rangeA ; i < rangeA + 3 ; i++ )
182 {
183 var row = table.$.insertRow( -1 );
184
185 for ( var j = rangeB ; j < rangeB + 3 ; j++ )
186 {
187 for ( var n = 0 ; n < 6 ; n++ )
188 {
189 appendColorCell( row, '#' + aColors[j] + aColors[n] + aColors[i] );
190 }
191 }
192 }
193 }
194
195 // This function create a single color cell in the color table.
196 function appendColorCell( targetRow, color )
197 {
198 var cell = new $el( targetRow.insertCell( -1 ) );
199 cell.setAttribute( 'class', 'ColorCell' );
200 cell.setStyle( 'background-color', color );
201
202 cell.setStyle( 'width', '15px' );
203 cell.setStyle( 'height', '15px' );
204
205 var index = cell.$.cellIndex + 1 + 18 * targetRow.rowIndex;
206 cell.append( CKEDITOR.dom.element.createFromHtml(
207 '<a href="javascript: void(0);" role="option"' +
208 ' aria-posinset="' + index + '"' +
209 ' aria-setsize="' + 13 * 18 + '"' +
210 ' style="cursor: pointer;display:block;width:100%;height:100% " title="'+ CKEDITOR.tools.htmlEncode( color )+ '"' +
211 ' onkeydown="CKEDITOR.tools.callFunction( ' + onKeydownHandler + ', event, this )"' +
212 ' onclick="CKEDITOR.tools.callFunction(' + onClickHandler + ', event, this ); return false;"' +
213 ' tabindex="-1"><span class="cke_voice_label">' + color + '</span>&nbsp;</a>', CKEDITOR.document ) );
214 }
215
216 appendColorRow( 0, 0 );
217 appendColorRow( 3, 0 );
218 appendColorRow( 0, 3 );
219 appendColorRow( 3, 3 );
220
221 // Create the last row.
222 var oRow = table.$.insertRow(-1) ;
223
224 // Create the gray scale colors cells.
225 for ( var n = 0 ; n < 6 ; n++ )
226 {
227 appendColorCell( oRow, '#' + aColors[n] + aColors[n] + aColors[n] ) ;
228 }
229
230 // Fill the row with black cells.
231 for ( var i = 0 ; i < 12 ; i++ )
232 {
233 appendColorCell( oRow, '#000000' ) ;
234 }
235 }
236
237 var table = new $el( 'table' );
238 createColorTable();
239 var html = table.getHtml();
240
241 var numbering = function( id )
242 {
243 return CKEDITOR.tools.getNextId() + '_' + id;
244 },
245 hicolorId = numbering( 'hicolor' ),
246 hicolorTextId = numbering( 'hicolortext' ),
247 selHiColorId = numbering( 'selhicolor' ),
248 tableLabelId = numbering( 'color_table_label' );
249
250 return {
251 title : lang.title,
252 minWidth : 360,
253 minHeight : 220,
254 onLoad : function()
255 {
256 // Update reference.
257 dialog = this;
258 },
259 contents : [
260 {
261 id : 'picker',
262 label : lang.title,
263 accessKey : 'I',
264 elements :
265 [
266 {
267 type : 'hbox',
268 padding : 0,
269 widths : [ '70%', '10%', '30%' ],
270 children :
271 [
272 {
273 type : 'html',
274 html : '<table role="listbox" aria-labelledby="' + tableLabelId + '" onmouseout="CKEDITOR.tools.callFunction( ' + onMouseout + ' );">' +
275 ( !CKEDITOR.env.webkit ? html : '' ) +
276 '</table><span id="' + tableLabelId + '" class="cke_voice_label">' + lang.options +'</span>',
277 onLoad : function()
278 {
279 var table = CKEDITOR.document.getById( this.domId );
280 table.on( 'mouseover', updateHighlight );
281 // In WebKit, the table content must be inserted after this event call (#6150)
282 CKEDITOR.env.webkit && table.setHtml( html );
283 },
284 focus: function()
285 {
286 var firstColor = this.getElement().getElementsByTag( 'a' ).getItem( 0 );
287 firstColor.focus();
288 }
289 },
290 spacer,
291 {
292 type : 'vbox',
293 padding : 0,
294 widths : [ '70%', '5%', '25%' ],
295 children :
296 [
297 {
298 type : 'html',
299 html : '<span>' + lang.highlight +'</span>\
300 <div id="' + hicolorId + '" style="border: 1px solid; height: 74px; width: 74px;"></div>\
301 <div id="' + hicolorTextId + '">&nbsp;</div><span>' + lang.selected + '</span>\
302 <div id="' + selHiColorId + '" style="border: 1px solid; height: 20px; width: 74px;"></div>'
303 },
304 {
305 type : 'text',
306 label : lang.selected,
307 labelStyle: 'display:none',
308 id : 'selectedColor',
309 style : 'width: 74px',
310 onChange : function()
311 {
312 // Try to update color preview with new value. If fails, then set it no none.
313 try
314 {
315 $doc.getById( selHiColorId ).setStyle( 'background-color', this.getValue() );
316 }
317 catch ( e )
318 {
319 clearSelected();
320 }
321 }
322 },
323 spacer,
324 {
325 type : 'button',
326 id : 'clear',
327 style : 'margin-top: 5px',
328 label : lang.clear,
329 onClick : clearSelected
330 }
331 ]
332 }
333 ]
334 }
335 ]
336 }
337 ]
338 };
339 }
340 );