Automatic installer.php lang files by installer_builder (20070726)
[moodle-linuxchix.git] / lib / speller / spellChecker.js
blob8e80a887e962e5f05a903ffee8874110bf320f6b
1 ////////////////////////////////////////////////////
2 // spellChecker.js
3 //
4 // spellChecker object
5 //
6 // This file is sourced on web pages that have a textarea object to evaluate
7 // for spelling. It includes the implementation for the spellCheckObject.
8 //
9 // Modified by LUDO (Marc Alier) for integration with the moogle environment
10 // august 2004 malier@lsi.upc.es
12 ////////////////////////////////////////////////////
15 // constructor
16 function spellChecker( textObject) {
17     // public properties - configurable
18     //this.popUpUrl = '/moodle/lib/speller/spellchecker.html';
19     this.popUpName = 'spellchecker';
20     this.popUpProps = "menu=no,width=440,height=350,top=70,left=120,resizable=yes,status=yes";
21     //this.spellCheckScript = '/moodle/lib/speller/server-scripts/spellchecker.php';
22     //this.spellCheckScript = '/cgi-bin/spellchecker.pl';
24     // values used to keep track of what happened to a word
25     this.replWordFlag = "R";    // single replace
26     this.ignrWordFlag = "I";    // single ignore
27     this.replAllFlag = "RA";    // replace all occurances
28     this.ignrAllFlag = "IA";    // ignore all occurances
29     this.fromReplAll = "~RA";   // an occurance of a "replace all" word
30     this.fromIgnrAll = "~IA";   // an occurance of a "ignore all" word
31     // properties set at run time
32     this.wordFlags = new Array();
33     this.currentTextIndex = 0;
34     this.currentWordIndex = 0;
35     this.spellCheckerWin = null;
36     this.controlWin = null;
37     this.wordWin = null;
38     this.textArea = textObject; // deprecated
39     this.textInputs = arguments;
41     this._editor=""; //  BY LUDO
42     // private methods
43     this._spellcheck = _spellcheck;
44     this._getSuggestions = _getSuggestions;
45     this._setAsIgnored = _setAsIgnored;
46     this._getTotalReplaced = _getTotalReplaced;
47     this._setWordText = _setWordText;
48     this._getFormInputs = _getFormInputs;
50     // public methods
51     this.openChecker = openChecker;
52     this.startCheck = startCheck;
53     this.checkTextBoxes = checkTextBoxes;
54     this.checkTextAreas = checkTextAreas;
55     this.spellCheckAll = spellCheckAll;
56     this.ignoreWord = ignoreWord;
57     this.ignoreAll = ignoreAll;
58     this.replaceWord = replaceWord;
59     this.replaceAll = replaceAll;
60     this.terminateSpell = terminateSpell;
61     this.undo = undo;
63     // set the current window's "speller" property to the instance of this class.
64     // this object can now be referenced by child windows/frames.
65     window.speller = this;
68 // call this method to check all text boxes (and only text boxes) in the HTML document
69 function checkTextBoxes() {
70     this.textInputs = this._getFormInputs( "^text$" );
71     this.openChecker();
74 // call this method to check all textareas (and only textareas ) in the HTML document
75 function checkTextAreas() {
76     this.textInputs = this._getFormInputs( "^textarea$" );
77     this.openChecker();
80 // call this method to check all text boxes and textareas in the HTML document
81 function spellCheckAll() {
82     this.textInputs = this._getFormInputs( "^text(area)?$" );
83     this.openChecker();
86 // call this method to check text boxe(s) and/or textarea(s) that were passed in to the
87 // object's constructor or to the textInputs property
88 function openChecker() {
89     this.spellCheckerWin = window.open( this.popUpUrl, this.popUpName, this.popUpProps );
90     if( !this.spellCheckerWin.opener ) {
91         this.spellCheckerWin.opener = window;
92     }
95 function startCheck( wordWindowObj, controlWindowObj ) {
97     // set properties from args
98     this.wordWin = wordWindowObj;
99     this.controlWin = controlWindowObj;
101     // reset properties
102     this.wordWin.resetForm();
103     this.controlWin.resetForm();
104     this.currentTextIndex = 0;
105     this.currentWordIndex = 0;
106     // initialize the flags to an array - one element for each text input
107     this.wordFlags = new Array( this.wordWin.textInputs.length );
108     // each element will be an array that keeps track of each word in the text
109     for( var i=0; i<this.wordFlags.length; i++ ) {
110         this.wordFlags[i] = [];
111     }
113     // start
114     this._spellcheck();
116     return true;
119 function ignoreWord() {
120     var wi = this.currentWordIndex;
121     var ti = this.currentTextIndex;
122     if( !this.wordWin ) {
123         alert( 'Error: Word frame not available.' );
124         return false;
125     }
126     if( !this.wordWin.getTextVal( ti, wi )) {
127         alert( 'Error: "Not in dictionary" text is missing.' );
128         return false;
129     }
130     // set as ignored
131     if( this._setAsIgnored( ti, wi, this.ignrWordFlag )) {
132         this.currentWordIndex++;
133         this._spellcheck();
134     }
137 function ignoreAll() {
138     var wi = this.currentWordIndex;
139     var ti = this.currentTextIndex;
140     if( !this.wordWin ) {
141         alert( 'Error: Word frame not available.' );
142         return false;
143     }
144     // get the word that is currently being evaluated.
145     var s_word_to_repl = this.wordWin.getTextVal( ti, wi );
146     if( !s_word_to_repl ) {
147         alert( 'Error: "Not in dictionary" text is missing' );
148         return false;
149     }
151     // set this word as an "ignore all" word.
152     this._setAsIgnored( ti, wi, this.ignrAllFlag );
154     // loop through all the words after this word
155     for( var i = ti; i < this.wordWin.textInputs.length; i++ ) {
156         for( var j = 0; j < this.wordWin.totalWords( i ); j++ ) {
157             if(( i == ti && j > wi ) || i > ti ) {
158                 // future word: set as "from ignore all" if
159                 // 1) do not already have a flag and
160                 // 2) have the same value as current word
161                 if(( this.wordWin.getTextVal( i, j ) == s_word_to_repl )
162                 && ( !this.wordFlags[i][j] )) {
163                     this._setAsIgnored( i, j, this.fromIgnrAll );
164                 }
165             }
166         }
167     }
169     // finally, move on
170     this.currentWordIndex++;
171     this._spellcheck();
174 function replaceWord() {
175     var wi = this.currentWordIndex;
176     var ti = this.currentTextIndex;
177     if( !this.wordWin ) {
178         alert( 'Error: Word frame not available.' );
179         return false;
180     }
181     if( !this.wordWin.getTextVal( ti, wi )) {
182         alert( 'Error: "Not in dictionary" text is missing' );
183         return false;
184     }
185     if( !this.controlWin.replacementText ) {
186         return;
187     }
188     var txt = this.controlWin.replacementText;
189     if( txt.value ) {
190         var newspell = new String( txt.value );
191         if( this._setWordText( ti, wi, newspell, this.replWordFlag )) {
192             this.currentWordIndex++;
193             this._spellcheck();
194         }
195     }
198 function replaceAll() {
199     var ti = this.currentTextIndex;
200     var wi = this.currentWordIndex;
201     if( !this.wordWin ) {
202         alert( 'Error: Word frame not available.' );
203         return false;
204     }
205     var s_word_to_repl = this.wordWin.getTextVal( ti, wi );
206     if( !s_word_to_repl ) {
207         alert( 'Error: "Not in dictionary" text is missing' );
208         return false;
209     }
210     var txt = this.controlWin.replacementText;
211     if( !txt.value ) return;
212     var newspell = new String( txt.value );
214     // set this word as a "replace all" word.
215     this._setWordText( ti, wi, newspell, this.replAllFlag );
217     // loop through all the words after this word
218     for( var i = ti; i < this.wordWin.textInputs.length; i++ ) {
219         for( var j = 0; j < this.wordWin.totalWords( i ); j++ ) {
220             if(( i == ti && j > wi ) || i > ti ) {
221                 // future word: set word text to s_word_to_repl if
222                 // 1) do not already have a flag and
223                 // 2) have the same value as s_word_to_repl
224                 if(( this.wordWin.getTextVal( i, j ) == s_word_to_repl )
225                 && ( !this.wordFlags[i][j] )) {
226                     this._setWordText( i, j, newspell, this.fromReplAll );
227                 }
228             }
229         }
230     }
232     // finally, move on
233     this.currentWordIndex++;
234     this._spellcheck();
237 function terminateSpell() {
238     // called when we have reached the end of the spell checking.
239     var msg = "Spell check complete:\n\n";
240     var numrepl = this._getTotalReplaced();
241     if( numrepl == 0 ) {
242         // see if there were no misspellings to begin with
243         if( !this.wordWin ) {
244             msg = "";
245         } else {
246             if( this.wordWin.totalMisspellings() ) {
247                 msg += "No words changed.";
248             } else {
249                 msg += "No misspellings found.";
250             }
251         }
252     } else if( numrepl == 1 ) {
253         msg += "One word changed.";
254     } else {
255         msg += numrepl + " words changed.";
256     }
257     if( msg ) {
258         msg += "\n";
259         alert( msg );
260     }
262     if( numrepl > 0 ) {
263         // update the text field(s) on the opener window
264         for( var i = 0; i < this.textInputs.length; i++ ) {
265             // this.textArea.value = this.wordWin.text;
266             if( this.wordWin ) {
267                 if( this.wordWin.textInputs[i] ) {
268                     this.textInputs[i].value = this.wordWin.textInputs[i];
269                 }
270             }
271         }
272         // START LUDO
273         try {
274             this._editor.setHTML(this._editor._textArea.value);
275         } catch (e) {
276                 // If were not in editor, just continue.
277             }
278         //LUDO END
279     }
281     // return back to the calling window
282     this.spellCheckerWin.close();
284     return true;
287 function undo() {
288     // skip if this is the first word!
289     var ti = this.currentTextIndex;
290     var wi = this.currentWordIndex
292     if( this.wordWin.totalPreviousWords( ti, wi ) > 0 ) {
293         this.wordWin.removeFocus( ti, wi );
295         // go back to the last word index that was acted upon
296         do {
297             // if the current word index is zero then reset the seed
298             if( this.currentWordIndex == 0 && this.currentTextIndex > 0 ) {
299                 this.currentTextIndex--;
300                 this.currentWordIndex = this.wordWin.totalWords( this.currentTextIndex )-1;
301                 if( this.currentWordIndex < 0 ) this.currentWordIndex = 0;
302             } else {
303                 if( this.currentWordIndex > 0 ) {
304                     this.currentWordIndex--;
305                 }
306             }
307         } while (
308             this.wordWin.totalWords( this.currentTextIndex ) == 0
309             || this.wordFlags[this.currentTextIndex][this.currentWordIndex] == this.fromIgnrAll
310             || this.wordFlags[this.currentTextIndex][this.currentWordIndex] == this.fromReplAll
311         );
313         var text_idx = this.currentTextIndex;
314         var idx = this.currentWordIndex;
315         var preReplSpell = this.wordWin.originalSpellings[text_idx][idx];
317         // if we got back to the first word then set the Undo button back to disabled
318         if( this.wordWin.totalPreviousWords( text_idx, idx ) == 0 ) {
319             this.controlWin.disableUndo();
320         }
322         // examine what happened to this current word.
323         switch( this.wordFlags[text_idx][idx] ) {
324             // replace all: go through this and all the future occurances of the word
325             // and revert them all to the original spelling and clear their flags
326             case this.replAllFlag :
327                 for( var i = text_idx; i < this.wordWin.textInputs.length; i++ ) {
328                     for( var j = 0; j < this.wordWin.totalWords( i ); j++ ) {
329                         if(( i == text_idx && j >= idx ) || i > text_idx ) {
330                             var origSpell = this.wordWin.originalSpellings[i][j];
331                             if( origSpell == preReplSpell ) {
332                                 this._setWordText ( i, j, origSpell, undefined );
333                             }
334                         }
335                     }
336                 }
337                 break;
339             // ignore all: go through all the future occurances of the word
340             // and clear their flags
341             case this.ignrAllFlag :
342                 for( var i = text_idx; i < this.wordWin.textInputs.length; i++ ) {
343                     for( var j = 0; j < this.wordWin.totalWords( i ); j++ ) {
344                         if(( i == text_idx && j >= idx ) || i > text_idx ) {
345                             var origSpell = this.wordWin.originalSpellings[i][j];
346                             if( origSpell == preReplSpell ) {
347                                 this.wordFlags[i][j] = undefined;
348                             }
349                         }
350                     }
351                 }
352                 break;
354             // replace: revert the word to its original spelling
355             case this.replWordFlag :
356                 this._setWordText ( text_idx, idx, preReplSpell, undefined );
357                 break;
358         }
360         // For all four cases, clear the wordFlag of this word. re-start the process
361         this.wordFlags[text_idx][idx] = undefined;
362         this._spellcheck();
363     }
366 function _spellcheck() {
367     var ww = this.wordWin;
369     // check if this is the last word in the current text element
370     if( this.currentWordIndex == ww.totalWords( this.currentTextIndex) ) {
371         this.currentTextIndex++;
372         this.currentWordIndex = 0;
373         // keep going if we're not yet past the last text element
374         if( this.currentTextIndex < this.wordWin.textInputs.length ) {
375             this._spellcheck();
376             return;
377         } else {
378             this.terminateSpell();
379             return;
380         }
381     }
383     // if this is after the first one make sure the Undo button is enabled
384     if( this.currentWordIndex > 0 ) {
385         this.controlWin.enableUndo();
386     }
388     // skip the current word if it has already been worked on
389     if( this.wordFlags[this.currentTextIndex][this.currentWordIndex] ) {
390         // increment the global current word index and move on.
391         this.currentWordIndex++;
392         this._spellcheck();
393     } else {
394         var evalText = ww.getTextVal( this.currentTextIndex, this.currentWordIndex );
395         if( evalText ) {
396             this.controlWin.evaluatedText.value = evalText;
397             ww.setFocus( this.currentTextIndex, this.currentWordIndex );
398             this._getSuggestions( this.currentTextIndex, this.currentWordIndex );
399         }
400     }
403 function _getSuggestions( text_num, word_num ) {
404     this.controlWin.clearSuggestions();
405     // add suggestion in list for each suggested word.
406     // get the array of suggested words out of the
407     // three-dimensional array containing all suggestions.
408     var a_suggests = this.wordWin.suggestions[text_num][word_num];
409     if( a_suggests ) {
410         // got an array of suggestions.
411         for( var ii = 0; ii < a_suggests.length; ii++ ) {
412             this.controlWin.addSuggestion( a_suggests[ii] );
413         }
414     }
415     this.controlWin.selectDefaultSuggestion();
418 function _setAsIgnored( text_num, word_num, flag ) {
419     // set the UI
420     this.wordWin.removeFocus( text_num, word_num );
421     // do the bookkeeping
422     this.wordFlags[text_num][word_num] = flag;
423     return true;
426 function _getTotalReplaced() {
427     var i_replaced = 0;
428     for( var i = 0; i < this.wordFlags.length; i++ ) {
429         for( var j = 0; j < this.wordFlags[i].length; j++ ) {
430             if(( this.wordFlags[i][j] == this.replWordFlag )
431             || ( this.wordFlags[i][j] == this.replAllFlag )
432             || ( this.wordFlags[i][j] == this.fromReplAll )) {
433                 i_replaced++;
434             }
435         }
436     }
437     return i_replaced;
440 function _setWordText( text_num, word_num, newText, flag ) {
441     // set the UI and form inputs
442     this.wordWin.setText( text_num, word_num, newText );
443     // keep track of what happened to this word:
444     this.wordFlags[text_num][word_num] = flag;
445     return true;
448 function _getFormInputs( inputPattern ) {
449     var inputs = new Array();
450     for( var i = 0; i < document.forms.length; i++ ) {
451         for( var j = 0; j < document.forms[i].elements.length; j++ ) {
452             if( document.forms[i].elements[j].type.match( inputPattern )) {
453                 inputs[inputs.length] = document.forms[i].elements[j];
454             }
455         }
456     }
457     return inputs;