332c62cdbdbd923d79ba27c35b8d1ead2e375526
4 * This JavaScript app is the driving power of the SquirrelSpell's
5 * main spellchecker window. Hope you have as much pain figuring
6 * it out as it took to write. ;))
8 * @copyright 1999-2020 The SquirrelMail Project Team
9 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
14 var CurrentLocation
=0;
18 var ChangesMade
=false;
21 * This function loads spellchecking errors into the form
22 * displayed to the user.
26 function populateSqspellForm(){
27 CurrentWord
=Word
=misses
[CurrentError
];
28 WordLocations
= locations
[CurrentError
].split(", ");
29 CurrentLoc
= WordLocations
[CurrentLocation
];
30 if(CurrentLocation
==WordLocations
.length
-1) {
36 tmp
= CurrentLoc
.split(":");
37 CurrentLine
=parseInt(tmp
[0]);
38 CurrentSymbol
=parseInt(tmp
[1]);
39 document
.forms
[0].sqspell_error
.value
=Word
;
40 LineValue
=sqspell_lines
[CurrentLine
];
43 if (CurrentSymbol
> 40){
44 StartWith
=CurrentSymbol
-40;
47 EndWith
=LineValue
.length
;
49 if (EndWith
> CurrentSymbol
+ 40){
50 EndWith
=CurrentSymbol
+40;
53 NewLineValue
+=LineValue
.substring(StartWith
, CurrentSymbol
) + "*" + Word
+ "*" + LineValue
.substring(CurrentSymbol
+ Word
.length
, EndWith
) + EndLine
;
54 document
.forms
[0].sqspell_line_area
.value
=NewLineValue
;
56 if (suggestions
[CurrentError
]){
57 WordSuggestions
= suggestions
[CurrentError
].split(", ");
58 for (i
=0; i
<WordSuggestions
.length
; i
++){
59 document
.forms
[0].sqspell_suggestion
.options
[i
] = new Option(WordSuggestions
[i
], WordSuggestions
[i
]);
62 document
.forms
[0].sqspell_suggestion
.options
[0] = new Option("No Suggestions", "_NONE");
63 document
.forms
[0].sqspell_oruse
.value
=Word
;
64 document
.forms
[0].sqspell_oruse
.focus();
65 document
.forms
[0].sqspell_oruse
.select();
68 document
.forms
[0].sqspell_suggestion
.selectedIndex
=0;
69 if (!document
.forms
[0].sqspell_oruse
.value
)
70 document
.forms
[0].sqspell_oruse
.value
=document
.forms
[0].sqspell_suggestion
.options
[document
.forms
[0].sqspell_suggestion
.selectedIndex
].value
;
71 occursTimes
= WordLocations
.length
;
72 if (CurrentLocation
) occursTimes
+= CurrentLocation
-1;
73 document
.forms
[0].sqspell_likethis
.value
=occursTimes
;
79 * This function updates a line from the message with a new value,
80 * received from the user.
82 * @param lLine line number.
83 * @param lSymbol symbol at which the misspelled word starts.
84 * @param lWord misspelled word
85 * @param lNewWord corrected word
88 function updateLine(lLine
, lSymbol
, lWord
, lNewWord
){
89 sqspell_lines
[lLine
] = sqspell_lines
[lLine
].substring(0, lSymbol
) + lNewWord
+ sqspell_lines
[lLine
].substring(lSymbol
+lWord
.length
, sqspell_lines
[lLine
].length
);
90 if (lWord
.length
!= lNewWord
.length
)
91 updateSymbol(lLine
, lSymbol
, lNewWord
.length
-lWord
.length
);
92 if (!ChangesMade
) ChangesMade
=true;
96 * This function is used to add a word user wishes to place in his/her
97 * user dictionary to the form field for later submission. Since there
98 * is no sane way to pass arrays between javascript and PHP, all words
99 * are concatenated into one strings and separated with a "%".
103 function sqspellRemember(){
104 CurrentWord
= misses
[CurrentError
] + "%";
105 document
.forms
[0].words
.value
+= CurrentWord
;
107 * Now ignore all occurances of this word.
113 * This function is called when the "Change" button is pressed.
117 function sqspellChange(){
118 CurrentWord
= misses
[CurrentError
];
119 NewWord
=document
.forms
[0].sqspell_oruse
.value
;
120 updateLine(CurrentLine
, CurrentSymbol
, CurrentWord
, NewWord
);
125 * This function is called when the "Change All" button is pressed.
129 function sqspellChangeAll(){
130 // Called when pressed the "Change All" button
131 allLoc
= locations
[CurrentError
].split(", ");
132 if (allLoc
.length
==1) {
134 * There's no need to "change all", only one occurance of this
135 * word in the whole text.
143 NewWord
=document
.forms
[0].sqspell_oruse
.value
;
144 CurrentWord
= misses
[CurrentError
];
145 for (z
=CurrentLocation
-1; z
<allLoc
.length
; z
++){
146 tmp
= allLoc
[z
].split(":");
147 lLine
= parseInt(tmp
[0]); lSymbol
= parseInt(tmp
[1]);
148 updateLine(lLine
, lSymbol
, CurrentWord
, NewWord
);
150 * Load it again to reflect the changes in symbol data
152 allLoc
= locations
[CurrentError
].split(", ");
159 * This function is only here for consistency. It is called when
160 * "Ignore" is pressed.
164 function sqspellIgnore(){
169 * This function is called when the "Ignore All" button is pressed.
173 function sqspellIgnoreAll(){
179 * This function clears the options in a select box "sqspell_suggestions".
183 function clearSqspellForm(){
184 for (i
=0; i
<document
.forms
[0].sqspell_suggestion
.length
; i
++){
185 document
.forms
[0].sqspell_suggestion
.options
[i
]=null;
189 * Now, I've been instructed by the Netscape Developer docs to call
190 * history.go(0) to refresh the page after I've changed the options.
191 * However, that brings so many pains with it that I just decided not
192 * to do it. It works like it is in Netscape 4.x. If there are problems
193 * in earlier versions of Netscape, then oh well. I'm not THAT anxious
194 * to have it working on all browsers... ;)
196 document
.forms
[0].sqspell_oruse
.value
="";
200 * This function goes on to the next error, or finishes nicely if
201 * no more errors are available.
206 if (!CurrentLocation
) CurrentError
++;
207 if (misses
[CurrentError
]){
209 populateSqspellForm();
211 if (ChangesMade
|| document
.forms
[0].words
.value
){
212 if (confirm(ui_completed
))
213 sqspellCommitChanges();
216 confirm (ui_nochange
);
223 * This function updates the symbol locations after there have been
224 * word length changes in the lines. Otherwise SquirrelSpell barfs all
225 * over your message... ;)
227 * @param lLine line number on which the error occurs
228 * @param lSymbol symbol number at which error occurs
229 * @param difference the difference in length between the old word
230 * and the new word. Can be negative or positive.
233 function updateSymbol(lLine
, lSymbol
, difference
){
235 * Now, I will admit that this is not the best way to do stuff,
236 * However that's the solution I've come up with.
238 * If you are wondering why I didn't use two-dimensional arrays instead,
239 * well, sometimes there will be a long line with an error close to the
240 * end of it, so the coordinates would be something like 2,98 and
241 * some Javascript implementations will create 98 empty members of an
242 * array just to have a filled number 98. This is too resource-wasteful
243 * and I have decided to go with the below solution instead. It takes
244 * a little more processing, but it saves a lot on memory.
246 * It just looks heinous. In real life it's really nice and sane. ;)
249 for (i
=0; i
<misses
.length
; i
++){
250 if(locations
[i
].indexOf(lLine
+ ":") >= 0){
251 allLoc
= locations
[i
].split(", ");
252 for (j
=0; j
<allLoc
.length
; j
++){
253 if (allLoc
[j
].indexOf(lLine
+":")==0){
254 tmp
= allLoc
[j
].split(":");
255 tmp
[0] = parseInt(tmp
[0]); tmp
[1] = parseInt(tmp
[1]);
256 if (tmp
[1] > lSymbol
){
257 tmp
[1] = tmp
[1] + difference
;
258 allLoc
[j
] = tmp
.join(":");
262 locations
[i
] = allLoc
.join(", ");
268 * This function writes the changes back into the compose form.
272 function sqspellCommitChanges(){
273 newSubject
= sqspell_lines
[0];
275 for (i
=1; i
<sqspell_lines
.length
; i
++){
276 if (i
!=1) newBody
+="\r\n";
277 newBody
+= sqspell_lines
[i
];
280 opener
.document
.compose
.subject
.value
=newSubject
;
281 opener
.document
.compose
.body
.value
=newBody
;
284 * See if any words were added to the dictionary.
286 if (document
.forms
[0].words
.value
){
290 document
.forms
[0].sqspell_line_area
.value
=ui_wait
;
292 * pass focus to the parent so we can do background save.
294 window
.opener
.focus();
295 document
.forms
[0].submit();