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(/&lt;/, '<');
98            a.value = a.value.replace(/&gt;/, '>');
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;">&nbsp;</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;">&nbsp;</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;">  &lt;font. . . &gt;text&lt;/font&gt;</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(/&lt;font(.*)\/font&gt;/) && !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(/&lt;/g, '<');
616                        text = text.replace(/&gt;/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} );