JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
vanilla ckeditor-3.0
[ckeditor.git] / _source / plugins / scayt / plugin.js
diff --git a/_source/plugins/scayt/plugin.js b/_source/plugins/scayt/plugin.js
new file mode 100644 (file)
index 0000000..cfe35d6
--- /dev/null
@@ -0,0 +1,511 @@
+/*\r
+Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved.\r
+For licensing, see LICENSE.html or http://ckeditor.com/license\r
+*/\r
+\r
+/**\r
+ * @fileOverview Spell Check As You Type (SCAYT).\r
+ * Button name : Scayt.\r
+ */\r
+\r
+(function()\r
+{\r
+       var commandName         = 'scaytcheck',\r
+               openPage                = '';\r
+\r
+       var onEngineLoad = function()\r
+       {\r
+               var editor = this;\r
+\r
+               var createInstance = function() // Create new instance every time Document is created.\r
+               {\r
+                       // Initialise Scayt instance.\r
+                       var oParams = {};\r
+                       oParams.srcNodeRef = editor.document.getWindow().$.frameElement;                // Get the iframe.\r
+                       // syntax : AppName.AppVersion@AppRevision\r
+                       oParams.assocApp  = "CKEDITOR." + CKEDITOR.version + "@" + CKEDITOR.revision;\r
+\r
+                       oParams.customerid = editor.config.scayt_customerid  || "1:11111111111111111111111111111111111111";\r
+                       oParams.customDictionaryName = editor.config.scayt_customDictionaryName;\r
+                       oParams.userDictionaryName = editor.config.scayt_userDictionaryName;\r
+                       oParams.defLang = editor.scayt_defLang;\r
+\r
+                       if ( CKEDITOR._scaytParams )\r
+                       {\r
+                               for ( var k in CKEDITOR._scaytParams )\r
+                               {\r
+                                       oParams[ k ] = CKEDITOR._scaytParams[ k ];\r
+                               }\r
+                       }\r
+\r
+                       var scayt_control = new window.scayt( oParams );\r
+\r
+                       // Copy config.\r
+                       var     lastInstance = plugin.instances[ editor.name ];\r
+                       if ( lastInstance )\r
+                       {\r
+                               scayt_control.sLang = lastInstance.sLang;\r
+                               scayt_control.option( lastInstance.option() );\r
+                               scayt_control.paused = lastInstance.paused;\r
+                       }\r
+\r
+                       plugin.instances[ editor.name ] = scayt_control;\r
+\r
+                       try {\r
+                               scayt_control.setDisabled( scayt_control.paused === false );                            // I really don't know why it causes JS error in IE\r
+                       } catch (e) {}\r
+                       editor.fire( 'showScaytState' );\r
+               };\r
+\r
+               editor.on( 'contentDom', createInstance );\r
+               editor.on( 'contentDomUnload', function()\r
+                       {\r
+                               // Remove scripts.\r
+                               var scripts = CKEDITOR.document.getElementsByTag( 'script' ),\r
+                                       scaytIdRegex =  /^dojoIoScript(\d+)$/i,\r
+                                       scaytSrcRegex =  /^https?:\/\/svc\.spellchecker\.net\/spellcheck\/script\/ssrv\.cgi/i;\r
+\r
+                               for ( var i=0; i < scripts.count(); i++ )\r
+                               {\r
+                                       var script = scripts.getItem( i ),\r
+                                               id = script.getId(),\r
+                                               src = script.getAttribute( 'src' );\r
+\r
+                                       if ( id && src && id.match( scaytIdRegex ) && src.match( scaytSrcRegex ))\r
+                                               script.remove();\r
+                               }\r
+                       });\r
+\r
+               editor.on( 'beforeCommandExec', function( ev )          // Disable SCAYT before Source command execution.\r
+                       {\r
+                               if ( (ev.data.name == 'source' ||  ev.data.name == 'newpage') && editor.mode == 'wysiwyg' )\r
+                               {\r
+                                       var scayt_instanse = plugin.getScayt( editor );\r
+                                       if ( scayt_instanse )\r
+                                       {\r
+                                               scayt_instanse.paused = !scayt_instanse.disabled;\r
+                                               scayt_instanse.destroy();\r
+                                               delete plugin.instances[ editor.name ];\r
+                                       }\r
+                               }\r
+                       });\r
+\r
+               // Listen to data manipulation to reflect scayt markup.\r
+               editor.on( 'afterSetData', function()\r
+                       {\r
+                               if ( plugin.isScaytEnabled( editor ) )\r
+                                       plugin.getScayt( editor ).refresh();\r
+                       });\r
+\r
+               // Reload spell-checking for current word after insertion completed.\r
+               editor.on( 'insertElement', function()\r
+                       {\r
+                               var scayt_instance = plugin.getScayt( editor );\r
+                               if ( plugin.isScaytEnabled( editor ) )\r
+                               {\r
+                                       // Unlock the selection before reload, SCAYT will take\r
+                                       // care selection update.\r
+                                       if ( CKEDITOR.env.ie )\r
+                                               editor.getSelection().unlock( true );\r
+\r
+                                       // Swallow any SCAYT engine errors.\r
+                                       try{\r
+                                               scayt_instance.refresh();\r
+                                       }catch( er )\r
+                                       {}\r
+                               }\r
+                       }, this, null, 50 );\r
+\r
+               editor.on( 'scaytDialog', function( ev )        // Communication with dialog.\r
+                       {\r
+                               ev.data.djConfig = window.djConfig;\r
+                               ev.data.scayt_control = plugin.getScayt( editor );\r
+                               ev.data.tab = openPage;\r
+                               ev.data.scayt = window.scayt;\r
+                       });\r
+\r
+               var dataProcessor = editor.dataProcessor,\r
+                       htmlFilter = dataProcessor && dataProcessor.htmlFilter;\r
+               if ( htmlFilter )\r
+               {\r
+                       htmlFilter.addRules(\r
+                               {\r
+                                       elements :\r
+                                       {\r
+                                               span : function( element )\r
+                                               {\r
+                                                       if ( element.attributes.scayt_word && element.attributes.scaytid )\r
+                                                       {\r
+                                                               delete element.name;    // Write children, but don't write this node.\r
+                                                               return element;\r
+                                                       }\r
+                                               }\r
+                                       }\r
+                               }\r
+                       );\r
+               }\r
+\r
+               if ( editor.document )\r
+                       createInstance();\r
+       };\r
+\r
+       CKEDITOR.plugins.scayt =\r
+       {\r
+               engineLoaded : false,\r
+               instances : {},\r
+               getScayt : function( editor )\r
+               {\r
+                       return this.instances[ editor.name ];\r
+               },\r
+               isScaytReady : function( editor )\r
+               {\r
+                       return this.engineLoaded === true &&\r
+                               'undefined' !== typeof window.scayt && this.getScayt( editor );\r
+               },\r
+               isScaytEnabled : function( editor )\r
+               {\r
+                       var scayt_instanse = this.getScayt( editor );\r
+                       return ( scayt_instanse ) ? scayt_instanse.disabled === false : false;\r
+               },\r
+               loadEngine : function( editor )\r
+               {\r
+                       if ( this.engineLoaded === true )\r
+                               return onEngineLoad.apply( editor );    // Add new instance.\r
+                       else if ( this.engineLoaded == -1 )                     // We are waiting.\r
+                               return CKEDITOR.on( 'scaytReady', function(){ onEngineLoad.apply( editor );} ); // Use function(){} to avoid rejection as duplicate.\r
+\r
+                       CKEDITOR.on( 'scaytReady', onEngineLoad, editor );\r
+                       CKEDITOR.on( 'scaytReady', function()\r
+                               {\r
+                                       this.engineLoaded = true;\r
+                               },\r
+                               this,\r
+                               null,\r
+                               0 );    // First to run.\r
+\r
+                       this.engineLoaded = -1; // Loading in progress.\r
+\r
+                       // compose scayt url\r
+                       var protocol = document.location.protocol;\r
+                       // Default to 'http' for unknown.\r
+                       protocol = protocol.search( /https?:/) != -1? protocol : 'http:';\r
+                       var baseUrl  = "svc.spellchecker.net/spellcheck/lf/scayt/scayt1.js";\r
+\r
+                       var scaytUrl  =  editor.config.scayt_srcUrl || ( protocol + "//" + baseUrl );\r
+                       var scaytConfigBaseUrl =  plugin.parseUrl( scaytUrl ).path +  "/";\r
+\r
+                       CKEDITOR._djScaytConfig =\r
+                       {\r
+                               baseUrl: scaytConfigBaseUrl,\r
+                               addOnLoad:\r
+                               [\r
+                                       function()\r
+                                       {\r
+                                               CKEDITOR.fireOnce( "scaytReady" );\r
+                                       }\r
+                               ],\r
+                               isDebug: false\r
+                       };\r
+                       // Append javascript code.\r
+                       CKEDITOR.document.getHead().append(\r
+                               CKEDITOR.document.createElement( 'script',\r
+                                       {\r
+                                               attributes :\r
+                                                       {\r
+                                                               type : 'text/javascript',\r
+                                                               src : scaytUrl\r
+                                                       }\r
+                                       })\r
+                       );\r
+\r
+                       return null;\r
+               },\r
+               parseUrl : function ( data )\r
+               {\r
+                       var match;\r
+                       if ( data.match && ( match = data.match(/(.*)[\/\\](.*?\.\w+)$/) ) )\r
+                               return { path: match[1], file: match[2] };\r
+                       else\r
+                               return data;\r
+               }\r
+       };\r
+\r
+       var plugin = CKEDITOR.plugins.scayt;\r
+\r
+       // Context menu constructing.\r
+       var addButtonCommand = function( editor, buttonName, buttonLabel, commandName, command, menugroup, menuOrder )\r
+       {\r
+               editor.addCommand( commandName, command );\r
+\r
+               // If the "menu" plugin is loaded, register the menu item.\r
+               editor.addMenuItem( commandName,\r
+                       {\r
+                               label : buttonLabel,\r
+                               command : commandName,\r
+                               group : menugroup,\r
+                               order : menuOrder\r
+                       });\r
+       };\r
+\r
+       var commandDefinition =\r
+       {\r
+               preserveState : true,\r
+\r
+               exec: function( editor )\r
+               {\r
+                       if ( plugin.isScaytReady( editor ) )\r
+                       {\r
+                               var isEnabled = plugin.isScaytEnabled( editor );\r
+\r
+                               this.setState( isEnabled ? CKEDITOR.TRISTATE_OFF : CKEDITOR.TRISTATE_ON );\r
+\r
+                               var scayt_control = plugin.getScayt( editor );\r
+                               scayt_control.setDisabled( isEnabled );\r
+                       }\r
+                       else if ( !editor.config.scayt_autoStartup && plugin.engineLoaded >= 0 )        // Load first time\r
+                       {\r
+                               this.setState( CKEDITOR.TRISTATE_DISABLED );\r
+\r
+                               editor.on( 'showScaytState', function()\r
+                                       {\r
+                                               this.removeListener();\r
+                                               this.setState( plugin.isScaytEnabled( editor ) ? CKEDITOR.TRISTATE_ON : CKEDITOR.TRISTATE_OFF );\r
+                                       },\r
+                                       this);\r
+\r
+                               plugin.loadEngine( editor );\r
+                       }\r
+               }\r
+       };\r
+\r
+       // Add scayt plugin.\r
+       CKEDITOR.plugins.add( 'scayt',\r
+       {\r
+               requires : [ 'menubutton' ],\r
+\r
+               beforeInit : function( editor )\r
+               {\r
+                       // Register own rbc menu group.\r
+                       editor.config.menu_groups = 'scayt_suggest,scayt_moresuggest,scayt_control,' + editor.config.menu_groups;\r
+               },\r
+\r
+               init : function( editor )\r
+               {\r
+                       var moreSuggestions = {};\r
+                       var mainSuggestions = {};\r
+\r
+                       // Scayt command.\r
+                       var command = editor.addCommand( commandName, commandDefinition );\r
+\r
+                       // Add Options dialog.\r
+                       CKEDITOR.dialog.add( commandName, CKEDITOR.getUrl( this.path + 'dialogs/options.js' ) );\r
+\r
+                       var menuGroup = 'scaytButton';\r
+                       editor.addMenuGroup( menuGroup );\r
+                       editor.addMenuItems(\r
+                               {\r
+                                       scaytToggle :\r
+                                       {\r
+                                               label : editor.lang.scayt.enable,\r
+                                               command : commandName,\r
+                                               group : menuGroup\r
+                                       },\r
+\r
+                                       scaytOptions :\r
+                                       {\r
+                                               label : editor.lang.scayt.options,\r
+                                               group : menuGroup,\r
+                                               onClick : function()\r
+                                               {\r
+                                                       openPage = 'options';\r
+                                                       editor.openDialog( commandName );\r
+                                               }\r
+                                       },\r
+\r
+                                       scaytLangs :\r
+                                       {\r
+                                               label : editor.lang.scayt.langs,\r
+                                               group : menuGroup,\r
+                                               onClick : function()\r
+                                               {\r
+                                                       openPage = 'langs';\r
+                                                       editor.openDialog( commandName );\r
+                                               }\r
+                                       },\r
+\r
+                                       scaytAbout :\r
+                                       {\r
+                                               label : editor.lang.scayt.about,\r
+                                               group : menuGroup,\r
+                                               onClick : function()\r
+                                               {\r
+                                                       openPage = 'about';\r
+                                                       editor.openDialog( commandName );\r
+                                               }\r
+                                       }\r
+                               });\r
+\r
+                               editor.ui.add( 'Scayt', CKEDITOR.UI_MENUBUTTON,\r
+                                       {\r
+                                               label : editor.lang.scayt.title,\r
+                                               title : editor.lang.scayt.title,\r
+                                               className : 'cke_button_scayt',\r
+                                               onRender: function()\r
+                                               {\r
+                                               command.on( 'state', function()\r
+                                                       {\r
+                                                               this.setState( command.state );\r
+                                                       },\r
+                                                       this);\r
+                                       },\r
+                                       onMenu : function()\r
+                                       {\r
+                                               var isEnabled = plugin.isScaytEnabled( editor );\r
+\r
+                                               editor.getMenuItem( 'scaytToggle' ).label = editor.lang.scayt[ isEnabled ? 'disable' : 'enable' ];\r
+\r
+                                                       return {\r
+                                                               scaytToggle : CKEDITOR.TRISTATE_OFF,\r
+                                                               scaytOptions : isEnabled ? CKEDITOR.TRISTATE_OFF : CKEDITOR.TRISTATE_DISABLED,\r
+                                                               scaytLangs : isEnabled ? CKEDITOR.TRISTATE_OFF : CKEDITOR.TRISTATE_DISABLED,\r
+                                                               scaytAbout : isEnabled ? CKEDITOR.TRISTATE_OFF : CKEDITOR.TRISTATE_DISABLED\r
+                                                       };\r
+                                               }\r
+                                       });\r
+\r
+                       // If the "contextmenu" plugin is loaded, register the listeners.\r
+                       if ( editor.contextMenu && editor.addMenuItems )\r
+                       {\r
+                               editor.contextMenu.addListener( function( element )\r
+                                       {\r
+                                               if ( !( plugin.isScaytEnabled( editor ) && element ) )\r
+                                                       return null;\r
+\r
+                                               var scayt_control = plugin.getScayt( editor ),\r
+                                                       word = scayt_control.getWord( element.$ );\r
+\r
+                                               if ( !word )\r
+                                                       return null;\r
+\r
+                                               var sLang = scayt_control.getLang(),\r
+                                                       _r = {},\r
+                                                       items_suggestion = window.scayt.getSuggestion( word, sLang );\r
+                                               if (!items_suggestion || !items_suggestion.length )\r
+                                                       return null;\r
+                                               // Remove unused commands and menuitems\r
+                                               for ( i in moreSuggestions )\r
+                                               {\r
+                                                       delete editor._.menuItems[ i ];\r
+                                                       delete editor._.commands[ i ];\r
+                                               }\r
+                                               for ( i in mainSuggestions )\r
+                                               {\r
+                                                       delete editor._.menuItems[ i ];\r
+                                                       delete editor._.commands[ i ];\r
+                                               }\r
+                                               moreSuggestions = {};           // Reset items.\r
+                                               mainSuggestions = {};\r
+\r
+                                               var moreSuggestionsUnable = false;\r
+\r
+                                               for ( var i = 0, l = items_suggestion.length; i < l; i += 1 )\r
+                                               {\r
+                                                       var commandName = 'scayt_suggestion_' + items_suggestion[i].replace( ' ', '_' );\r
+                                                       var exec = ( function( el, s )\r
+                                                               {\r
+                                                                       return {\r
+                                                                               exec: function()\r
+                                                                               {\r
+                                                                                       scayt_control.replace(el, s);\r
+                                                                               }\r
+                                                                       };\r
+                                                               })( element.$, items_suggestion[i] );\r
+\r
+                                                       if ( i < editor.config.scayt_maxSuggestions )\r
+                                                       {\r
+                                                               addButtonCommand( editor, 'button_' + commandName, items_suggestion[i],\r
+                                                                       commandName, exec, 'scayt_suggest', i + 1 );\r
+                                                               _r[ commandName ] = CKEDITOR.TRISTATE_OFF;\r
+                                                               mainSuggestions[ commandName ] = CKEDITOR.TRISTATE_OFF;\r
+                                                       }\r
+                                                       else\r
+                                                       {\r
+                                                               addButtonCommand( editor, 'button_' + commandName, items_suggestion[i],\r
+                                                                       commandName, exec, 'scayt_moresuggest', i + 1 );\r
+                                                               moreSuggestions[ commandName ] = CKEDITOR.TRISTATE_OFF;\r
+                                                               moreSuggestionsUnable = true;\r
+                                                       }\r
+                                               }\r
+                                               if ( moreSuggestionsUnable )\r
+                                                       // Rgister the More suggestions group;\r
+                                                       editor.addMenuItem( 'scayt_moresuggest',\r
+                                                               {\r
+                                                                       label : editor.lang.scayt.moreSuggestions,\r
+                                                                       group : 'scayt_moresuggest',\r
+                                                                       order : 10,\r
+                                                                       getItems : function()\r
+                                                                       {\r
+                                                                               return moreSuggestions;\r
+                                                                       }\r
+                                                               });\r
+\r
+\r
+                                               var ignore_command =\r
+                                               {\r
+                                                       exec: function()\r
+                                                       {\r
+                                                               scayt_control.ignore( element.$ );\r
+                                                       }\r
+                                               };\r
+                                               var ignore_all_command =\r
+                                               {\r
+                                                       exec: function()\r
+                                                       {\r
+                                                               scayt_control.ignoreAll( element.$ );\r
+                                                       }\r
+                                               };\r
+                                               var addword_command =\r
+                                               {\r
+                                                       exec: function()\r
+                                                       {\r
+                                                               window.scayt.addWordToUserDictionary( element.$ );\r
+                                                       }\r
+                                               };\r
+\r
+                                               addButtonCommand( editor, 'ignore', editor.lang.scayt.ignore,\r
+                                                       'scayt_ignore', ignore_command, 'scayt_control', 1);\r
+                                               addButtonCommand( editor, 'ignore_all', editor.lang.scayt.ignoreAll,\r
+                                                       'scayt_ignore_all', ignore_all_command, 'scayt_control', 2);\r
+                                               addButtonCommand( editor, 'add_word', editor.lang.scayt.addWord,\r
+                                                       'scayt_add_word', addword_command, 'scayt_control', 3);\r
+\r
+                                               mainSuggestions[ 'scayt_moresuggest' ] = CKEDITOR.TRISTATE_OFF;\r
+                                               mainSuggestions[ 'scayt_ignore' ] = CKEDITOR.TRISTATE_OFF;\r
+                                               mainSuggestions[ 'scayt_ignore_all' ] = CKEDITOR.TRISTATE_OFF;\r
+                                               mainSuggestions[ 'scayt_add_word' ] = CKEDITOR.TRISTATE_OFF;\r
+\r
+                                               if ( scayt_control.fireOnContextMenu )\r
+                                                       scayt_control.fireOnContextMenu( editor );\r
+\r
+                                               return mainSuggestions;\r
+                                       });\r
+                       }\r
+\r
+                       // Start plugin\r
+                       if ( editor.config.scayt_autoStartup )\r
+                       {\r
+                               var showInitialState = function()\r
+                               {\r
+                                       editor.removeListener( 'showScaytState', showInitialState );\r
+                                       command.setState( plugin.isScaytEnabled( editor ) ? CKEDITOR.TRISTATE_ON : CKEDITOR.TRISTATE_OFF );\r
+                               };\r
+                               editor.on( 'showScaytState', showInitialState );\r
+\r
+                               plugin.loadEngine( editor );\r
+                       }\r
+               }\r
+       });\r
+})();\r
+\r
+CKEDITOR.config.scayt_maxSuggestions =  5;\r
+CKEDITOR.config.scayt_autoStartup = false;\r