1 ////////////////////////////////////////////////////
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.
9 // Modified by LUDO (Marc Alier) for integration with the moogle environment
10 // august 2004 malier@lsi.upc.es
12 ////////////////////////////////////////////////////
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;
38 this.textArea
= textObject
; // deprecated
39 this.textInputs
= arguments
;
41 this._editor
=""; // BY LUDO
43 this._spellcheck
= _spellcheck
;
44 this._getSuggestions
= _getSuggestions
;
45 this._setAsIgnored
= _setAsIgnored
;
46 this._getTotalReplaced
= _getTotalReplaced
;
47 this._setWordText
= _setWordText
;
48 this._getFormInputs
= _getFormInputs
;
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
;
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$" );
74 // call this method to check all textareas (and only textareas ) in the HTML document
75 function checkTextAreas() {
76 this.textInputs
= this._getFormInputs( "^textarea$" );
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)?$" );
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
;
95 function startCheck( wordWindowObj
, controlWindowObj
) {
97 // set properties from args
98 this.wordWin
= wordWindowObj
;
99 this.controlWin
= controlWindowObj
;
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
] = [];
119 function ignoreWord() {
120 var wi
= this.currentWordIndex
;
121 var ti
= this.currentTextIndex
;
122 if( !this.wordWin
) {
123 alert( 'Error: Word frame not available.' );
126 if( !this.wordWin
.getTextVal( ti
, wi
)) {
127 alert( 'Error: "Not in dictionary" text is missing.' );
131 if( this._setAsIgnored( ti
, wi
, this.ignrWordFlag
)) {
132 this.currentWordIndex
++;
137 function ignoreAll() {
138 var wi
= this.currentWordIndex
;
139 var ti
= this.currentTextIndex
;
140 if( !this.wordWin
) {
141 alert( 'Error: Word frame not available.' );
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' );
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
);
170 this.currentWordIndex
++;
174 function replaceWord() {
175 var wi
= this.currentWordIndex
;
176 var ti
= this.currentTextIndex
;
177 if( !this.wordWin
) {
178 alert( 'Error: Word frame not available.' );
181 if( !this.wordWin
.getTextVal( ti
, wi
)) {
182 alert( 'Error: "Not in dictionary" text is missing' );
185 if( !this.controlWin
.replacementText
) {
188 var txt
= this.controlWin
.replacementText
;
190 var newspell
= new String( txt
.value
);
191 if( this._setWordText( ti
, wi
, newspell
, this.replWordFlag
)) {
192 this.currentWordIndex
++;
198 function replaceAll() {
199 var ti
= this.currentTextIndex
;
200 var wi
= this.currentWordIndex
;
201 if( !this.wordWin
) {
202 alert( 'Error: Word frame not available.' );
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' );
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
);
233 this.currentWordIndex
++;
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();
242 // see if there were no misspellings to begin with
243 if( !this.wordWin
) {
246 if( this.wordWin
.totalMisspellings() ) {
247 msg
+= "No words changed.";
249 msg
+= "No misspellings found.";
252 } else if( numrepl
== 1 ) {
253 msg
+= "One word changed.";
255 msg
+= numrepl
+ " words changed.";
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;
267 if( this.wordWin
.textInputs
[i
] ) {
268 this.textInputs
[i
].value
= this.wordWin
.textInputs
[i
];
274 this._editor
.setHTML(this._editor
._textArea
.value
);
276 // If were not in editor, just continue.
281 // return back to the calling window
282 this.spellCheckerWin
.close();
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
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;
303 if( this.currentWordIndex
> 0 ) {
304 this.currentWordIndex
--;
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
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();
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 );
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;
354 // replace: revert the word to its original spelling
355 case this.replWordFlag
:
356 this._setWordText ( text_idx
, idx
, preReplSpell
, undefined );
360 // For all four cases, clear the wordFlag of this word. re-start the process
361 this.wordFlags
[text_idx
][idx
] = undefined;
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
) {
378 this.terminateSpell();
383 // if this is after the first one make sure the Undo button is enabled
384 if( this.currentWordIndex
> 0 ) {
385 this.controlWin
.enableUndo();
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
++;
394 var evalText
= ww
.getTextVal( this.currentTextIndex
, this.currentWordIndex
);
396 this.controlWin
.evaluatedText
.value
= evalText
;
397 ww
.setFocus( this.currentTextIndex
, this.currentWordIndex
);
398 this._getSuggestions( this.currentTextIndex
, this.currentWordIndex
);
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
];
410 // got an array of suggestions.
411 for( var ii
= 0; ii
< a_suggests
.length
; ii
++ ) {
412 this.controlWin
.addSuggestion( a_suggests
[ii
] );
415 this.controlWin
.selectDefaultSuggestion();
418 function _setAsIgnored( text_num
, word_num
, flag
) {
420 this.wordWin
.removeFocus( text_num
, word_num
);
421 // do the bookkeeping
422 this.wordFlags
[text_num
][word_num
] = flag
;
426 function _getTotalReplaced() {
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
)) {
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
;
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
];