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