1 /* 2 Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved. 3 For licensing, see LICENSE.html or http://ckeditor.com/license 4 */ 5 6 CKEDITOR.dialog.add( 'specialchar', function( editor ) 7 { 8 /** 9 * Simulate "this" of a dialog for non-dialog events. 10 * @type {CKEDITOR.dialog} 11 */ 12 var dialog; 13 var onChoice = function( evt ) 14 { 15 var target, value; 16 if ( evt.data ) 17 target = evt.data.getTarget(); 18 else 19 target = new CKEDITOR.dom.element( evt ); 20 21 if ( target.getName() == 'a' && ( value = target.getChild( 0 ).getHtml() ) ) 22 { 23 target.removeClass( "cke_light_background" ); 24 dialog.hide(); 25 editor.insertHtml( value ); 26 } 27 }; 28 29 var onClick = CKEDITOR.tools.addFunction( onChoice ); 30 31 var focusedNode; 32 33 var onFocus = function( evt, target ) 34 { 35 var value; 36 target = target || evt.data.getTarget(); 37 38 if ( target.getName() == 'span' ) 39 target = target.getParent(); 40 41 if ( target.getName() == 'a' && ( value = target.getChild( 0 ).getHtml() ) ) 42 { 43 // Trigger blur manually if there is focused node. 44 if ( focusedNode ) 45 onBlur( null, focusedNode ); 46 47 var htmlPreview = dialog.getContentElement( 'info', 'htmlPreview' ).getElement(); 48 49 dialog.getContentElement( 'info', 'charPreview' ).getElement().setHtml( value ); 50 htmlPreview.setHtml( CKEDITOR.tools.htmlEncode( value ) ); 51 target.getParent().addClass( "cke_light_background" ); 52 53 // Memorize focused node. 54 focusedNode = target; 55 } 56 }; 57 58 var onBlur = function( evt, target ) 59 { 60 target = target || evt.data.getTarget(); 61 62 if ( target.getName() == 'span' ) 63 target = target.getParent(); 64 65 if ( target.getName() == 'a' ) 66 { 67 dialog.getContentElement( 'info', 'charPreview' ).getElement().setHtml( ' ' ); 68 dialog.getContentElement( 'info', 'htmlPreview' ).getElement().setHtml( ' ' ); 69 target.getParent().removeClass( "cke_light_background" ); 70 71 focusedNode = undefined; 72 } 73 }; 74 75 var onKeydown = CKEDITOR.tools.addFunction( function( ev ) 76 { 77 ev = new CKEDITOR.dom.event( ev ); 78 79 // Get an Anchor element. 80 var element = ev.getTarget(); 81 var relative, nodeToMove; 82 var keystroke = ev.getKeystroke(); 83 84 switch ( keystroke ) 85 { 86 // RIGHT-ARROW 87 case 39 : 88 // relative is TD 89 if ( ( relative = element.getParent().getNext() ) ) 90 { 91 nodeToMove = relative.getChild( 0 ); 92 if ( nodeToMove.type == 1 ) 93 { 94 nodeToMove.focus(); 95 onBlur( null, element ); 96 onFocus( null, nodeToMove ); 97 } 98 } 99 ev.preventDefault(); 100 break; 101 // LEFT-ARROW 102 case 37 : 103 // relative is TD 104 if ( ( relative = element.getParent().getPrevious() ) ) 105 { 106 nodeToMove = relative.getChild( 0 ); 107 nodeToMove.focus(); 108 onBlur( null, element ); 109 onFocus( null, nodeToMove ); 110 } 111 ev.preventDefault(); 112 break; 113 // UP-ARROW 114 case 38 : 115 // relative is TR 116 if ( ( relative = element.getParent().getParent().getPrevious() ) ) 117 { 118 nodeToMove = relative.getChild( [element.getParent().getIndex(), 0] ); 119 nodeToMove.focus(); 120 onBlur( null, element ); 121 onFocus( null, nodeToMove ); 122 } 123 ev.preventDefault(); 124 break; 125 // DOWN-ARROW 126 case 40 : 127 // relative is TR 128 if ( ( relative = element.getParent().getParent().getNext() ) ) 129 { 130 nodeToMove = relative.getChild( [ element.getParent().getIndex(), 0 ] ); 131 if ( nodeToMove && nodeToMove.type == 1 ) 132 { 133 nodeToMove.focus(); 134 onBlur( null, element ); 135 onFocus( null, nodeToMove ); 136 } 137 } 138 ev.preventDefault(); 139 break; 140 // SPACE 141 // ENTER is already handled as onClick 142 case 32 : 143 onChoice( { data: ev } ); 144 ev.preventDefault(); 145 break; 146 // TAB 147 case 9 : 148 // relative is TD 149 if ( ( relative = element.getParent().getNext() ) ) 150 { 151 nodeToMove = relative.getChild( 0 ); 152 if ( nodeToMove.type == 1 ) 153 { 154 nodeToMove.focus(); 155 onBlur( null, element ); 156 onFocus( null, nodeToMove ); 157 ev.preventDefault( true ); 158 } 159 else 160 onBlur( null, element ); 161 } 162 // relative is TR 163 else if ( ( relative = element.getParent().getParent().getNext() ) ) 164 { 165 nodeToMove = relative.getChild( [ 0, 0 ] ); 166 if ( nodeToMove && nodeToMove.type == 1 ) 167 { 168 nodeToMove.focus(); 169 onBlur( null, element ); 170 onFocus( null, nodeToMove ); 171 ev.preventDefault( true ); 172 } 173 else 174 onBlur( null, element ); 175 } 176 break; 177 // SHIFT + TAB 178 case CKEDITOR.SHIFT + 9 : 179 // relative is TD 180 if ( ( relative = element.getParent().getPrevious() ) ) 181 { 182 nodeToMove = relative.getChild( 0 ); 183 nodeToMove.focus(); 184 onBlur( null, element ); 185 onFocus( null, nodeToMove ); 186 ev.preventDefault( true ); 187 } 188 // relative is TR 189 else if ( ( relative = element.getParent().getParent().getPrevious() ) ) 190 { 191 nodeToMove = relative.getLast().getChild( 0 ); 192 nodeToMove.focus(); 193 onBlur( null, element ); 194 onFocus( null, nodeToMove ); 195 ev.preventDefault( true ); 196 } 197 else 198 onBlur( null, element ); 199 break; 200 default : 201 // Do not stop not handled events. 202 return; 203 } 204 }); 205 206 return { 207 title : editor.lang.specialChar.title, 208 minWidth : 430, 209 minHeight : 280, 210 buttons : [ CKEDITOR.dialog.cancelButton ], 211 charColumns : 17, 212 chars : 213 [ 214 '!','"','#','$','%','&',"'",'(',')','*','+','-','.','/', 215 '0','1','2','3','4','5','6','7','8','9',':',';', 216 '<','=','>','?','@', 217 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O', 218 'P','Q','R','S','T','U','V','W','X','Y','Z', 219 '[',']','^','_','`', 220 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p', 221 'q','r','s','t','u','v','w','x','y','z', 222 '{','|','}','~','€','‘','’','’','“', 223 '”','–','—','¡','¢','£', 224 '¤','¥','¦','§','¨','©','ª', 225 '«','¬','®','¯','°','±','²', 226 '³','´','µ','¶','·','¸', 227 '¹','º','»','¼','½','¾', 228 '¿','À','Á','Â','Ã','Ä', 229 'Å','Æ','Ç','È','É','Ê', 230 'Ë','Ì','Í','Î','Ï','Ð', 231 'Ñ','Ò','Ó','Ô','Õ','Ö', 232 '×','Ø','Ù','Ú','Û','Ü', 233 'Ý','Þ','ß','à','á','â', 234 'ã','ä','å','æ','ç','è', 235 'é','ê','ë','ì','í','î', 236 'ï','ð','ñ','ò','ó','ô', 237 'õ','ö','÷','ø','ù','ú', 238 'û','ü','ü','ý','þ','ÿ', 239 'Œ','œ','Ŵ','Ŷ','ŵ','ŷ','‚', 240 '‛','„','…','™','►','•', 241 '→','⇒','⇔','♦','≈' 242 ], 243 onLoad : function() 244 { 245 var columns = this.definition.charColumns, 246 chars = this.definition.chars; 247 248 var html = [ '<table style="width: 320px; height: 100%; border-collapse: separate;" align="center" cellspacing="2" cellpadding="2" border="0">' ]; 249 250 var i = 0 ; 251 while ( i < chars.length ) 252 { 253 html.push( '<tr>' ) ; 254 255 for( var j = 0 ; j < columns ; j++, i++ ) 256 { 257 if ( chars[ i ] ) 258 { 259 html.push( 260 '<td class="cke_dark_background">' + 261 '<a href="javascript: void(0);" style="display: block; height: 1.25em; margin-top: 0.25em; text-align: center;" title="', chars[i].replace( /&/g, '&' ), '"' + 262 ' onkeydown="CKEDITOR.tools.callFunction( ' + onKeydown + ', event, this )"' + 263 ' onclick="CKEDITOR.tools.callFunction(' + onClick + ', this); return false;"' + 264 ' tabindex="-1">' + 265 '<span style="margin: 0 auto;">' + 266 chars[i] + 267 '</span></a>'); 268 } 269 else 270 html.push( '<td class="cke_dark_background"> ' ); 271 272 html.push( '</td>' ); 273 } 274 html.push( '</tr>' ); 275 } 276 277 html.push( '</tbody></table>' ); 278 279 this.getContentElement( 'info', 'charContainer' ).getElement().setHtml( html.join( '' ) ); 280 }, 281 contents : [ 282 { 283 id : 'info', 284 label : editor.lang.common.generalTab, 285 title : editor.lang.common.generalTab, 286 padding : 0, 287 align : 'top', 288 elements : [ 289 { 290 type : 'hbox', 291 align : 'top', 292 widths : [ '320px', '90px' ], 293 children : 294 [ 295 { 296 type : 'html', 297 id : 'charContainer', 298 html : '', 299 onMouseover : onFocus, 300 onMouseout : onBlur, 301 focus : function() 302 { 303 var firstChar = this.getElement().getChild( [0, 0, 0, 0, 0] ); 304 setTimeout(function() 305 { 306 firstChar.focus(); 307 onFocus( null, firstChar ); 308 }); 309 }, 310 // Needed only for webkit. 311 onShow : function() 312 { 313 var firstChar = this.getElement().getChild( [0, 0, 0, 0, 0] ); 314 setTimeout(function() 315 { 316 firstChar.focus(); 317 onFocus( null, firstChar ); 318 }); 319 }, 320 onLoad : function( event ) 321 { 322 dialog = event.sender; 323 } 324 }, 325 { 326 type : 'hbox', 327 align : 'top', 328 widths : [ '100%' ], 329 children : 330 [ 331 { 332 type : 'vbox', 333 align : 'top', 334 children : 335 [ 336 { 337 type : 'html', 338 html : '<div></div>' 339 }, 340 { 341 type : 'html', 342 id : 'charPreview', 343 style : 'border:1px solid #eeeeee;background-color:#EAEAD1;font-size:28px;height:40px;width:70px;padding-top:9px;font-family:\'Microsoft Sans Serif\',Arial,Helvetica,Verdana;text-align:center;', 344 html : '<div> </div>' 345 }, 346 { 347 type : 'html', 348 id : 'htmlPreview', 349 style : 'border:1px solid #eeeeee;background-color:#EAEAD1;font-size:14px;height:20px;width:70px;padding-top:2px;font-family:\'Microsoft Sans Serif\',Arial,Helvetica,Verdana;text-align:center;', 350 html : '<div> </div>' 351 } 352 ] 353 } 354 ] 355 } 356 ] 357 } 358 ] 359 } 360 ] 361 }; 362 } ); 363