Ticket #5773: 5773.patch

File 5773.patch, 38.7 KB (added by WebSpellChecker.net, 12 years ago)
  • _source/plugins/scayt/plugin.js

     
    2828                }
    2929                return found;
    3030        }
    31 
    32         var onEngineLoad = function()
    33         {
    34                 var editor = this;
    35 
    36                 var createInstance = function() // Create new instance every time Document is created.
    37                 {
    38                         var config = editor.config;
    39                         // Initialise Scayt instance.
    40                         var oParams = {};
    41                         // Get the iframe.
    42                         oParams.srcNodeRef = editor.document.getWindow().$.frameElement;
    43                         // syntax : AppName.AppVersion@AppRevision
    44                         oParams.assocApp  = 'CKEDITOR.' + CKEDITOR.version + '@' + CKEDITOR.revision;
    45                         oParams.customerid = config.scayt_customerid  || '1:WvF0D4-UtPqN1-43nkD4-NKvUm2-daQqk3-LmNiI-z7Ysb4-mwry24-T8YrS3-Q2tpq2';
    46                         oParams.customDictionaryIds = config.scayt_customDictionaryIds || '';
    47                         oParams.userDictionaryName = config.scayt_userDictionaryName || '';
    48                         oParams.sLang = config.scayt_sLang || 'en_US';
    49 
    50                         // Introduce SCAYT onLoad callback. (#5632)
    51                         oParams.onLoad = function()
    52                                 {
    53                                         // Draw down word marker to avoid being covered by background-color style.(#5466)
    54                                         if ( !( CKEDITOR.env.ie && CKEDITOR.env.version < 8 ) )
    55                                                 this.addStyle( this.selectorCss(), 'padding-bottom: 2px !important;' );
    56 
    57                                         // Call scayt_control.focus when SCAYT loaded
    58                                         // and only if editor has focus and scayt control creates at first time (#5720)
    59                                         if ( editor.focusManager.hasFocus && !plugin.isControlRestored( editor ) )
    60                                                 this.focus();
    61 
    62                                 };
    63 
    64                         oParams.onBeforeChange = function()
    65                         {
    66                                 if ( plugin.getScayt( editor ) && !editor.checkDirty() )
    67                                         setTimeout( function(){ editor.resetDirty(); }, 0 );
    68                         };
    69 
    70                         var scayt_custom_params = window.scayt_custom_params;
    71                         if ( typeof scayt_custom_params == 'object' )
    72                         {
    73                                 for ( var k in scayt_custom_params )
    74                                         oParams[ k ] = scayt_custom_params[ k ];
    75                         }
    76                         // needs for restoring a specific scayt control settings
    77                         if ( plugin.getControlId( editor ) )
    78                                 oParams.id = plugin.getControlId( editor );
    79 
    80                         var scayt_control = new window.scayt( oParams );
    81 
    82                         scayt_control.afterMarkupRemove.push( function( node )
    83                         {
    84                                 ( new CKEDITOR.dom.element( node, scayt_control.document ) ).mergeSiblings();
    85                         } );
    86 
    87                         // Copy config.
    88                         var lastInstance = plugin.instances[ editor.name ];
    89                         if ( lastInstance )
    90                         {
    91                                 scayt_control.sLang = lastInstance.sLang;
    92                                 scayt_control.option( lastInstance.option() );
    93                                 scayt_control.paused = lastInstance.paused;
    94                         }
    95 
    96                         plugin.instances[ editor.name ] = scayt_control;
    97 
    98                         try {
    99                                 scayt_control.setDisabled( plugin.isPaused( editor ) === false );
    100                         } catch (e) {}
    101 
    102                         editor.fire( 'showScaytState' );
    103                 };
    104 
    105                 editor.on( 'contentDom', createInstance );
    106                 editor.on( 'contentDomUnload', function()
    107                         {
    108                                 // Remove scripts.
    109                                 var scripts = CKEDITOR.document.getElementsByTag( 'script' ),
    110                                         scaytIdRegex =  /^dojoIoScript(\d+)$/i,
    111                                         scaytSrcRegex =  /^https?:\/\/svc\.webspellchecker\.net\/spellcheck\/script\/ssrv\.cgi/i;
    112 
    113                                 for ( var i=0; i < scripts.count(); i++ )
    114                                 {
    115                                         var script = scripts.getItem( i ),
    116                                                 id = script.getId(),
    117                                                 src = script.getAttribute( 'src' );
    118 
    119                                         if ( id && src && id.match( scaytIdRegex ) && src.match( scaytSrcRegex ))
    120                                                 script.remove();
    121                                 }
    122                         });
    123 
    124                 editor.on( 'beforeCommandExec', function( ev )          // Disable SCAYT before Source command execution.
    125                         {
    126                                 if ( ( ev.data.name == 'source' || ev.data.name == 'newpage' ) && editor.mode == 'wysiwyg' )
    127                                 {
    128                                         var scayt_instance = plugin.getScayt( editor );
    129                                         if ( scayt_instance )
    130                                         {
    131                                                 plugin.setPaused( editor, !scayt_instance.disabled );
    132                                                 // store a control id for restore a specific scayt control settings
    133                                                 plugin.setControlId( editor, scayt_instance.id );
    134                                                 scayt_instance.destroy( true );
    135                                                 delete plugin.instances[ editor.name ];
    136                                         }
    137                                 }
    138                                 // Catch on source mode switch off (#5720)
    139                                 else if ( ev.data.name == 'source'  && editor.mode == 'source' )
    140                                         plugin.markControlRestore( editor );
    141                         });
    142 
    143                 editor.on( 'afterCommandExec', function( ev )
    144                         {
    145                                 if ( !plugin.isScaytEnabled( editor ) )
    146                                         return;
    147 
    148                                 if ( editor.mode == 'wysiwyg' && ( ev.data.name == 'undo' || ev.data.name == 'redo' ) )
    149                                         window.setTimeout( function() { plugin.getScayt( editor ).refresh(); }, 10 );
    150                         });
    151 
    152                 editor.on( 'destroy', function( ev )
    153                         {
    154                                 var editor = ev.editor,
    155                                         scayt_instance = plugin.getScayt( editor );
    156 
    157                                 // SCAYT instance might already get destroyed by mode switch (#5744).
    158                                 if ( !scayt_instance )
    159                                         return;
    160 
    161                                 delete plugin.instances[ editor.name ];
    162                                 // store a control id for restore a specific scayt control settings
    163                                 plugin.setControlId( editor, scayt_instance.id );
    164                                 scayt_instance.destroy( true );
    165                         });
    166 
    167                 // Listen to data manipulation to reflect scayt markup.
    168                 editor.on( 'afterSetData', function()
    169                         {
    170                                 if ( plugin.isScaytEnabled( editor ) ) {
    171                                         window.setTimeout( function()
    172                                                 {
    173                                                         var instance = plugin.getScayt( editor );
    174                                                         instance && instance.refresh();
    175                                                 }, 10 );
    176                                 }
    177                         });
    178 
    179                 // Reload spell-checking for current word after insertion completed.
    180                 editor.on( 'insertElement', function()
    181                         {
    182                                 var scayt_instance = plugin.getScayt( editor );
    183                                 if ( plugin.isScaytEnabled( editor ) )
    184                                 {
    185                                         // Unlock the selection before reload, SCAYT will take
    186                                         // care selection update.
    187                                         if ( CKEDITOR.env.ie )
    188                                                 editor.getSelection().unlock( true );
    189 
    190                                         // Return focus to the editor and refresh SCAYT markup (#5573).
    191                                         window.setTimeout( function()
    192                                         {
    193                                                 scayt_instance.focus();
    194                                                 scayt_instance.refresh();
    195                                         }, 10 );
    196                                 }
    197                         }, this, null, 50 );
    198 
    199                 editor.on( 'insertHtml', function()
    200                         {
    201                                 var scayt_instance = plugin.getScayt( editor );
    202                                 if ( plugin.isScaytEnabled( editor ) )
    203                                 {
    204                                         // Unlock the selection before reload, SCAYT will take
    205                                         // care selection update.
    206                                         if ( CKEDITOR.env.ie )
    207                                                 editor.getSelection().unlock( true );
    208 
    209                                         // Return focus to the editor (#5573)
    210                                         // Refresh SCAYT markup
    211                                         window.setTimeout( function()
    212                                         {
    213                                                 scayt_instance.focus();
    214                                                 scayt_instance.refresh();
    215                                         }, 10 );
    216                                 }
    217                         }, this, null, 50 );
    218 
    219                 editor.on( 'scaytDialog', function( ev )        // Communication with dialog.
    220                         {
    221                                 ev.data.djConfig = window.djConfig;
    222                                 ev.data.scayt_control = plugin.getScayt( editor );
    223                                 ev.data.tab = openPage;
    224                                 ev.data.scayt = window.scayt;
    225                         });
    226 
    227                 var dataProcessor = editor.dataProcessor,
    228                         htmlFilter = dataProcessor && dataProcessor.htmlFilter;
    229 
    230                 if ( htmlFilter )
    231                 {
    232                         htmlFilter.addRules(
    233                                 {
    234                                         elements :
    235                                         {
    236                                                 span : function( element )
    237                                                 {
    238                                                         if ( element.attributes[ 'data-scayt_word' ]
    239                                                                         && element.attributes[ 'data-scaytid' ] )
    240                                                         {
    241                                                                 delete element.name;    // Write children, but don't write this node.
    242                                                                 return element;
    243                                                         }
    244                                                 }
    245                                         }
    246                                 }
    247                         );
    248                 }
    249 
    250                 // Override Image.equals method avoid CK snapshot module to add SCAYT markup to snapshots. (#5546)
    251                 var undoImagePrototype = CKEDITOR.plugins.undo.Image.prototype;
    252                 undoImagePrototype.equals = CKEDITOR.tools.override( undoImagePrototype.equals, function( org )
    253                 {
    254                         return function( otherImage )
    255                         {
    256                                 var thisContents = this.contents,
    257                                         otherContents = otherImage.contents;
    258                                 var scayt_instance = plugin.getScayt( this.editor );
    259                                 // Making the comparison based on content without SCAYT word markers.
    260                                 if ( scayt_instance && plugin.isScaytReady( this.editor ) )
    261                                 {
    262                                         // scayt::reset might return value undefined. (#5742)
    263                                         this.contents = scayt_instance.reset( thisContents ) || '';
    264                                         otherImage.contents = scayt_instance.reset( otherContents ) || '';
    265                                 }
    266 
    267                                 var retval = org.apply( this, arguments );
    268 
    269                                 this.contents = thisContents;
    270                                 otherImage.contents = otherContents;
    271                                 return retval;
    272                         };
    273                 });
    274 
    275                 if ( editor.document )
    276                         createInstance();
    277         };
    278 
     31         
    27932CKEDITOR.plugins.scayt =
    28033        {
    28134                engineLoaded : false,
     35                editor: '',
    28236                instances : {},
    28337                // Data storage for SCAYT control, based on editor instances
    28438                controlInfo : {},
     
    34599                isScaytEnabled : function( editor )
    346100                {
    347101                        var scayt_instance = this.getScayt( editor );
    348                         return ( scayt_instance ) ? scayt_instance.disabled === false : false;
     102                        return ( scayt_instance ) ? scayt_instance.disabled === false : false; 
    349103                },
    350104                getUiTabs : function( editor )
    351105                {
     
    360114                        // "About us" should be always shown for standard config
    361115                        configUiTabs[3] = "1";
    362116
    363                         for ( var i = 0; i < 4; i++ ) {
     117                        for ( var i = 0; i < 4; i++ )
     118                        {
    364119                                uiTabs[i] = (typeof window.scayt != "undefined" && typeof window.scayt.uiTags != "undefined")
    365120                                                                ? (parseInt(configUiTabs[i],10) && window.scayt.uiTags[i])
    366121                                                                : parseInt(configUiTabs[i],10);
    367122                        }
    368123                        return uiTabs;
    369124                },
     125               
     126                createInstance: function()
     127                {
     128                        var editor = this;
     129                        var config = editor.config;
     130                       
     131                        // Initialise Scayt instance.
     132                        var oParams = {};
     133                       
     134                        // Get the iframe.
     135                        oParams.srcNodeRef = editor.document.getWindow().$.frameElement;
     136
     137                        // syntax : AppName.AppVersion@AppRevision
     138                        oParams.assocApp  = 'CKEDITOR.' + CKEDITOR.version + '@' + CKEDITOR.revision;
     139                        oParams.customerid = config.scayt_customerid  || '1:WvF0D4-UtPqN1-43nkD4-NKvUm2-daQqk3-LmNiI-z7Ysb4-mwry24-T8YrS3-Q2tpq2';
     140                        oParams.customDictionaryIds = config.scayt_customDictionaryIds || '';
     141                        oParams.userDictionaryName = config.scayt_userDictionaryName || '';
     142                        oParams.sLang = config.scayt_sLang || 'en_US';
     143
     144                        // Introduce SCAYT onLoad callback. (#5632)
     145                        oParams.onLoad = function()
     146                        {
     147                                // Draw down word marker to avoid being covered by background-color style.(#5466)
     148                                if ( !( CKEDITOR.env.ie && CKEDITOR.env.version < 8 ) )
     149                                        this.addStyle( this.selectorCss(), 'padding-bottom: 2px !important;' );
     150
     151                                        // Call scayt_control.focus when SCAYT loaded
     152                                        // and only if editor has focus and scayt control creates at first time (#5720)
     153                                if ( editor.focusManager.hasFocus && !plugin.isControlRestored( editor ) )
     154                                        this.focus();
     155                        };
     156                                               
     157                        oParams.onBeforeChange = function()
     158                        {
     159                                if ( plugin.getScayt( editor ) && !editor.checkDirty() )
     160                                        setTimeout( function(){ editor.resetDirty(); }, 0 );
     161                        };
     162
     163                        var scayt_custom_params = window.scayt_custom_params;
     164                        if ( typeof scayt_custom_params == 'object' )
     165                        {
     166                                for ( var k in scayt_custom_params )
     167                                        oParams[ k ] = scayt_custom_params[ k ];
     168                        }
     169
     170                                                // needs for restoring a specific scayt control settings
     171                        if ( plugin.getControlId( editor ) )
     172                                oParams.id = plugin.getControlId( editor );
     173                                               
     174                         setTimeout(function()
     175                                 {
     176                                        if(typeof window.scayt == "function")
     177                                        {
     178                                                var scayt_control = new window.scayt(oParams);
     179                                                scayt_control.afterMarkupRemove.push( function( node )
     180                                                        {
     181                                                                ( new CKEDITOR.dom.element( node, scayt_control.document ) ).mergeSiblings();
     182                                                        } );
     183                                                        // Copy config.
     184                                                        var lastInstance = plugin.instances[ editor.name ];
     185                                                        if ( lastInstance )
     186                                                        {
     187                                                                scayt_control.sLang = lastInstance.sLang;
     188                                                                scayt_control.option( lastInstance.option() );
     189                                                                scayt_control.paused = lastInstance.paused;
     190                                                        }
     191                                                        plugin.instances[ editor.name ] = scayt_control;
     192                                                        scayt_control.setDisabled( plugin.isPaused( editor ) === false );
     193                                                        editor.fire( 'showScaytState' );
     194                                        }
     195                                                   
     196                                 }, 100);
     197                },
     198               
     199                onEngineLoad : function()
     200                {
     201                        var editor = this;
     202                        editor.on( 'contentDom', plugin.createInstance );
     203                        editor.on( 'contentDomUnload', function()
     204                                {
     205                                        // Remove scripts.
     206                                        var scripts = CKEDITOR.document.getElementsByTag( 'script' ),
     207                                                scaytIdRegex =  /^dojoIoScript(\d+)$/i,
     208                                                scaytSrcRegex =  /^https?:\/\/svc\.webspellchecker\.net\/spellcheck\/script\/ssrv\.cgi/i;
     209
     210                                        for ( var i=0; i < scripts.count(); i++ )
     211                                        {
     212                                                var script = scripts.getItem( i ),
     213                                                        id = script.getId(),
     214                                                        src = script.getAttribute( 'src' );
     215
     216                                                if ( id && src && id.match( scaytIdRegex ) && src.match( scaytSrcRegex ))
     217                                                        script.remove();
     218                                        }
     219                                });
     220
     221                        editor.on( 'destroy', function( ev )
     222                                {
     223                                        var editor = ev.editor,
     224                                        scayt_instance = plugin.getScayt( editor );
     225                                        // SCAYT instance might already get destroyed by mode switch (#5744).
     226
     227                                        if ( !scayt_instance )
     228                                                return;
     229
     230                                        delete plugin.instances[ editor.name ];
     231                                        // store a control id for restore a specific scayt control settings
     232                                        plugin.setControlId( editor, scayt_instance.id );
     233                                        scayt_instance.destroy( true );
     234                                });
     235
     236                        // Listen to data manipulation to reflect scayt markup.
     237                        editor.on( 'dialogShow', function( ev )
     238                                {
     239                                        var editor = ev.editor;
     240                                        if ( plugin.isScaytEnabled( editor ) )
     241                                        {
     242                                                        var instance = plugin.getScayt( editor );
     243                                                        instance.setPaused(true);
     244                                        }
     245                                });
     246
     247                        editor.on( 'dialogHide', function( ev )
     248                                {
     249                                        var editor = ev.editor;
     250                                        if ( plugin.isScaytEnabled( editor ) )
     251                                        {
     252                                                window.setTimeout( function()
     253                                                        {
     254                                                                var instance = plugin.getScayt( editor );
     255                                       
     256                                                                instance.setPaused(false);
     257                                                                instance && instance.refresh();
     258                                                        }, 1 );
     259                                        }
     260                                });
     261
     262                        var dataProcessor = editor.dataProcessor,
     263                        htmlFilter = dataProcessor && dataProcessor.htmlFilter;
     264
     265                        if ( htmlFilter )
     266                        {
     267                                htmlFilter.addRules(
     268                                {
     269                                        elements :
     270                                        {
     271                                                span : function( element )
     272                                                {
     273                                                        if ( element.attributes[ 'data-scayt_word' ]
     274                                                                        && element.attributes[ 'data-scaytid' ] )
     275                                                        {
     276                                                                delete element.name;    // Write children, but don't write this node.
     277                                                                return element;
     278                                                        }
     279                                                }
     280                                        },
     281                                        attributes :
     282                                        {
     283                                                'class' : function( value, element )
     284                                                {
     285                                                        return value.replace( /(scayt-enabled)|(scayt-disabled)/, '' ) || false;
     286                                                }
     287                                        }
     288                                } );
     289                        }
     290
     291                        // Override Image.equals method avoid CK snapshot module to add SCAYT markup to snapshots. (#5546)
     292                        var undoImagePrototype = CKEDITOR.plugins.undo.Image.prototype;
     293                        undoImagePrototype.equals = CKEDITOR.tools.override( undoImagePrototype.equals, function( org )
     294                                {
     295                                        return function( otherImage )
     296                                        {
     297                                                var thisContents = this.contents,
     298                                                        otherContents = otherImage.contents;
     299                                                var scayt_instance = plugin.getScayt( this.editor );
     300                                                // Making the comparison based on content without SCAYT word markers.
     301                                                if ( scayt_instance && plugin.isScaytReady( this.editor ) )
     302                                                {
     303                                                        // scayt::reset might return value undefined. (#5742)
     304                                                        this.contents = scayt_instance.reset( thisContents ) || '';
     305                                                        otherImage.contents = scayt_instance.reset( otherContents ) || '';
     306                                                }
     307
     308                                                var retval = org.apply( this, arguments );
     309
     310                                                this.contents = thisContents;
     311                                                otherImage.contents = otherContents;
     312                                                return retval;
     313                                        };
     314                                });
     315
     316                         if ( editor.document )
     317                         {
     318                                plugin.createInstance.apply(editor);
     319                         }
     320                         
     321                        return true;
     322                },
     323
    370324                loadEngine : function( editor )
    371325                {
    372326                        // SCAYT doesn't work with Firefox2, Opera and AIR.
    373327                        if ( CKEDITOR.env.gecko && CKEDITOR.env.version < 10900 || CKEDITOR.env.opera || CKEDITOR.env.air )
    374328                                return editor.fire( 'showScaytState' );
    375 
     329                 
    376330                        if ( this.engineLoaded === true )
    377                                 return onEngineLoad.apply( editor );    // Add new instance.
    378                         else if ( this.engineLoaded == -1 )                     // We are waiting.
    379                                 return CKEDITOR.on( 'scaytReady', function(){ onEngineLoad.apply( editor ); } );        // Use function(){} to avoid rejection as duplicate.
     331                        {
     332                                return this.onEngineLoad.apply(editor);
     333                        }
    380334
    381                         CKEDITOR.on( 'scaytReady', onEngineLoad, editor );
    382                         CKEDITOR.on( 'scaytReady', function()
    383                                 {
    384                                         this.engineLoaded = true;
    385                                 },
    386                                 this,
    387                                 null,
    388                                 0
    389                         );      // First to run.
    390 
    391                         this.engineLoaded = -1; // Loading in progress.
    392 
     335                        // Loading in progress.
    393336                        // compose scayt url
    394337                        var protocol = document.location.protocol;
    395338                        // Default to 'http' for unknown.
     
    399342                        var scaytUrl  =  editor.config.scayt_srcUrl || ( protocol + '//' + baseUrl );
    400343                        var scaytConfigBaseUrl =  plugin.parseUrl( scaytUrl ).path +  '/';
    401344
    402                         if( window.scayt == undefined )
     345                        if( window.scayt == undefined && this.engineLoaded != -1)
    403346                        {
     347                                this.engineLoaded = -1;
    404348                                CKEDITOR._djScaytConfig =
    405349                                {
    406350                                        baseUrl: scaytConfigBaseUrl,
     
    414358                                        isDebug: false
    415359                                };
    416360                                // Append javascript code.
     361                                 
    417362                                CKEDITOR.document.getHead().append(
    418363                                        CKEDITOR.document.createElement( 'script',
    419364                                                {
     
    429374                        else
    430375                                CKEDITOR.fireOnce( 'scaytReady' );
    431376
     377                        CKEDITOR.on( 'scaytReady', function()
     378                                {
     379                                        this.engineLoaded = true;
     380                                        for(var oi in CKEDITOR.instances)
     381                                        {
     382                                                if(CKEDITOR.instances[oi].config.scayt_autoStartup && !CKEDITOR.plugins.scayt.instances[oi])
     383                                                        this.onEngineLoad.apply(CKEDITOR.instances[oi]);
     384                                        }
     385                                },
     386                                this,
     387                                null,
     388                                0
     389                        );      // First to run. */
    432390                        return null;
    433391                },
     392
    434393                parseUrl : function ( data )
    435394                {
    436395                        var match;
     
    485444                        else if ( !editor.config.scayt_autoStartup && plugin.engineLoaded >= 0 )        // Load first time
    486445                        {
    487446                                this.setState( CKEDITOR.TRISTATE_DISABLED );
     447                               
     448                                 editor.config.scayt_autoStartup = true;
    488449                                plugin.loadEngine( editor );
    489450                        }
    490451                }
     
    515476
    516477                init : function( editor )
    517478                {
    518                         // Delete span[data-scaytid] when text pasting in editor (#6921)
    519479                        var dataFilter = editor.dataProcessor && editor.dataProcessor.dataFilter;
    520480                        var dataFilterRules =
    521481                        {
    522                                         elements :
     482                                elements :
     483                                {
     484                                        span : function( element )
    523485                                        {
    524                                                         span : function( element )
    525                                                         {
    526                                                                         var attrs = element.attributes;
    527                                                                         if ( attrs && attrs[ 'data-scaytid' ] )
    528                                                                                         delete element.name;
    529                                                         }
     486                                                var attrs = element.attributes;
     487                                                if ( attrs && attrs[ 'data-scaytid' ] )
     488                                                                delete element.name;
    530489                                        }
     490                                }
    531491                        };
    532492                        dataFilter && dataFilter.addRules( dataFilterRules );
    533493
     
    551511
    552512                        // always added
    553513                        uiMenuItems.scaytToggle =
    554                                 {
    555                                         label : lang.enable,
    556                                         command : commandName,
    557                                         group : menuGroup
    558                                 };
     514                        {
     515                                label : lang.enable,
     516                                command : commandName,
     517                                group : menuGroup
     518                        };
    559519
    560520                        if ( uiTabs[0] == 1 )
    561521                                uiMenuItems.scaytOptions =
     
    580540                                                editor.openDialog( commandName );
    581541                                        }
    582542                                };
     543
    583544                        if ( uiTabs[2] == 1 )
    584545                                uiMenuItems.scaytDict =
    585546                                {
     
    591552                                                editor.openDialog( commandName );
    592553                                        }
    593554                                };
    594                         // always added
     555
     556                                // always added
    595557                        uiMenuItems.scaytAbout =
    596558                                {
    597559                                        label : editor.lang.scayt.about,
     
    605567
    606568                        editor.addMenuItems( uiMenuItems );
    607569
    608                                 editor.ui.add( 'Scayt', CKEDITOR.UI_MENUBUTTON,
     570                        editor.ui.add( 'Scayt', CKEDITOR.UI_MENUBUTTON,
     571                                {
     572                                        label : lang.title,
     573                                        title : "Spell Check As You Type",
     574                                        className : 'cke_button_scayt',
     575                                        modes : { wysiwyg : 1 },
     576                                        onRender: function()
    609577                                        {
    610                                                 label : lang.title,
    611                                                 title : CKEDITOR.env.opera ? lang.opera_title : lang.title,
    612                                                 className : 'cke_button_scayt',
    613                                                 modes : { wysiwyg : 1 },
    614                                                 onRender: function()
     578                                                command.on( 'state', function()
    615579                                                {
    616                                                         command.on( 'state', function()
    617                                                         {
    618                                                                 this.setState( command.state );
    619                                                         },
    620                                                         this);
     580                                                        this.setState( command.state );
    621581                                                },
    622                                                 onMenu : function()
    623                                                 {
    624                                                         var isEnabled = plugin.isScaytEnabled( editor );
     582                                                this);
     583                                        },
     584                                        onMenu : function()
     585                                        {
     586                                                var isEnabled = plugin.isScaytEnabled( editor );
    625587
    626                                                         editor.getMenuItem( 'scaytToggle' ).label = lang[ isEnabled ? 'disable' : 'enable' ];
     588                                                editor.getMenuItem( 'scaytToggle' ).label = lang[ isEnabled ? 'disable' : 'enable' ];
    627589
    628                                                         var uiTabs = plugin.getUiTabs( editor );
     590                                                var uiTabs = plugin.getUiTabs( editor );
    629591
    630                                                         return {
    631                                                                 scaytToggle  : CKEDITOR.TRISTATE_OFF,
    632                                                                 scaytOptions : isEnabled && uiTabs[0] ? CKEDITOR.TRISTATE_OFF : CKEDITOR.TRISTATE_DISABLED,
    633                                                                 scaytLangs   : isEnabled && uiTabs[1] ? CKEDITOR.TRISTATE_OFF : CKEDITOR.TRISTATE_DISABLED,
    634                                                                 scaytDict    : isEnabled && uiTabs[2] ? CKEDITOR.TRISTATE_OFF : CKEDITOR.TRISTATE_DISABLED,
    635                                                                 scaytAbout   : isEnabled && uiTabs[3] ? CKEDITOR.TRISTATE_OFF : CKEDITOR.TRISTATE_DISABLED
    636                                                         };
    637                                                 }
    638                                         });
     592                                                return {
     593                                                        scaytToggle  : CKEDITOR.TRISTATE_OFF,
     594                                                        scaytOptions : isEnabled && uiTabs[0] ? CKEDITOR.TRISTATE_OFF : CKEDITOR.TRISTATE_DISABLED,
     595                                                        scaytLangs   : isEnabled && uiTabs[1] ? CKEDITOR.TRISTATE_OFF : CKEDITOR.TRISTATE_DISABLED,
     596                                                        scaytDict    : isEnabled && uiTabs[2] ? CKEDITOR.TRISTATE_OFF : CKEDITOR.TRISTATE_DISABLED,
     597                                                        scaytAbout   : isEnabled && uiTabs[3] ? CKEDITOR.TRISTATE_OFF : CKEDITOR.TRISTATE_DISABLED
     598                                                };
     599                                        }
     600                                });
    639601
    640602                        // If the "contextmenu" plugin is loaded, register the listeners.
    641603                        if ( editor.contextMenu && editor.addMenuItems )
     
    643605                                editor.contextMenu.addListener( function( element, selection )
    644606                                        {
    645607                                                if ( !plugin.isScaytEnabled( editor )
    646                                                                 || selection.getRanges()[ 0 ].checkReadOnly() )
     608                                                                || ( selection.getRanges().length && selection.getCommonAncestor().isReadOnly() ) )
    647609                                                        return null;
    648610
    649611                                                var scayt_control = plugin.getScayt( editor ),
    650                                                         node = scayt_control.getScaytNode();
     612                                                        node = CKEDITOR.env.mac || CKEDITOR.env.opera ? scayt_control.getScaytNode(editor.contextMenu._.target.$) : scayt_control.getScaytNode();
    651613
    652614                                                if ( !node )
    653615                                                        return null;
    654616
    655                                                         var word = scayt_control.getWord( node );
     617                                                var word = scayt_control.getWord( node );
    656618
    657619                                                if ( !word )
    658620                                                        return null;
    659621
    660622                                                var sLang = scayt_control.getLang(),
    661                                                         _r = {},
    662623                                                        items_suggestion = window.scayt.getSuggestion( word, sLang );
    663                                                 if ( !items_suggestion || !items_suggestion.length )
    664                                                         return null;
    665624                                                // Remove unused commands and menuitems
    666                                                 for ( var m in moreSuggestions )
     625                                                for ( var i in moreSuggestions )
    667626                                                {
    668                                                         delete editor._.menuItems[ m ];
    669                                                         delete editor._.commands[ m ];
     627                                                        delete editor._.menuItems[ i ];
     628                                                        delete editor._.commands[ i ];
    670629                                                }
    671                                                 for ( m in mainSuggestions )
     630                                                for ( i in mainSuggestions )
    672631                                                {
    673                                                         delete editor._.menuItems[ m ];
    674                                                         delete editor._.commands[ m ];
     632                                                        delete editor._.menuItems[ i ];
     633                                                        delete editor._.commands[ i ];
    675634                                                }
    676635                                                moreSuggestions = {};           // Reset items.
    677636                                                mainSuggestions = {};
     
    686645                                                var contextCommands = editor.config.scayt_contextCommands || 'all';
    687646                                                contextCommands = contextCommands.split( '|' );
    688647
    689                                                 for ( var i = 0, l = items_suggestion.length; i < l; i += 1 )
     648                                                if ( items_suggestion && items_suggestion.length )
    690649                                                {
    691                                                         var commandName = 'scayt_suggestion_' + items_suggestion[i].replace( ' ', '_' );
    692                                                         var exec = ( function( el, s )
     650                                                        for ( i = 0, l = items_suggestion.length; i < l; i += 1 )
     651                                                        {
     652                                                                var commandName = 'scayt_suggestion_' + items_suggestion[i].replace( ' ', '_' );
     653                                                                var exec = ( function( el, s )
     654                                                                        {
     655                                                                                return {
     656                                                                                        exec: function()
     657                                                                                        {
     658                                                                                                scayt_control.replace(el, s);
     659                                                                                        }
     660                                                                                };
     661                                                                        })( node, items_suggestion[i] );
     662
     663                                                                if ( i < maxSuggestions )
    693664                                                                {
    694                                                                         return {
    695                                                                                 exec: function()
    696                                                                                 {
    697                                                                                         scayt_control.replace( el, s );
    698                                                                                 }
    699                                                                         };
    700                                                                 })( node, items_suggestion[i] );
     665                                                                        addButtonCommand( editor, 'button_' + commandName, items_suggestion[i],
     666                                                                                commandName, exec, 'scayt_suggest', i + 1 );
     667                                                                        mainSuggestions[ commandName ] = CKEDITOR.TRISTATE_OFF;
     668                                                                }
     669                                                                else if ( moreSuggestionsUnable == 'on' )
     670                                                                {
     671                                                                        addButtonCommand( editor, 'button_' + commandName, items_suggestion[i],
     672                                                                                commandName, exec, 'scayt_moresuggest', i + 1 );
     673                                                                        moreSuggestions[ commandName ] = CKEDITOR.TRISTATE_OFF;
     674                                                                        moreSuggestionsUnableAdded = true;
     675                                                                }
     676                                                        }
    701677
    702                                                         if ( i < maxSuggestions )
     678                                                        if ( moreSuggestionsUnableAdded )
    703679                                                        {
    704                                                                 addButtonCommand( editor, 'button_' + commandName, items_suggestion[i],
    705                                                                         commandName, exec, 'scayt_suggest', i + 1 );
    706                                                                 _r[ commandName ] = CKEDITOR.TRISTATE_OFF;
    707                                                                 mainSuggestions[ commandName ] = CKEDITOR.TRISTATE_OFF;
     680                                                                // Register the More suggestions group;
     681                                                                editor.addMenuItem( 'scayt_moresuggest',
     682                                                                {
     683                                                                        label : editor.lang.scayt.moreSuggestions,
     684                                                                        group : 'scayt_moresuggest',
     685                                                                        order : 10,
     686                                                                        getItems : function()
     687                                                                        {
     688                                                                                return moreSuggestions;
     689                                                                        }
     690                                                                });
     691                                                                mainSuggestions[ 'scayt_moresuggest' ] = CKEDITOR.TRISTATE_OFF;
    708692                                                        }
    709                                                         else if ( moreSuggestionsUnable == 'on' )
    710                                                         {
    711                                                                 addButtonCommand( editor, 'button_' + commandName, items_suggestion[i],
    712                                                                         commandName, exec, 'scayt_moresuggest', i + 1 );
    713                                                                 moreSuggestions[ commandName ] = CKEDITOR.TRISTATE_OFF;
    714                                                                 moreSuggestionsUnableAdded = true;
    715                                                         }
    716693                                                }
    717 
    718                                                 if ( moreSuggestionsUnableAdded )
     694                                                else
    719695                                                {
    720                                                         // Register the More suggestions group;
    721                                                         editor.addMenuItem( 'scayt_moresuggest',
     696                                                        // "No suggestions" feature
     697                                                        editor.addMenuItem( 'scayt_nosuggest',
    722698                                                        {
    723                                                                 label : lang.moreSuggestions,
    724                                                                 group : 'scayt_moresuggest',
    725                                                                 order : 10,
    726                                                                 getItems : function()
    727                                                                 {
    728                                                                         return moreSuggestions;
    729                                                                 }
     699                                                                label : editor.lang.scayt.noSuggestions ? editor.lang.scayt.noSuggestions : (editor.lang.spellCheck.noSuggestions ? editor.lang.spellCheck.noSuggestions : 'No suggestions'),
     700                                                                group : 'scayt_suggest',
     701                                                                order : 1
    730702                                                        });
    731                                                         mainSuggestions[ 'scayt_moresuggest' ] = CKEDITOR.TRISTATE_OFF;
     703                                                        mainSuggestions[ 'scayt_nosuggest' ] = CKEDITOR.TRISTATE_OFF;
    732704                                                }
    733 
     705                                               
    734706                                                if ( in_array( 'all', contextCommands )  || in_array( 'ignore', contextCommands)  )
    735707                                                {
    736708                                                        var ignore_command = {
     
    765737                                                }
    766738
    767739                                                if ( scayt_control.fireOnContextMenu )
     740                                                {
    768741                                                        scayt_control.fireOnContextMenu( editor );
    769 
     742                                                }
     743                                                 
    770744                                                return mainSuggestions;
    771745                                        });
    772746                        }
    773747
    774748                        var showInitialState = function()
    775                                 {
    776                                         editor.removeListener( 'showScaytState', showInitialState );
     749                        {
     750                                editor.removeListener( 'showScaytState', showInitialState );
    777751
    778                                         if ( !CKEDITOR.env.opera && !CKEDITOR.env.air )
    779                                                 command.setState( plugin.isScaytEnabled( editor ) ? CKEDITOR.TRISTATE_ON : CKEDITOR.TRISTATE_OFF );
    780                                         else
    781                                                 command.setState( CKEDITOR.TRISTATE_DISABLED );
    782                                 };
     752                                if ( !CKEDITOR.env.opera && !CKEDITOR.env.air )
     753                                        command.setState( plugin.isScaytEnabled( editor ) ? CKEDITOR.TRISTATE_ON : CKEDITOR.TRISTATE_OFF );
     754                                else
     755                                        command.setState( CKEDITOR.TRISTATE_DISABLED );
     756                        };
    783757
    784758                        editor.on( 'showScaytState', showInitialState );
    785759
     
    799773                                        plugin.loadEngine( editor );
    800774                                });
    801775                        }
    802                 },
    803776
    804                 afterInit : function( editor )
    805                 {
    806                         // Prevent word marker line from displaying in elements path and been removed when cleaning format. (#3570) (#4125)
    807                         var elementsPathFilters,
    808                                         scaytFilter = function( element )
     777                        // Delete span[data-scaytid] when text pasting in editor (#6921)
     778                        editor.on( 'afterSetData', function()
     779                                {
     780                                         if ( plugin.isScaytEnabled( editor ) )
     781                                         {
     782                                                window.setTimeout( function()
     783                                                        {
     784                                                                var instance = plugin.getScayt( editor );
     785                                                               
     786                                                                instance && instance.refresh();
     787                                                        }, 10 );
     788                                        }
     789                                });
     790
     791                        editor.on( 'beforeCommandExec', function( ev )          // Disable SCAYT before Source command execution.
     792                                {
     793                                        if ( ( ev.data.name == 'source' || ev.data.name == 'newpage' || ev.data.name == 'checkspell' || ev.data.name =='templates' ) && editor.mode == 'wysiwyg' )
    809794                                        {
    810                                                 if ( element.hasAttribute( 'data-scaytid' ) )
    811                                                         return false;
    812                                         };
     795                                                var scayt_instance = plugin.getScayt( editor );
     796                                                if ( scayt_instance )
     797                                                {
     798                                                        plugin.setPaused( editor, !scayt_instance.disabled );
     799                                                        // store a control id for restore a specific scayt control settings
     800                                                        plugin.setControlId( editor, scayt_instance.id );
     801                                                        scayt_instance.destroy( true );
     802                                                        delete plugin.instances[ editor.name ];
     803                                                         
     804                                                }
     805                                        }
     806                                        // Catch on source mode switch off (#5720)
     807                                        else if ( ev.data.name == 'source'  && editor.mode == 'source' )
     808                                        {
     809                                                plugin.markControlRestore( editor );
     810                                        }
     811                                });
     812                        editor.on( 'afterCommandExec', function( ev )
     813                                {
     814                                        if ( !plugin.isScaytEnabled( editor ) )
     815                                                return;
    813816
    814                         if ( editor._.elementsPath && ( elementsPathFilters = editor._.elementsPath.filters ) )
    815                                 elementsPathFilters.push( scaytFilter );
     817                                        if ( editor.mode == 'wysiwyg' && ( ev.data.name == 'undo' || ev.data.name == 'redo' ) )
     818                                        {         
     819                                                window.setTimeout( function() { plugin.getScayt( editor ).refresh(); }, 10 );   
     820                                        }
     821                                });
    816822
    817                         editor.addRemoveFormatFilter && editor.addRemoveFormatFilter( scaytFilter );
     823                        editor.on( 'destroy', function( ev )
     824                                {
     825                                        var editor = ev.editor,
     826                                                scayt_instance = plugin.getScayt( editor );
    818827
    819                 }
    820         });
    821 })();
     828                                        // SCAYT instance might already get destroyed by mode switch (#5744).
     829                                        if ( !scayt_instance )
     830                                                return;
    822831
    823 /**
    824  * If enabled (set to <code>true</code>), turns on SCAYT automatically
    825  * after loading the editor.
    826  * @name CKEDITOR.config.scayt_autoStartup
    827  * @type Boolean
    828  * @default <code>false</code>
    829  * @example
    830  * config.scayt_autoStartup = true;
    831  */
     832                                        delete plugin.instances[ editor.name ];
     833                                        // store a control id for restore a specific scayt control settings
     834                                        plugin.setControlId( editor, scayt_instance.id );
     835                                        scayt_instance.destroy( true );
     836                                });
    832837
    833 /**
    834  * Defines the number of SCAYT suggestions to show in the main context menu.
    835  * Possible values are:
    836  * <ul>
    837  *      <li><code>0</code> (zero) &ndash; All suggestions are displayed in the main context menu.</li>
    838  *      <li>Positive number &ndash; The maximum number of suggestions to show in the context
    839  *              menu. Other entries will be shown in the "More Suggestions" sub-menu.</li>
    840  *      <li>Negative number &ndash; No suggestions are shown in the main context menu. All
    841  *              entries will be listed in the the "Suggestions" sub-menu.</li>
    842  * </ul>
    843  * @name CKEDITOR.config.scayt_maxSuggestions
    844  * @type Number
    845  * @default <code>5</code>
    846  * @example
    847  * // Display only three suggestions in the main context menu.
    848  * config.scayt_maxSuggestions = 3;
    849  * @example
    850  * // Do not show the suggestions directly.
    851  * config.scayt_maxSuggestions = -1;
    852  */
     838                        // Listen to data manipulation to reflect scayt markup.
     839                        editor.on( 'afterSetData', function()
     840                        {
     841                                if ( plugin.isScaytEnabled( editor ) ) {
     842                                        window.setTimeout( function()
     843                                                {
     844                                                        var instance = plugin.getScayt( editor );
     845                                                        instance && instance.refresh();
     846                                                }, 10 );
     847                                }
     848                        });
    853849
    854 /**
    855  * Sets the customer ID for SCAYT. Required for migration from free,
    856  * ad-supported version to paid, ad-free version.
    857  * @name CKEDITOR.config.scayt_customerid
    858  * @type String
    859  * @default <code>''</code>
    860  * @example
    861  * // Load SCAYT using my customer ID.
    862  * config.scayt_customerid  = 'your-encrypted-customer-id';
    863  */
     850                        // Reload spell-checking for current word after insertion completed.
     851                        editor.on( 'insertElement', function()
     852                                {
     853                                        var scayt_instance = plugin.getScayt( editor );
     854                                        if ( plugin.isScaytEnabled( editor ) )
     855                                        {
     856                                                // Unlock the selection before reload, SCAYT will take
     857                                                // care selection update.
     858                                                if ( CKEDITOR.env.ie )
     859                                                        editor.getSelection().unlock( true );
    864860
    865 /**
    866  * Enables/disables the "More Suggestions" sub-menu in the context menu.
    867  * Possible values are <code>on</code> and <code>off</code>.
    868  * @name CKEDITOR.config.scayt_moreSuggestions
    869  * @type String
    870  * @default <code>'on'</code>
    871  * @example
    872  * // Disables the "More Suggestions" sub-menu.
    873  * config.scayt_moreSuggestions = 'off';
    874  */
     861                                                // Return focus to the editor and refresh SCAYT markup (#5573).
     862                                                window.setTimeout( function()
     863                                                {
     864                                                        scayt_instance.focus();
     865                                                        scayt_instance.refresh();
     866                                                }, 10 );
     867                                        }
     868                                }, this, null, 50 );
    875869
    876 /**
    877  * Customizes the display of SCAYT context menu commands ("Add Word", "Ignore"
    878  * and "Ignore All"). This must be a string with one or more of the following
    879  * words separated by a pipe character ("|"):
    880  * <ul>
    881  *      <li><code>off</code> &ndash; disables all options.</li>
    882  *      <li><code>all</code> &ndash; enables all options.</li>
    883  *      <li><code>ignore</code> &ndash; enables the "Ignore" option.</li>
    884  *      <li><code>ignoreall</code> &ndash; enables the "Ignore All" option.</li>
    885  *      <li><code>add</code> &ndash; enables the "Add Word" option.</li>
    886  * </ul>
    887  * @name CKEDITOR.config.scayt_contextCommands
    888  * @type String
    889  * @default <code>'all'</code>
    890  * @example
    891  * // Show only "Add Word" and "Ignore All" in the context menu.
    892  * config.scayt_contextCommands = 'add|ignoreall';
    893  */
     870                        editor.on( 'insertHtml', function()
     871                                {
     872                                        var scayt_instance = plugin.getScayt( editor );
     873                                        if ( plugin.isScaytEnabled( editor ) )
     874                                        {
     875                                                // Unlock the selection before reload, SCAYT will take
     876                                                // care selection update.
     877                                                if ( CKEDITOR.env.ie )
     878                                                        editor.getSelection().unlock( true );
    894879
    895 /**
    896  * Sets the default spell checking language for SCAYT. Possible values are:
    897  * <code>en_US</code>, <code>en_GB</code>, <code>pt_BR</code>, <code>da_DK</code>,
    898  * <code>nl_NL</code>, <code>en_CA</code>, <code>fi_FI</code>, <code>fr_FR</code>,
    899  * <code>fr_CA</code>, <code>de_DE</code>, <code>el_GR</code>, <code>it_IT</code>,
    900  * <code>nb_NO</code>, <code>pt_PT</code>, <code>es_ES</code>, <code>sv_SE</code>.
    901  * @name CKEDITOR.config.scayt_sLang
    902  * @type String
    903  * @default <code>'en_US'</code>
    904  * @example
    905  * // Sets SCAYT to German.
    906  * config.scayt_sLang = 'de_DE';
    907  */
     880                                                // Return focus to the editor (#5573)
     881                                                // Refresh SCAYT markup
     882                                                window.setTimeout( function()
     883                                                {
     884                                                        scayt_instance.focus();
     885                                                        scayt_instance.refresh();
     886                                                }, 10 );
     887                                        }
     888                                }, this, null, 50 );
    908889
    909 /**
    910  * Sets the visibility of particular tabs in the SCAYT dialog window and toolbar
    911  * button. This setting must contain a <code>1</code> (enabled) or <code>0</code>
    912  * (disabled) value for each of the following entries, in this precise order,
    913  * separated by a comma (","): "Options", "Languages", and "Dictionary".
    914  * @name CKEDITOR.config.scayt_uiTabs
    915  * @type String
    916  * @default <code>'1,1,1'</code>
    917  * @example
    918  * // Hides the "Languages" tab.
    919  * config.scayt_uiTabs = '1,0,1';
    920  */
     890                        editor.on( 'scaytDialog', function( ev )        // Communication with dialog.
     891                                {
     892                                        ev.data.djConfig = window.djConfig;
     893                                        ev.data.scayt_control = plugin.getScayt( editor );
     894                                        ev.data.tab = openPage;
     895                                        ev.data.scayt = window.scayt;
     896                                });     
     897                },
    921898
     899                afterInit : function( editor )
     900                {
     901                        // Prevent word marker line from displaying in elements path and been removed when cleaning format. (#3570) (#4125)
     902                        var elementsPathFilters,
     903                                scaytFilter = function( element )
     904                                {
     905                                        if ( element.hasAttribute( 'data-scaytid' ) )
     906                                                return false;
     907                                };
    922908
    923 /**
    924  * Sets the URL to SCAYT core. Required to switch to the licensed version of SCAYT application.
    925  * Further details available at
    926  * <a href="http://wiki.webspellchecker.net/doku.php?id=migration:hosredfreetolicensedck">
    927  * http://wiki.webspellchecker.net/doku.php?id=migration:hosredfreetolicensedck</a>.
    928  * @name CKEDITOR.config.scayt_srcUrl
    929  * @type String
    930  * @default <code>''</code>
    931  * @example
    932  * config.scayt_srcUrl = "http://my-host/spellcheck/lf/scayt/scayt.js";
    933  */
     909                        if ( editor._.elementsPath && ( elementsPathFilters = editor._.elementsPath.filters ) )
     910                                elementsPathFilters.push( scaytFilter );
    934911
    935 /**
    936  * Links SCAYT to custom dictionaries. This is a string containing dictionary IDs
    937  * separared by commas (","). Available only for the licensed version.
    938  * Further details at
    939  * <a href="http://wiki.webspellchecker.net/doku.php?id=installationandconfiguration:customdictionaries:licensed">
    940  * http://wiki.webspellchecker.net/doku.php?id=installationandconfiguration:customdictionaries:licensed</a>.
    941  * @name CKEDITOR.config.scayt_customDictionaryIds
    942  * @type String
    943  * @default <code>''</code>
    944  * @example
    945  * config.scayt_customDictionaryIds = '3021,3456,3478"';
    946  */
    947 
    948 /**
    949  * Makes it possible to activate a custom dictionary in SCAYT. The user
    950  * dictionary name must be used. Available only for the licensed version.
    951  * @name CKEDITOR.config.scayt_userDictionaryName
    952  * @type String
    953  * @default <code>''</code>
    954  * @example
    955  * config.scayt_userDictionaryName = 'MyDictionary';
    956  */
    957 
    958 /**
    959  * Defines the order SCAYT context menu items by groups.
    960  * This must be a string with one or more of the following
    961  * words separated by a pipe character ("|"):
    962  * <ul>
    963  *     <li><code>suggest</code> &ndash; main suggestion word list,</li>
    964  *     <li><code>moresuggest</code> &ndash; more suggestions word list,</li>
    965  *     <li><code>control</code> &ndash; SCAYT commands, such as "Ignore" and "Add Word".</li>
    966  * </ul>
    967  *
    968  * @name CKEDITOR.config.scayt_contextMenuItemsOrder
    969  * @type String
    970  * @default <code>'suggest|moresuggest|control'</code>
    971  * @example
    972  * config.scayt_contextMenuItemsOrder = 'moresuggest|control|suggest';
    973  */
     912                        editor.addRemoveFormatFilter && editor.addRemoveFormatFilter( scaytFilter );
     913                }
     914        });
     915})();
© 2003 – 2022, CKSource sp. z o.o. sp.k. All rights reserved. | Terms of use | Privacy policy