1// Register a new CKEditor plugin. 2// http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.resourceManager.html#add 3 4CKEDITOR.plugins.add( 'fontAssist', 5{ 6 7 // The plugin initialization logic goes inside this method. 8 // http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.pluginDefinition.html#init 9 init: function( editor ) 10 { 11 // Create an editor command that stores the dialog initialization command. 12 // http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.command.html 13 // http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.dialogCommand.html 14 editor.addCommand( 'fontAssistDialog', new CKEDITOR.dialogCommand( 'fontAssistDialog' ) ); 15 var lang = editor.lang.fontassist; 16 if(!lang) { 17 lang = CKEDITOR.lang['default']['fontassist']; 18 } 19 else { 20 var lang_default = CKEDITOR.lang['default']['fontassist']; 21 for(var k in lang_default) { 22 if(!lang[k]) { 23 lang[k] = lang_default[k]; 24 } 25 } 26 } 27 28 29 // Create a toolbar button that executes the plugin command defined above. 30 // http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.ui.html#addButton 31 editor.ui.addButton( 'FontAssist', 32 { 33 // Toolbar button tooltip. 34 label: lang.ToolTip, //'Check and Revise Font Styling', 35 // Reference to the plugin command name. 36 command: 'fontAssistDialog', 37 // Button's icon file path. 38 icon: this.path + 'images/fonts.png' 39 } ); 40 41 // Add a new dialog window definition containing all UI elements and listeners. 42 // http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.dialog.html#.add 43 // http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.dialog.dialogDefinition.html 44 CKEDITOR.dialog.add( 'fontAssistDialog', function( editor ) 45 { 46 var ohtml; 47 var selectedText; 48 var nonReplaceable = false; 49 var style_spec = { 50 fg : "", 51 bg : "", 52 font_style : "", 53 font : "", 54 font_size: "", 55 start :'<', 56 close : '>', 57 save_color: function(which, color) { 58 this[which] = color; 59 }, 60 get: function(which) { 61 return this[which]; 62 }, 63 save_font: function(family) { 64 this['font'] = family; 65 }, 66 save_size: function(sz) { 67 this['font_size'] = sz; 68 }, 69 get_font_style: function(slash) { 70 var sep = slash ? '/' : " "; 71 return this['font_size'] + sep + this['font']; 72 }, 73 open_tag: function() { 74 return this.start + 'font ' + this.get_font_style(true) + ';;' + this.get('fg') + ';;' + this.get('bg') + this.close; 75 }, 76 close_tag: function() { 77 return this.start + '/font' + this.close; 78 }, 79 }; 80 81 var original_styles = { 82 fg : "", 83 bg : "", 84 font : "", 85 font_size: "", 86 }; 87 88 var ckgedit_getEID = function (dialog,page,el) { 89 var InputId = dialog.getContentElement(page,el).getInputElement().$.id; 90 return document.getElementById(InputId); 91 }; 92 93 // displays open tag of font plugin below display window 94 var display_fontOpen = function(dialog){ 95 var a = ckgedit_getEID(dialog,'general','alert'); 96 a.value = style_spec.open_tag(); 97 a.value = a.value.replace(/</, '<'); 98 a.value = a.value.replace(/>/, '>'); 99 }; 100 /* 1 .Assign either forground or background color to css style of the display div: general:contents 101 If the foreground color has been changed, pass the text through 102 replace_formats() 103 2. save the value in the style_spec object 104 3. enable the OK button 105 4. switch from the color tab to the main tab to display result of color change 106 107 */ 108 var setColor = function(dialog,ui_el) { 109 var which = (ui_el == 'colors') ? 'fg': 'bg'; // ui_el = colors or backgroundcolors 110 var el = ckgedit_getEID(dialog,ui_el,which); 111 style_spec.save_color(which,el.value); 112 var el = ckgedit_getEID(dialog,'general','contents'); 113 if(which == 'fg') { 114 el.style.color = style_spec.get(which); 115 var d = ckgedit_getEID(dialog,'general','contents'); 116 d.innerHTML = replace_formats(selectedText); 117 } 118 else { 119 el.style.backgroundColor = style_spec.get(which); 120 } 121 dialog.enableButton( 'ok' ); 122 dialog.selectPage( 'general' ); 123 display_fontOpen(dialog); 124 }; 125 126 var resetColor = function(dialog) { 127 style_spec.save_color('fg', original_styles['fg']); 128 style_spec.save_color('bg', original_styles['bg']); 129 130 var el = ckgedit_getEID(dialog,'general','contents'); 131 132 el.style.color = style_spec.get('fg'); 133 el.style.backgroundColor = style_spec.get('bg'); 134 135 el.innerHTML = replace_formats(selectedText); 136 display_fontOpen(dialog); 137 }; 138 139 var setFont = function(dialog) { 140 var font_style = style_spec.get_font_style(false); 141 var d = ckgedit_getEID(dialog,'general','contents'); 142 d.style.font = font_style; 143 d.innerHTML = replace_formats(selectedText); 144 display_fontOpen(dialog); 145 }; 146 147 var resetFont = function(dialog) { 148 style_spec.save_font(original_styles['font']); 149 style_spec.save_size(original_styles['font_size']); 150 setFont(dialog); 151 var n = ckgedit_getEID(dialog,'general','fontopts'); 152 n.options[0].selected = true; 153 n = ckgedit_getEID(dialog,'general','sizeopts'); 154 n.options[0].selected = true; 155 156 }; 157 158 var onClickfg = function (evt,data) { 159 var dialog = this.getDialog(); 160 dialog.disableButton('ok'); 161 var n = ckgedit_getEID(dialog,'colors','fg'); 162 var value = onClickInsert(evt, n); 163 var n = ckgedit_getEID(dialog,'colors','fgsample'); 164 n.style.backgroundColor = value; 165 toggle_ok(dialog,true); 166 }; 167 168 var onClickbg = function (evt,data) { 169 var dialog = this.getDialog(); 170 dialog.disableButton('ok'); 171 var n = ckgedit_getEID(dialog,'backgroundcolors','bg'); 172 var value = onClickInsert(evt, n); 173 var n = ckgedit_getEID(dialog,'backgroundcolors','bgsample'); 174 n.style.backgroundColor = value; 175 toggle_ok(dialog,true); 176 }; 177 178 var onClickInsert = function( evt ,which) { 179 var target = evt.data.getTarget(), 180 targetName = target.getName(); 181 182 if ( targetName != 'td' ) return; 183 var elems = target.getAttribute( 'style' ).split(/#/); 184 var matches = target.getAttribute( 'style' ).match(/(#[A-Z0-9]+);/); 185 if(!matches) { 186 matches = target.getAttribute( 'style' ).match(/(rgb\([,\s\d]+\))/); 187 } 188 else matches[1] = hex2rgb(matches[1]); 189 which.value = matches[1]; 190 return matches[1]; 191 }; 192 193 var toggle_ok = function(dialog,onff) { 194 var t = ckgedit_getEID(dialog,'general','oktoggle'); 195 t.checked = onff; 196 }; 197 198 var hex2rgb = function(val) { 199 var hexToR = function(h) { return parseInt((cutHex(h)).substring(0,2),16)}; 200 var hexToG = function(h) { return parseInt((cutHex(h)).substring(2,4),16)}; 201 var hexToB = function(h) { return parseInt((cutHex(h)).substring(4,6),16)}; 202 var cutHex = function(h) { return (h.charAt(0)=="#") ? h.substring(1,7):h}; 203 204 R = hexToR(val); 205 G = hexToG(val); 206 B = hexToB(val); 207 return "rgb(" + R +", " +G +", " +B+")"; 208 }; 209 210 var createSelectList = function(sel, list) { 211 for(var i = 0; i < list.length; i++) { 212 var elems = list[i].split('\/'); 213 sel.options[sel.options.length] = new Option(elems[0],elems[1]); 214 } 215 }; 216 217 var updateSelectList = function (sel, item) { 218 219 for(var i = 0; i < sel.options.length; i++) { 220 var regex = new RegExp(sel.options[i].label,"i"); 221 if(item.match(regex) ) { 222 sel.options[i].selected = true; 223 break; 224 } 225 } 226 }; 227 // Create the color chart for fg and bg colors 228 function colorSelector() 229 { 230 if(ohtml) return ohtml.join(''); 231 232 ohtml = [ 233 '<div style="width:90%;margin:auto; height: 400px; overflow:auto;">', 234 '<style type="text/css">#c_chart td { height: 16px; width: 16px; border: 2px solid white; }</style>', 235 '<table id = "c_chart" style="border:2px solid white;" cellspacing="2" cellpadding="2"><tbody><tr>' 236 ]; 237 238 var color_vals = editor.config.colors; 239 for(var i = 0; i< color_vals.length; i++) { 240 241 if(i%26 == 0) { 242 ohtml.push('<tr>'); 243 } 244 ohtml.push('<td style="background-color: #' + color_vals[i] + ';" title= #"'+ color_vals[i] + '"></td>'); 245 246 } 247 248 ohtml.push( '</tbody></table></div>' ); 249 var s = ohtml.join(''); 250 251 return s; 252 253 }; 254 255 /* 256 Assign color and font values to formatted text, i.e. bold, italic, underline, etc. 257 */ 258 function replace_formats(text) 259 { 260 261 262 text = text.replace(/<(b|i|em|u|strong|sup|sub|code)>/g, function(el,tag) { 263 var font_style = style_spec.get_font_style(false), 264 fg_color = style_spec.get('fg'), 265 font_family = style_spec.get('font'), 266 size = style_spec.get('font_size') ; 267 268 var format=""; 269 var alt_font_style = ""; 270 switch(tag) { 271 case 'b': 272 case 'strong': 273 format = "; font-weight: bold; " ; 274 break; 275 case 'i': 276 case 'em': 277 format = "; font-style: italic; " ; 278 break; 279 case 'u': 280 format = "; text-decoration:underline; "; 281 break; 282 case 'sup': 283 var sz = parseInt(size); 284 sz = parseInt(sz *.75); 285 // format = "; vertical-align: text-top; font-size: " + sz +"pt; "; 286 format = "; vertical-align:super; "; 287 alt_font_style = sz + "pt " + font_family ; 288 break; 289 case 'sub': 290 var sz = parseInt(size); 291 sz = parseInt(sz *.75); 292 format = "; vertical-align: sub; "; 293 alt_font_style = sz + "pt " + font_family ; 294 break; 295 case 'code': 296 fg_color = 'black'; 297 format = "; background-color: white; "; 298 break; 299 } 300 return "<" + tag + " style='color:" + fg_color + "; font: " + (alt_font_style ? alt_font_style : font_style) + format +"'>"; 301 }); 302 303 return text; 304 } 305 306 return { 307 // Basic properties of the dialog window: title, minimum size. 308 // http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.dialog.dialogDefinition.html 309 title : lang.Title, //'Font Plugin Assitant', 310 minWidth : 440, 311 minHeight : 480, 312 // Dialog window contents. 313 // http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.dialog.definition.content.html 314 contents : 315 [ 316 { 317 // Definition of the Settings dialog window tab (page) with its id, label and contents. 318 // http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.dialog.contentDefinition.html 319 id : 'general', 320 label : lang.Main, //'Main', 321 elements : 322 [ 323 // Dialog window UI element: HTML code field. 324 // http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.ui.dialog.html.html 325 { 326 type : 'html', 327 // HTML code to be shown inside the field. 328 // http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.ui.dialog.html.html#constructor 329 html : lang.MainHeader, //'View and optionally alter text styled with the font plugin .' 330 }, 331 { 332 type : 'html', 333 html: '<div style="max-width:400px; white-space: pre-wrap;border:1px solid black; margin:auto; height: 300px; overflow:auto;"></div>', 334 id : 'contents', 335 // Text that labels the field. 336 // http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.ui.dialog.labeledElement.html#constructor 337 label : lang.Text, //'Text', 338 }, 339 { 340 type : 'text', 341 id : 'alert', 342 // style: 'outline:none; border:0;', 343 // Text that labels the field. 344 // http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.ui.dialog.labeledElement.html#constructor 345 onClick: function() { 346 var dialog = this.getDialog(); 347 var el = ckgedit_getEID(dialog,'general','alert') 348 el.focus(); 349 el.select(); 350 }, 351 }, 352 353 { 354 id: 'oktoggle', 355 label: lang.IfChecked, //' If checked, uncheck to activate OK button', 356 type: 'checkbox', 357 'default' : false, 358 onChange: function() { 359 var dialog = this.getDialog(); 360 dialog.enableButton( 'ok' ); 361 toggle_ok(dialog,false); 362 }, 363 }, 364 { 365 type: 'hbox', 366 children:[ 367 { 368 type : 'select', 369 id : 'fontopts', 370 label : lang.Fonts, //'Fonts', 371 // Items that will appear inside the selection field, in pairs of displayed text and value. 372 // http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.ui.dialog.select.html#constructor 373 items : 374 [ 375 [ '< '+ lang.none + ' >', '' ] 376 ], 377 onChange: function() { 378 style_spec.save_font(this.getValue()); 379 setFont(this.getDialog()); 380 }, 381 commit : function( data ) 382 { 383 data.style = this.getValue(); 384 } 385 }, //end fontopts 386 387 { 388 type : 'select', 389 id : 'sizeopts', 390 label : lang.FontSizes, // 'Font Sizes (px)', 391 // Items that will appear inside the selection field, in pairs of displayed text and value. 392 // http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.ui.dialog.select.html#constructor 393 items : 394 [ 395 [ '< '+ lang.none + ' >', '' ] 396 ], 397 onChange: function() { 398 style_spec.save_size(this.getValue()); 399 setFont(this.getDialog()); 400 }, 401 commit : function( data ) 402 { 403 data.style = this.getValue(); 404 } 405 }, //end sizeopts 406 ] // end hbox children 407 }, // end hbox font selection 408 { 409 type: 'hbox', // resets 410 children:[ 411 { 412 type: 'button', 413 label: lang.ResetFont, //'Reset font', 414 onClick: function() { 415 resetFont(this.getDialog()); 416 }, 417 }, 418 419 { 420 type: 'button', 421 label: lang.ResetAll, //'Reset all', 422 onClick: function() { 423 var dialog = this.getDialog(); 424 resetFont(dialog); 425 resetColor(dialog); 426 }, 427 }, 428 ] 429 }, // end hbox resets 430 ] //end Main elements 431 }, 432 { 433 id : 'colors', 434 label : lang.TextColors, // 'Text Colors', 435 elements : 436 [ 437 { 438 type : 'html', 439 // HTML code to be shown inside the field. 440 // http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.ui.dialog.html.html#constructor 441 html : lang.SelectColor, //'Select Color' 442 }, 443 { 444 id: 'textcolors', 445 type : 'html', 446 // HTML code to be shown inside the field. 447 // http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.ui.dialog.html.html#constructor 448 html : colorSelector(), 449 onClick: onClickfg 450 }, 451 { 452 type: 'hbox', 453 widths: [ '40%', '10%', '25%', '25%' ], 454 children: [ 455 { 456 type : 'text', 457 id : 'fg', 458 width: '12em', 459 label : lang.SelectedTextColor, //'Selected Text Color', 460 commit : function( data ) 461 { 462 data.fg = this.getValue(); 463 } 464 }, 465 { 466 type: 'html', 467 id: 'fgsample', 468 html: '<table style="border: 1px solid silver;"><tr><td style="width:24px;"> </td><tr></table>', 469 }, 470 { 471 type : 'button', 472 id : 'fgb_confirm', 473 label : lang.Accept, //'Accept', 474 onClick: function() { 475 var dialog = this.getDialog(); 476 setColor(dialog,'colors'); 477 dialog.enableButton( 'ok' ); 478 toggle_ok(dialog,false); 479 }, 480 }, 481 { 482 type : 'button', 483 id : 'fgb_reset', 484 label : lang.Reset, //'Reset', 485 onClick: function() { 486 var dialog = this.getDialog(); 487 var el = ckgedit_getEID(dialog,'colors','fg'); 488 el.value = ""; 489 dialog.enableButton( 'ok' ); 490 toggle_ok(dialog,false); 491 } , 492 }, 493 ], 494 } 495 ], 496 }, 497 { 498 id : 'backgroundcolors', 499 label : lang.BGColors, //'Background Colors', 500 elements : 501 [ 502 { 503 type : 'html', 504 // HTML code to be shown inside the field. 505 // http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.ui.dialog.html.html#constructor 506 html : lang.SelectColor, // ' Select Color' 507 }, 508 { 509 id: 'bgcolors', 510 type : 'html', 511 // HTML code to be shown inside the field. 512 // http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.ui.dialog.html.html#constructor 513 html : colorSelector(), 514 onClick: onClickbg 515 }, 516 517 { 518 type: 'hbox', 519 widths: [ '40%', '10%', '25%', '25%' ], 520 children: [ 521 { 522 type : 'text', 523 id : 'bg', 524 width: '12em', 525 label : lang.SelectedBGColor, 526 commit : function( data ) 527 { 528 data.fg = this.getValue(); 529 } 530 }, 531 { 532 type: 'html', 533 id: 'bgsample', 534 html: '<table style="border: 1px solid silver;"><tr><td style="width:24px;"> </td><tr></table>', 535 }, 536 { 537 type : 'button', 538 id : 'bgb_confirm', 539 label : lang.Accept, //'Accept', 540 onClick: function() { 541 var dialog = this.getDialog(); 542 setColor(dialog,'backgroundcolors'); 543 dialog.enableButton( 'ok' ); 544 toggle_ok(dialog,false); 545 }, 546 }, 547 { 548 type : 'button', 549 id : 'bgb_reset', 550 label : lang.Reset, //'Reset', 551 onClick: function() { 552 var dialog = this.getDialog(); 553 var el = ckgedit_getEID(dialog,'backgroundcolors','bg'); 554 el.value = ""; 555 dialog.enableButton( 'ok' ); 556 toggle_ok(dialog,false); 557 } , 558 }, 559 ], 560 }, 561 562 ], 563 }, 564 { 565 id: 'info', 566 label: 'Info', 567 elements: 568 [ 569 { 570 type: 'html', 571 html: lang.InfoText, 572 /*'<div style="max-width:400px; font-size: 12pt; white-space: pre-wrap;border:1px solid #cccccc; margin:auto; height: 350px; overflow:auto;">' + 573 'This tool works with the font plugin and is used to update the font plugin\'s syntax and/or view its enclosed text. ' + 574'Clicking anywhere on the plugin syntax or its text will enable you to check the appearance of the font, its colors, and its size.'+ 575'<br /><br />You can also update the plugin syntax in place. To do this you must select both the font syntax itself and the enclosed text:' + 576'<p style="text-indent: 50px; font-size: 12pt;"> <font. . . >text</font></p>' + 577'Then whatever changes you make with this tool can be inserted into the editor window, by clicking OK, and will replace the current font syntax. ' + 578'<br /><br />The font syntax will appear in the textbox below the display window and is updated with each change. '+ 579'Clicking on the text will select the text for copying.</div>'*/ 580 581 } 582 ], 583 } 584 ], 585 586 onShow : function() 587 { 588 var editor = this.getParentEditor(), 589 selection = editor.getSelection(); 590 nonReplaceable = false; 591 var a = ckgedit_getEID(this,'general','alert'); 592 a.innerHTML = ""; 593 594 this.enableButton( 'ok' ); 595 var text1 = selection.getSelectedText(); 596 var range = selection.getRanges( true )[ 0 ]; 597 range.shrink( CKEDITOR.SHRINK_TEXT ); 598 var root = range.getCommonAncestor(); 599 var p = root.getAscendant( 'p', true ); 600 if(!p) return; 601 if(!text1.match(/<font(.*)\/font>/) && !text1.match(/<font(.*)\/font>/)) { 602 nonReplaceable = true; 603 var a = ckgedit_getEID(this,'general','alert'); 604 a.value = "Changes will not be inserted into editor. See Info for details"; 605 } 606 607 608 text = p.getHtml(); 609 if(!text && nonReplaceable) { 610 if(text1) { 611 text = text1; 612 } 613 614 } 615 text = text.replace(/</g, '<'); 616 text = text.replace(/>/g, '>'); 617 text = text.replace(/<span.*?scayt.*?>(.*?)<\/span>/g,"$1"); 618 619 var d = ckgedit_getEID(this,'general','contents'); 620 621 var matches = text.match(/<font(.*?)>(.*)/m); 622 if(matches && matches[2]) { 623 var elems = matches[1].split(/;;/); 624 d.style.color = elems[1]; 625 d.style.backgroundColor = elems[2]; 626 627 style_spec.save_color('fg',elems[1]); 628 style_spec.save_color('bg',elems[2]); 629 original_styles['fg'] = elems[1]; 630 original_styles['bg'] = elems[2]; 631 632 var font = elems[0].split('/'); 633 var font_style = font[0] + " " + font[1]; 634 d.style.font = font_style; 635 636 style_spec.save_size(font[0]); 637 style_spec.save_font(font[1]); 638 original_styles['font'] = font[1]; 639 original_styles['font_size'] = font[0]; 640 641 matches[2] = matches[2].replace(/<\/font>/,""); 642 matches[2] = matches[2].replace(/<br\/?>/, ' ' ); 643 selectedText = matches[2]; 644 d.innerHTML = replace_formats(matches[2]); 645 646 var sel = ckgedit_getEID(this,'general','fontopts'); 647 updateSelectList(sel,original_styles['font']); 648 sel = ckgedit_getEID(this,'general','sizeopts'); 649 updateSelectList(sel,original_styles['font_size']); 650 } 651 652 }, 653 654 onLoad : function() 655 { 656 editor = this.getParentEditor(); 657 658 var n = ckgedit_getEID(this,'general','fontopts'); 659 var font_names = CKEDITOR.config.font_names.split(/;/); 660 createSelectList(n,font_names); 661 662 var n = ckgedit_getEID(this,'general','sizeopts'); 663 var size_list = CKEDITOR.config.fontSize_sizes.split(/;/); 664 createSelectList(n,size_list); 665 666 var tab = this._.tabs[ 'general' ] && this._.tabs[ 'general' ][ 0 ]; 667 var dialog = this; 668 tab.on('focus', function(evt) { 669 dialog.enableButton( 'ok' ); 670 var t = ckgedit_getEID(dialog,'general','oktoggle'); 671 t.checked = false; 672 }); 673 674 //CKEDITOR.config.fontSize_sizes = '8/8px;9/9px;10/10px;11/11px;12/12px;14/14px;16/16px;18/18px;20/20px;22/22px;24/24px;26/26px;28/28px;36/36px;48/48px;72/72px'; 675 }, 676 onOk : function() 677 { 678 if(nonReplaceable) return; 679 680 var p = editor.document.createElement( 'p' ); 681 var revision = style_spec.open_tag() + selectedText + style_spec.close_tag(); 682 p.setHtml( revision); 683 684 // Insert paragraph element into the current cursor position in the editor. 685 // http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.editor.html#insertElement 686 editor.insertElement( p ); 687 } 688 }; 689 } ); 690 } 691} );