(function()\r
{\r
var commandName = 'scaytcheck',\r
- openPage = '',\r
- scayt_paused = null,\r
- scayt_control_id = null;\r
+ openPage = '';\r
\r
// Checks if a value exists in an array\r
function in_array(needle, haystack)\r
oParams.userDictionaryName = editor.config.scayt_userDictionaryName || '';\r
oParams.sLang = editor.config.scayt_sLang || 'en_US';\r
\r
+ // Introduce SCAYT onLoad callback. (#5632)\r
+ oParams.onLoad = function()\r
+ {\r
+ // Draw down word marker to avoid being covered by background-color style.(#5466)\r
+ if ( !( CKEDITOR.env.ie && CKEDITOR.env.version < 8 ) )\r
+ this.addStyle( this.selectorCss(), 'padding-bottom: 2px !important;' );\r
+\r
+ // Call scayt_control.focus when SCAYT loaded\r
+ // and only if editor has focus and scayt control creates at first time (#5720)\r
+ if ( editor.focusManager.hasFocus && !plugin.isControlRestored( editor ) )\r
+ this.focus();\r
+\r
+ };\r
+\r
oParams.onBeforeChange = function()\r
{\r
- if ( !editor.checkDirty() )\r
+ if ( plugin.getScayt( editor ) && !editor.checkDirty() )\r
setTimeout( function(){ editor.resetDirty(); } );\r
};\r
\r
}\r
}\r
// needs for restoring a specific scayt control settings\r
- if ( scayt_control_id )\r
- oParams.id = scayt_control_id;\r
+ if ( plugin.getControlId(editor) )\r
+ oParams.id = plugin.getControlId(editor);\r
\r
var scayt_control = new window.scayt( oParams );\r
\r
+ scayt_control.afterMarkupRemove.push( function( node )\r
+ {\r
+ ( new CKEDITOR.dom.element( node, scayt_control.document ) ).mergeSiblings();\r
+ } );\r
+\r
// Copy config.\r
var lastInstance = plugin.instances[ editor.name ];\r
if ( lastInstance )\r
\r
plugin.uiTabs = fTabs;\r
try {\r
- scayt_control.setDisabled( scayt_paused === false );\r
+ scayt_control.setDisabled( plugin.isPaused( editor ) === false );\r
} catch (e) {}\r
\r
editor.fire( 'showScaytState' );\r
var scayt_instance = plugin.getScayt( editor );\r
if ( scayt_instance )\r
{\r
- scayt_paused = scayt_instance.paused = !scayt_instance.disabled;\r
+ plugin.setPaused( editor, !scayt_instance.disabled );\r
// store a control id for restore a specific scayt control settings\r
- scayt_control_id = scayt_instance.id;\r
+ plugin.setControlId( editor, scayt_instance.id );\r
scayt_instance.destroy( true );\r
delete plugin.instances[ editor.name ];\r
}\r
}\r
+ // Catch on source mode switch off (#5720)\r
+ else if ( ev.data.name == 'source' && editor.mode == 'source' )\r
+ plugin.markControlRestore( editor );\r
+ });\r
+\r
+ editor.on( 'afterCommandExec', function( ev )\r
+ {\r
+ if ( !plugin.isScaytEnabled( editor ) )\r
+ return;\r
+\r
+ if ( editor.mode == 'wysiwyg' && ( ev.data.name == 'undo' || ev.data.name == 'redo' ) )\r
+ window.setTimeout( function() { plugin.getScayt( editor ).refresh(); }, 10 );\r
});\r
\r
editor.on( 'destroy', function( ev )\r
{\r
var editor = ev.editor,\r
scayt_instance = plugin.getScayt( editor );\r
+\r
+ // SCAYT instance might already get destroyed by mode switch (#5744).\r
+ if ( !scayt_instance )\r
+ return;\r
+\r
+ delete plugin.instances[ editor.name ];\r
// store a control id for restore a specific scayt control settings\r
- scayt_control_id = scayt_instance.id;\r
+ plugin.setControlId( editor, scayt_instance.id );\r
scayt_instance.destroy( true );\r
- delete plugin.instances[ editor.name ];\r
});\r
\r
// Listen to data manipulation to reflect scayt markup.\r
editor.on( 'afterSetData', function()\r
{\r
if ( plugin.isScaytEnabled( editor ) ) {\r
- window.setTimeout( function(){ plugin.getScayt( editor ).refresh(); }, 10 );\r
+ window.setTimeout( function()\r
+ {\r
+ var instance = plugin.getScayt( editor );\r
+ instance && instance.refresh();\r
+ }, 10 );\r
}\r
});\r
\r
if ( CKEDITOR.env.ie )\r
editor.getSelection().unlock( true );\r
\r
- // Swallow any SCAYT engine errors.\r
- window.setTimeout( function(){ scayt_instance.refresh(); }, 10 );\r
+ // Return focus to the editor and refresh SCAYT markup (#5573).\r
+ window.setTimeout( function()\r
+ {\r
+ scayt_instance.focus();\r
+ scayt_instance.refresh();\r
+ }, 10 );\r
}\r
}, this, null, 50 );\r
\r
if ( CKEDITOR.env.ie )\r
editor.getSelection().unlock( true );\r
\r
- // Swallow any SCAYT engine errors.\r
- window.setTimeout( function(){ scayt_instance.refresh(); },10 );\r
+ // Return focus to the editor (#5573)\r
+ // Refresh SCAYT markup\r
+ window.setTimeout( function()\r
+ {\r
+ scayt_instance.focus();\r
+ scayt_instance.refresh();\r
+ }, 10 );\r
}\r
}, this, null, 50 );\r
\r
);\r
}\r
\r
+ // Override Image.equals method avoid CK snapshot module to add SCAYT markup to snapshots. (#5546)\r
+ var undoImagePrototype = CKEDITOR.plugins.undo.Image.prototype;\r
+ undoImagePrototype.equals = CKEDITOR.tools.override( undoImagePrototype.equals, function( org )\r
+ {\r
+ return function( otherImage )\r
+ {\r
+ var thisContents = this.contents,\r
+ otherContents = otherImage.contents;\r
+ var scayt_instance = plugin.getScayt( this.editor );\r
+ // Making the comparison based on content without SCAYT word markers.\r
+ if ( scayt_instance && plugin.isScaytReady( this.editor ) )\r
+ {\r
+ // scayt::reset might return value undefined. (#5742)\r
+ this.contents = scayt_instance.reset( thisContents ) || '';\r
+ otherImage.contents = scayt_instance.reset( otherContents ) || '';\r
+ }\r
+\r
+ var retval = org.apply( this, arguments );\r
+\r
+ this.contents = thisContents;\r
+ otherImage.contents = otherContents;\r
+ return retval;\r
+ };\r
+ });\r
+\r
if ( editor.document )\r
createInstance();\r
};\r
\r
- CKEDITOR.plugins.scayt =\r
+CKEDITOR.plugins.scayt =\r
{\r
engineLoaded : false,\r
instances : {},\r
+ // Data storage for SCAYT control, based on editor instances\r
+ controlInfo : {},\r
+ setControlInfo : function( editor, o )\r
+ {\r
+ if ( editor && editor.name && typeof ( this.controlInfo[ editor.name ] ) != 'object' )\r
+ this.controlInfo[ editor.name ] = {};\r
+\r
+ for ( var infoOpt in o )\r
+ this.controlInfo[ editor.name ][ infoOpt ] = o[ infoOpt ];\r
+ },\r
+ isControlRestored : function ( editor )\r
+ {\r
+ if ( editor &&\r
+ editor.name &&\r
+ this.controlInfo[ editor.name ] )\r
+ {\r
+ return this.controlInfo[ editor.name ].restored ;\r
+ }\r
+ return false;\r
+ },\r
+ markControlRestore : function ( editor )\r
+ {\r
+ this.setControlInfo( editor,{ restored:true } );\r
+ },\r
+ setControlId: function (editor, id)\r
+ {\r
+ this.setControlInfo( editor,{ id:id } );\r
+ },\r
+ getControlId: function (editor)\r
+ {\r
+ if ( editor &&\r
+ editor.name &&\r
+ this.controlInfo[ editor.name ] &&\r
+ this.controlInfo[ editor.name ].id )\r
+ {\r
+ return this.controlInfo[ editor.name ].id;\r
+ }\r
+ return null;\r
+ },\r
+ setPaused: function ( editor , bool )\r
+ {\r
+ this.setControlInfo( editor,{ paused:bool } );\r
+ },\r
+ isPaused: function (editor)\r
+ {\r
+ if ( editor &&\r
+ editor.name &&\r
+ this.controlInfo[editor.name] )\r
+ {\r
+ return this.controlInfo[editor.name].paused ;\r
+ }\r
+ return undefined;\r
+ },\r
getScayt : function( editor )\r
{\r
return this.instances[ editor.name ];\r
{\r
// SCAYT doesn't work with Opera.\r
if ( CKEDITOR.env.opera )\r
- return null;\r
+ return editor.fire( 'showScaytState' );\r
\r
if ( this.engineLoaded === true )\r
return onEngineLoad.apply( editor ); // Add new instance.\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/spellcheck31/lf/scayt/scayt22.js';\r
+ var baseUrl = 'svc.spellchecker.net/spellcheck31/lf/scayt24/loader__base.js';\r
\r
var scaytUrl = editor.config.scayt_srcUrl || ( protocol + '//' + baseUrl );\r
var scaytConfigBaseUrl = plugin.parseUrl( scaytUrl ).path + '/';\r
\r
- CKEDITOR._djScaytConfig =\r
+ if( window.scayt == undefined )\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
+ 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
+ else\r
+ CKEDITOR.fireOnce( 'scaytReady' );\r
\r
return null;\r
},\r
\r
exec: function( editor )\r
{\r
+ var autoStartup = editor.config.scayt_autoStartup;\r
+ autoStartup = ( autoStartup == undefined ) || autoStartup;\r
+\r
if ( plugin.isScaytReady( editor ) )\r
{\r
var isEnabled = plugin.isScaytEnabled( editor );\r
this.setState( isEnabled ? CKEDITOR.TRISTATE_OFF : CKEDITOR.TRISTATE_ON );\r
\r
var scayt_control = plugin.getScayt( editor );\r
+ // the place where the status of editor focus should be restored\r
+ // after there will be ability to store its state before SCAYT button click\r
+ // if (storedFocusState is focused )\r
+ // scayt_control.focus();\r
+ //\r
+ // now focus is set certainly\r
+ scayt_control.focus( );\r
scayt_control.setDisabled( isEnabled );\r
}\r
- else if ( !editor.config.scayt_autoStartup && plugin.engineLoaded >= 0 ) // Load first time\r
+ else if ( !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
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
+ var items_order = editor.config.scayt_contextMenuItemsOrder\r
+ || 'suggest|moresuggest|control',\r
+ items_order_str = "";\r
+\r
+ items_order = items_order.split( '|' );\r
+\r
+ if ( items_order && items_order.length )\r
+ {\r
+ for ( var pos in items_order )\r
+ items_order_str += 'scayt_' + items_order[ pos ] + ( items_order.length != parseInt( pos, 10 ) + 1 ? ',' : '' );\r
+ }\r
+\r
+ // Register scayt rbc menu group.\r
+ if ( editor.config.scayt_contextMenuOntop )\r
+ // Put it on top of all context menu items\r
+ editor.config.menu_groups = items_order_str + ',' + editor.config.menu_groups;\r
+ else\r
+ // Put it down\r
+ editor.config.menu_groups = editor.config.menu_groups + ',' +items_order_str;\r
},\r
\r
init : function( editor )\r
editor.ui.add( 'Scayt', CKEDITOR.UI_MENUBUTTON,\r
{\r
label : editor.lang.scayt.title,\r
- title : editor.lang.scayt.title,\r
+ title : CKEDITOR.env.opera ? editor.lang.scayt.opera_title : editor.lang.scayt.title,\r
className : 'cke_button_scayt',\r
onRender: function()\r
{\r
});\r
}\r
\r
- // Start plugin\r
- if ( editor.config.scayt_autoStartup )\r
- {\r
- var showInitialState = function()\r
+ var showInitialState = function()\r
{\r
editor.removeListener( 'showScaytState', showInitialState );\r
- command.setState( plugin.isScaytEnabled( editor ) ? CKEDITOR.TRISTATE_ON : CKEDITOR.TRISTATE_OFF );\r
+\r
+ if ( !CKEDITOR.env.opera )\r
+ command.setState( plugin.isScaytEnabled( editor ) ? CKEDITOR.TRISTATE_ON : CKEDITOR.TRISTATE_OFF );\r
+ else\r
+ command.setState( CKEDITOR.TRISTATE_DISABLED );\r
};\r
- editor.on( 'showScaytState', showInitialState );\r
+\r
+ editor.on( 'showScaytState', showInitialState );\r
+\r
+ if ( CKEDITOR.env.opera )\r
+ {\r
+ editor.on( 'instanceReady', function()\r
+ {\r
+ showInitialState();\r
+ });\r
+ }\r
+\r
+ // Start plugin\r
+ var autoStartup = editor.config.scayt_autoStartup;\r
+ if ( ( autoStartup == undefined ) || autoStartup )\r
+ {\r
editor.on( 'instanceReady', function()\r
{\r
plugin.loadEngine( editor );\r
\r
afterInit : function( editor )\r
{\r
- // Prevent word marker line from displaying in elements path. (#3570)\r
- var elementsPathFilters;\r
+ // Prevent word marker line from displaying in elements path and been removed when cleaning format. (#3570) (#4125)\r
+ var elementsPathFilters,\r
+ scaytFilter = function( element )\r
+ {\r
+ if ( element.hasAttribute( 'scaytid' ) )\r
+ return false;\r
+ };\r
+\r
if ( editor._.elementsPath && ( elementsPathFilters = editor._.elementsPath.filters ) )\r
- {\r
- elementsPathFilters.push( function( element )\r
- {\r
- if ( element.hasAttribute( 'scaytid' ) )\r
- return false;\r
- } );\r
- }\r
+ elementsPathFilters.push( scaytFilter );\r
+\r
+ editor.addRemoveFormatFilter && editor.addRemoveFormatFilter( scaytFilter );\r
\r
}\r
});\r
* If enabled (true), turns on SCAYT automatically after loading the editor.\r
* @name CKEDITOR.config.scayt_autoStartup\r
* @type Boolean\r
- * @default false\r
+ * @default true\r
* @example\r
- * config.scayt_autoStartup = true;\r
+ * config.scayt_autoStartup = false;\r
*/\r
\r
/**\r
* @example\r
* config.scayt_userDictionaryName = 'MyDictionary';\r
*/\r
+\r
+/**\r
+ * Makes it possible to place the SCAYT context menu items above others.\r
+ * @name CKEDITOR.config.scayt_contextMenuOntop\r
+ * @type Boolean\r
+ * @default false\r
+ * @example\r
+ * config.scayt_contextMenuOntop = true;\r
+ */\r
+\r
+/**\r
+ * Define order of placing of SCAYT context menu items by groups.\r
+ * It must be a string with one or more of the following\r
+ * words separated by a pipe ("|"):\r
+ * <ul>\r
+ * <li>'suggest' - main suggestion word list,</li>\r
+ * <li>'moresuggest' - more suggestions word list,</li>\r
+ * <li>'control' - SCAYT commands, such as 'Ignore' and 'Add Word'</li>\r
+ * </ul>\r
+ *\r
+ * @name CKEDITOR.config.scayt_contextMenuItemsOrder\r
+ * @type String\r
+ * @default 'suggest|moresuggest|control'\r
+ * @example\r
+ * config.scayt_contextMenuItemsOrder = 'moresuggest|control|suggest';\r
+ */\r