]> git.immae.eu Git - perso/Immae/Projets/packagist/connexionswing-ckeditor-component.git/blame - sources/plugins/scayt/plugin.js
Upgrade to 4.5.7 and add some plugin
[perso/Immae/Projets/packagist/connexionswing-ckeditor-component.git] / sources / plugins / scayt / plugin.js
CommitLineData
7adcb81e
IB
1'use strict';\r
2CKEDITOR.plugins.add('scayt', {\r
3\r
4 //requires : ['menubutton', 'dialog'],\r
5 requires: 'menubutton,dialog',\r
6 lang: 'af,ar,bg,bn,bs,ca,cs,cy,da,de,el,en-au,en-ca,en-gb,en,eo,es,et,eu,fa,fi,fo,fr-ca,fr,gl,gu,he,hi,hr,hu,is,it,ja,ka,km,ko,lt,lv,mk,mn,ms,nb,nl,no,pl,pt-br,pt,ro,ru,sk,sl,sr-latn,sr,sv,th,tr,ug,uk,vi,zh-cn,zh', // %REMOVE_LINE_CORE%\r
7 icons: 'scayt', // %REMOVE_LINE_CORE%\r
8 hidpi: true, // %REMOVE_LINE_CORE%\r
9 tabToOpen : null,\r
10 dialogName: 'scaytDialog',\r
11 init: function(editor) {\r
12 var self = this,\r
13 plugin = CKEDITOR.plugins.scayt;\r
14\r
15 this.bindEvents(editor);\r
16 this.parseConfig(editor);\r
17 this.addRule(editor);\r
18\r
19 // source mode\r
20 CKEDITOR.dialog.add(this.dialogName, CKEDITOR.getUrl(this.path + 'dialogs/options.js'));\r
21 // end source mode\r
22\r
23 this.addMenuItems(editor);\r
24 var config = editor.config,\r
25 lang = editor.lang.scayt,\r
26 env = CKEDITOR.env;\r
27\r
28 editor.ui.add('Scayt', CKEDITOR.UI_MENUBUTTON, {\r
29 label : lang.text_title,\r
30 title : ( editor.plugins.wsc ? editor.lang.wsc.title : lang.text_title ),\r
31 // SCAYT doesn't work in IE Compatibility Mode and IE (8 & 9) Quirks Mode\r
32 modes : {wysiwyg: !(env.ie && ( env.version < 8 || env.quirks ) ) },\r
33 toolbar: 'spellchecker,20',\r
34 refresh: function() {\r
35 var buttonState = editor.ui.instances.Scayt.getState();\r
36\r
37 // check if scayt is created\r
38 if(editor.scayt) {\r
39 // check if scayt is enabled\r
40 if(plugin.state.scayt[editor.name]) {\r
41 buttonState = CKEDITOR.TRISTATE_ON;\r
42 } else {\r
43 buttonState = CKEDITOR.TRISTATE_OFF;\r
44 }\r
45 }\r
46\r
47 editor.fire('scaytButtonState', buttonState);\r
48 },\r
49 onRender: function() {\r
50 var that = this;\r
51\r
52 editor.on('scaytButtonState', function(ev) {\r
53 if(typeof ev.data !== undefined) {\r
54 that.setState(ev.data);\r
55 }\r
56 });\r
57 },\r
58 onMenu : function() {\r
59 var scaytInstance = editor.scayt;\r
60\r
61 editor.getMenuItem('scaytToggle').label = editor.lang.scayt[(scaytInstance ? plugin.state.scayt[editor.name] : false) ? 'btn_disable' : 'btn_enable'];\r
62\r
63 // If UI tab is disabled we shouldn't show menu item\r
64 var menuDefinition = {\r
65 scaytToggle : CKEDITOR.TRISTATE_OFF,\r
66 scaytOptions : scaytInstance ? CKEDITOR.TRISTATE_OFF : CKEDITOR.TRISTATE_DISABLED,\r
67 scaytLangs : scaytInstance ? CKEDITOR.TRISTATE_OFF : CKEDITOR.TRISTATE_DISABLED,\r
68 scaytDict : scaytInstance ? CKEDITOR.TRISTATE_OFF : CKEDITOR.TRISTATE_DISABLED,\r
69 scaytAbout : scaytInstance ? CKEDITOR.TRISTATE_OFF : CKEDITOR.TRISTATE_DISABLED,\r
70 WSC : editor.plugins.wsc ? CKEDITOR.TRISTATE_OFF : CKEDITOR.TRISTATE_DISABLED\r
71 };\r
72\r
73 if(!editor.config.scayt_uiTabs[0]) {\r
74 delete menuDefinition.scaytOptions;\r
75 }\r
76\r
77 if(!editor.config.scayt_uiTabs[1]) {\r
78 delete menuDefinition.scaytLangs;\r
79 }\r
80\r
81 if(!editor.config.scayt_uiTabs[2]) {\r
82 delete menuDefinition.scaytDict;\r
83 }\r
84\r
85 return menuDefinition;\r
86 }\r
87 });\r
88\r
89 // If the 'contextmenu' plugin is loaded, register the listeners.\r
90 if(editor.contextMenu && editor.addMenuItems) {\r
91 editor.contextMenu.addListener(function(element, selection) {\r
92 var scaytInstance = editor.scayt,\r
93 result, selectionNode;\r
94\r
95 if(scaytInstance) {\r
96 selectionNode = scaytInstance.getSelectionNode();\r
97\r
98 // SCAYT shouldn't build context menu if instance isnot created or word is without misspelling or grammar problem\r
99 if(selectionNode) {\r
100 var items = self.menuGenerator(editor, selectionNode);\r
101\r
102 scaytInstance.showBanner('.' + editor.contextMenu._.definition.panel.className.split(' ').join(' .'));\r
103 result = items;\r
104 }\r
105 }\r
106\r
107 return result;\r
108 });\r
109\r
110 editor.contextMenu._.onHide = CKEDITOR.tools.override(editor.contextMenu._.onHide, function(org) {\r
111 return function() {\r
112 var scaytInstance = editor.scayt;\r
113\r
114 if(scaytInstance) {\r
115 scaytInstance.hideBanner();\r
116 }\r
117\r
118 return org.apply(this);\r
119 };\r
120 });\r
121 }\r
122 },\r
123 addMenuItems: function(editor) {\r
124 var self = this,\r
125 plugin = CKEDITOR.plugins.scayt,\r
126 graytGroups = ['grayt_description', 'grayt_suggest', 'grayt_control'],\r
127 menuGroup = 'scaytButton';\r
128\r
129 editor.addMenuGroup(menuGroup);\r
130\r
131 var items_order = editor.config.scayt_contextMenuItemsOrder.split('|');\r
132\r
133 for(var pos = 0 ; pos < items_order.length ; pos++) {\r
134 items_order[pos] = 'scayt_' + items_order[pos];\r
135 }\r
136 items_order = graytGroups.concat(items_order);\r
137\r
138 if(items_order && items_order.length) {\r
139 for(var pos = 0 ; pos < items_order.length ; pos++) {\r
140 editor.addMenuGroup(items_order[pos], pos - 10);\r
141 }\r
142 }\r
143\r
144 editor.addCommand( 'scaytToggle', {\r
145 exec: function(editor) {\r
146 var scaytInstance = editor.scayt;\r
147\r
148 plugin.state.scayt[editor.name] = !plugin.state.scayt[editor.name];\r
149\r
150 if(plugin.state.scayt[editor.name] === true) {\r
151 if(!scaytInstance) {\r
152 plugin.createScayt(editor);\r
153 }\r
154 } else {\r
155 if(scaytInstance) {\r
156 plugin.destroy(editor);\r
157 }\r
158 }\r
159 }\r
160 } );\r
161\r
162 editor.addCommand( 'scaytAbout', {\r
163 exec: function(editor) {\r
164 var scaytInstance = editor.scayt;\r
165\r
166 scaytInstance.tabToOpen = 'about';\r
167 editor.lockSelection();\r
168 editor.openDialog(self.dialogName);\r
169 }\r
170 } );\r
171\r
172 editor.addCommand( 'scaytOptions', {\r
173 exec: function(editor) {\r
174 var scaytInstance = editor.scayt;\r
175\r
176 scaytInstance.tabToOpen = 'options';\r
177 editor.lockSelection();\r
178 editor.openDialog(self.dialogName);\r
179 }\r
180 } );\r
181\r
182 editor.addCommand( 'scaytLangs', {\r
183 exec: function(editor) {\r
184 var scaytInstance = editor.scayt;\r
185\r
186 scaytInstance.tabToOpen = 'langs';\r
187 editor.lockSelection();\r
188 editor.openDialog(self.dialogName);\r
189 }\r
190 } );\r
191\r
192 editor.addCommand( 'scaytDict', {\r
193 exec: function(editor) {\r
194 var scaytInstance = editor.scayt;\r
195\r
196 scaytInstance.tabToOpen = 'dictionaries';\r
197 editor.lockSelection();\r
198 editor.openDialog(self.dialogName);\r
199 }\r
200 } );\r
201\r
202 var uiMenuItems = {\r
203 scaytToggle: {\r
204 label : editor.lang.scayt.btn_enable,\r
205 group : menuGroup,\r
206 command: 'scaytToggle'\r
207 },\r
208 scaytAbout: {\r
209 label : editor.lang.scayt.btn_about,\r
210 group : menuGroup,\r
211 command: 'scaytAbout'\r
212 },\r
213 scaytOptions: {\r
214 label : editor.lang.scayt.btn_options,\r
215 group : menuGroup,\r
216 command: 'scaytOptions'\r
217 },\r
218 scaytLangs: {\r
219 label : editor.lang.scayt.btn_langs,\r
220 group : menuGroup,\r
221 command: 'scaytLangs'\r
222 },\r
223 scaytDict: {\r
224 label : editor.lang.scayt.btn_dictionaries,\r
225 group : menuGroup,\r
226 command: 'scaytDict'\r
227 }\r
228 };\r
229\r
230 if(editor.plugins.wsc) {\r
231 uiMenuItems.WSC = {\r
232 label : editor.lang.wsc.toolbar,\r
233 group : menuGroup,\r
234 onClick: function() {\r
235 var inlineMode = (editor.elementMode == CKEDITOR.ELEMENT_MODE_INLINE),\r
236 plugin = CKEDITOR.plugins.scayt,\r
237 scaytInstance = editor.scayt,\r
238 text = inlineMode ? editor.container.getText() : editor.document.getBody().getText();\r
239\r
240 text = text.replace(/\s/g, '');\r
241\r
242 if(text) {\r
243 if(scaytInstance && plugin.state.scayt[editor.name] && scaytInstance.setMarkupPaused) {\r
244 scaytInstance.setMarkupPaused(true);\r
245 }\r
246\r
247 editor.lockSelection();\r
248 editor.execCommand('checkspell');\r
249 } else {\r
250 alert('Nothing to check!');\r
251 }\r
252 }\r
253 }\r
254 }\r
255\r
256 editor.addMenuItems(uiMenuItems);\r
257 },\r
258 bindEvents: function(editor) {\r
259 var self = this,\r
260 plugin = CKEDITOR.plugins.scayt,\r
261 inline_mode = (editor.elementMode == CKEDITOR.ELEMENT_MODE_INLINE);\r
262\r
263 var scaytDestroy = function() {\r
264 plugin.destroy(editor);\r
265 };\r
266\r
3b35bd27 267 /*\r
7adcb81e
IB
268 * Dirty fix for placeholder drag&drop\r
269 * Should be fixed with next release\r
270 */\r
271 /*\r
272 editor.on('drop', function(evt) {\r
273 var dropRange = evt.data.dropRange;\r
274 var b = dropRange.createBookmark(true);\r
275 editor.scayt.removeMarkupInSelectionNode({ selectionNode: evt.data.target.$, forceBookmark: false });\r
276 dropRange.moveToBookmark(b);\r
277\r
278 evt.data.dropRange = dropRange;\r
279 return evt;\r
280 }, this, null, 0); // We should be sure that we modify dropRange before CKEDITOR.plugins.clipboard calls\r
281 */\r
282\r
283 var contentDomReady = function() {\r
284 // The event is fired when editable iframe node was reinited so we should restart our service\r
285 if (plugin.state.scayt[editor.name] && !editor.readOnly && !editor.scayt) {\r
286 plugin.createScayt(editor);\r
287 }\r
288 };\r
289\r
290 var addMarkupStateHandlers = function() {\r
291 var editable = editor.editable();\r
292\r
293 editable.attachListener( editable, 'focus', function( evt ) {\r
294 if( CKEDITOR.plugins.scayt && !editor.scayt ) {\r
295 setTimeout(contentDomReady, 0); // we need small timeout in order to correctly set initial 'focused' option value in SCAYT core\r
296 }\r
297\r
298 var pluginStatus = CKEDITOR.plugins.scayt && CKEDITOR.plugins.scayt.state.scayt[editor.name] && editor.scayt,\r
299 selectedElement, ranges, textLength, range;\r
300\r
301 if((inline_mode ? true : pluginStatus) && editor._.savedSelection) {\r
302 selectedElement = editor._.savedSelection.getSelectedElement();\r
303 ranges = !selectedElement && editor._.savedSelection.getRanges();\r
304\r
305 for(var i = 0; i < ranges.length; i++) {\r
306 range = ranges[i];\r
307 // we need to check type of node value in order to avoid error in IE when accessing 'nodeValue' property\r
308 if(typeof range.startContainer.$.nodeValue === 'string') {\r
309 textLength = range.startContainer.getText().length;\r
310 if(textLength < range.startOffset || textLength < range.endOffset) {\r
311 editor.unlockSelection(false);\r
312 }\r
313 }\r
314 }\r
315 }\r
316 }, this, null, -10 ); // priority "-10" is set to call SCAYT CKEDITOR.editor#unlockSelection before CKEDITOR.editor#unlockSelection call\r
317 };\r
318\r
319 var contentDomHandler = function() {\r
320 if(inline_mode) {\r
321\r
322 if (!editor.config.scayt_inlineModeImmediateMarkup) {\r
3b35bd27 323 /*\r
7adcb81e
IB
324 * Give an opportunity to CKEditor to perform all needed updates\r
325 * and only after that call 'scaytDestroy' method (#72725)\r
326 */\r
327 editor.on('blur', function () { setTimeout( scaytDestroy, 0 ); } );\r
328 editor.on('focus', contentDomReady);\r
329\r
330 // We need to check if editor has focus(created) right now.\r
331 // If editor is active - make attempt to create scayt\r
332 if(editor.focusManager.hasFocus) {\r
333 contentDomReady();\r
334 }\r
335\r
336 } else {\r
337 contentDomReady();\r
338 }\r
339\r
340 } else {\r
341 contentDomReady();\r
342 }\r
343\r
344 addMarkupStateHandlers();\r
345\r
3b35bd27 346 /*\r
7adcb81e
IB
347 * 'mousedown' handler handle widget selection (click on widget). To\r
348 * fix the issue when widget#wrapper referenced to element which can\r
349 * be broken after markup.\r
350 */\r
351 var editable = editor.editable();\r
352 editable.attachListener(editable, 'mousedown', function( evt ) {\r
353 var target = evt.data.getTarget();\r
354 var widget = editor.widgets && editor.widgets.getByElement( target );\r
355 if ( widget ) {\r
356 widget.wrapper = target.getAscendant( function( el ) {\r
357 return el.hasAttribute( 'data-cke-widget-wrapper' )\r
358 }, true );\r
359 }\r
360 }, this, null, -10); // '-10': we need to be shure that widget#wrapper updated before any other calls\r
361 };\r
362\r
363 editor.on('contentDom', contentDomHandler);\r
364\r
365 editor.on('beforeCommandExec', function(ev) {\r
366 var scaytInstance = editor.scayt,\r
367 selectedLangElement = null,\r
368 forceBookmark = false,\r
369 removeMarkupInsideSelection = true;\r
370\r
371 // TODO: after switching in source mode not recreate SCAYT instance, try to just rerun markuping to don't make requests to server\r
372 if(ev.data.name in plugin.options.disablingCommandExec && editor.mode == 'wysiwyg') {\r
373 if(scaytInstance) {\r
374 plugin.destroy(editor);\r
375 editor.fire('scaytButtonState', CKEDITOR.TRISTATE_DISABLED);\r
376 }\r
377 } else if( ev.data.name === 'bold' || ev.data.name === 'italic' || ev.data.name === 'underline' ||\r
378 ev.data.name === 'strike' || ev.data.name === 'subscript' || ev.data.name === 'superscript' ||\r
379 ev.data.name === 'enter' || ev.data.name === 'cut' || ev.data.name === 'language') {\r
380 if(scaytInstance) {\r
381 if(ev.data.name === 'cut') {\r
382 removeMarkupInsideSelection = false;\r
383 // We need to force bookmark before we remove our markup.\r
384 // Otherwise we will get issues with cutting text via context menu.\r
385 forceBookmark = true;\r
386 }\r
387\r
388 // We need to remove all SCAYT markup from 'lang' node before it will be deleted.\r
389 // We need to remove SCAYT markup from selected text before creating 'lang' node as well.\r
390 if(ev.data.name === 'language') {\r
391 selectedLangElement = editor.plugins.language.getCurrentLangElement(editor);\r
392 selectedLangElement = selectedLangElement && selectedLangElement.$;\r
393 // We need to force bookmark before we remove our markup.\r
394 // Otherwise we will get issues with cutting text via language plugin menu.\r
395 forceBookmark = true;\r
396 }\r
397\r
398 editor.fire('reloadMarkupScayt', {\r
399 removeOptions: {\r
400 removeInside: removeMarkupInsideSelection,\r
401 forceBookmark: forceBookmark,\r
402 selectionNode: selectedLangElement\r
403 },\r
404 timeout: 0\r
405 });\r
406 }\r
407 }\r
408 });\r
409\r
410 editor.on('beforeSetMode', function(ev) {\r
411 var scaytInstance;\r
412 // needed when we use:\r
413 // CKEDITOR.instances.editor_ID.setMode("source")\r
414 // CKEDITOR.instances.editor_ID.setMode("wysiwyg")\r
415 // can't be implemented in editor.on('mode', function(ev) {});\r
416 if (ev.data == 'source') {\r
417 scaytInstance = editor.scayt;\r
418 if(scaytInstance) {\r
419 plugin.destroy(editor);\r
420 editor.fire('scaytButtonState', CKEDITOR.TRISTATE_DISABLED);\r
421 }\r
422\r
423 // remove custom data from body, to prevent waste properties showing in IE8\r
424 if(editor.document) { //GitHub #84 : make sure that document exists(e.g. when startup mode set to 'source')\r
425 editor.document.getBody().removeAttribute('_jquid');\r
426 }\r
427 }\r
428 });\r
429\r
430 editor.on('afterCommandExec', function(ev) {\r
431 if(editor.mode == 'wysiwyg' && (ev.data.name == 'undo' || ev.data.name == 'redo')) {\r
432 setTimeout(function() {\r
433 var scaytInstance = editor.scayt,\r
434 scaytLangList = scaytInstance && scaytInstance.getScaytLangList();\r
435\r
3b35bd27 436 /*\r
7adcb81e
IB
437 * Checks SCAYT initialization of LangList. To prevent immediate\r
438 * markup which is triggered by 'startSpellCheck' event.\r
439 * E.g.: Drop into inline CKEDITOR with scayt_autoStartup = true;\r
440 */\r
441 if (!scaytLangList || !(scaytLangList.ltr && scaytLangList.rtl)) return;\r
442\r
443 scaytInstance.fire('startSpellCheck, startGrammarCheck');\r
444 }, 250);\r
445 }\r
446 });\r
447\r
448 // handle readonly changes\r
449 editor.on('readOnly', function(ev) {\r
450 var scaytInstance;\r
451\r
452 if(ev) {\r
453 scaytInstance = editor.scayt;\r
454\r
455 if(ev.editor.readOnly === true) {\r
456 if(scaytInstance) {\r
457 scaytInstance.fire('removeMarkupInDocument', {});\r
458 }\r
459 } else {\r
460 if(scaytInstance) {\r
461 scaytInstance.fire('startSpellCheck, startGrammarCheck');\r
462 } else if(ev.editor.mode == 'wysiwyg' && plugin.state.scayt[ev.editor.name] === true) {\r
463 plugin.createScayt(editor);\r
464 ev.editor.fire('scaytButtonState', CKEDITOR.TRISTATE_ON);\r
465 }\r
466 }\r
467 }\r
468 });\r
469\r
470 // we need to destroy SCAYT before CK editor will be completely destroyed\r
471 editor.on('beforeDestroy', scaytDestroy);\r
472\r
473 //#9439 after SetData method fires contentDom event and SCAYT create additional instanse\r
474 // This way we should destroy SCAYT on setData event when contenteditable Iframe was re-created\r
475 editor.on('setData', function() {\r
476 scaytDestroy();\r
477\r
478 // in inline mode SetData does not fire contentDom event\r
479 if(editor.elementMode == CKEDITOR.ELEMENT_MODE_INLINE || editor.plugins.divarea) {\r
480 contentDomHandler();\r
481 }\r
482 }, this, null, 50);\r
483\r
3b35bd27 484 /*\r
7adcb81e
IB
485 * Main entry point to react on changes in document\r
486 */\r
487 editor.on('reloadMarkupScayt', function(ev) {\r
488 var removeOptions = ev.data && ev.data.removeOptions,\r
489 timeout = ev.data && ev.data.timeout;\r
490\r
3b35bd27 491 /*\r
7adcb81e
IB
492 * Perform removeMarkupInSelectionNode and 'startSpellCheck' fire\r
493 * asynchroniosly and keep CKEDITOR flow as expected\r
494 */\r
495 setTimeout(function() {\r
496 var scaytInstance = editor.scayt,\r
497 scaytLangList = scaytInstance && scaytInstance.getScaytLangList();\r
498\r
3b35bd27 499 /*\r
7adcb81e
IB
500 * Checks SCAYT initialization of LangList. To prevent immediate\r
501 * markup which is triggered by 'startSpellCheck' event.\r
502 * E.g.: Drop into inline CKEDITOR with scayt_autoStartup = true;\r
503 */\r
504 if (!scaytLangList || !(scaytLangList.ltr && scaytLangList.rtl)) return;\r
505\r
3b35bd27 506 /*\r
7adcb81e
IB
507 * CKEditor can keep \u200B character in document (with selection#selectRanges)\r
508 * we need to take care about that. For this case we fire\r
509 * 'keydown' [left arrow], what will trigger 'removeFillingChar' on Webkit\r
510 * to cleanup the document\r
511 */\r
512 editor.document.fire( 'keydown', new CKEDITOR.dom.event( { keyCode: 37 } ) );\r
513\r
514 /* trigger remove markup with 'startSpellCheck' */\r
515 scaytInstance.removeMarkupInSelectionNode(removeOptions);\r
516 scaytInstance.fire('startSpellCheck, startGrammarCheck');\r
517 }, timeout || 0 );\r
518 });\r
519\r
520 // Reload spell-checking for current word after insertion completed.\r
521 editor.on('insertElement', function() {\r
522 // IE bug: we need wait here to make sure that focus is returned to editor, and we can store the selection before we proceed with markup\r
523 editor.fire('reloadMarkupScayt', {removeOptions: {forceBookmark: true}});\r
524 }, this, null, 50);\r
525\r
526 editor.on('insertHtml', function() {\r
527 editor.fire('reloadMarkupScayt');\r
528 }, this, null, 50);\r
529\r
530 editor.on('insertText', function() {\r
531 editor.fire('reloadMarkupScayt');\r
532 }, this, null, 50);\r
533\r
534 // The event is listening to open necessary dialog tab\r
535 editor.on('scaytDialogShown', function(ev) {\r
536 var dialog = ev.data,\r
537 scaytInstance = editor.scayt;\r
538\r
539 dialog.selectPage(scaytInstance.tabToOpen);\r
540 });\r
541 },\r
542 parseConfig: function(editor) {\r
543 var plugin = CKEDITOR.plugins.scayt;\r
544\r
545 // preprocess config for backward compatibility\r
546 plugin.replaceOldOptionsNames(editor.config);\r
547\r
548 // Checking editor's config after initialization\r
549 if(typeof editor.config.scayt_autoStartup !== 'boolean') {\r
550 editor.config.scayt_autoStartup = false;\r
551 }\r
552 plugin.state.scayt[editor.name] = editor.config.scayt_autoStartup;\r
553\r
554 if(typeof editor.config.grayt_autoStartup !== 'boolean') {\r
555 editor.config.grayt_autoStartup = false;\r
556 }\r
557 if(typeof editor.config.scayt_inlineModeImmediateMarkup !== 'boolean') {\r
558 editor.config.scayt_inlineModeImmediateMarkup = false;\r
559 }\r
560 plugin.state.grayt[editor.name] = editor.config.grayt_autoStartup;\r
561\r
562 if(!editor.config.scayt_contextCommands) {\r
563 editor.config.scayt_contextCommands = 'ignore|ignoreall|add';\r
564 }\r
565\r
566 if(!editor.config.scayt_contextMenuItemsOrder) {\r
567 editor.config.scayt_contextMenuItemsOrder = 'suggest|moresuggest|control';\r
568 }\r
569\r
570 if(!editor.config.scayt_sLang) {\r
571 editor.config.scayt_sLang = 'en_US';\r
572 }\r
573\r
574 if(editor.config.scayt_maxSuggestions === undefined || typeof editor.config.scayt_maxSuggestions != 'number' || editor.config.scayt_maxSuggestions < 0) {\r
575 editor.config.scayt_maxSuggestions = 5;\r
576 }\r
577\r
578 if(editor.config.scayt_minWordLength === undefined || typeof editor.config.scayt_minWordLength != 'number' || editor.config.scayt_minWordLength < 1) {\r
579 editor.config.scayt_minWordLength = 4;\r
580 }\r
581\r
582 if(editor.config.scayt_customDictionaryIds === undefined || typeof editor.config.scayt_customDictionaryIds !== 'string') {\r
583 editor.config.scayt_customDictionaryIds = '';\r
584 }\r
585\r
586 if(editor.config.scayt_userDictionaryName === undefined || typeof editor.config.scayt_userDictionaryName !== 'string') {\r
587 editor.config.scayt_userDictionaryName = null;\r
588 }\r
589\r
590 if(typeof editor.config.scayt_uiTabs === 'string' && editor.config.scayt_uiTabs.split(',').length === 3) {\r
591 var scayt_uiTabs = [], _tempUITabs = [];\r
592 editor.config.scayt_uiTabs = editor.config.scayt_uiTabs.split(',');\r
593\r
594 CKEDITOR.tools.search(editor.config.scayt_uiTabs, function(value) {\r
595 if (Number(value) === 1 || Number(value) === 0) {\r
596 _tempUITabs.push(true);\r
597 scayt_uiTabs.push(Number(value));\r
598 } else {\r
599 _tempUITabs.push(false);\r
600 }\r
601 });\r
602\r
603 if (CKEDITOR.tools.search(_tempUITabs, false) === null) {\r
604 editor.config.scayt_uiTabs = scayt_uiTabs;\r
605 } else {\r
606 editor.config.scayt_uiTabs = [1,1,1];\r
607 }\r
608\r
609 } else {\r
610 editor.config.scayt_uiTabs = [1,1,1];\r
611 }\r
612\r
613 if(typeof editor.config.scayt_serviceProtocol != 'string') {\r
614 editor.config.scayt_serviceProtocol = null;\r
615 }\r
616\r
617 if(typeof editor.config.scayt_serviceHost != 'string') {\r
618 editor.config.scayt_serviceHost = null;\r
619 }\r
620\r
621 if(typeof editor.config.scayt_servicePort != 'string') {\r
622 editor.config.scayt_servicePort = null;\r
623 }\r
624\r
625 if(typeof editor.config.scayt_servicePath != 'string') {\r
626 editor.config.scayt_servicePath = null;\r
627 }\r
628\r
629 if(!editor.config.scayt_moreSuggestions) {\r
630 editor.config.scayt_moreSuggestions = 'on';\r
631 }\r
632\r
633 if(typeof editor.config.scayt_customerId !== 'string') {\r
634 editor.config.scayt_customerId = '1:WvF0D4-UtPqN1-43nkD4-NKvUm2-daQqk3-LmNiI-z7Ysb4-mwry24-T8YrS3-Q2tpq2';\r
635 }\r
636\r
637 if(typeof editor.config.scayt_srcUrl !== 'string') {\r
638 var protocol = document.location.protocol;\r
639 protocol = protocol.search(/https?:/) != -1 ? protocol : 'http:';\r
640\r
641 editor.config.scayt_srcUrl = protocol + '//svc.webspellchecker.net/spellcheck31/lf/scayt3/ckscayt/ckscayt.js';\r
642 }\r
643\r
644 if(typeof CKEDITOR.config.scayt_handleCheckDirty !== 'boolean') {\r
645 CKEDITOR.config.scayt_handleCheckDirty = true;\r
646 }\r
647\r
648 if(typeof CKEDITOR.config.scayt_handleUndoRedo !== 'boolean') {\r
649 /* set default as 'true' */\r
650 CKEDITOR.config.scayt_handleUndoRedo = true;\r
651 }\r
652 /* checking 'undo' plugin, if no disable SCAYT handler */\r
653 CKEDITOR.config.scayt_handleUndoRedo = CKEDITOR.plugins.undo ? CKEDITOR.config.scayt_handleUndoRedo : false;\r
654\r
655 if(typeof editor.config.scayt_multiLanguageMode !== 'boolean') {\r
656 editor.config.scayt_multiLanguageMode = false;\r
657 }\r
658\r
659 if(typeof editor.config.scayt_multiLanguageStyles !== 'object') {\r
660 editor.config.scayt_multiLanguageStyles = {};\r
661 }\r
662\r
663 if(editor.config.scayt_ignoreAllCapsWords && typeof editor.config.scayt_ignoreAllCapsWords !== 'boolean') {\r
664 editor.config.scayt_ignoreAllCapsWords = false;\r
665 }\r
666\r
667 if(editor.config.scayt_ignoreDomainNames && typeof editor.config.scayt_ignoreDomainNames !== 'boolean') {\r
668 editor.config.scayt_ignoreDomainNames = false;\r
669 }\r
670\r
671 if(editor.config.scayt_ignoreWordsWithMixedCases && typeof editor.config.scayt_ignoreWordsWithMixedCases !== 'boolean') {\r
672 editor.config.scayt_ignoreWordsWithMixedCases = false;\r
673 }\r
674\r
675 if(editor.config.scayt_ignoreWordsWithNumbers && typeof editor.config.scayt_ignoreWordsWithNumbers !== 'boolean') {\r
676 editor.config.scayt_ignoreWordsWithNumbers = false;\r
677 }\r
678\r
679 if( editor.config.scayt_disableOptionsStorage ) {\r
680 var userOptions = CKEDITOR.tools.isArray( editor.config.scayt_disableOptionsStorage ) ? editor.config.scayt_disableOptionsStorage : ( typeof editor.config.scayt_disableOptionsStorage === 'string' ) ? [ editor.config.scayt_disableOptionsStorage ] : undefined,\r
681 availableValue = [ 'all', 'options', 'lang', 'ignore-all-caps-words', 'ignore-domain-names', 'ignore-words-with-mixed-cases', 'ignore-words-with-numbers'],\r
682 valuesOption = ['lang', 'ignore-all-caps-words', 'ignore-domain-names', 'ignore-words-with-mixed-cases', 'ignore-words-with-numbers'],\r
683 search = CKEDITOR.tools.search,\r
684 indexOf = CKEDITOR.tools.indexOf;\r
685\r
686 var isValidOption = function( option ) {\r
687 return !!search( availableValue, option );\r
688 };\r
689\r
690 var makeOptionsToStorage = function( options ) {\r
691 var retval = [];\r
692\r
693 for (var i = 0; i < options.length; i++) {\r
694 var value = options[i],\r
695 isGroupOptionInUserOptions = !!search( options, 'options' );\r
696\r
697 if( !isValidOption( value ) || isGroupOptionInUserOptions && !!search( valuesOption, function( val ) { if( val === 'lang' ) { return false; } } ) ) {\r
698 return;\r
699 }\r
700\r
701 if( !!search( valuesOption, value ) ) {\r
702 valuesOption.splice( indexOf( valuesOption, value ), 1 );\r
703 }\r
704\r
705 if( value === 'all' || isGroupOptionInUserOptions && !!search( options, 'lang' )) {\r
706 return [];\r
707 }\r
708\r
709 if( value === 'options' ) {\r
710 valuesOption = [ 'lang' ];\r
711 }\r
712 }\r
713\r
714 retval = retval.concat( valuesOption );\r
715\r
716 return retval;\r
717 };\r
718\r
719 editor.config.scayt_disableOptionsStorage = makeOptionsToStorage( userOptions );\r
720 }\r
721 },\r
722 addRule: function(editor) {\r
723 var plugin = CKEDITOR.plugins.scayt,\r
724 dataProcessor = editor.dataProcessor,\r
725 htmlFilter = dataProcessor && dataProcessor.htmlFilter,\r
726 pathFilters = editor._.elementsPath && editor._.elementsPath.filters,\r
727 dataFilter = dataProcessor && dataProcessor.dataFilter,\r
728 removeFormatFilter = editor.addRemoveFormatFilter,\r
729 pathFilter = function(element) {\r
730 var scaytInstance = editor.scayt;\r
731\r
732 if( scaytInstance && (element.hasAttribute(plugin.options.data_attribute_name) || element.hasAttribute(plugin.options.problem_grammar_data_attribute)) ) {\r
733 return false;\r
734 }\r
735 },\r
736 removeFormatFilterTemplate = function(element) {\r
737 var scaytInstance = editor.scayt,\r
738 result = true;\r
739\r
740 if( scaytInstance && (element.hasAttribute(plugin.options.data_attribute_name) || element.hasAttribute(plugin.options.problem_grammar_data_attribute)) ) {\r
741 result = false;\r
742 }\r
743\r
744 return result;\r
745 };\r
746\r
747 if(pathFilters) {\r
748 pathFilters.push(pathFilter);\r
749 }\r
750\r
751 if(dataFilter) {\r
752 var dataFilterRules = {\r
753 elements: {\r
754 span: function(element) {\r
755\r
756 var scaytState = element.hasClass(plugin.options.misspelled_word_class) && element.attributes[plugin.options.data_attribute_name],\r
757 graytState = element.hasClass(plugin.options.problem_grammar_class) && element.attributes[plugin.options.problem_grammar_data_attribute];\r
758\r
759 if(plugin && (scaytState || graytState)) {\r
760 delete element.name;\r
761 }\r
762\r
763 return element;\r
764 }\r
765 }\r
766 };\r
767\r
768 dataFilter.addRules(dataFilterRules);\r
769 }\r
770\r
771 if (htmlFilter) {\r
772 var htmlFilterRules = {\r
773 elements: {\r
774 span: function(element) {\r
775\r
776 var scaytState = element.hasClass(plugin.options.misspelled_word_class) && element.attributes[plugin.options.data_attribute_name],\r
777 graytState = element.hasClass(plugin.options.problem_grammar_class) && element.attributes[plugin.options.problem_grammar_data_attribute];\r
778\r
779 if(plugin && (scaytState || graytState)) {\r
780 delete element.name;\r
781 }\r
782\r
783 return element;\r
784 }\r
785 }\r
786 };\r
787\r
788 htmlFilter.addRules(htmlFilterRules);\r
789 }\r
790\r
791 if(removeFormatFilter) {\r
792 removeFormatFilter.call(editor, removeFormatFilterTemplate);\r
793 }\r
794 },\r
795 scaytMenuDefinition: function(editor) {\r
796 var self = this,\r
797 plugin = CKEDITOR.plugins.scayt,\r
798 scayt_instance = editor.scayt;\r
799\r
800 return {\r
801 scayt: {\r
802 scayt_ignore: {\r
803 label: scayt_instance.getLocal('btn_ignore'),\r
804 group : 'scayt_control',\r
805 order : 1,\r
806 exec: function(editor) {\r
807 var scaytInstance = editor.scayt;\r
808 scaytInstance.ignoreWord();\r
809 }\r
810 },\r
811 scayt_ignoreall: {\r
812 label : scayt_instance.getLocal('btn_ignoreAll'),\r
813 group : 'scayt_control',\r
814 order : 2,\r
815 exec: function(editor) {\r
816 var scaytInstance = editor.scayt;\r
817 scaytInstance.ignoreAllWords();\r
818 }\r
819 },\r
820 scayt_add: {\r
821 label : scayt_instance.getLocal('btn_addWord'),\r
822 group : 'scayt_control',\r
823 order : 3,\r
824 exec : function(editor) {\r
825 var scaytInstance = editor.scayt;\r
826\r
827 // @TODO: We need to add set/restore bookmark logic to 'addWordToUserDictionary' method inside dictionarymanager.\r
828 // Timeout is used as tmp fix for IE9, when after hitting 'Add word' menu item, document container was blurred.\r
829 setTimeout(function() {\r
830 scaytInstance.addWordToUserDictionary();\r
831 }, 10);\r
832 }\r
833 },\r
834 scayt_option: {\r
835 label : scayt_instance.getLocal('btn_options'),\r
836 group : 'scayt_control',\r
837 order : 4,\r
838 exec: function(editor) {\r
839 var scaytInstance = editor.scayt;\r
840\r
841 scaytInstance.tabToOpen = 'options';\r
842 editor.lockSelection();\r
843 editor.openDialog(self.dialogName);\r
844 },\r
845 verification: function(editor) {\r
846 return (editor.config.scayt_uiTabs[0] == 1) ? true : false;\r
847 }\r
848 },\r
849 scayt_language: {\r
850 label : scayt_instance.getLocal('btn_langs'),\r
851 group : 'scayt_control',\r
852 order : 5,\r
853 exec: function(editor) {\r
854 var scaytInstance = editor.scayt;\r
855\r
856 scaytInstance.tabToOpen = 'langs';\r
857 editor.lockSelection();\r
858 editor.openDialog(self.dialogName);\r
859 },\r
860 verification: function(editor) {\r
861 return (editor.config.scayt_uiTabs[1] == 1) ? true : false;\r
862 }\r
863 },\r
864 scayt_dictionary: {\r
865 label : scayt_instance.getLocal('btn_dictionaries'),\r
866 group : 'scayt_control',\r
867 order : 6,\r
868 exec: function(editor) {\r
869 var scaytInstance = editor.scayt;\r
870\r
871 scaytInstance.tabToOpen = 'dictionaries';\r
872 editor.lockSelection();\r
873 editor.openDialog(self.dialogName);\r
874 },\r
875 verification: function(editor) {\r
876 return (editor.config.scayt_uiTabs[2] == 1) ? true : false;\r
877 }\r
878 },\r
879 scayt_about: {\r
880 label : scayt_instance.getLocal('btn_about'),\r
881 group : 'scayt_control',\r
882 order : 7,\r
883 exec: function(editor) {\r
884 var scaytInstance = editor.scayt;\r
885\r
886 scaytInstance.tabToOpen = 'about';\r
887 editor.lockSelection();\r
888 editor.openDialog(self.dialogName);\r
889 }\r
890 }\r
891 },\r
892 grayt: {\r
893 grayt_problemdescription: {\r
894 label : 'Grammar problem description',\r
895 group : 'grayt_description', // look at addMenuItems method for further info\r
896 order : 1,\r
897 state : CKEDITOR.TRISTATE_DISABLED,\r
898 exec: function(editor) {}\r
899 },\r
900 grayt_ignore: {\r
901 label : scayt_instance.getLocal('btn_ignore'),\r
902 group : 'grayt_control',\r
903 order : 2,\r
904 exec: function(editor) {\r
905 var scaytInstance = editor.scayt;\r
906\r
907 scaytInstance.ignorePhrase();\r
908 }\r
909 }\r
910 }\r
911 };\r
912 },\r
913 buildSuggestionMenuItems: function(editor, suggestions, isScaytNode) {\r
914 var self = this,\r
915 itemList = {},\r
916 subItemList = {},\r
917 replaceKeyName = isScaytNode ? 'word' : 'phrase',\r
918 updateEventName = isScaytNode ? 'startGrammarCheck' : 'startSpellCheck',\r
919 plugin = CKEDITOR.plugins.scayt,\r
920 scayt_instance = editor.scayt;\r
921\r
922 if(suggestions.length > 0 && suggestions[0] !== 'no_any_suggestions') {\r
923\r
924 if(isScaytNode) {\r
925 // build SCAYT suggestions\r
926 for(var i = 0; i < suggestions.length; i++) {\r
927\r
928 var commandName = 'scayt_suggest_' + CKEDITOR.plugins.scayt.suggestions[i].replace(' ', '_');\r
929\r
930 editor.addCommand(commandName, self.createCommand(CKEDITOR.plugins.scayt.suggestions[i], replaceKeyName, updateEventName));\r
931\r
932 if(i < editor.config.scayt_maxSuggestions) {\r
933\r
934 // mainSuggestions\r
935 editor.addMenuItem(commandName, {\r
936 label: suggestions[i],\r
937 command: commandName,\r
938 group: 'scayt_suggest',\r
939 order: i + 1\r
940 });\r
941\r
942 itemList[commandName] = CKEDITOR.TRISTATE_OFF;\r
943\r
944 } else {\r
945\r
946 // moreSuggestions\r
947 editor.addMenuItem(commandName, {\r
948 label: suggestions[i],\r
949 command: commandName,\r
950 group: 'scayt_moresuggest',\r
951 order: i + 1\r
952 });\r
953\r
954 subItemList[commandName] = CKEDITOR.TRISTATE_OFF;\r
955\r
956 if(editor.config.scayt_moreSuggestions === 'on') {\r
957\r
958 editor.addMenuItem('scayt_moresuggest', {\r
959 label : scayt_instance.getLocal('btn_moreSuggestions'),\r
960 group : 'scayt_moresuggest',\r
961 order : 10,\r
962 getItems : function() {\r
963 return subItemList;\r
964 }\r
965 });\r
966\r
967 itemList['scayt_moresuggest'] = CKEDITOR.TRISTATE_OFF;\r
968 }\r
969 }\r
970 }\r
971 } else {\r
972 // build GRAYT suggestions\r
973 for(var i = 0; i < suggestions.length; i++) {\r
974 var commandName = 'grayt_suggest_' + CKEDITOR.plugins.scayt.suggestions[i].replace(' ', '_');\r
975\r
976 editor.addCommand(commandName, self.createCommand(CKEDITOR.plugins.scayt.suggestions[i], replaceKeyName, updateEventName));\r
977\r
978 // mainSuggestions\r
979 editor.addMenuItem(commandName, {\r
980 label: suggestions[i],\r
981 command: commandName,\r
982 group: 'grayt_suggest',\r
983 order: i + 1\r
984 });\r
985\r
986 itemList[commandName] = CKEDITOR.TRISTATE_OFF;\r
987 }\r
988 }\r
989 } else {\r
990 var noSuggestionsCommand = 'no_scayt_suggest';\r
991 itemList[noSuggestionsCommand] = CKEDITOR.TRISTATE_DISABLED;\r
992\r
993 editor.addCommand(noSuggestionsCommand, {\r
994 exec: function() {\r
995\r
996 }\r
997 });\r
998\r
999 editor.addMenuItem(noSuggestionsCommand, {\r
1000 label : scayt_instance.getLocal('btn_noSuggestions') || noSuggestionsCommand,\r
1001 command: noSuggestionsCommand,\r
1002 group : 'scayt_suggest',\r
1003 order : 0\r
1004 });\r
1005 }\r
1006\r
1007 return itemList;\r
1008 },\r
1009 menuGenerator: function(editor, selectionNode) {\r
1010 var self = this,\r
1011 scaytInstance = editor.scayt,\r
1012 menuItems = this.scaytMenuDefinition(editor),\r
1013 itemList = {},\r
1014 allowedOption = editor.config.scayt_contextCommands.split('|'),\r
1015 lang = selectionNode.getAttribute(scaytInstance.getLangAttribute()) || scaytInstance.getLang(),\r
1016 word, grammarPhrase, isScaytNode, isGrammarNode, problemDescriptionText;\r
1017\r
1018\r
1019 isScaytNode = scaytInstance.isScaytNode(selectionNode);\r
1020 isGrammarNode = scaytInstance.isGraytNode(selectionNode);\r
1021\r
1022 if(isScaytNode) {\r
1023 // we clicked scayt misspelling\r
1024 // get suggestions\r
1025 menuItems = menuItems.scayt;\r
1026\r
1027 word = selectionNode.getAttribute(scaytInstance.getScaytNodeAttributeName());\r
1028\r
1029 scaytInstance.fire('getSuggestionsList', {\r
1030 lang: lang,\r
1031 word: word\r
1032 });\r
1033\r
1034 itemList = this.buildSuggestionMenuItems(editor, CKEDITOR.plugins.scayt.suggestions, isScaytNode);\r
1035 } else if(isGrammarNode) {\r
1036 // we clicked grammar problem\r
1037 // get suggestions\r
1038 menuItems = menuItems.grayt;\r
1039 grammarPhrase = selectionNode.getAttribute(scaytInstance.getGraytNodeAttributeName());\r
1040\r
1041 // setup grammar problem description\r
1042 problemDescriptionText = scaytInstance.getProblemDescriptionText(grammarPhrase, lang);\r
1043 if(menuItems.grayt_problemdescription && problemDescriptionText) {\r
1044 menuItems.grayt_problemdescription.label = problemDescriptionText;\r
1045 }\r
1046\r
1047 scaytInstance.fire('getGrammarSuggestionsList', {\r
1048 lang: lang,\r
1049 phrase: grammarPhrase\r
1050 });\r
1051\r
1052 itemList = this.buildSuggestionMenuItems(editor, CKEDITOR.plugins.scayt.suggestions, isScaytNode);\r
1053 }\r
1054\r
1055 if(isScaytNode && editor.config.scayt_contextCommands == 'off') {\r
1056 return itemList;\r
1057 }\r
1058\r
1059 for(var key in menuItems) {\r
1060 if(isScaytNode && CKEDITOR.tools.indexOf(allowedOption, key.replace('scayt_', '')) == -1 && editor.config.scayt_contextCommands != 'all') {\r
1061 continue;\r
1062 }\r
1063\r
1064 if(typeof menuItems[key].state != 'undefined') {\r
1065 itemList[key] = menuItems[key].state;\r
1066 } else {\r
1067 itemList[key] = CKEDITOR.TRISTATE_OFF;\r
1068 }\r
1069\r
1070 // delete item from context menu if its state isn't verified as allowed\r
1071 if(typeof menuItems[key].verification === 'function' && !menuItems[key].verification(editor)) {\r
1072 // itemList[key] = (menuItems[key].verification(editor)) ? CKEDITOR.TRISTATE_OFF : CKEDITOR.TRISTATE_DISABLED;\r
1073 delete itemList[key];\r
1074 }\r
1075\r
1076 editor.addCommand(key, {\r
1077 exec: menuItems[key].exec\r
1078 });\r
1079\r
1080 editor.addMenuItem(key, {\r
1081 label : editor.lang.scayt[menuItems[key].label] || menuItems[key].label,\r
1082 command: key,\r
1083 group : menuItems[key].group,\r
1084 order : menuItems[key].order\r
1085 });\r
1086 }\r
1087\r
1088 return itemList;\r
1089 },\r
1090 createCommand: function(suggestion, replaceKeyName, updateEventName) {\r
1091 return {\r
1092 exec: function(editor) {\r
1093 var scaytInstance = editor.scayt,\r
1094 eventObject = {};\r
1095\r
1096 eventObject[replaceKeyName] = suggestion;\r
1097 scaytInstance.replaceSelectionNode(eventObject);\r
1098\r
1099 // we need to remove grammar markup from selection node if we just performed replace action for misspelling\r
1100 if(updateEventName === 'startGrammarCheck') {\r
1101 scaytInstance.removeMarkupInSelectionNode({grammarOnly: true});\r
1102 }\r
1103 // for grayt problem replacement we need to fire 'startSpellCheck'\r
1104 // for scayt misspelling replacement we need to fire 'startGrammarCheck'\r
1105 scaytInstance.fire(updateEventName);\r
1106 }\r
1107 };\r
1108 }\r
1109});\r
1110\r
1111CKEDITOR.plugins.scayt = {\r
1112 state: {\r
1113 scayt: {},\r
1114 grayt: {}\r
1115 },\r
1116 suggestions: [],\r
1117 loadingHelper: {\r
1118 loadOrder: []\r
1119 },\r
1120 isLoading: false,\r
1121 options: {\r
1122 disablingCommandExec: {\r
1123 source: true,\r
1124 newpage: true,\r
1125 templates: true\r
1126 },\r
1127 data_attribute_name: 'data-scayt-word',\r
1128 misspelled_word_class: 'scayt-misspell-word',\r
1129 problem_grammar_data_attribute: 'data-grayt-phrase',\r
1130 problem_grammar_class: 'gramm-problem'\r
1131 },\r
1132 backCompatibilityMap: {\r
1133 'scayt_service_protocol': 'scayt_serviceProtocol',\r
1134 'scayt_service_host' : 'scayt_serviceHost',\r
1135 'scayt_service_port' : 'scayt_servicePort',\r
1136 'scayt_service_path' : 'scayt_servicePath',\r
1137 'scayt_customerid' : 'scayt_customerId'\r
1138 },\r
1139 replaceOldOptionsNames: function(config) {\r
1140 for(var key in config) {\r
1141 if(key in this.backCompatibilityMap) {\r
1142 config[this.backCompatibilityMap[key]] = config[key];\r
1143 delete config[key];\r
1144 }\r
1145 }\r
1146 },\r
1147 createScayt : function(editor) {\r
1148 var self = this,\r
1149 plugin = CKEDITOR.plugins.scayt;\r
1150\r
1151 this.loadScaytLibrary(editor, function(_editor) {\r
1152 var textContainer = _editor.window && _editor.window.getFrame() || _editor.editable();\r
1153\r
1154 // Do not create SCAYT if there is no text container for usage\r
1155 if(!textContainer) {\r
1156 plugin.state.scayt[_editor.name] = false;\r
1157 return;\r
1158 }\r
1159\r
1160 var scaytInstanceOptions = {\r
1161 lang : _editor.config.scayt_sLang,\r
1162 container : textContainer.$,\r
1163 customDictionary : _editor.config.scayt_customDictionaryIds,\r
1164 userDictionaryName : _editor.config.scayt_userDictionaryName,\r
1165 localization : _editor.langCode,\r
1166 customer_id : _editor.config.scayt_customerId,\r
1167 debug : _editor.config.scayt_debug,\r
1168 data_attribute_name : self.options.data_attribute_name,\r
1169 misspelled_word_class: self.options.misspelled_word_class,\r
1170 problem_grammar_data_attribute: self.options.problem_grammar_data_attribute,\r
1171 problem_grammar_class: self.options.problem_grammar_class,\r
1172 'options-to-restore': _editor.config.scayt_disableOptionsStorage,\r
1173 focused : _editor.editable().hasFocus, // #30260 we need to set focused=true if CKEditor is focused before SCAYT initialization\r
1174 ignoreElementsRegex : _editor.config.scayt_elementsToIgnore,\r
1175 minWordLength : _editor.config.scayt_minWordLength,\r
1176 multiLanguageMode : _editor.config.scayt_multiLanguageMode,\r
1177 multiLanguageStyles : _editor.config.scayt_multiLanguageStyles,\r
1178 graytAutoStartup : plugin.state.grayt[_editor.name]\r
1179 };\r
1180\r
1181 if(_editor.config.scayt_serviceProtocol) {\r
1182 scaytInstanceOptions['service_protocol'] = _editor.config.scayt_serviceProtocol;\r
1183 }\r
1184\r
1185 if(_editor.config.scayt_serviceHost) {\r
1186 scaytInstanceOptions['service_host'] = _editor.config.scayt_serviceHost;\r
1187 }\r
1188\r
1189 if(_editor.config.scayt_servicePort) {\r
1190 scaytInstanceOptions['service_port'] = _editor.config.scayt_servicePort;\r
1191 }\r
1192\r
1193 if(_editor.config.scayt_servicePath) {\r
1194 scaytInstanceOptions['service_path'] = _editor.config.scayt_servicePath;\r
1195 }\r
1196\r
1197 //predefined options\r
1198 if(typeof _editor.config.scayt_ignoreAllCapsWords === 'boolean') {\r
1199 scaytInstanceOptions['ignore-all-caps-words'] = _editor.config.scayt_ignoreAllCapsWords;\r
1200 }\r
1201\r
1202 if(typeof _editor.config.scayt_ignoreDomainNames === 'boolean') {\r
1203 scaytInstanceOptions['ignore-domain-names'] = _editor.config.scayt_ignoreDomainNames;\r
1204 }\r
1205\r
1206 if(typeof _editor.config.scayt_ignoreWordsWithMixedCases === 'boolean') {\r
1207 scaytInstanceOptions['ignore-words-with-mixed-cases'] = _editor.config.scayt_ignoreWordsWithMixedCases;\r
1208 }\r
1209\r
1210 if(typeof _editor.config.scayt_ignoreWordsWithNumbers === 'boolean') {\r
1211 scaytInstanceOptions['ignore-words-with-numbers'] = _editor.config.scayt_ignoreWordsWithNumbers;\r
1212 }\r
1213\r
1214 var scaytInstance = new SCAYT.CKSCAYT(scaytInstanceOptions, function() {\r
1215 // success callback\r
1216 }, function() {\r
1217 // error callback\r
1218 }),\r
1219 wordsPrefix = 'word_';\r
1220\r
1221 scaytInstance.subscribe('suggestionListSend', function(data) {\r
1222 // TODO: 1. Maybe store suggestions for specific editor\r
1223 // TODO: 2. Fix issue with suggestion duplicates on on server\r
1224 //CKEDITOR.plugins.scayt.suggestions = data.suggestionList;\r
1225 var _wordsCollection = {},\r
1226 _suggestionList =[];\r
1227\r
1228 for (var i = 0; i < data.suggestionList.length; i++) {\r
1229 if (!_wordsCollection[wordsPrefix + data.suggestionList[i]]) {\r
1230 _wordsCollection[wordsPrefix + data.suggestionList[i]] = data.suggestionList[i];\r
1231 _suggestionList.push(data.suggestionList[i]);\r
1232 }\r
1233 }\r
1234\r
1235 CKEDITOR.plugins.scayt.suggestions = _suggestionList;\r
1236 });\r
1237\r
1238 // if selection has changed programmatically by SCAYT we need to react appropriately\r
1239 scaytInstance.subscribe('selectionIsChanged', function(data) {\r
1240 var selection = _editor.getSelection();\r
1241\r
1242 if(selection.isLocked) {\r
1243 _editor.lockSelection();\r
1244 }\r
1245 });\r
1246\r
1247 scaytInstance.subscribe('graytStateChanged', function(data) {\r
1248 plugin.state.grayt[_editor.name] = data.state;\r
1249 });\r
1250\r
1251 _editor.scayt = scaytInstance;\r
1252\r
1253 _editor.fire('scaytButtonState', _editor.readOnly ? CKEDITOR.TRISTATE_DISABLED : CKEDITOR.TRISTATE_ON);\r
1254 });\r
1255 },\r
1256 destroy: function(editor) {\r
1257 if(editor.scayt) {\r
1258 editor.scayt.destroy();\r
1259 }\r
1260\r
1261 delete editor.scayt;\r
1262 editor.fire('scaytButtonState', CKEDITOR.TRISTATE_OFF);\r
1263 },\r
1264 loadScaytLibrary: function(editor, callback) {\r
1265 var self = this,\r
1266 date,\r
1267 timestamp,\r
1268 scaytUrl;\r
1269\r
1270 // no need to process load requests from same editor as it can cause bugs with\r
1271 // loading ckscayt app due to subsequent calls of some events\r
1272 // need to be before 'if' statement, because of timing issue in CKEDITOR.scriptLoader\r
1273 // when callback executing is delayed for a few milliseconds, and scayt can be created twise\r
1274 // on one instance\r
1275 if(this.loadingHelper[editor.name]) return;\r
1276\r
1277 if(typeof window.SCAYT === 'undefined' || typeof window.SCAYT.CKSCAYT !== 'function') {\r
1278\r
1279 // add onLoad callbacks for editors while SCAYT is loading\r
1280 this.loadingHelper[editor.name] = callback;\r
1281 this.loadingHelper.loadOrder.push(editor.name);\r
1282\r
1283 //creating unique timestamp for SCAYT URL\r
1284 date = new Date();\r
1285 timestamp = date.getTime();\r
1286 scaytUrl = editor.config.scayt_srcUrl;\r
1287\r
1288 //if there already implemented timstamp for scayr_srcURL use it, if not use our timestamp\r
1289 scaytUrl = scaytUrl + (scaytUrl.indexOf('?') >= 0 ? '' : '?' + timestamp);\r
1290\r
1291 if (!this.loadingHelper.ckscaytLoading) {\r
1292 CKEDITOR.scriptLoader.load(scaytUrl, function(success) {\r
1293 var editorName;\r
1294\r
1295 if ( success ) {\r
1296 CKEDITOR.fireOnce('scaytReady');\r
1297\r
1298 for(var i = 0; i < self.loadingHelper.loadOrder.length; i++) {\r
1299 editorName = self.loadingHelper.loadOrder[i];\r
1300\r
1301 if(typeof self.loadingHelper[editorName] === 'function') {\r
1302 self.loadingHelper[editorName](CKEDITOR.instances[editorName]);\r
1303 }\r
1304\r
1305 delete self.loadingHelper[editorName];\r
1306 }\r
1307 self.loadingHelper.loadOrder = [];\r
1308 }\r
1309 });\r
1310 this.loadingHelper.ckscaytLoading = true;\r
1311 }\r
1312\r
1313\r
1314 } else if(window.SCAYT && typeof window.SCAYT.CKSCAYT === 'function') {\r
1315 CKEDITOR.fireOnce('scaytReady');\r
1316\r
1317 if(!editor.scayt) {\r
1318 if(typeof callback === 'function') {\r
1319 callback(editor);\r
1320 }\r
1321 }\r
1322 }\r
1323 }\r
1324};\r
1325\r
1326CKEDITOR.on('dialogDefinition', function(dialogDefinitionEvent) {\r
1327 var dialogName = dialogDefinitionEvent.data.name,\r
1328 dialogDefinition = dialogDefinitionEvent.data.definition,\r
1329 dialog = dialogDefinition.dialog;\r
1330\r
1331 if (dialogName === 'scaytDialog') {\r
1332 dialog.on('cancel', function(cancelEvent) {\r
1333 return false;\r
1334 }, this, null, -1);\r
1335 }\r
1336\r
1337 if ( dialogName === 'checkspell' ) {\r
1338 dialog.on( 'cancel', function( cancelEvent ) {\r
1339 var editor = cancelEvent.sender && cancelEvent.sender.getParentEditor(),\r
1340 plugin = CKEDITOR.plugins.scayt,\r
1341 scaytInstance = editor.scayt;\r
1342\r
1343 if ( scaytInstance && plugin.state.scayt[ editor.name ] && scaytInstance.setMarkupPaused ) {\r
1344 scaytInstance.setMarkupPaused( false );\r
1345 }\r
1346\r
1347 editor.unlockSelection();\r
1348 }, this, null, -2 ); // we need to call cancel callback before WSC plugin\r
1349 }\r
1350\r
1351 if (dialogName === 'link') {\r
1352 dialog.on('ok', function(okEvent) {\r
1353 var editor = okEvent.sender && okEvent.sender.getParentEditor();\r
1354\r
1355 if(editor) {\r
1356 setTimeout(function() {\r
1357 editor.fire('reloadMarkupScayt', {\r
1358 removeOptions: {\r
1359 removeInside: true,\r
1360 forceBookmark: true\r
1361 },\r
1362 timeout: 0\r
1363 });\r
1364 }, 0);\r
1365 }\r
1366 });\r
1367 }\r
1368});\r
1369\r
1370CKEDITOR.on('scaytReady', function() {\r
1371\r
1372 // Override editor.checkDirty method avoid CK checkDirty functionality to fix SCAYT issues with incorrect checkDirty behavior.\r
1373 if(CKEDITOR.config.scayt_handleCheckDirty === true) {\r
1374 var editorCheckDirty = CKEDITOR.editor.prototype;\r
1375\r
1376 editorCheckDirty.checkDirty = CKEDITOR.tools.override(editorCheckDirty.checkDirty, function(org) {\r
1377\r
1378 return function() {\r
1379 var retval = null,\r
1380 pluginStatus = CKEDITOR.plugins.scayt && CKEDITOR.plugins.scayt.state.scayt[this.name] && this.scayt,\r
1381 scaytInstance = this.scayt;\r
1382\r
1383 if(!pluginStatus) {\r
1384 retval = org.call(this);\r
1385 } else {\r
1386 retval = (this.status == 'ready');\r
1387\r
1388 if (retval) {\r
1389 var currentData = scaytInstance.removeMarkupFromString(this.getSnapshot()),\r
1390 prevData = scaytInstance.removeMarkupFromString(this._.previousValue);\r
1391\r
1392 retval = (retval && (prevData !== currentData))\r
1393 }\r
1394 }\r
1395\r
1396 return retval;\r
1397 };\r
1398 });\r
1399\r
1400 editorCheckDirty.resetDirty = CKEDITOR.tools.override(editorCheckDirty.resetDirty, function(org) {\r
1401 return function() {\r
1402 var pluginStatus = CKEDITOR.plugins.scayt && CKEDITOR.plugins.scayt.state.scayt[this.name] && this.scayt,\r
1403 scaytInstance = this.scayt;//CKEDITOR.plugins.scayt.getScayt(this);\r
1404\r
1405 if(!pluginStatus) {\r
1406 org.call(this);\r
1407 } else {\r
1408 this._.previousValue = scaytInstance.removeMarkupFromString(this.getSnapshot());\r
1409 }\r
1410 };\r
1411 });\r
1412 }\r
1413\r
1414 if (CKEDITOR.config.scayt_handleUndoRedo === true) {\r
1415 var undoImagePrototype = CKEDITOR.plugins.undo.Image.prototype;\r
1416\r
1417 // add backword compatibility for CKEDITOR 4.2. method equals was repleced on other method\r
1418 var equalsContentMethodName = (typeof undoImagePrototype.equalsContent == "function") ? 'equalsContent' : 'equals';\r
1419\r
1420 undoImagePrototype[equalsContentMethodName] = CKEDITOR.tools.override(undoImagePrototype[equalsContentMethodName], function(org) {\r
1421 return function(otherImage) {\r
1422 var pluginState = CKEDITOR.plugins.scayt && CKEDITOR.plugins.scayt.state.scayt[otherImage.editor.name] && otherImage.editor.scayt,\r
1423 scaytInstance = otherImage.editor.scayt,\r
1424 thisContents = this.contents,\r
1425 otherContents = otherImage.contents,\r
1426 retval = null;\r
1427\r
1428 // Making the comparison based on content without SCAYT word markers.\r
1429 if(pluginState) {\r
1430 this.contents = scaytInstance.removeMarkupFromString(thisContents) || '';\r
1431 otherImage.contents = scaytInstance.removeMarkupFromString(otherContents) || '';\r
1432 }\r
1433\r
1434 var retval = org.apply(this, arguments);\r
1435\r
1436 this.contents = thisContents;\r
1437 otherImage.contents = otherContents;\r
1438\r
1439 return retval;\r
1440 };\r
1441 });\r
1442 }\r
1443});\r
1444\r
1445/**\r
3b35bd27
IB
1446 * Automatically enables SCAYT on editor startup. When set to `true`, this option turns on SCAYT automatically\r
1447 * after loading the editor.\r
1448 *\r
1449 * Read more in the [documentation](#!/guide/dev_spellcheck) and see the [SDK sample](http://sdk.ckeditor.com/samples/spellchecker.html).\r
7adcb81e
IB
1450 *\r
1451 * config.scayt_autoStartup = true;\r
1452 *\r
1453 * @cfg {Boolean} [scayt_autoStartup=false]\r
1454 * @member CKEDITOR.config\r
1455 */\r
1456\r
1457/**\r
3b35bd27
IB
1458 * Enables Grammar As You Type (GRAYT) on SCAYT startup. When set to `true`, this option turns on GRAYT automatically\r
1459 * after SCAYT started.\r
1460 *\r
1461 * Read more in the [documentation](#!/guide/dev_spellcheck) and see the [SDK sample](http://sdk.ckeditor.com/samples/spellchecker.html).\r
7adcb81e
IB
1462 *\r
1463 * config.grayt_autoStartup = true;\r
1464 *\r
3b35bd27 1465 * @since 4.5.6\r
7adcb81e
IB
1466 * @cfg {Boolean} [grayt_autoStartup=false]\r
1467 * @member CKEDITOR.config\r
1468 */\r
1469\r
1470/**\r
3b35bd27
IB
1471 * Enables SCAYT initialization when inline CKEditor is not focused. When set to `true`, SCAYT markup is\r
1472 * displayed in both inline editor states, focused and unfocused, so the SCAYT instance is not destroyed.\r
1473 *\r
1474 * Read more in the [documentation](#!/guide/dev_spellcheck) and see the [SDK sample](http://sdk.ckeditor.com/samples/spellchecker.html).\r
7adcb81e
IB
1475 *\r
1476 * config.scayt_inlineModeImmediateMarkup = true;\r
1477 *\r
3b35bd27 1478 * @since 4.5.6\r
7adcb81e
IB
1479 * @cfg {Boolean} [scayt_inlineModeImmediateMarkup=false]\r
1480 * @member CKEDITOR.config\r
1481 */\r
1482\r
7adcb81e 1483/**\r
3b35bd27 1484 * Defines the number of SCAYT suggestions to show in the main context menu.\r
7adcb81e
IB
1485 * Possible values are:\r
1486 *\r
1487 * * `0` (zero) &ndash; No suggestions are shown in the main context menu. All\r
1488 * entries will be listed in the "More Suggestions" sub-menu.\r
1489 * * Positive number &ndash; The maximum number of suggestions to show in the context\r
1490 * menu. Other entries will be shown in the "More Suggestions" sub-menu.\r
3b35bd27 1491 * * Negative number &ndash; Five suggestions are shown in the main context menu. All other\r
7adcb81e
IB
1492 * entries will be listed in the "More Suggestions" sub-menu.\r
1493 *\r
3b35bd27
IB
1494 * Read more in the [documentation](#!/guide/dev_spellcheck) and see the [SDK sample](http://sdk.ckeditor.com/samples/spellchecker.html).\r
1495 *\r
7adcb81e
IB
1496 * Examples:\r
1497 *\r
1498 * // Display only three suggestions in the main context menu.\r
1499 * config.scayt_maxSuggestions = 3;\r
1500 *\r
1501 * // Do not show the suggestions directly.\r
1502 * config.scayt_maxSuggestions = 0;\r
1503 *\r
1504 * @cfg {Number} [scayt_maxSuggestions=5]\r
1505 * @member CKEDITOR.config\r
1506 */\r
1507\r
1508/**\r
3b35bd27 1509 * Defines the minimum length of words that will be collected from the editor content for spell checking.\r
7adcb81e
IB
1510 * Possible value is any positive number.\r
1511 *\r
3b35bd27
IB
1512 * Read more in the [documentation](#!/guide/dev_spellcheck) and see the [SDK sample](http://sdk.ckeditor.com/samples/spellchecker.html).\r
1513 *\r
7adcb81e
IB
1514 * Examples:\r
1515 *\r
3b35bd27 1516 * // Set the minimum length of words that will be collected from editor text.\r
7adcb81e
IB
1517 * config.scayt_minWordLength = 5;\r
1518 *\r
1519 * @cfg {Number} [scayt_minWordLength=4]\r
1520 * @member CKEDITOR.config\r
1521 */\r
1522\r
1523/**\r
3b35bd27 1524 * Sets the customer ID for SCAYT. Used for hosted users only. Required for migration from free\r
7adcb81e
IB
1525 * to trial or paid versions.\r
1526 *\r
3b35bd27
IB
1527 * Read more in the [documentation](#!/guide/dev_spellcheck) and see the [SDK sample](http://sdk.ckeditor.com/samples/spellchecker.html).\r
1528 *\r
7adcb81e
IB
1529 * // Load SCAYT using my customer ID.\r
1530 * config.scayt_customerId = 'your-encrypted-customer-id';\r
1531 *\r
1532 * @cfg {String} [scayt_customerId='1:WvF0D4-UtPqN1-43nkD4-NKvUm2-daQqk3-LmNiI-z7Ysb4-mwry24-T8YrS3-Q2tpq2']\r
1533 * @member CKEDITOR.config\r
1534 */\r
1535\r
1536/**\r
3b35bd27 1537 * Enables and disables the "More Suggestions" sub-menu in the context menu.\r
7adcb81e
IB
1538 * Possible values are `'on'` and `'off'`.\r
1539 *\r
3b35bd27
IB
1540 * Read more in the [documentation](#!/guide/dev_spellcheck) and see the [SDK sample](http://sdk.ckeditor.com/samples/spellchecker.html).\r
1541 *\r
7adcb81e
IB
1542 * // Disables the "More Suggestions" sub-menu.\r
1543 * config.scayt_moreSuggestions = 'off';\r
1544 *\r
1545 * @cfg {String} [scayt_moreSuggestions='on']\r
1546 * @member CKEDITOR.config\r
1547 */\r
1548\r
1549/**\r
3b35bd27 1550 * Customizes the display of SCAYT context menu commands ("Add Word", "Ignore",\r
7adcb81e
IB
1551 * "Ignore All", "Options", "Languages", "Dictionaries" and "About").\r
1552 * This must be a string with one or more of the following\r
1553 * words separated by a pipe character (`'|'`):\r
1554 *\r
3b35bd27
IB
1555 * * `off` &ndash; Disables all options.\r
1556 * * `all` &ndash; Enables all options.\r
1557 * * `ignore` &ndash; Enables the "Ignore" option.\r
1558 * * `ignoreall` &ndash; Enables the "Ignore All" option.\r
1559 * * `add` &ndash; Enables the "Add Word" option.\r
1560 * * `option` &ndash; Enables the "Options" menu item.\r
1561 * * `language` &ndash; Enables the "Languages" menu item.\r
1562 * * `dictionary` &ndash; Enables the "Dictionaries" menu item.\r
1563 * * `about` &ndash; Enables the "About" menu item.\r
1564 *\r
1565 * Please note that availability of the "Options", "Languages" and "Dictionaries" items\r
1566 * also depends on the {@link CKEDITOR.config#scayt_uiTabs} option.\r
1567 *\r
1568 * Read more in the [documentation](#!/guide/dev_spellcheck) and see the [SDK sample](http://sdk.ckeditor.com/samples/spellchecker.html).\r
1569 *\r
7adcb81e
IB
1570 * Example:\r
1571 *\r
1572 * // Show only "Add Word" and "Ignore All" in the context menu.\r
1573 * config.scayt_contextCommands = 'add|ignoreall';\r
1574 *\r
1575 * @cfg {String} [scayt_contextCommands='ignore|ignoreall|add']\r
1576 * @member CKEDITOR.config\r
1577 */\r
1578\r
1579/**\r
3b35bd27 1580 * Sets the default spell checking language for SCAYT. Possible values are:\r
7adcb81e
IB
1581 * `'en_US'`, `'en_GB'`, `'pt_BR'`, `'da_DK'`,\r
1582 * `'nl_NL'`, `'en_CA'`, `'fi_FI'`, `'fr_FR'`,\r
1583 * `'fr_CA'`, `'de_DE'`, `'el_GR'`, `'it_IT'`,\r
1584 * `'nb_NO'`, `'pt_PT'`, `'es_ES'`, `'sv_SE'`.\r
1585 *\r
3b35bd27
IB
1586 * Read more in the [documentation](#!/guide/dev_spellcheck) and see the [SDK sample](http://sdk.ckeditor.com/samples/spellchecker.html).\r
1587 *\r
7adcb81e
IB
1588 * // Sets SCAYT to German.\r
1589 * config.scayt_sLang = 'de_DE';\r
1590 *\r
1591 * @cfg {String} [scayt_sLang='en_US']\r
1592 * @member CKEDITOR.config\r
1593 */\r
1594\r
1595/**\r
3b35bd27 1596 * Customizes the SCAYT dialog and SCAYT toolbar menu to show particular tabs and items.\r
7adcb81e
IB
1597 * This setting must contain a `1` (enabled) or `0`\r
1598 * (disabled) value for each of the following entries, in this precise order,\r
1599 * separated by a comma (`','`): `'Options'`, `'Languages'`, and `'Dictionary'`.\r
1600 *\r
3b35bd27
IB
1601 * Read more in the [documentation](#!/guide/dev_spellcheck) and see the [SDK sample](http://sdk.ckeditor.com/samples/spellchecker.html).\r
1602 *\r
7adcb81e
IB
1603 * // Hides the "Languages" tab.\r
1604 * config.scayt_uiTabs = '1,0,1';\r
1605 *\r
1606 * @cfg {String} [scayt_uiTabs='1,1,1']\r
1607 * @member CKEDITOR.config\r
1608 */\r
1609\r
1610/**\r
3b35bd27 1611 * Sets the protocol for the WebSpellChecker service (`ssrv.cgi`) full path.\r
7adcb81e 1612 *\r
3b35bd27
IB
1613 * Read more in the [documentation](#!/guide/dev_spellcheck) and see the [SDK sample](http://sdk.ckeditor.com/samples/spellchecker.html).\r
1614 *\r
1615 * // Defines the protocol for the WebSpellChecker service (ssrv.cgi) path.\r
7adcb81e
IB
1616 * config.scayt_serviceProtocol = 'https';\r
1617 *\r
1618 * @cfg {String} [scayt_serviceProtocol='http']\r
1619 * @member CKEDITOR.config\r
1620 */\r
1621\r
1622/**\r
3b35bd27
IB
1623 * Sets the host for the WebSpellChecker service (`ssrv.cgi`) full path.\r
1624 *\r
1625 * Read more in the [documentation](#!/guide/dev_spellcheck) and see the [SDK sample](http://sdk.ckeditor.com/samples/spellchecker.html).\r
7adcb81e 1626 *\r
3b35bd27 1627 * // Defines the host for the WebSpellChecker service (ssrv.cgi) path.\r
7adcb81e
IB
1628 * config.scayt_serviceHost = 'my-host';\r
1629 *\r
1630 * @cfg {String} [scayt_serviceHost='svc.webspellchecker.net']\r
1631 * @member CKEDITOR.config\r
1632 */\r
1633\r
1634/**\r
3b35bd27 1635 * Sets the port for the WebSpellChecker service (`ssrv.cgi`) full path.\r
7adcb81e 1636 *\r
3b35bd27
IB
1637 * Read more in the [documentation](#!/guide/dev_spellcheck) and see the [SDK sample](http://sdk.ckeditor.com/samples/spellchecker.html).\r
1638 *\r
1639 * // Defines the port for the WebSpellChecker service (ssrv.cgi) path.\r
7adcb81e
IB
1640 * config.scayt_servicePort = '2330';\r
1641 *\r
1642 * @cfg {String} [scayt_servicePort='80']\r
1643 * @member CKEDITOR.config\r
1644 */\r
1645\r
1646/**\r
3b35bd27
IB
1647 * Sets the path to the WebSpellChecker service (`ssrv.cgi`).\r
1648 *\r
1649 * Read more in the [documentation](#!/guide/dev_spellcheck) and see the [SDK sample](http://sdk.ckeditor.com/samples/spellchecker.html).\r
7adcb81e 1650 *\r
3b35bd27 1651 * // Defines the path to the WebSpellChecker service (ssrv.cgi).\r
7adcb81e
IB
1652 * config.scayt_servicePath = 'my-path/ssrv.cgi';\r
1653 *\r
1654 * @cfg {String} [scayt_servicePath='spellcheck31/script/ssrv.cgi']\r
1655 * @member CKEDITOR.config\r
1656 */\r
1657\r
1658/**\r
3b35bd27 1659 * Sets the URL to SCAYT core. Required to switch to the licensed version of SCAYT.\r
7adcb81e 1660 *\r
3b35bd27
IB
1661 * Refer to [SCAYT documentation](http://wiki.webspellchecker.net/doku.php?id=migration:hosredfreetolicensedck)\r
1662 * for more details.\r
1663 *\r
1664 * Read more in the [documentation](#!/guide/dev_spellcheck) and see the [SDK sample](http://sdk.ckeditor.com/samples/spellchecker.html).\r
7adcb81e
IB
1665 *\r
1666 * config.scayt_srcUrl = "http://my-host/spellcheck/lf/scayt/scayt.js";\r
1667 *\r
1668 * @cfg {String} [scayt_srcUrl='//svc.webspellchecker.net/spellcheck31/lf/scayt3/ckscayt/ckscayt.js']\r
1669 * @member CKEDITOR.config\r
1670 */\r
1671\r
1672/**\r
3b35bd27 1673 * Links SCAYT to custom dictionaries. This is a string containing the dictionary IDs\r
7adcb81e
IB
1674 * separated by commas (`','`). Available only for the licensed version.\r
1675 *\r
3b35bd27
IB
1676 * Refer to [SCAYT documentation](http://wiki.webspellchecker.net/doku.php?id=installationandconfiguration:customdictionaries:licensed)\r
1677 * for more details.\r
1678 *\r
1679 * Read more in the [documentation](#!/guide/dev_spellcheck) and see the [SDK sample](http://sdk.ckeditor.com/samples/spellchecker.html).\r
7adcb81e
IB
1680 *\r
1681 * config.scayt_customDictionaryIds = '3021,3456,3478';\r
1682 *\r
1683 * @cfg {String} [scayt_customDictionaryIds='']\r
1684 * @member CKEDITOR.config\r
1685 */\r
1686\r
1687/**\r
3b35bd27 1688 * Activates a User Dictionary in SCAYT. The user\r
7adcb81e
IB
1689 * dictionary name must be used. Available only for the licensed version.\r
1690 *\r
3b35bd27
IB
1691 * Refer to [SCAYT documentation](http://wiki.webspellchecker.net/doku.php?id=installationandconfiguration:userdictionaries)\r
1692 * for more details.\r
1693 *\r
1694 * Read more in the [documentation](#!/guide/dev_spellcheck) and see the [SDK sample](http://sdk.ckeditor.com/samples/spellchecker.html).\r
1695 *\r
7adcb81e
IB
1696 * config.scayt_userDictionaryName = 'MyDictionary';\r
1697 *\r
1698 * @cfg {String} [scayt_userDictionaryName='']\r
1699 * @member CKEDITOR.config\r
1700 */\r
1701\r
1702/**\r
3b35bd27 1703 * Defines the order of SCAYT context menu items by groups.\r
7adcb81e
IB
1704 * This must be a string with one or more of the following\r
1705 * words separated by a pipe character (`'|'`):\r
1706 *\r
3b35bd27
IB
1707 * * `suggest` &ndash; The main suggestion word list.\r
1708 * * `moresuggest` &ndash; The "More suggestions" word list.\r
7adcb81e
IB
1709 * * `control` &ndash; SCAYT commands, such as "Ignore" and "Add Word".\r
1710 *\r
3b35bd27
IB
1711 * Read more in the [documentation](#!/guide/dev_spellcheck) and see the [SDK sample](http://sdk.ckeditor.com/samples/spellchecker.html).\r
1712 *\r
7adcb81e
IB
1713 * Example:\r
1714 *\r
1715 * config.scayt_contextMenuItemsOrder = 'moresuggest|control|suggest';\r
1716 *\r
1717 * @cfg {String} [scayt_contextMenuItemsOrder='suggest|moresuggest|control']\r
1718 * @member CKEDITOR.config\r
1719 */\r
1720\r
1721/**\r
3b35bd27
IB
1722 * If set to `true`, it overrides the {@link CKEDITOR.editor#checkDirty checkDirty} functionality of CKEditor\r
1723 * to fix SCAYT issues with incorrect `checkDirty` behavior. If set to `false`,\r
1724 * it provides better performance on big preloaded text.\r
1725 *\r
1726 * Read more in the [documentation](#!/guide/dev_spellcheck) and see the [SDK sample](http://sdk.ckeditor.com/samples/spellchecker.html).\r
7adcb81e
IB
1727 *\r
1728 * config.scayt_handleCheckDirty = 'false';\r
1729 *\r
1730 * @cfg {String} [scayt_handleCheckDirty='true']\r
1731 * @member CKEDITOR.config\r
1732 */\r
1733\r
1734/**\r
3b35bd27
IB
1735 * Configures undo/redo behavior of SCAYT in CKEditor.\r
1736 * If set to `true`, it overrides the undo/redo functionality of CKEditor\r
1737 * to fix SCAYT issues with incorrect undo/redo behavior. If set to `false`,\r
1738 * it provides better performance on text undo/redo.\r
1739 *\r
1740 * Read more in the [documentation](#!/guide/dev_spellcheck) and see the [SDK sample](http://sdk.ckeditor.com/samples/spellchecker.html).\r
7adcb81e
IB
1741 *\r
1742 * config.scayt_handleUndoRedo = 'false';\r
1743 *\r
1744 * @cfg {String} [scayt_handleUndoRedo='true']\r
1745 * @member CKEDITOR.config\r
1746 */\r
1747\r
1748/**\r
3b35bd27
IB
1749 * Enables the "Ignore All-Caps Words" option by default.\r
1750 * You may need to {@link CKEDITOR.config#scayt_disableOptionsStorage disable option storing} for this setting to be\r
1751 * effective because option storage has a higher priority.\r
7adcb81e 1752 *\r
3b35bd27 1753 * Read more in the [documentation](#!/guide/dev_spellcheck) and see the [SDK sample](http://sdk.ckeditor.com/samples/spellchecker.html).\r
7adcb81e 1754 *\r
3b35bd27
IB
1755 * config.scayt_ignoreAllCapsWords = true;\r
1756 *\r
1757 * @since 4.5.6\r
7adcb81e
IB
1758 * @cfg {Boolean} [scayt_ignoreAllCapsWords=false]\r
1759 * @member CKEDITOR.config\r
1760 */\r
1761\r
1762/**\r
3b35bd27
IB
1763 * Enables the "Ignore Domain Names" option by default.\r
1764 * You may need to {@link CKEDITOR.config#scayt_disableOptionsStorage disable option storing} for this setting to be\r
1765 * effective because option storage has a higher priority.\r
1766 *\r
1767 * Read more in the [documentation](#!/guide/dev_spellcheck) and see the [SDK sample](http://sdk.ckeditor.com/samples/spellchecker.html).\r
7adcb81e 1768 *\r
3b35bd27 1769 * config.scayt_ignoreDomainNames = true;\r
7adcb81e 1770 *\r
3b35bd27 1771 * @since 4.5.6\r
7adcb81e
IB
1772 * @cfg {Boolean} [scayt_ignoreDomainNames=false]\r
1773 * @member CKEDITOR.config\r
1774 */\r
1775\r
1776/**\r
3b35bd27
IB
1777 * Enables the "Ignore Words with Mixed Case" option by default.\r
1778 * You may need to {@link CKEDITOR.config#scayt_disableOptionsStorage disable option storing} for this setting to be\r
1779 * effective because option storage has a higher priority.\r
7adcb81e 1780 *\r
3b35bd27 1781 * Read more in the [documentation](#!/guide/dev_spellcheck) and see the [SDK sample](http://sdk.ckeditor.com/samples/spellchecker.html).\r
7adcb81e 1782 *\r
3b35bd27
IB
1783 * config.scayt_ignoreWordsWithMixedCases = true;\r
1784 *\r
1785 * @since 4.5.6\r
7adcb81e
IB
1786 * @cfg {Boolean} [scayt_ignoreWordsWithMixedCases=false]\r
1787 * @member CKEDITOR.config\r
1788 */\r
1789\r
1790/**\r
3b35bd27
IB
1791 * Enables the "Ignore Words with Numbers" option by default.\r
1792 * You may need to {@link CKEDITOR.config#scayt_disableOptionsStorage disable option storing} for this setting to be\r
1793 * effective because option storage has a higher priority.\r
1794 *\r
1795 * Read more in the [documentation](#!/guide/dev_spellcheck) and see the [SDK sample](http://sdk.ckeditor.com/samples/spellchecker.html).\r
7adcb81e 1796 *\r
3b35bd27 1797 * config.scayt_ignoreWordsWithNumbers = true;\r
7adcb81e 1798 *\r
3b35bd27 1799 * @since 4.5.6\r
7adcb81e
IB
1800 * @cfg {Boolean} [scayt_ignoreWordsWithNumbers=false]\r
1801 * @member CKEDITOR.config\r
1802 */\r
1803\r
1804/**\r
3b35bd27
IB
1805 * Disables storing of SCAYT options between sessions. Option storing will be turned off after a page refresh.\r
1806 * The following settings can be used:\r
1807 *\r
1808 * * `'options'` &ndash; Disables storing of all SCAYT Ignore options.\r
1809 * * `'ignore-all-caps-words'` &ndash; Disables storing of the "Ignore All-Caps Words" option.\r
1810 * * `'ignore-domain-names'` &ndash; Disables storing of the "Ignore Domain Names" option.\r
1811 * * `'ignore-words-with-mixed-cases'` &ndash; Disables storing of the "Ignore Words with Mixed Case" option.\r
1812 * * `'ignore-words-with-numbers'` &ndash; Disables storing of the "Ignore Words with Numbers" option.\r
1813 * * `'lang'` &ndash; Disables storing of the SCAYT spell check language.\r
1814 * * `'all'` &ndash; Disables storing of all SCAYT options.\r
7adcb81e 1815 *\r
3b35bd27 1816 * Read more in the [documentation](#!/guide/dev_spellcheck) and see the [SDK sample](http://sdk.ckeditor.com/samples/spellchecker.html).\r
7adcb81e
IB
1817 *\r
1818 * Example:\r
1819 *\r
3b35bd27 1820 * // Disabling one option.\r
7adcb81e
IB
1821 * config.scayt_disableOptionsStorage = 'all';\r
1822 *\r
3b35bd27 1823 * // Disabling several options.\r
7adcb81e
IB
1824 * config.scayt_disableOptionsStorage = ['lang', 'ignore-domain-names', 'ignore-words-with-numbers'];\r
1825 *\r
1826 *\r
1827 * @cfg {String|Array} [scayt_disableOptionsStorage = '']\r
1828 * @member CKEDITOR.config\r
1829 */\r
1830\r
3b35bd27 1831/**\r
7adcb81e 1832 * Specifies the names of tags that will be skipped while spell checking. This is a string containing tag names\r
3b35bd27
IB
1833 * separated by commas (`','`). Please note that the `'style'` tag would be added to specified tags list.\r
1834 *\r
1835 * Read more in the [documentation](#!/guide/dev_spellcheck) and see the [SDK sample](http://sdk.ckeditor.com/samples/spellchecker.html).\r
7adcb81e
IB
1836 *\r
1837 * config.scayt_elementsToIgnore = 'del,pre';\r
1838 *\r
1839 * @cfg {String} [scayt_elementsToIgnore='style']\r
1840 * @member CKEDITOR.config\r
1841 */\r
1842\r
3b35bd27
IB
1843/**\r
1844 * Enables multi-language support in SCAYT. If set to `true`, turns on SCAYT multi-language support after loading the editor.\r
1845 *\r
1846 * Read more in the [documentation](#!/guide/dev_spellcheck) and see the [SDK sample](http://sdk.ckeditor.com/samples/spellchecker.html).\r
7adcb81e
IB
1847 *\r
1848 * config.scayt_multiLanguageMode = true;\r
1849 *\r
1850 * @cfg {Boolean} [scayt_multiLanguageMode=false]\r
1851 * @member CKEDITOR.config\r
1852 */\r
1853\r
3b35bd27
IB
1854/**\r
1855 * Defines additional styles for misspellings for specified languages. Styles will be applied only if\r
1856 * the {@link CKEDITOR.config#scayt_multiLanguageMode} option is set to `true` and the [Language](http://ckeditor.com/addon/language)\r
1857 * plugin is included and loaded in the editor. By default, all misspellings will still be underlined with the red waveline.\r
1858 *\r
1859 * Read more in the [documentation](#!/guide/dev_spellcheck) and see the [SDK sample](http://sdk.ckeditor.com/samples/spellchecker.html).\r
7adcb81e
IB
1860 *\r
1861 * Example:\r
1862 *\r
3b35bd27 1863 * // Display misspellings in French language with green color and underlined with red waveline.\r
7adcb81e
IB
1864 * config.scayt_multiLanguageStyles = {\r
1865 * 'fr': 'color: green'\r
1866 * };\r
1867 *\r
3b35bd27
IB
1868 * // Display misspellings in Italian language with green color and underlined with red waveline\r
1869 * // and German misspellings with red color only.\r
7adcb81e
IB
1870 * config.scayt_multiLanguageStyles = {\r
1871 * 'it': 'color: green',\r
1872 * 'de': 'background-image: none; color: red'\r
1873 * };\r
1874 *\r
1875 * @cfg {Object} [scayt_multiLanguageStyles = {}]\r
1876 * @member CKEDITOR.config\r
1877 */\r