diff options
| author | Lester Caine <lester@lsces.co.uk> | 2010-03-22 22:53:04 +0000 |
|---|---|---|
| committer | Lester Caine <lester@lsces.co.uk> | 2010-03-22 22:53:04 +0000 |
| commit | 53bc2c91b49c39fcd56fabf69c28bd64f485593b (patch) | |
| tree | 11c4c265afc4e3aec4eae06e935455f6ad92b60b /plugins | |
| parent | 71224fa72e9c7cb45518813513750b5305030b90 (diff) | |
| download | ckeditor-53bc2c91b49c39fcd56fabf69c28bd64f485593b.tar.gz ckeditor-53bc2c91b49c39fcd56fabf69c28bd64f485593b.tar.bz2 ckeditor-53bc2c91b49c39fcd56fabf69c28bd64f485593b.zip | |
Add aspell plugin for open source spell checker in ckeditor
Diffstat (limited to 'plugins')
| -rwxr-xr-x | plugins/aspell/aspell.css | 6 | ||||
| -rwxr-xr-x | plugins/aspell/dialogs/aspell.js | 169 | ||||
| -rwxr-xr-x | plugins/aspell/plugin.js | 31 | ||||
| -rwxr-xr-x | plugins/aspell/spellerpages/blank.html | 0 | ||||
| -rwxr-xr-x | plugins/aspell/spellerpages/controlWindow.js | 86 | ||||
| -rwxr-xr-x | plugins/aspell/spellerpages/controls.html | 153 | ||||
| -rwxr-xr-x | plugins/aspell/spellerpages/server-scripts/spellchecker.cfm | 148 | ||||
| -rwxr-xr-x | plugins/aspell/spellerpages/server-scripts/spellchecker.php | 200 | ||||
| -rwxr-xr-x | plugins/aspell/spellerpages/server-scripts/spellchecker.pl | 181 | ||||
| -rwxr-xr-x | plugins/aspell/spellerpages/spellChecker.js | 461 | ||||
| -rwxr-xr-x | plugins/aspell/spellerpages/spellchecker.html | 71 | ||||
| -rwxr-xr-x | plugins/aspell/spellerpages/spellerStyle.css | 49 | ||||
| -rwxr-xr-x | plugins/aspell/spellerpages/wordWindow.js | 272 |
13 files changed, 1827 insertions, 0 deletions
diff --git a/plugins/aspell/aspell.css b/plugins/aspell/aspell.css new file mode 100755 index 0000000..fc68ae2 --- /dev/null +++ b/plugins/aspell/aspell.css @@ -0,0 +1,6 @@ +
+.cke_editor .cke_button_aspell .cke_icon
+{
+ background-position: 0 -192px !important;
+}
+
diff --git a/plugins/aspell/dialogs/aspell.js b/plugins/aspell/dialogs/aspell.js new file mode 100755 index 0000000..ed66439 --- /dev/null +++ b/plugins/aspell/dialogs/aspell.js @@ -0,0 +1,169 @@ +
+var FCKLang;
+var OnSpellerControlsLoad;
+
+CKEDITOR.dialog.add('aspell', function( editor )
+{
+ var number = CKEDITOR.tools.getNextNumber(),
+ iframeId = 'cke_frame_' + number,
+ textareaId = 'cke_data_' + number,
+ interval,
+ errorMsg = editor.lang.spellCheck.notAvailable;
+
+ var spellHTML =
+ // Input for exchanging data CK<--->spellcheck
+ '<textarea name="'+textareaId+'" id="'+textareaId+
+ '" style="display: none;"></textarea>' +
+ // Spellcheck iframe
+ '<iframe src="" style="width:485px; height:380px"' +
+ ' frameborder="0" name="' + iframeId + '" id="' + iframeId + '"' +
+ ' allowtransparency="1"></iframe>';
+
+ function spellTime(dialog, errorMsg)
+ {
+ var i = 0;
+ return function()
+ {
+ if (typeof window.spellChecker == 'function')
+ {
+ // Call from window.setInteval expected at once.
+ if (typeof interval != 'undefined')
+ window.clearInterval(interval);
+
+ // Create spellcheck object, set options/attributes
+ var oSpeller = new spellChecker(document.getElementById(textareaId));
+ oSpeller.spellCheckScript = editor.plugins.aspell.path+'spellerpages/server-scripts/spellchecker.php';
+ oSpeller.OnFinished = function (numChanges) { oSpeller_OnFinished(dialog, numChanges) };
+ oSpeller.popUpUrl = editor.plugins.aspell.path+'spellerpages/spellchecker.html';
+ oSpeller.popUpName = iframeId;
+ oSpeller.popUpProps = null;
+
+ // Place language in global variable;
+ // A bit of a hack, but how does e.g. controls.html know which language to use?
+ FCKLang = {};
+ // spellChecker.js
+ FCKLang.DlgSpellNoChanges = CKEDITOR.lang[editor.langCode].spellCheck.noChanges;
+ FCKLang.DlgSpellNoMispell = CKEDITOR.lang[editor.langCode].spellCheck.noMispell;
+ FCKLang.DlgSpellOneChange = CKEDITOR.lang[editor.langCode].spellCheck.oneChange;
+ FCKLang.DlgSpellManyChanges = CKEDITOR.lang[editor.langCode].spellCheck.manyChanges;
+ // controls.html
+ FCKLang.DlgSpellNotInDic = CKEDITOR.lang[editor.langCode].spellCheck.notInDic;
+ FCKLang.DlgSpellChangeTo = CKEDITOR.lang[editor.langCode].spellCheck.changeTo;
+ FCKLang.DlgSpellBtnIgnore = CKEDITOR.lang[editor.langCode].spellCheck.btnIgnore;
+ FCKLang.DlgSpellBtnIgnoreAll = CKEDITOR.lang[editor.langCode].spellCheck.btnIgnoreAll;
+ FCKLang.DlgSpellBtnReplace = CKEDITOR.lang[editor.langCode].spellCheck.btnReplace;
+ FCKLang.DlgSpellBtnReplaceAll = CKEDITOR.lang[editor.langCode].spellCheck.btnReplaceAll;
+ FCKLang.DlgSpellBtnUndo = CKEDITOR.lang[editor.langCode].spellCheck.btnUndo;
+ // controlWindow.js
+ FCKLang.DlgSpellNoSuggestions = CKEDITOR.lang[editor.langCode].spellCheck.noSuggestions;
+ // spellchecker.html
+ FCKLang.DlgSpellProgress = CKEDITOR.lang[editor.langCode].spellCheck.progress;
+ // End language
+
+ // Start spellcheck!
+ oSpeller.openChecker();
+ }
+ else if (i++ == 180) // Timeout: 180 * 250ms = 45s.
+ {
+ alert(errorMsg);
+ dialog.hide();
+ }
+ };
+ }
+
+ function oSpeller_OnFinished(dialog, numberOCorrections)
+ {
+ if (numberOCorrections > 0)
+ {
+ editor.focus();
+ editor.fire('saveSnapshot'); // Best way I could find to trigger undo steps.
+ dialog.getParentEditor().setData(document.getElementById(textareaId).value);
+ editor.fire('saveSnapshot'); // But there's a blank one between!
+ }
+ dialog.hide();
+ }
+
+ // Fx and IE don't see the same sizes, it seems. That or Fx is allowing everything to grow.
+ var minW = 485;
+ var minH = 380;
+ if (document.all)
+ {
+ minW = 510;
+ minH = 405;
+ }
+
+ return {
+ title: editor.lang.spellCheck.title,
+ minWidth: minW,
+ minHeight: minH,
+ buttons: [ CKEDITOR.dialog.cancelButton ],
+ onShow: function()
+ {
+ // Put spellcheck input and iframe in the dialog content
+ var contentArea = this.getContentElement('general', 'content').getElement();
+ contentArea.setHtml(spellHTML);
+
+ // Define spellcheck init function
+ OnSpellerControlsLoad = function (controlsWindow)
+ {
+ // Translate the dialog box texts
+ var spans = controlsWindow.document.getElementsByTagName('span');
+ var inputs = controlsWindow.document.getElementsByTagName('input');
+ var i, attr;
+
+ for (i=0; i < spans.length; i++)
+ {
+ attr = spans[i].getAttribute && spans[i].getAttribute('fckLang');
+ if (attr)
+ spans[i].innerHTML = FCKLang[attr];
+ }
+ for (i=0; i < inputs.length; i++)
+ {
+ attr = inputs[i].getAttribute && inputs[i].getAttribute('fckLang');
+ if (attr)
+ inputs[i].value = FCKLang[attr];
+ }
+ }
+
+ // Add spellcheck script to head
+ CKEDITOR.document.getHead().append(CKEDITOR.document.createElement('script', {
+ attributes: {
+ type: 'text/javascript',
+ src: editor.plugins.aspell.path+'spellerpages/spellChecker.js'
+ }}));
+
+ // Get the data to be checked.
+ var sData = editor.getData();
+ //CKEDITOR.document.getById(textareaId).setValue(sData); <-- doesn't work for some reason
+ document.getElementById(textareaId).value = sData;
+
+ // Wait for spellcheck script to load, then execute
+ interval = window.setInterval(spellTime(this, errorMsg), 250);
+ },
+ onHide: function()
+ {
+ window.ooo = undefined;
+ window.int_framsetLoaded = undefined;
+ window.framesetLoaded = undefined;
+ window.is_window_opened = false;
+
+ OnSpellerControlsLoad = null;
+ FCKLang = null;
+ },
+ contents: [
+ {
+ id: 'general',
+ label: editor.lang.spellCheck.title,
+ padding: 0,
+ elements: [
+ {
+ type: 'html',
+ id: 'content',
+ style: 'width:485;height:380px',
+ html: '<div></div>'
+ }
+ ]
+ }
+ ]
+ };
+});
diff --git a/plugins/aspell/plugin.js b/plugins/aspell/plugin.js new file mode 100755 index 0000000..6ced98f --- /dev/null +++ b/plugins/aspell/plugin.js @@ -0,0 +1,31 @@ +/**
+ * Aspell plug-in for CKeditor 3.0
+ * Ported from FCKeditor 2.x by Christian Boisjoli, SilenceIT
+ * Requires toolbar, aspell
+ */
+
+CKEDITOR.plugins.add('aspell', {
+ init: function (editor) {
+ // Create dialog-based command named "aspell"
+ editor.addCommand('aspell', new CKEDITOR.dialogCommand('aspell'));
+
+ // Add button to toolbar. Not sure why only that name works for me.
+ editor.ui.addButton('SpellCheck', {
+ label: editor.lang.spellCheck.toolbar,
+ command: 'aspell'
+ });
+
+ // Add link dialog code
+ CKEDITOR.dialog.add('aspell', this.path + 'dialogs/aspell.js');
+
+ // Add CSS
+ var aspellCSS = document.createElement('link');
+ aspellCSS.setAttribute( 'rel', 'stylesheet');
+ aspellCSS.setAttribute('type', 'text/css');
+ aspellCSS.setAttribute('href', this.path+'aspell.css');
+ document.getElementsByTagName("head")[0].appendChild(aspellCSS);
+ delete aspellCSS;
+ },
+ requires: ['toolbar']
+});
+
diff --git a/plugins/aspell/spellerpages/blank.html b/plugins/aspell/spellerpages/blank.html new file mode 100755 index 0000000..e69de29 --- /dev/null +++ b/plugins/aspell/spellerpages/blank.html diff --git a/plugins/aspell/spellerpages/controlWindow.js b/plugins/aspell/spellerpages/controlWindow.js new file mode 100755 index 0000000..32ab759 --- /dev/null +++ b/plugins/aspell/spellerpages/controlWindow.js @@ -0,0 +1,86 @@ +////////////////////////////////////////////////////
+// controlWindow object
+////////////////////////////////////////////////////
+function controlWindow( controlForm ) {
+ // private properties
+ this._form = controlForm;
+
+ // public properties
+ this.windowType = "controlWindow";
+ this.noSuggestionSelection = "- No suggestions -";
+ // set up the properties for elements of the given control form
+ this.suggestionList = this._form.sugg;
+ this.evaluatedText = this._form.misword;
+ this.replacementText = this._form.txtsugg;
+ this.undoButton = this._form.btnUndo;
+
+ // public methods
+ this.addSuggestion = addSuggestion;
+ this.clearSuggestions = clearSuggestions;
+ this.selectDefaultSuggestion = selectDefaultSuggestion;
+ this.resetForm = resetForm;
+ this.setSuggestedText = setSuggestedText;
+ this.enableUndo = enableUndo;
+ this.disableUndo = disableUndo;
+}
+
+function resetForm() {
+ if( this._form ) {
+ this._form.reset();
+ }
+}
+
+function setSuggestedText() {
+ var slct = this.suggestionList;
+ var txt = this.replacementText;
+ var str = "";
+ if( (slct.options[0].text) && slct.options[0].text != this.noSuggestionSelection ) {
+ str = slct.options[slct.selectedIndex].text;
+ }
+ txt.value = str;
+}
+
+function selectDefaultSuggestion() {
+ var slct = this.suggestionList;
+ var txt = this.replacementText;
+ if( slct.options.length == 0 ) {
+ this.addSuggestion( this.noSuggestionSelection );
+ } else {
+ slct.options[0].selected = true;
+ }
+ this.setSuggestedText();
+}
+
+function addSuggestion( sugg_text ) {
+ var slct = this.suggestionList;
+ if( sugg_text ) {
+ var i = slct.options.length;
+ var newOption = new Option( sugg_text, 'sugg_text'+i );
+ slct.options[i] = newOption;
+ }
+}
+
+function clearSuggestions() {
+ var slct = this.suggestionList;
+ for( var j = slct.length - 1; j > -1; j-- ) {
+ if( slct.options[j] ) {
+ slct.options[j] = null;
+ }
+ }
+}
+
+function enableUndo() {
+ if( this.undoButton ) {
+ if( this.undoButton.disabled == true ) {
+ this.undoButton.disabled = false;
+ }
+ }
+}
+
+function disableUndo() {
+ if( this.undoButton ) {
+ if( this.undoButton.disabled == false ) {
+ this.undoButton.disabled = true;
+ }
+ }
+}
diff --git a/plugins/aspell/spellerpages/controls.html b/plugins/aspell/spellerpages/controls.html new file mode 100755 index 0000000..e15e000 --- /dev/null +++ b/plugins/aspell/spellerpages/controls.html @@ -0,0 +1,153 @@ +<html>
+ <head>
+ <link rel="stylesheet" type="text/css" href="spellerStyle.css" />
+ <script type="text/javascript" src="controlWindow.js"></script>
+ <script type="text/javascript">
+var spellerObject;
+var controlWindowObj;
+
+if( parent.opener ) {
+ spellerObject = parent.opener.speller;
+}
+
+function ignore_word() {
+ if( spellerObject ) {
+ spellerObject.ignoreWord();
+ }
+}
+
+function ignore_all() {
+ if( spellerObject ) {
+ spellerObject.ignoreAll();
+ }
+}
+
+function replace_word() {
+ if( spellerObject ) {
+ spellerObject.replaceWord();
+ }
+}
+
+function replace_all() {
+ if( spellerObject ) {
+ spellerObject.replaceAll();
+ }
+}
+
+function end_spell() {
+ if( spellerObject ) {
+ spellerObject.terminateSpell();
+ }
+}
+
+function undo() {
+ if( spellerObject ) {
+ spellerObject.undo();
+ }
+}
+
+function suggText() {
+ if( controlWindowObj ) {
+ controlWindowObj.setSuggestedText();
+ }
+}
+
+function init_spell() {
+ // By FredCK (fckLang attributes have been added to the HTML source of this page)
+ window.parent.parent.OnSpellerControlsLoad(this);
+
+ var controlForm = document.spellcheck;
+
+ // create a new controlWindow object
+ controlWindowObj = new controlWindow( controlForm );
+ // Let's take this out of the constructor, shall we?
+ controlWindowObj.noSuggestionSelection = window.parent.parent.FCKLang.DlgSpellNoSuggestions; // By ChrisB
+
+ // call the init_spell() function in the parent frameset
+ if( parent.frames.length ) {
+ parent.init_spell( controlWindowObj );
+ } else {
+ alert( 'This page was loaded outside of a frameset. It might not display properly' );
+ }
+}
+
+</script>
+ </head>
+ <body class="controlWindowBody" onLoad="init_spell();" style="OVERFLOW: hidden" scroll="no"> <!-- by FredCK -->
+ <form name="spellcheck">
+ <table border="0" cellpadding="0" cellspacing="0" border="0" align="center">
+ <tr>
+ <td colspan="3" class="normalLabel"><span fckLang="DlgSpellNotInDic">Not in dictionary</span><span>:</span></td>
+ </tr>
+ <tr>
+ <td colspan="3"><input class="readonlyInput" type="text" name="misword" readonly /></td>
+ </tr>
+ <tr>
+ <td colspan="3" height="5"></td>
+ </tr>
+ <tr>
+ <td class="normalLabel"><span fckLang="DlgSpellChangeTo">Change to</span>:</td>
+ </tr>
+ <tr valign="top">
+ <td>
+ <table border="0" cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="normalLabel">
+ <input class="textDefault" type="text" name="txtsugg" />
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <select class="suggSlct" name="sugg" size="7" onChange="suggText();" onDblClick="replace_word();">
+ <option></option>
+ </select>
+ </td>
+ </tr>
+ </table>
+ </td>
+ <td> </td>
+ <td>
+ <table border="0" cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td>
+ <input class="buttonDefault" type="button" fckLang="DlgSpellBtnIgnore" value="Ignore" onClick="ignore_word();">
+ </td>
+ <td> </td>
+ <td>
+ <input class="buttonDefault" type="button" fckLang="DlgSpellBtnIgnoreAll" value="Ignore All" onClick="ignore_all();">
+ </td>
+ </tr>
+ <tr>
+ <td colspan="3" height="5"></td>
+ </tr>
+ <tr>
+ <td>
+ <input class="buttonDefault" type="button" fckLang="DlgSpellBtnReplace" value="Replace" onClick="replace_word();">
+ </td>
+ <td> </td>
+ <td>
+ <input class="buttonDefault" type="button" fckLang="DlgSpellBtnReplaceAll" value="Replace All" onClick="replace_all();">
+ </td>
+ </tr>
+ <tr>
+ <td colspan="3" height="5"></td>
+ </tr>
+ <tr>
+ <td>
+ <input class="buttonDefault" type="button" name="btnUndo" fckLang="DlgSpellBtnUndo" value="Undo" onClick="undo();"
+ disabled>
+ </td>
+ <td> </td>
+ <td>
+ <!-- by FredCK
+ <input class="buttonDefault" type="button" value="Close" onClick="end_spell();">
+ -->
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </form>
+ </body>
+</html>
diff --git a/plugins/aspell/spellerpages/server-scripts/spellchecker.cfm b/plugins/aspell/spellerpages/server-scripts/spellchecker.cfm new file mode 100755 index 0000000..27e368e --- /dev/null +++ b/plugins/aspell/spellerpages/server-scripts/spellchecker.cfm @@ -0,0 +1,148 @@ +<cfsetting enablecfoutputonly="true">
+<!---
+This code uses a CF User Defined Function and should work in CF version 5.0
+and up without alteration.
+
+Also if you are hosting your site at an ISP, you will have to check with them
+to see if the use of <CFEXECUTE> is allowed. In most cases ISP will not allow
+the use of that tag for security reasons. Clients would be able to access each
+others files in certain cases.
+--->
+
+<!--- The following variables values must reflect your installation. --->
+<cfset aspell_dir = "C:\Program Files\Aspell\bin">
+<cfset lang = "en_US">
+<cfset aspell_opts = "-a --lang=#lang# --encoding=utf-8 -H --rem-sgml-check=alt">
+<cfset tempfile_in = GetTempFile(GetTempDirectory(), "spell_")>
+<cfset tempfile_out = GetTempFile(GetTempDirectory(), "spell_")>
+<cfset spellercss = "../spellerStyle.css">
+<cfset word_win_src = "../wordWindow.js">
+
+<cfset form.checktext = form["textinputs[]"]>
+
+<!--- make no difference between URL and FORM scopes --->
+<cfparam name="url.checktext" default="">
+<cfparam name="form.checktext" default="#url.checktext#">
+
+<!--- Takes care of those pesky smart quotes from MS apps, replaces them with regular quotes --->
+<cfset submitted_text = ReplaceList(form.checktext,"%u201C,%u201D","%22,%22")>
+
+<!--- submitted_text now is ready for processing --->
+
+<!--- use carat on each line to escape possible aspell commands --->
+<cfset text = "">
+<cfset CRLF = Chr(13) & Chr(10)>
+
+<cfloop list="#submitted_text#" index="field" delimiters=",">
+ <cfset text = text & "%" & CRLF
+ & "^A" & CRLF
+ & "!" & CRLF>
+ <!--- Strip all tags for the text. (by FredCK - #339 / #681) --->
+ <cfset field = REReplace(URLDecode(field), "<[^>]+>", " ", "all")>
+ <cfloop list="#field#" index="line" delimiters="#CRLF#">
+ <cfset text = ListAppend(text, "^" & Trim(JSStringFormat(line)), CRLF)>
+ </cfloop>
+</cfloop>
+
+<!--- create temp file from the submitted text, this will be passed to aspell to be check for misspelled words --->
+<cffile action="write" file="#tempfile_in#" output="#text#" charset="utf-8">
+
+<!--- execute aspell in an UTF-8 console and redirect output to a file. UTF-8 encoding is lost if done differently --->
+<cfexecute name="cmd.exe" arguments='/c type "#tempfile_in#" | "#aspell_dir#\aspell.exe" #aspell_opts# > "#tempfile_out#"' timeout="100"/>
+
+<!--- read output file for further processing --->
+<cffile action="read" file="#tempfile_out#" variable="food" charset="utf-8">
+
+<!--- remove temp files --->
+<cffile action="delete" file="#tempfile_in#">
+<cffile action="delete" file="#tempfile_out#">
+
+<cfset texts = StructNew()>
+<cfset texts.textinputs = "">
+<cfset texts.words = "">
+<cfset texts.abort = "">
+
+<!--- Generate Text Inputs --->
+<cfset i = 0>
+<cfloop list="#submitted_text#" index="textinput">
+ <cfset texts.textinputs = ListAppend(texts.textinputs, 'textinputs[#i#] = decodeURIComponent("#textinput#");', CRLF)>
+ <cfset i = i + 1>
+</cfloop>
+
+<!--- Generate Words Lists --->
+<cfset word_cnt = 0>
+<cfset input_cnt = -1>
+<cfloop list="#food#" index="aspell_line" delimiters="#CRLF#">
+ <cfset leftChar = Left(aspell_line, 1)>
+ <cfif leftChar eq "*">
+ <cfset input_cnt = input_cnt + 1>
+ <cfset word_cnt = 0>
+ <cfset texts.words = ListAppend(texts.words, "words[#input_cnt#] = [];", CRLF)>
+ <cfset texts.words = ListAppend(texts.words, "suggs[#input_cnt#] = [];", CRLF)>
+ <cfelse>
+ <cfif leftChar eq "&" or leftChar eq "##">
+ <!--- word that misspelled --->
+ <cfset bad_word = Trim(ListGetAt(aspell_line, 2, " "))>
+ <cfset bad_word = Replace(bad_word, "'", "\'", "ALL")>
+ <!--- sugestions --->
+ <cfset sug_list = Trim(ListRest(aspell_line, ":"))>
+ <cfset sug_list = ListQualify(Replace(sug_list, "'", "\'", "ALL"), "'")>
+ <!--- javascript --->
+ <cfset texts.words = ListAppend(texts.words, "words[#input_cnt#][#word_cnt#] = '#bad_word#';", CRLF)>
+ <cfset texts.words = ListAppend(texts.words, "suggs[#input_cnt#][#word_cnt#] = [#sug_list#];", CRLF)>
+ <cfset word_cnt = word_cnt + 1>
+ </cfif>
+ </cfif>
+</cfloop>
+
+<cfif texts.words eq "">
+ <cfset texts.abort = "alert('Spell check complete.\n\nNo misspellings found.'); top.window.close();">
+</cfif>
+
+<cfcontent type="text/html; charset=utf-8">
+
+<cfoutput><html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<link rel="stylesheet" type="text/css" href="#spellercss#" />
+<script language="javascript" src="#word_win_src#"></script>
+<script language="javascript">
+var suggs = new Array();
+var words = new Array();
+var textinputs = new Array();
+var error;
+
+#texts.textinputs##CRLF#
+#texts.words#
+#texts.abort#
+
+var wordWindowObj = new wordWindow();
+wordWindowObj.originalSpellings = words;
+wordWindowObj.suggestions = suggs;
+wordWindowObj.textInputs = textinputs;
+
+function init_spell() {
+ // check if any error occured during server-side processing
+ if( error ) {
+ alert( error );
+ } else {
+ // call the init_spell() function in the parent frameset
+ if (parent.frames.length) {
+ parent.init_spell( wordWindowObj );
+ } else {
+ alert('This page was loaded outside of a frameset. It might not display properly');
+ }
+ }
+}
+</script>
+
+</head>
+<body onLoad="init_spell();">
+
+<script type="text/javascript">
+wordWindowObj.writeBody();
+</script>
+
+</body>
+</html></cfoutput>
+<cfsetting enablecfoutputonly="false">
diff --git a/plugins/aspell/spellerpages/server-scripts/spellchecker.php b/plugins/aspell/spellerpages/server-scripts/spellchecker.php new file mode 100755 index 0000000..4aa95cd --- /dev/null +++ b/plugins/aspell/spellerpages/server-scripts/spellchecker.php @@ -0,0 +1,200 @@ +<?php
+header('Content-type: text/html; charset=utf-8');
+
+// The following variables values must reflect your installation needs.
+
+//$aspell_prog = '"C:\Program Files\Aspell\bin\aspell.exe"'; // by FredCK (for Windows)
+$aspell_prog = 'aspell'; // by FredCK (for Linux)
+
+$lang = 'en_US';
+$aspell_opts = "-a --lang=$lang --encoding=utf-8 -H --rem-sgml-check=alt"; // by FredCK
+
+//$tempfiledir = "./";
+$tempfiledir = '/tmp/';
+
+$spellercss = '../spellerStyle.css'; // by FredCK
+$word_win_src = '../wordWindow.js'; // by FredCK
+
+$textinputs = $_POST['textinputs']; # array
+$input_separator = "A";
+
+# set the JavaScript variable to the submitted text.
+# textinputs is an array, each element corresponding to the (url-encoded)
+# value of the text control submitted for spell-checking
+function print_textinputs_var() {
+ global $textinputs;
+ foreach( $textinputs as $key=>$val ) {
+ # $val = str_replace( "'", "%27", $val );
+ echo "textinputs[$key] = decodeURIComponent(\"" . $val . "\");\n";
+ }
+}
+
+# make declarations for the text input index
+function print_textindex_decl( $text_input_idx ) {
+ echo "words[$text_input_idx] = [];\n";
+ echo "suggs[$text_input_idx] = [];\n";
+}
+
+# set an element of the JavaScript 'words' array to a misspelled word
+function print_words_elem( $word, $index, $text_input_idx ) {
+ echo "words[$text_input_idx][$index] = '" . escape_quote( $word ) . "';\n";
+}
+
+
+# set an element of the JavaScript 'suggs' array to a list of suggestions
+function print_suggs_elem( $suggs, $index, $text_input_idx ) {
+ echo "suggs[$text_input_idx][$index] = [";
+ foreach( $suggs as $key=>$val ) {
+ if( $val ) {
+ echo "'" . escape_quote( $val ) . "'";
+ if ( $key+1 < count( $suggs )) {
+ echo ", ";
+ }
+ }
+ }
+ echo "];\n";
+}
+
+# escape single quote
+function escape_quote( $str ) {
+ return preg_replace ( "/'/", "\\'", $str );
+}
+
+
+# handle a server-side error.
+function error_handler( $err ) {
+ echo "error = '" . preg_replace( "/['\\\\]/", "\\\\$0", $err ) . "';\n";
+}
+
+## get the list of misspelled words. Put the results in the javascript words array
+## for each misspelled word, get suggestions and put in the javascript suggs array
+function print_checker_results() {
+
+ global $aspell_prog;
+ global $aspell_opts;
+ global $tempfiledir;
+ global $textinputs;
+ global $input_separator;
+ $aspell_err = "";
+ # create temp file
+ $tempfile = tempnam( $tempfiledir, 'aspell_data_' );
+
+ # open temp file, add the submitted text.
+ if( $fh = fopen( $tempfile, 'w' )) {
+ for( $i = 0; $i < count( $textinputs ); $i++ ) {
+ $text = urldecode( $textinputs[$i] );
+
+ // Strip all tags for the text. (by FredCK - #339 / #681)
+ $text = preg_replace( "/<[^>]+>/", " ", $text ) ;
+
+ $lines = explode( "\n", $text );
+ fwrite ( $fh, "%\n" ); # exit terse mode
+ fwrite ( $fh, "^$input_separator\n" );
+ fwrite ( $fh, "!\n" ); # enter terse mode
+ foreach( $lines as $key=>$value ) {
+ # use carat on each line to escape possible aspell commands
+ fwrite( $fh, "^$value\n" );
+ }
+ }
+ fclose( $fh );
+
+ # exec aspell command - redirect STDERR to STDOUT
+ $cmd = "$aspell_prog $aspell_opts < $tempfile 2>&1";
+ if( $aspellret = shell_exec( $cmd )) {
+ $linesout = explode( "\n", $aspellret );
+ $index = 0;
+ $text_input_index = -1;
+ # parse each line of aspell return
+ foreach( $linesout as $key=>$val ) {
+ $chardesc = substr( $val, 0, 1 );
+ # if '&', then not in dictionary but has suggestions
+ # if '#', then not in dictionary and no suggestions
+ # if '*', then it is a delimiter between text inputs
+ # if '@' then version info
+ if( $chardesc == '&' || $chardesc == '#' ) {
+ $line = explode( " ", $val, 5 );
+ print_words_elem( $line[1], $index, $text_input_index );
+ if( isset( $line[4] )) {
+ $suggs = explode( ", ", $line[4] );
+ } else {
+ $suggs = array();
+ }
+ print_suggs_elem( $suggs, $index, $text_input_index );
+ $index++;
+ } elseif( $chardesc == '*' ) {
+ $text_input_index++;
+ print_textindex_decl( $text_input_index );
+ $index = 0;
+ } elseif( $chardesc != '@' && $chardesc != "" ) {
+ # assume this is error output
+ $aspell_err .= $val;
+ }
+ }
+ if( $aspell_err ) {
+ $aspell_err = "Error executing `$cmd`\\n$aspell_err";
+ error_handler( $aspell_err );
+ }
+ } else {
+ error_handler( "System error: Aspell program execution failed (`$cmd`)" );
+ }
+ } else {
+ error_handler( "System error: Could not open file '$tempfile' for writing" );
+ }
+
+ # close temp file, delete file
+ unlink( $tempfile );
+}
+
+
+?>
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<link rel="stylesheet" type="text/css" href="<?php echo $spellercss ?>" />
+<script language="javascript" src="<?php echo $word_win_src ?>"></script>
+<script language="javascript">
+var suggs = new Array();
+var words = new Array();
+var textinputs = new Array();
+var error;
+<?php
+
+print_textinputs_var();
+
+print_checker_results();
+
+?>
+
+var wordWindowObj = new wordWindow();
+wordWindowObj.originalSpellings = words;
+wordWindowObj.suggestions = suggs;
+wordWindowObj.textInputs = textinputs;
+
+function init_spell() {
+ // check if any error occured during server-side processing
+ if( error ) {
+ alert( error );
+ } else {
+ // call the init_spell() function in the parent frameset
+ if (parent.frames.length) {
+ parent.init_spell( wordWindowObj );
+ } else {
+ alert('This page was loaded outside of a frameset. It might not display properly');
+ }
+ }
+}
+
+
+
+</script>
+
+</head>
+<!-- <body onLoad="init_spell();"> by FredCK -->
+<body onLoad="init_spell();" bgcolor="#ffffff">
+
+<script type="text/javascript">
+wordWindowObj.writeBody();
+</script>
+
+</body>
+</html>
diff --git a/plugins/aspell/spellerpages/server-scripts/spellchecker.pl b/plugins/aspell/spellerpages/server-scripts/spellchecker.pl new file mode 100755 index 0000000..fae010d --- /dev/null +++ b/plugins/aspell/spellerpages/server-scripts/spellchecker.pl @@ -0,0 +1,181 @@ +#!/usr/bin/perl
+
+use CGI qw/ :standard /;
+use File::Temp qw/ tempfile tempdir /;
+
+# my $spellercss = '/speller/spellerStyle.css'; # by FredCK
+my $spellercss = '../spellerStyle.css'; # by FredCK
+# my $wordWindowSrc = '/speller/wordWindow.js'; # by FredCK
+my $wordWindowSrc = '../wordWindow.js'; # by FredCK
+my @textinputs = param( 'textinputs[]' ); # array
+# my $aspell_cmd = 'aspell'; # by FredCK (for Linux)
+my $aspell_cmd = '"C:\Program Files\Aspell\bin\aspell.exe"'; # by FredCK (for Windows)
+my $lang = 'en_US';
+# my $aspell_opts = "-a --lang=$lang --encoding=utf-8"; # by FredCK
+my $aspell_opts = "-a --lang=$lang --encoding=utf-8 -H --rem-sgml-check=alt"; # by FredCK
+my $input_separator = "A";
+
+# set the 'wordtext' JavaScript variable to the submitted text.
+sub printTextVar {
+ for( my $i = 0; $i <= $#textinputs; $i++ ) {
+ print "textinputs[$i] = decodeURIComponent('" . escapeQuote( $textinputs[$i] ) . "')\n";
+ }
+}
+
+sub printTextIdxDecl {
+ my $idx = shift;
+ print "words[$idx] = [];\n";
+ print "suggs[$idx] = [];\n";
+}
+
+sub printWordsElem {
+ my( $textIdx, $wordIdx, $word ) = @_;
+ print "words[$textIdx][$wordIdx] = '" . escapeQuote( $word ) . "';\n";
+}
+
+sub printSuggsElem {
+ my( $textIdx, $wordIdx, @suggs ) = @_;
+ print "suggs[$textIdx][$wordIdx] = [";
+ for my $i ( 0..$#suggs ) {
+ print "'" . escapeQuote( $suggs[$i] ) . "'";
+ if( $i < $#suggs ) {
+ print ", ";
+ }
+ }
+ print "];\n";
+}
+
+sub printCheckerResults {
+ my $textInputIdx = -1;
+ my $wordIdx = 0;
+ my $unhandledText;
+ # create temp file
+ my $dir = tempdir( CLEANUP => 1 );
+ my( $fh, $tmpfilename ) = tempfile( DIR => $dir );
+
+ # temp file was created properly?
+
+ # open temp file, add the submitted text.
+ for( my $i = 0; $i <= $#textinputs; $i++ ) {
+ $text = url_decode( $textinputs[$i] );
+ # Strip all tags for the text. (by FredCK - #339 / #681)
+ $text =~ s/<[^>]+>/ /g;
+ @lines = split( /\n/, $text );
+ print $fh "\%\n"; # exit terse mode
+ print $fh "^$input_separator\n";
+ print $fh "!\n"; # enter terse mode
+ for my $line ( @lines ) {
+ # use carat on each line to escape possible aspell commands
+ print $fh "^$line\n";
+ }
+
+ }
+ # exec aspell command
+ my $cmd = "$aspell_cmd $aspell_opts < $tmpfilename 2>&1";
+ open ASPELL, "$cmd |" or handleError( "Could not execute `$cmd`\\n$!" ) and return;
+ # parse each line of aspell return
+ for my $ret ( <ASPELL> ) {
+ chomp( $ret );
+ # if '&', then not in dictionary but has suggestions
+ # if '#', then not in dictionary and no suggestions
+ # if '*', then it is a delimiter between text inputs
+ if( $ret =~ /^\*/ ) {
+ $textInputIdx++;
+ printTextIdxDecl( $textInputIdx );
+ $wordIdx = 0;
+
+ } elsif( $ret =~ /^(&|#)/ ) {
+ my @tokens = split( " ", $ret, 5 );
+ printWordsElem( $textInputIdx, $wordIdx, $tokens[1] );
+ my @suggs = ();
+ if( $tokens[4] ) {
+ @suggs = split( ", ", $tokens[4] );
+ }
+ printSuggsElem( $textInputIdx, $wordIdx, @suggs );
+ $wordIdx++;
+ } else {
+ $unhandledText .= $ret;
+ }
+ }
+ close ASPELL or handleError( "Error executing `$cmd`\\n$unhandledText" ) and return;
+}
+
+sub escapeQuote {
+ my $str = shift;
+ $str =~ s/'/\\'/g;
+ return $str;
+}
+
+sub handleError {
+ my $err = shift;
+ print "error = '" . escapeQuote( $err ) . "';\n";
+}
+
+sub url_decode {
+ local $_ = @_ ? shift : $_;
+ defined or return;
+ # change + signs to spaces
+ tr/+/ /;
+ # change hex escapes to the proper characters
+ s/%([a-fA-F0-9]{2})/pack "H2", $1/eg;
+ return $_;
+}
+
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+# Display HTML
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+print <<EOF;
+Content-type: text/html; charset=utf-8
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<link rel="stylesheet" type="text/css" href="$spellercss"/>
+<script src="$wordWindowSrc"></script>
+<script type="text/javascript">
+var suggs = new Array();
+var words = new Array();
+var textinputs = new Array();
+var error;
+EOF
+
+printTextVar();
+
+printCheckerResults();
+
+print <<EOF;
+var wordWindowObj = new wordWindow();
+wordWindowObj.originalSpellings = words;
+wordWindowObj.suggestions = suggs;
+wordWindowObj.textInputs = textinputs;
+
+
+function init_spell() {
+ // check if any error occured during server-side processing
+ if( error ) {
+ alert( error );
+ } else {
+ // call the init_spell() function in the parent frameset
+ if (parent.frames.length) {
+ parent.init_spell( wordWindowObj );
+ } else {
+ error = "This page was loaded outside of a frameset. ";
+ error += "It might not display properly";
+ alert( error );
+ }
+ }
+}
+
+</script>
+
+</head>
+<body onLoad="init_spell();">
+
+<script type="text/javascript">
+wordWindowObj.writeBody();
+</script>
+
+</body>
+</html>
+EOF
diff --git a/plugins/aspell/spellerpages/spellChecker.js b/plugins/aspell/spellerpages/spellChecker.js new file mode 100755 index 0000000..cf22262 --- /dev/null +++ b/plugins/aspell/spellerpages/spellChecker.js @@ -0,0 +1,461 @@ +////////////////////////////////////////////////////
+// spellChecker.js
+//
+// spellChecker object
+//
+// This file is sourced on web pages that have a textarea object to evaluate
+// for spelling. It includes the implementation for the spellCheckObject.
+//
+////////////////////////////////////////////////////
+
+
+// constructor
+function spellChecker( textObject ) {
+
+ // public properties - configurable
+ this.popUpUrl = '/speller/spellchecker.html'; // by FredCK
+// this.popUpUrl = 'fck_spellerpages/spellerpages/spellchecker.html'; // by FredCK
+ this.popUpName = 'spellchecker';
+ this.popUpProps = "menu=no,width=440,height=350,top=70,left=120,resizable=yes,status=yes"; // by FredCK
+// this.popUpProps = null ; // by FredCK
+ this.spellCheckScript = '/speller/server-scripts/spellchecker.php'; // by FredCK
+ //this.spellCheckScript = '/cgi-bin/spellchecker.pl';
+
+ // values used to keep track of what happened to a word
+ this.replWordFlag = "R"; // single replace
+ this.ignrWordFlag = "I"; // single ignore
+ this.replAllFlag = "RA"; // replace all occurances
+ this.ignrAllFlag = "IA"; // ignore all occurances
+ this.fromReplAll = "~RA"; // an occurance of a "replace all" word
+ this.fromIgnrAll = "~IA"; // an occurance of a "ignore all" word
+ // properties set at run time
+ this.wordFlags = new Array();
+ this.currentTextIndex = 0;
+ this.currentWordIndex = 0;
+ this.spellCheckerWin = null;
+ this.controlWin = null;
+ this.wordWin = null;
+ this.textArea = textObject; // deprecated
+ this.textInputs = arguments;
+
+ // private methods
+ this._spellcheck = _spellcheck;
+ this._getSuggestions = _getSuggestions;
+ this._setAsIgnored = _setAsIgnored;
+ this._getTotalReplaced = _getTotalReplaced;
+ this._setWordText = _setWordText;
+ this._getFormInputs = _getFormInputs;
+
+ // public methods
+ this.openChecker = openChecker;
+ this.startCheck = startCheck;
+ this.checkTextBoxes = checkTextBoxes;
+ this.checkTextAreas = checkTextAreas;
+ this.spellCheckAll = spellCheckAll;
+ this.ignoreWord = ignoreWord;
+ this.ignoreAll = ignoreAll;
+ this.replaceWord = replaceWord;
+ this.replaceAll = replaceAll;
+ this.terminateSpell = terminateSpell;
+ this.undo = undo;
+
+ // set the current window's "speller" property to the instance of this class.
+ // this object can now be referenced by child windows/frames.
+ window.speller = this;
+}
+
+// call this method to check all text boxes (and only text boxes) in the HTML document
+function checkTextBoxes() {
+ this.textInputs = this._getFormInputs( "^text$" );
+ this.openChecker();
+}
+
+// call this method to check all textareas (and only textareas ) in the HTML document
+function checkTextAreas() {
+ this.textInputs = this._getFormInputs( "^textarea$" );
+ this.openChecker();
+}
+
+// call this method to check all text boxes and textareas in the HTML document
+function spellCheckAll() {
+ this.textInputs = this._getFormInputs( "^text(area)?$" );
+ this.openChecker();
+}
+
+// call this method to check text boxe(s) and/or textarea(s) that were passed in to the
+// object's constructor or to the textInputs property
+function openChecker() {
+ this.spellCheckerWin = window.open( this.popUpUrl, this.popUpName, this.popUpProps );
+ if( !this.spellCheckerWin.opener ) {
+ this.spellCheckerWin.opener = window;
+ }
+}
+
+function startCheck( wordWindowObj, controlWindowObj ) {
+
+ // set properties from args
+ this.wordWin = wordWindowObj;
+ this.controlWin = controlWindowObj;
+
+ // reset properties
+ this.wordWin.resetForm();
+ this.controlWin.resetForm();
+ this.currentTextIndex = 0;
+ this.currentWordIndex = 0;
+ // initialize the flags to an array - one element for each text input
+ this.wordFlags = new Array( this.wordWin.textInputs.length );
+ // each element will be an array that keeps track of each word in the text
+ for( var i=0; i<this.wordFlags.length; i++ ) {
+ this.wordFlags[i] = [];
+ }
+
+ // start
+ this._spellcheck();
+
+ return true;
+}
+
+function ignoreWord() {
+ var wi = this.currentWordIndex;
+ var ti = this.currentTextIndex;
+ if( !this.wordWin ) {
+ alert( 'Error: Word frame not available.' );
+ return false;
+ }
+ if( !this.wordWin.getTextVal( ti, wi )) {
+ alert( 'Error: "Not in dictionary" text is missing.' );
+ return false;
+ }
+ // set as ignored
+ if( this._setAsIgnored( ti, wi, this.ignrWordFlag )) {
+ this.currentWordIndex++;
+ this._spellcheck();
+ }
+ return true;
+}
+
+function ignoreAll() {
+ var wi = this.currentWordIndex;
+ var ti = this.currentTextIndex;
+ if( !this.wordWin ) {
+ alert( 'Error: Word frame not available.' );
+ return false;
+ }
+ // get the word that is currently being evaluated.
+ var s_word_to_repl = this.wordWin.getTextVal( ti, wi );
+ if( !s_word_to_repl ) {
+ alert( 'Error: "Not in dictionary" text is missing' );
+ return false;
+ }
+
+ // set this word as an "ignore all" word.
+ this._setAsIgnored( ti, wi, this.ignrAllFlag );
+
+ // loop through all the words after this word
+ for( var i = ti; i < this.wordWin.textInputs.length; i++ ) {
+ for( var j = 0; j < this.wordWin.totalWords( i ); j++ ) {
+ if(( i == ti && j > wi ) || i > ti ) {
+ // future word: set as "from ignore all" if
+ // 1) do not already have a flag and
+ // 2) have the same value as current word
+ if(( this.wordWin.getTextVal( i, j ) == s_word_to_repl )
+ && ( !this.wordFlags[i][j] )) {
+ this._setAsIgnored( i, j, this.fromIgnrAll );
+ }
+ }
+ }
+ }
+
+ // finally, move on
+ this.currentWordIndex++;
+ this._spellcheck();
+ return true;
+}
+
+function replaceWord() {
+ var wi = this.currentWordIndex;
+ var ti = this.currentTextIndex;
+ if( !this.wordWin ) {
+ alert( 'Error: Word frame not available.' );
+ return false;
+ }
+ if( !this.wordWin.getTextVal( ti, wi )) {
+ alert( 'Error: "Not in dictionary" text is missing' );
+ return false;
+ }
+ if( !this.controlWin.replacementText ) {
+ return false ;
+ }
+ var txt = this.controlWin.replacementText;
+ if( txt.value ) {
+ var newspell = new String( txt.value );
+ if( this._setWordText( ti, wi, newspell, this.replWordFlag )) {
+ this.currentWordIndex++;
+ this._spellcheck();
+ }
+ }
+ return true;
+}
+
+function replaceAll() {
+ var ti = this.currentTextIndex;
+ var wi = this.currentWordIndex;
+ if( !this.wordWin ) {
+ alert( 'Error: Word frame not available.' );
+ return false;
+ }
+ var s_word_to_repl = this.wordWin.getTextVal( ti, wi );
+ if( !s_word_to_repl ) {
+ alert( 'Error: "Not in dictionary" text is missing' );
+ return false;
+ }
+ var txt = this.controlWin.replacementText;
+ if( !txt.value ) return false;
+ var newspell = new String( txt.value );
+
+ // set this word as a "replace all" word.
+ this._setWordText( ti, wi, newspell, this.replAllFlag );
+
+ // loop through all the words after this word
+ for( var i = ti; i < this.wordWin.textInputs.length; i++ ) {
+ for( var j = 0; j < this.wordWin.totalWords( i ); j++ ) {
+ if(( i == ti && j > wi ) || i > ti ) {
+ // future word: set word text to s_word_to_repl if
+ // 1) do not already have a flag and
+ // 2) have the same value as s_word_to_repl
+ if(( this.wordWin.getTextVal( i, j ) == s_word_to_repl )
+ && ( !this.wordFlags[i][j] )) {
+ this._setWordText( i, j, newspell, this.fromReplAll );
+ }
+ }
+ }
+ }
+
+ // finally, move on
+ this.currentWordIndex++;
+ this._spellcheck();
+ return true;
+}
+
+function terminateSpell() {
+ // called when we have reached the end of the spell checking.
+ var msg = ""; // by FredCK
+ var numrepl = this._getTotalReplaced();
+ if( numrepl == 0 ) {
+ // see if there were no misspellings to begin with
+ if( !this.wordWin ) {
+ msg = "";
+ } else {
+ if( this.wordWin.totalMisspellings() ) {
+// msg += "No words changed."; // by FredCK
+ msg += FCKLang.DlgSpellNoChanges ; // by FredCK
+ } else {
+// msg += "No misspellings found."; // by FredCK
+ msg += FCKLang.DlgSpellNoMispell ; // by FredCK
+ }
+ }
+ } else if( numrepl == 1 ) {
+// msg += "One word changed."; // by FredCK
+ msg += FCKLang.DlgSpellOneChange ; // by FredCK
+ } else {
+// msg += numrepl + " words changed."; // by FredCK
+ msg += FCKLang.DlgSpellManyChanges.replace( /%1/g, numrepl ) ;
+ }
+ if( msg ) {
+// msg += "\n"; // by FredCK
+ alert( msg );
+ }
+
+ if( numrepl > 0 ) {
+ // update the text field(s) on the opener window
+ for( var i = 0; i < this.textInputs.length; i++ ) {
+ // this.textArea.value = this.wordWin.text;
+ if( this.wordWin ) {
+ if( this.wordWin.textInputs[i] ) {
+ this.textInputs[i].value = this.wordWin.textInputs[i];
+ }
+ }
+ }
+ }
+
+ // return back to the calling window
+// this.spellCheckerWin.close(); // by FredCK
+ if ( typeof( this.OnFinished ) == 'function' ) // by FredCK
+ this.OnFinished(numrepl) ; // by FredCK
+
+ return true;
+}
+
+function undo() {
+ // skip if this is the first word!
+ var ti = this.currentTextIndex;
+ var wi = this.currentWordIndex;
+
+ if( this.wordWin.totalPreviousWords( ti, wi ) > 0 ) {
+ this.wordWin.removeFocus( ti, wi );
+
+ // go back to the last word index that was acted upon
+ do {
+ // if the current word index is zero then reset the seed
+ if( this.currentWordIndex == 0 && this.currentTextIndex > 0 ) {
+ this.currentTextIndex--;
+ this.currentWordIndex = this.wordWin.totalWords( this.currentTextIndex )-1;
+ if( this.currentWordIndex < 0 ) this.currentWordIndex = 0;
+ } else {
+ if( this.currentWordIndex > 0 ) {
+ this.currentWordIndex--;
+ }
+ }
+ } while (
+ this.wordWin.totalWords( this.currentTextIndex ) == 0
+ || this.wordFlags[this.currentTextIndex][this.currentWordIndex] == this.fromIgnrAll
+ || this.wordFlags[this.currentTextIndex][this.currentWordIndex] == this.fromReplAll
+ );
+
+ var text_idx = this.currentTextIndex;
+ var idx = this.currentWordIndex;
+ var preReplSpell = this.wordWin.originalSpellings[text_idx][idx];
+
+ // if we got back to the first word then set the Undo button back to disabled
+ if( this.wordWin.totalPreviousWords( text_idx, idx ) == 0 ) {
+ this.controlWin.disableUndo();
+ }
+
+ var i, j, origSpell ;
+ // examine what happened to this current word.
+ switch( this.wordFlags[text_idx][idx] ) {
+ // replace all: go through this and all the future occurances of the word
+ // and revert them all to the original spelling and clear their flags
+ case this.replAllFlag :
+ for( i = text_idx; i < this.wordWin.textInputs.length; i++ ) {
+ for( j = 0; j < this.wordWin.totalWords( i ); j++ ) {
+ if(( i == text_idx && j >= idx ) || i > text_idx ) {
+ origSpell = this.wordWin.originalSpellings[i][j];
+ if( origSpell == preReplSpell ) {
+ this._setWordText ( i, j, origSpell, undefined );
+ }
+ }
+ }
+ }
+ break;
+
+ // ignore all: go through all the future occurances of the word
+ // and clear their flags
+ case this.ignrAllFlag :
+ for( i = text_idx; i < this.wordWin.textInputs.length; i++ ) {
+ for( j = 0; j < this.wordWin.totalWords( i ); j++ ) {
+ if(( i == text_idx && j >= idx ) || i > text_idx ) {
+ origSpell = this.wordWin.originalSpellings[i][j];
+ if( origSpell == preReplSpell ) {
+ this.wordFlags[i][j] = undefined;
+ }
+ }
+ }
+ }
+ break;
+
+ // replace: revert the word to its original spelling
+ case this.replWordFlag :
+ this._setWordText ( text_idx, idx, preReplSpell, undefined );
+ break;
+ }
+
+ // For all four cases, clear the wordFlag of this word. re-start the process
+ this.wordFlags[text_idx][idx] = undefined;
+ this._spellcheck();
+ }
+}
+
+function _spellcheck() {
+ var ww = this.wordWin;
+
+ // check if this is the last word in the current text element
+ if( this.currentWordIndex == ww.totalWords( this.currentTextIndex) ) {
+ this.currentTextIndex++;
+ this.currentWordIndex = 0;
+ // keep going if we're not yet past the last text element
+ if( this.currentTextIndex < this.wordWin.textInputs.length ) {
+ this._spellcheck();
+ return;
+ } else {
+ this.terminateSpell();
+ return;
+ }
+ }
+
+ // if this is after the first one make sure the Undo button is enabled
+ if( this.currentWordIndex > 0 ) {
+ this.controlWin.enableUndo();
+ }
+
+ // skip the current word if it has already been worked on
+ if( this.wordFlags[this.currentTextIndex][this.currentWordIndex] ) {
+ // increment the global current word index and move on.
+ this.currentWordIndex++;
+ this._spellcheck();
+ } else {
+ var evalText = ww.getTextVal( this.currentTextIndex, this.currentWordIndex );
+ if( evalText ) {
+ this.controlWin.evaluatedText.value = evalText;
+ ww.setFocus( this.currentTextIndex, this.currentWordIndex );
+ this._getSuggestions( this.currentTextIndex, this.currentWordIndex );
+ }
+ }
+}
+
+function _getSuggestions( text_num, word_num ) {
+ this.controlWin.clearSuggestions();
+ // add suggestion in list for each suggested word.
+ // get the array of suggested words out of the
+ // three-dimensional array containing all suggestions.
+ var a_suggests = this.wordWin.suggestions[text_num][word_num];
+ if( a_suggests ) {
+ // got an array of suggestions.
+ for( var ii = 0; ii < a_suggests.length; ii++ ) {
+ this.controlWin.addSuggestion( a_suggests[ii] );
+ }
+ }
+ this.controlWin.selectDefaultSuggestion();
+}
+
+function _setAsIgnored( text_num, word_num, flag ) {
+ // set the UI
+ this.wordWin.removeFocus( text_num, word_num );
+ // do the bookkeeping
+ this.wordFlags[text_num][word_num] = flag;
+ return true;
+}
+
+function _getTotalReplaced() {
+ var i_replaced = 0;
+ for( var i = 0; i < this.wordFlags.length; i++ ) {
+ for( var j = 0; j < this.wordFlags[i].length; j++ ) {
+ if(( this.wordFlags[i][j] == this.replWordFlag )
+ || ( this.wordFlags[i][j] == this.replAllFlag )
+ || ( this.wordFlags[i][j] == this.fromReplAll )) {
+ i_replaced++;
+ }
+ }
+ }
+ return i_replaced;
+}
+
+function _setWordText( text_num, word_num, newText, flag ) {
+ // set the UI and form inputs
+ this.wordWin.setText( text_num, word_num, newText );
+ // keep track of what happened to this word:
+ this.wordFlags[text_num][word_num] = flag;
+ return true;
+}
+
+function _getFormInputs( inputPattern ) {
+ var inputs = new Array();
+ for( var i = 0; i < document.forms.length; i++ ) {
+ for( var j = 0; j < document.forms[i].elements.length; j++ ) {
+ if( document.forms[i].elements[j].type.match( inputPattern )) {
+ inputs[inputs.length] = document.forms[i].elements[j];
+ }
+ }
+ }
+ return inputs;
+}
diff --git a/plugins/aspell/spellerpages/spellchecker.html b/plugins/aspell/spellerpages/spellchecker.html new file mode 100755 index 0000000..cbcd7db --- /dev/null +++ b/plugins/aspell/spellerpages/spellchecker.html @@ -0,0 +1,71 @@ +
+<script>
+
+var wordWindow = null;
+var controlWindow = null;
+
+function init_spell( spellerWindow ) {
+
+ if( spellerWindow ) {
+ if( spellerWindow.windowType == "wordWindow" ) {
+ wordWindow = spellerWindow;
+ } else if ( spellerWindow.windowType == "controlWindow" ) {
+ controlWindow = spellerWindow;
+ }
+ }
+
+ if( controlWindow && wordWindow ) {
+ // populate the speller object and start it off!
+ var speller = opener.speller;
+ wordWindow.speller = speller;
+ speller.startCheck( wordWindow, controlWindow );
+ }
+}
+
+// encodeForPost
+function encodeForPost( str ) {
+ var s = new String( str );
+ s = encodeURIComponent( s );
+ // additionally encode single quotes to evade any PHP
+ // magic_quotes_gpc setting (it inserts escape characters and
+ // therefore skews the btye positions of misspelled words)
+ return s.replace( /\'/g, '%27' );
+}
+
+// post the text area data to the script that populates the speller
+function postWords() {
+ var bodyDoc = window.frames[0].document;
+ bodyDoc.open();
+ bodyDoc.write('<html>');
+ bodyDoc.write('<meta http-equiv="Content-Type" content="text/html; charset=utf-8">');
+ bodyDoc.write('<link rel="stylesheet" type="text/css" href="spellerStyle.css"/>');
+ if (opener) {
+ var speller = opener.speller;
+ bodyDoc.write('<body class="normalText" onLoad="document.forms[0].submit();">');
+ bodyDoc.write('<p>' + window.parent.FCKLang.DlgSpellProgress + '<\/p>'); // by FredCK
+ bodyDoc.write('<form action="'+speller.spellCheckScript+'" method="post">');
+ for( var i = 0; i < speller.textInputs.length; i++ ) {
+ bodyDoc.write('<input type="hidden" name="textinputs[]" value="'+encodeForPost(speller.textInputs[i].value)+'">');
+ }
+ bodyDoc.write('<\/form>');
+ bodyDoc.write('<\/body>');
+ } else {
+ bodyDoc.write('<body class="normalText">');
+ bodyDoc.write('<p><b>This page cannot be displayed<\/b><\/p><p>The window was not opened from another window.<\/p>');
+ bodyDoc.write('<\/body>');
+ }
+ bodyDoc.write('<\/html>');
+ bodyDoc.close();
+}
+</script>
+
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<head>
+<title>Speller Pages</title>
+</head>
+<frameset rows="*,201" onLoad="postWords();">
+<frame src="blank.html">
+<frame src="controls.html">
+</frameset>
+</html>
diff --git a/plugins/aspell/spellerpages/spellerStyle.css b/plugins/aspell/spellerpages/spellerStyle.css new file mode 100755 index 0000000..d747e31 --- /dev/null +++ b/plugins/aspell/spellerpages/spellerStyle.css @@ -0,0 +1,49 @@ +.blend {
+ font-family: courier new;
+ font-size: 10pt;
+ border: 0;
+ margin-bottom:-1;
+}
+.normalLabel {
+ font-size:8pt;
+}
+.normalText {
+ font-family:arial, helvetica, sans-serif;
+ font-size:10pt;
+ color:000000;
+ background-color:FFFFFF;
+}
+.plainText {
+ font-family: courier new, courier, monospace;
+ font-size: 10pt;
+ color:000000;
+ background-color:FFFFFF;
+}
+.controlWindowBody {
+ font-family:arial, helvetica, sans-serif;
+ font-size:8pt;
+ padding-top: 7px; /* by FredCK */
+ margin: 0px; /* by FredCK */
+ color:000000;
+ background-color:DADADA;
+}
+.readonlyInput {
+ background-color:DADADA;
+ color:000000;
+ font-size:8pt;
+ width:392px;
+}
+.textDefault {
+ font-size:8pt;
+ width: 200px;
+}
+.buttonDefault {
+ width:90px;
+ height:22px;
+ font-size:8pt;
+}
+.suggSlct {
+ width:200px;
+ margin-top:2;
+ font-size:8pt;
+}
diff --git a/plugins/aspell/spellerpages/wordWindow.js b/plugins/aspell/spellerpages/wordWindow.js new file mode 100755 index 0000000..7990296 --- /dev/null +++ b/plugins/aspell/spellerpages/wordWindow.js @@ -0,0 +1,272 @@ +////////////////////////////////////////////////////
+// wordWindow object
+////////////////////////////////////////////////////
+function wordWindow() {
+ // private properties
+ this._forms = [];
+
+ // private methods
+ this._getWordObject = _getWordObject;
+ //this._getSpellerObject = _getSpellerObject;
+ this._wordInputStr = _wordInputStr;
+ this._adjustIndexes = _adjustIndexes;
+ this._isWordChar = _isWordChar;
+ this._lastPos = _lastPos;
+
+ // public properties
+ this.wordChar = /[a-zA-Z]/;
+ this.windowType = "wordWindow";
+ this.originalSpellings = new Array();
+ this.suggestions = new Array();
+ this.checkWordBgColor = "pink";
+ this.normWordBgColor = "white";
+ this.text = "";
+ this.textInputs = new Array();
+ this.indexes = new Array();
+ //this.speller = this._getSpellerObject();
+
+ // public methods
+ this.resetForm = resetForm;
+ this.totalMisspellings = totalMisspellings;
+ this.totalWords = totalWords;
+ this.totalPreviousWords = totalPreviousWords;
+ //this.getTextObjectArray = getTextObjectArray;
+ this.getTextVal = getTextVal;
+ this.setFocus = setFocus;
+ this.removeFocus = removeFocus;
+ this.setText = setText;
+ //this.getTotalWords = getTotalWords;
+ this.writeBody = writeBody;
+ this.printForHtml = printForHtml;
+}
+
+function resetForm() {
+ if( this._forms ) {
+ for( var i = 0; i < this._forms.length; i++ ) {
+ this._forms[i].reset();
+ }
+ }
+ return true;
+}
+
+function totalMisspellings() {
+ var total_words = 0;
+ for( var i = 0; i < this.textInputs.length; i++ ) {
+ total_words += this.totalWords( i );
+ }
+ return total_words;
+}
+
+function totalWords( textIndex ) {
+ return this.originalSpellings[textIndex].length;
+}
+
+function totalPreviousWords( textIndex, wordIndex ) {
+ var total_words = 0;
+ for( var i = 0; i <= textIndex; i++ ) {
+ for( var j = 0; j < this.totalWords( i ); j++ ) {
+ if( i == textIndex && j == wordIndex ) {
+ break;
+ } else {
+ total_words++;
+ }
+ }
+ }
+ return total_words;
+}
+
+//function getTextObjectArray() {
+// return this._form.elements;
+//}
+
+function getTextVal( textIndex, wordIndex ) {
+ var word = this._getWordObject( textIndex, wordIndex );
+ if( word ) {
+ return word.value;
+ }
+}
+
+function setFocus( textIndex, wordIndex ) {
+ var word = this._getWordObject( textIndex, wordIndex );
+ if( word ) {
+ if( word.type == "text" ) {
+ word.focus();
+ word.style.backgroundColor = this.checkWordBgColor;
+ }
+ }
+}
+
+function removeFocus( textIndex, wordIndex ) {
+ var word = this._getWordObject( textIndex, wordIndex );
+ if( word ) {
+ if( word.type == "text" ) {
+ word.blur();
+ word.style.backgroundColor = this.normWordBgColor;
+ }
+ }
+}
+
+function setText( textIndex, wordIndex, newText ) {
+ var word = this._getWordObject( textIndex, wordIndex );
+ var beginStr;
+ var endStr;
+ if( word ) {
+ var pos = this.indexes[textIndex][wordIndex];
+ var oldText = word.value;
+ // update the text given the index of the string
+ beginStr = this.textInputs[textIndex].substring( 0, pos );
+ endStr = this.textInputs[textIndex].substring(
+ pos + oldText.length,
+ this.textInputs[textIndex].length
+ );
+ this.textInputs[textIndex] = beginStr + newText + endStr;
+
+ // adjust the indexes on the stack given the differences in
+ // length between the new word and old word.
+ var lengthDiff = newText.length - oldText.length;
+ this._adjustIndexes( textIndex, wordIndex, lengthDiff );
+
+ word.size = newText.length;
+ word.value = newText;
+ this.removeFocus( textIndex, wordIndex );
+ }
+}
+
+
+function writeBody() {
+ var d = window.document;
+ var is_html = false;
+
+ d.open();
+
+ // iterate through each text input.
+ for( var txtid = 0; txtid < this.textInputs.length; txtid++ ) {
+ var end_idx = 0;
+ var begin_idx = 0;
+ d.writeln( '<form name="textInput'+txtid+'">' );
+ var wordtxt = this.textInputs[txtid];
+ this.indexes[txtid] = [];
+
+ if( wordtxt ) {
+ var orig = this.originalSpellings[txtid];
+ if( !orig ) break;
+
+ //!!! plain text, or HTML mode?
+ d.writeln( '<div class="plainText">' );
+ // iterate through each occurrence of a misspelled word.
+ for( var i = 0; i < orig.length; i++ ) {
+ // find the position of the current misspelled word,
+ // starting at the last misspelled word.
+ // and keep looking if it's a substring of another word
+ do {
+ begin_idx = wordtxt.indexOf( orig[i], end_idx );
+ end_idx = begin_idx + orig[i].length;
+ // word not found? messed up!
+ if( begin_idx == -1 ) break;
+ // look at the characters immediately before and after
+ // the word. If they are word characters we'll keep looking.
+ var before_char = wordtxt.charAt( begin_idx - 1 );
+ var after_char = wordtxt.charAt( end_idx );
+ } while (
+ this._isWordChar( before_char )
+ || this._isWordChar( after_char )
+ );
+
+ // keep track of its position in the original text.
+ this.indexes[txtid][i] = begin_idx;
+
+ // write out the characters before the current misspelled word
+ for( var j = this._lastPos( txtid, i ); j < begin_idx; j++ ) {
+ // !!! html mode? make it html compatible
+ d.write( this.printForHtml( wordtxt.charAt( j )));
+ }
+
+ // write out the misspelled word.
+ d.write( this._wordInputStr( orig[i] ));
+
+ // if it's the last word, write out the rest of the text
+ if( i == orig.length-1 ){
+ d.write( printForHtml( wordtxt.substr( end_idx )));
+ }
+ }
+
+ d.writeln( '</div>' );
+
+ }
+ d.writeln( '</form>' );
+ }
+ //for ( var j = 0; j < d.forms.length; j++ ) {
+ // alert( d.forms[j].name );
+ // for( var k = 0; k < d.forms[j].elements.length; k++ ) {
+ // alert( d.forms[j].elements[k].name + ": " + d.forms[j].elements[k].value );
+ // }
+ //}
+
+ // set the _forms property
+ this._forms = d.forms;
+ d.close();
+}
+
+// return the character index in the full text after the last word we evaluated
+function _lastPos( txtid, idx ) {
+ if( idx > 0 )
+ return this.indexes[txtid][idx-1] + this.originalSpellings[txtid][idx-1].length;
+ else
+ return 0;
+}
+
+function printForHtml( n ) {
+ return n ; // by FredCK
+/*
+ var htmlstr = n;
+ if( htmlstr.length == 1 ) {
+ // do simple case statement if it's just one character
+ switch ( n ) {
+ case "\n":
+ htmlstr = '<br/>';
+ break;
+ case "<":
+ htmlstr = '<';
+ break;
+ case ">":
+ htmlstr = '>';
+ break;
+ }
+ return htmlstr;
+ } else {
+ htmlstr = htmlstr.replace( /</g, '<' );
+ htmlstr = htmlstr.replace( />/g, '>' );
+ htmlstr = htmlstr.replace( /\n/g, '<br/>' );
+ return htmlstr;
+ }
+*/
+}
+
+function _isWordChar( letter ) {
+ if( letter.search( this.wordChar ) == -1 ) {
+ return false;
+ } else {
+ return true;
+ }
+}
+
+function _getWordObject( textIndex, wordIndex ) {
+ if( this._forms[textIndex] ) {
+ if( this._forms[textIndex].elements[wordIndex] ) {
+ return this._forms[textIndex].elements[wordIndex];
+ }
+ }
+ return null;
+}
+
+function _wordInputStr( word ) {
+ var str = '<input readonly ';
+ str += 'class="blend" type="text" value="' + word + '" size="' + word.length + '">';
+ return str;
+}
+
+function _adjustIndexes( textIndex, wordIndex, lengthDiff ) {
+ for( var i = wordIndex + 1; i < this.originalSpellings[textIndex].length; i++ ) {
+ this.indexes[textIndex][i] = this.indexes[textIndex][i] + lengthDiff;
+ }
+}
|
