JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
vanilla ckeditor-3.6.3
[ckeditor.git] / _source / plugins / colordialog / dialogs / colordialog.js
1 /*\r
2 Copyright (c) 2003-2012, CKSource - Frederico Knabben. All rights reserved.\r
3 For licensing, see LICENSE.html or http://ckeditor.com/license\r
4 */\r
5 \r
6 CKEDITOR.dialog.add( 'colordialog', function( editor )\r
7         {\r
8                 // Define some shorthands.\r
9                 var $el = CKEDITOR.dom.element,\r
10                         $doc = CKEDITOR.document,\r
11                         lang = editor.lang.colordialog;\r
12 \r
13                 // Reference the dialog.\r
14                 var dialog;\r
15 \r
16                 var spacer =\r
17                 {\r
18                         type : 'html',\r
19                         html : ' '\r
20                 };\r
21 \r
22                 var selected;\r
23 \r
24                 function clearSelected()\r
25                 {\r
26                         $doc.getById( selHiColorId ).removeStyle( 'background-color' );\r
27                         dialog.getContentElement( 'picker', 'selectedColor' ).setValue( '' );\r
28                         selected && selected.removeAttribute( 'aria-selected' );\r
29                         selected = null;\r
30                 }\r
31 \r
32                 function updateSelected( evt )\r
33                 {\r
34                         var target = evt.data.getTarget(),\r
35                                 color;\r
36 \r
37                         if ( target.getName() == 'td' &&\r
38                                  ( color = target.getChild( 0 ).getHtml() ) )\r
39                         {\r
40                                 selected = target;\r
41                                 selected.setAttribute( 'aria-selected', true );\r
42                                 dialog.getContentElement( 'picker', 'selectedColor' ).setValue( color );\r
43                         }\r
44                 }\r
45 \r
46                 // Basing black-white decision off of luma scheme using the Rec. 709 version\r
47                 function whiteOrBlack( color )\r
48                 {\r
49                         color = color.replace( /^#/, '' );\r
50                         for ( var i = 0, rgb = []; i <= 2; i++ )\r
51                                 rgb[i] = parseInt( color.substr( i * 2, 2 ), 16 );\r
52                         var luma = (0.2126 * rgb[0]) + (0.7152 * rgb[1]) + (0.0722 * rgb[2]);\r
53                         return '#' + ( luma >= 165 ? '000' : 'fff' );\r
54                 }\r
55 \r
56                 // Distinguish focused and hover states.\r
57                 var focused, hovered;\r
58 \r
59                 // Apply highlight style.\r
60                 function updateHighlight( event )\r
61                 {\r
62                         // Convert to event.\r
63                         !event.name && ( event = new CKEDITOR.event( event ) );\r
64 \r
65                         var isFocus = !(/mouse/).test( event.name ),\r
66                                 target = event.data.getTarget(),\r
67                                 color;\r
68 \r
69                         if ( target.getName() == 'td' && ( color = target.getChild( 0 ).getHtml() ) )\r
70                         {\r
71                                 removeHighlight( event );\r
72 \r
73                                 isFocus ? focused = target : hovered = target;\r
74 \r
75                                 // Apply outline style to show focus.\r
76                                 if ( isFocus )\r
77                                 {\r
78                                         target.setStyle( 'border-color', whiteOrBlack( color ) );\r
79                                         target.setStyle( 'border-style', 'dotted' );\r
80                                 }\r
81 \r
82                                 $doc.getById( hicolorId ).setStyle( 'background-color', color );\r
83                                 $doc.getById( hicolorTextId ).setHtml( color );\r
84                         }\r
85                 }\r
86 \r
87                 function clearHighlight()\r
88                 {\r
89                         var color = focused.getChild( 0 ).getHtml();\r
90                         focused.setStyle( 'border-color', color );\r
91                         focused.setStyle( 'border-style', 'solid' );\r
92                         $doc.getById( hicolorId ).removeStyle( 'background-color' );\r
93                         $doc.getById( hicolorTextId ).setHtml( '&nbsp;' );\r
94                         focused = null;\r
95                 }\r
96 \r
97                 // Remove previously focused style.\r
98                 function removeHighlight( event )\r
99                 {\r
100                         var isFocus = !(/mouse/).test( event.name ),\r
101                                 target = isFocus && focused;\r
102 \r
103                         if ( target )\r
104                         {\r
105                                 var color = target.getChild( 0 ).getHtml();\r
106                                 target.setStyle( 'border-color', color );\r
107                                 target.setStyle( 'border-style', 'solid' );\r
108                         }\r
109 \r
110                         if ( ! ( focused || hovered ) )\r
111                         {\r
112                                 $doc.getById( hicolorId ).removeStyle( 'background-color' );\r
113                                 $doc.getById( hicolorTextId ).setHtml( '&nbsp;' );\r
114                         }\r
115                 }\r
116 \r
117                 function onKeyStrokes( evt )\r
118                 {\r
119                         var domEvt = evt.data;\r
120 \r
121                         var element = domEvt.getTarget();\r
122                         var relative, nodeToMove;\r
123                         var keystroke = domEvt.getKeystroke(),\r
124                                 rtl = editor.lang.dir == 'rtl';\r
125 \r
126                         switch ( keystroke )\r
127                         {\r
128                                 // UP-ARROW\r
129                                 case 38 :\r
130                                         // relative is TR\r
131                                         if ( ( relative = element.getParent().getPrevious() ) )\r
132                                         {\r
133                                                 nodeToMove = relative.getChild( [ element.getIndex() ] );\r
134                                                 nodeToMove.focus();\r
135                                         }\r
136                                         domEvt.preventDefault();\r
137                                         break;\r
138                                 // DOWN-ARROW\r
139                                 case 40 :\r
140                                         // relative is TR\r
141                                         if ( ( relative = element.getParent().getNext() ) )\r
142                                         {\r
143                                                 nodeToMove = relative.getChild( [ element.getIndex() ] );\r
144                                                 if ( nodeToMove && nodeToMove.type == 1 )\r
145                                                 {\r
146                                                         nodeToMove.focus();\r
147                                                 }\r
148                                         }\r
149                                         domEvt.preventDefault();\r
150                                         break;\r
151 \r
152                                 // SPACE\r
153                                 // ENTER\r
154                                 case 32 :\r
155                                 case 13 :\r
156                                         updateSelected( evt );\r
157                                         domEvt.preventDefault();\r
158                                         break;\r
159 \r
160                                 // RIGHT-ARROW\r
161                                 case rtl ? 37 : 39 :\r
162                                         // relative is TD\r
163                                         if ( ( nodeToMove = element.getNext() ) )\r
164                                         {\r
165                                                 if ( nodeToMove.type == 1 )\r
166                                                 {\r
167                                                         nodeToMove.focus();\r
168                                                         domEvt.preventDefault( true );\r
169                                                 }\r
170                                         }\r
171                                         // relative is TR\r
172                                         else if ( ( relative = element.getParent().getNext() ) )\r
173                                         {\r
174                                                 nodeToMove = relative.getChild( [ 0 ] );\r
175                                                 if ( nodeToMove && nodeToMove.type == 1 )\r
176                                                 {\r
177                                                         nodeToMove.focus();\r
178                                                         domEvt.preventDefault( true );\r
179                                                 }\r
180                                         }\r
181                                         break;\r
182 \r
183                                 // LEFT-ARROW\r
184                                 case rtl ? 39 : 37 :\r
185                                         // relative is TD\r
186                                         if ( ( nodeToMove = element.getPrevious() ) )\r
187                                         {\r
188                                                 nodeToMove.focus();\r
189                                                 domEvt.preventDefault( true );\r
190                                         }\r
191                                         // relative is TR\r
192                                         else if ( ( relative = element.getParent().getPrevious() ) )\r
193                                         {\r
194                                                 nodeToMove = relative.getLast();\r
195                                                 nodeToMove.focus();\r
196                                                 domEvt.preventDefault( true );\r
197                                         }\r
198                                         break;\r
199                                 default :\r
200                                         // Do not stop not handled events.\r
201                                         return;\r
202                         }\r
203                 }\r
204 \r
205                 function createColorTable()\r
206                 {\r
207                         table = CKEDITOR.dom.element.createFromHtml\r
208                         (\r
209                                 '<table tabIndex="-1" aria-label="' + lang.options + '"' +\r
210                                 ' role="grid" style="border-collapse:separate;" cellspacing="0">' +\r
211                                 '<caption class="cke_voice_label">' + lang.options + '</caption>' +\r
212                                 '<tbody role="presentation"></tbody></table>'\r
213                         );\r
214 \r
215                         table.on( 'mouseover', updateHighlight );\r
216                         table.on( 'mouseout', removeHighlight );\r
217 \r
218                         // Create the base colors array.\r
219                         var aColors = [ '00', '33', '66', '99', 'cc', 'ff' ];\r
220 \r
221                         // This function combines two ranges of three values from the color array into a row.\r
222                         function appendColorRow( rangeA, rangeB )\r
223                         {\r
224                                 for ( var i = rangeA ; i < rangeA + 3 ; i++ )\r
225                                 {\r
226                                         var row = new $el( table.$.insertRow( -1 ) );\r
227                                         row.setAttribute( 'role', 'row' );\r
228 \r
229                                         for ( var j = rangeB ; j < rangeB + 3 ; j++ )\r
230                                         {\r
231                                                 for ( var n = 0 ; n < 6 ; n++ )\r
232                                                 {\r
233                                                         appendColorCell( row.$, '#' + aColors[j] + aColors[n] + aColors[i] );\r
234                                                 }\r
235                                         }\r
236                                 }\r
237                         }\r
238 \r
239                         // This function create a single color cell in the color table.\r
240                         function appendColorCell( targetRow, color )\r
241                         {\r
242                                 var cell = new $el( targetRow.insertCell( -1 ) );\r
243                                 cell.setAttribute( 'class', 'ColorCell' );\r
244                                 cell.setAttribute( 'tabIndex', -1 );\r
245                                 cell.setAttribute( 'role', 'gridcell' );\r
246 \r
247                                 cell.on( 'keydown', onKeyStrokes );\r
248                                 cell.on( 'click', updateSelected );\r
249                                 cell.on( 'focus', updateHighlight );\r
250                                 cell.on( 'blur', removeHighlight );\r
251 \r
252                                 cell.setStyle( 'background-color', color );\r
253                                 cell.setStyle( 'border', '1px solid ' + color );\r
254 \r
255                                 cell.setStyle( 'width', '14px' );\r
256                                 cell.setStyle( 'height', '14px' );\r
257 \r
258                                 var colorLabel = numbering( 'color_table_cell' );\r
259                                 cell.setAttribute( 'aria-labelledby',colorLabel );\r
260                                 cell.append( CKEDITOR.dom.element.createFromHtml( '<span id="' + colorLabel + '" class="cke_voice_label">' + color + '</span>', CKEDITOR.document ) );\r
261                         }\r
262 \r
263                         appendColorRow( 0, 0 );\r
264                         appendColorRow( 3, 0 );\r
265                         appendColorRow( 0, 3 );\r
266                         appendColorRow( 3, 3 );\r
267 \r
268                         // Create the last row.\r
269                         var oRow = new $el( table.$.insertRow( -1 ) ) ;\r
270                         oRow.setAttribute( 'role', 'row' );\r
271 \r
272                         // Create the gray scale colors cells.\r
273                         for ( var n = 0 ; n < 6 ; n++ )\r
274                         {\r
275                                 appendColorCell( oRow.$, '#' + aColors[n] + aColors[n] + aColors[n] ) ;\r
276                         }\r
277 \r
278                         // Fill the row with black cells.\r
279                         for ( var i = 0 ; i < 12 ; i++ )\r
280                         {\r
281                                 appendColorCell( oRow.$, '#000000' ) ;\r
282                         }\r
283                 }\r
284 \r
285                 var numbering = function( id )\r
286                         {\r
287                                 return CKEDITOR.tools.getNextId() + '_' + id;\r
288                         },\r
289                         hicolorId = numbering( 'hicolor' ),\r
290                         hicolorTextId = numbering( 'hicolortext' ),\r
291                         selHiColorId = numbering( 'selhicolor' ),\r
292                         table;\r
293 \r
294                 createColorTable();\r
295 \r
296                 return {\r
297                         title : lang.title,\r
298                         minWidth : 360,\r
299                         minHeight : 220,\r
300                         onLoad : function()\r
301                         {\r
302                                 // Update reference.\r
303                                 dialog = this;\r
304                         },\r
305                         onHide : function()\r
306                         {\r
307                                 clearSelected();\r
308                                 clearHighlight();\r
309                         },\r
310                         contents : [\r
311                                 {\r
312                                         id : 'picker',\r
313                                         label : lang.title,\r
314                                         accessKey : 'I',\r
315                                         elements :\r
316                                         [\r
317                                                 {\r
318                                                         type : 'hbox',\r
319                                                         padding : 0,\r
320                                                         widths : [ '70%', '10%', '30%' ],\r
321                                                         children :\r
322                                                         [\r
323                                                                 {\r
324                                                                         type : 'html',\r
325                                                                         html :  '<div></div>',\r
326                                                                         onLoad : function()\r
327                                                                         {\r
328                                                                                 CKEDITOR.document.getById( this.domId ).append( table );\r
329                                                                         },\r
330                                                                         focus : function()\r
331                                                                         {\r
332                                                                                 // Restore the previously focused cell,\r
333                                                                                 // otherwise put the initial focus on the first table cell.\r
334                                                                                 ( focused || this.getElement().getElementsByTag( 'td' ).getItem( 0 ) ).focus();\r
335                                                                         }\r
336                                                                 },\r
337                                                                 spacer,\r
338                                                                 {\r
339                                                                         type : 'vbox',\r
340                                                                         padding : 0,\r
341                                                                         widths : [ '70%', '5%', '25%' ],\r
342                                                                         children :\r
343                                                                         [\r
344                                                                                 {\r
345                                                                                         type : 'html',\r
346                                                                                         html : '<span>' + lang.highlight +'</span>\\r
347                                                                                                 <div id="' + hicolorId + '" style="border: 1px solid; height: 74px; width: 74px;"></div>\\r
348                                                                                                 <div id="' + hicolorTextId + '">&nbsp;</div><span>' + lang.selected + '</span>\\r
349                                                                                                 <div id="' + selHiColorId + '" style="border: 1px solid; height: 20px; width: 74px;"></div>'\r
350                                                                                 },\r
351                                                                                 {\r
352                                                                                         type : 'text',\r
353                                                                                         label : lang.selected,\r
354                                                                                         labelStyle: 'display:none',\r
355                                                                                         id : 'selectedColor',\r
356                                                                                         style : 'width: 74px',\r
357                                                                                         onChange : function()\r
358                                                                                         {\r
359                                                                                                 // Try to update color preview with new value. If fails, then set it no none.\r
360                                                                                                 try\r
361                                                                                                 {\r
362                                                                                                         $doc.getById( selHiColorId ).setStyle( 'background-color', this.getValue() );\r
363                                                                                                 }\r
364                                                                                                 catch ( e )\r
365                                                                                                 {\r
366                                                                                                         clearSelected();\r
367                                                                                                 }\r
368                                                                                         }\r
369                                                                                 },\r
370                                                                                 spacer,\r
371                                                                                 {\r
372                                                                                         type : 'button',\r
373                                                                                         id : 'clear',\r
374                                                                                         style : 'margin-top: 5px',\r
375                                                                                         label : lang.clear,\r
376                                                                                         onClick : clearSelected\r
377                                                                                 }\r
378                                                                         ]\r
379                                                                 }\r
380                                                         ]\r
381                                                 }\r
382                                         ]\r
383                                 }\r
384                         ]\r
385                 };\r
386         }\r
387         );\r