Chris@76
|
1 // These are variables the popup is going to want to access...
|
Chris@76
|
2 var spell_formname, spell_fieldname;
|
Chris@76
|
3
|
Chris@76
|
4 // Spell check the specified field in the specified form.
|
Chris@76
|
5 function spellCheck(formName, fieldName)
|
Chris@76
|
6 {
|
Chris@76
|
7 // Grab the (hidden) spell checking form.
|
Chris@76
|
8 var spellform = document.forms.spell_form;
|
Chris@76
|
9
|
Chris@76
|
10 // Register the name of the editing form for future reference.
|
Chris@76
|
11 spell_formname = formName;
|
Chris@76
|
12 spell_fieldname = fieldName;
|
Chris@76
|
13
|
Chris@76
|
14 // This should match a word (most of the time).
|
Chris@76
|
15 var regexpWordMatch = /(?:<[^>]+>)|(?:\[[^ ][^\]]*\])|(?:&[^; ]+;)|(?:[^0-9\s\]\[{};:"\\|,<.>\/?`~!@#$%^&*()_+=]+)/g;
|
Chris@76
|
16
|
Chris@76
|
17 // These characters can appear within words.
|
Chris@76
|
18 var aWordCharacters = ['-', '\''];
|
Chris@76
|
19
|
Chris@76
|
20 var aWords = new Array(), aResult = new Array();
|
Chris@76
|
21 var sText = document.forms[formName][fieldName].value;
|
Chris@76
|
22 var bInCode = false;
|
Chris@76
|
23 var iOffset1, iOffset2;
|
Chris@76
|
24
|
Chris@76
|
25 // Loop through all words.
|
Chris@76
|
26 while ((aResult = regexpWordMatch.exec(sText)) && typeof(aResult) != 'undefined')
|
Chris@76
|
27 {
|
Chris@76
|
28 iOffset1 = 0;
|
Chris@76
|
29 iOffset2 = aResult[0].length - 1;
|
Chris@76
|
30
|
Chris@76
|
31 // Strip the dashes and hyphens from the begin of the word.
|
Chris@76
|
32 while (in_array(aResult[0].charAt(iOffset1), aWordCharacters) && iOffset1 < iOffset2)
|
Chris@76
|
33 iOffset1++;
|
Chris@76
|
34
|
Chris@76
|
35 // Strip the dashes and hyphens from the end of the word.
|
Chris@76
|
36 while (in_array(aResult[0].charAt(iOffset2), aWordCharacters) && iOffset1 < iOffset2)
|
Chris@76
|
37 iOffset2--;
|
Chris@76
|
38
|
Chris@76
|
39 // I guess there's only dashes and hyphens in this word...
|
Chris@76
|
40 if (iOffset1 == iOffset2)
|
Chris@76
|
41 continue;
|
Chris@76
|
42
|
Chris@76
|
43 // Ignore code blocks.
|
Chris@76
|
44 if (aResult[0].substr(0, 5).toLowerCase() == '[code')
|
Chris@76
|
45 bInCode = true;
|
Chris@76
|
46
|
Chris@76
|
47 // Glad we're out of that code block!
|
Chris@76
|
48 else if (bInCode && aResult[0].substr(0, 7).toLowerCase() == '[/code]')
|
Chris@76
|
49 bInCode = false;
|
Chris@76
|
50
|
Chris@76
|
51 // Now let's get to business.
|
Chris@76
|
52 else if (!bInCode && !in_array(aResult[0].charAt(0), ['[', '<']) && aResult[0].toUpperCase() != aResult[0])
|
Chris@76
|
53 aWords[aWords.length] = aResult[0].substr(iOffset1, iOffset2 - iOffset1 + 1) + '|' + (iOffset1 + sText.substr(0, aResult.index).length) + '|' + (iOffset2 + sText.substr(0, aResult.index).length);
|
Chris@76
|
54 }
|
Chris@76
|
55
|
Chris@76
|
56 // Open the window...
|
Chris@76
|
57 openSpellWin(640, 480);
|
Chris@76
|
58
|
Chris@76
|
59 // Pass the data to a form...
|
Chris@76
|
60 spellform.spellstring.value = aWords.join('\n');
|
Chris@76
|
61
|
Chris@76
|
62 // and go!
|
Chris@76
|
63 spellform.submit();
|
Chris@76
|
64
|
Chris@76
|
65 return true;
|
Chris@76
|
66 }
|
Chris@76
|
67
|
Chris@76
|
68 // Private functions -------------------------------
|
Chris@76
|
69
|
Chris@76
|
70 // Globals...
|
Chris@76
|
71 var wordindex = -1, offsetindex = 0;
|
Chris@76
|
72 var ignoredWords = [];
|
Chris@76
|
73
|
Chris@76
|
74 // A "misspelled word" object.
|
Chris@76
|
75 function misp(word, start, end, suggestions)
|
Chris@76
|
76 {
|
Chris@76
|
77 // The word, start index, end index, and array of suggestions.
|
Chris@76
|
78 this.word = word;
|
Chris@76
|
79 this.start = start;
|
Chris@76
|
80 this.end = end;
|
Chris@76
|
81 this.suggestions = suggestions;
|
Chris@76
|
82 }
|
Chris@76
|
83
|
Chris@76
|
84 // Replace the word in the misps array at the "wordindex" index. The
|
Chris@76
|
85 // misps array is generated by a PHP script after the string to be spell
|
Chris@76
|
86 // checked is evaluated with pspell.
|
Chris@76
|
87 function replaceWord()
|
Chris@76
|
88 {
|
Chris@76
|
89 var strstart = "";
|
Chris@76
|
90 var strend;
|
Chris@76
|
91
|
Chris@76
|
92 // If this isn't the beginning of the string then get all of the string
|
Chris@76
|
93 // that is before the word we are replacing.
|
Chris@76
|
94 if (misps[wordindex].start != 0)
|
Chris@76
|
95 strstart = mispstr.slice(0, misps[wordindex].start + offsetindex);
|
Chris@76
|
96
|
Chris@76
|
97 // Get the end of the string after the word we are replacing.
|
Chris@76
|
98 strend = mispstr.slice(misps[wordindex].end + 1 + offsetindex);
|
Chris@76
|
99
|
Chris@76
|
100 // Rebuild the string with the new word.
|
Chris@76
|
101 mispstr = strstart + document.forms.spellingForm.changeto.value + strend;
|
Chris@76
|
102
|
Chris@76
|
103 // Update offsetindex to compensate for replacing a word with a word
|
Chris@76
|
104 // of a different length.
|
Chris@76
|
105 offsetindex += document.forms.spellingForm.changeto.value.length - misps[wordindex].word.length;
|
Chris@76
|
106
|
Chris@76
|
107 // Update the word so future replaceAll calls don't change it.
|
Chris@76
|
108 misps[wordindex].word = document.forms.spellingForm.changeto.value;
|
Chris@76
|
109
|
Chris@76
|
110 nextWord(false);
|
Chris@76
|
111 }
|
Chris@76
|
112
|
Chris@76
|
113 // Replaces all instances of currently selected word with contents chosen by user.
|
Chris@76
|
114 // Note: currently only replaces words after highlighted word. I think we can re-index
|
Chris@76
|
115 // all words at replacement or ignore time to have it wrap to the beginning if we want
|
Chris@76
|
116 // to.
|
Chris@76
|
117 function replaceAll()
|
Chris@76
|
118 {
|
Chris@76
|
119 var strend;
|
Chris@76
|
120 var idx;
|
Chris@76
|
121 var origword;
|
Chris@76
|
122 var localoffsetindex = offsetindex;
|
Chris@76
|
123
|
Chris@76
|
124 origword = misps[wordindex].word;
|
Chris@76
|
125
|
Chris@76
|
126 // Re-index everything past the current word.
|
Chris@76
|
127 for (idx = wordindex; idx < misps.length; idx++)
|
Chris@76
|
128 {
|
Chris@76
|
129 misps[idx].start += localoffsetindex;
|
Chris@76
|
130 misps[idx].end += localoffsetindex;
|
Chris@76
|
131 }
|
Chris@76
|
132
|
Chris@76
|
133 localoffsetindex = 0;
|
Chris@76
|
134
|
Chris@76
|
135 for (idx = 0; idx < misps.length; idx++)
|
Chris@76
|
136 {
|
Chris@76
|
137 if (misps[idx].word == origword)
|
Chris@76
|
138 {
|
Chris@76
|
139 var strstart = "";
|
Chris@76
|
140 if (misps[idx].start != 0)
|
Chris@76
|
141 strstart = mispstr.slice(0, misps[idx].start + localoffsetindex);
|
Chris@76
|
142
|
Chris@76
|
143 // Get the end of the string after the word we are replacing.
|
Chris@76
|
144 strend = mispstr.slice(misps[idx].end + 1 + localoffsetindex);
|
Chris@76
|
145
|
Chris@76
|
146 // Rebuild the string with the new word.
|
Chris@76
|
147 mispstr = strstart + document.forms.spellingForm.changeto.value + strend;
|
Chris@76
|
148
|
Chris@76
|
149 // Update offsetindex to compensate for replacing a word with a word
|
Chris@76
|
150 // of a different length.
|
Chris@76
|
151 localoffsetindex += document.forms.spellingForm.changeto.value.length - misps[idx].word.length;
|
Chris@76
|
152 }
|
Chris@76
|
153
|
Chris@76
|
154 // We have to re-index everything after replacements.
|
Chris@76
|
155 misps[idx].start += localoffsetindex;
|
Chris@76
|
156 misps[idx].end += localoffsetindex;
|
Chris@76
|
157 }
|
Chris@76
|
158
|
Chris@76
|
159 // Add the word to the ignore array.
|
Chris@76
|
160 ignoredWords[origword] = true;
|
Chris@76
|
161
|
Chris@76
|
162 // Reset offsetindex since we re-indexed.
|
Chris@76
|
163 offsetindex = 0;
|
Chris@76
|
164
|
Chris@76
|
165 nextWord(false);
|
Chris@76
|
166 }
|
Chris@76
|
167
|
Chris@76
|
168 // Highlight the word that was selected using the nextWord function.
|
Chris@76
|
169 function highlightWord()
|
Chris@76
|
170 {
|
Chris@76
|
171 var strstart = "";
|
Chris@76
|
172 var strend;
|
Chris@76
|
173
|
Chris@76
|
174 // If this isn't the beginning of the string then get all of the string
|
Chris@76
|
175 // that is before the word we are replacing.
|
Chris@76
|
176 if (misps[wordindex].start != 0)
|
Chris@76
|
177 strstart = mispstr.slice(0, misps[wordindex].start + offsetindex);
|
Chris@76
|
178
|
Chris@76
|
179 // Get the end of the string after the word we are replacing.
|
Chris@76
|
180 strend = mispstr.slice(misps[wordindex].end + 1 + offsetindex);
|
Chris@76
|
181
|
Chris@76
|
182 // Rebuild the string with a span wrapped around the misspelled word
|
Chris@76
|
183 // so we can highlight it in the div the user is viewing the string in.
|
Chris@76
|
184 var divptr, newValue;
|
Chris@76
|
185 divptr = document.getElementById("spellview");
|
Chris@76
|
186
|
Chris@76
|
187 newValue = htmlspecialchars(strstart) + '<span class="highlight" id="h1">' + misps[wordindex].word + '</span>' + htmlspecialchars(strend);
|
Chris@76
|
188 setInnerHTML(divptr, newValue.replace(/_\|_/g, '<br />'));
|
Chris@76
|
189
|
Chris@76
|
190 // We could use scrollIntoView, but it's just not that great anyway.
|
Chris@76
|
191 var spellview_height = typeof(document.getElementById("spellview").currentStyle) != "undefined" ? parseInt(document.getElementById("spellview").currentStyle.height) : document.getElementById("spellview").offsetHeight;
|
Chris@76
|
192 var word_position = document.getElementById("h1").offsetTop;
|
Chris@76
|
193 var current_position = document.getElementById("spellview").scrollTop;
|
Chris@76
|
194
|
Chris@76
|
195 // The spellview is not tall enough! Scroll down!
|
Chris@76
|
196 if (spellview_height <= (word_position + current_position))
|
Chris@76
|
197 document.getElementById("spellview").scrollTop = word_position + current_position - spellview_height + 32;
|
Chris@76
|
198 }
|
Chris@76
|
199
|
Chris@76
|
200 // Display the next misspelled word to the user and populate the suggested spellings box.
|
Chris@76
|
201 function nextWord(ignoreall)
|
Chris@76
|
202 {
|
Chris@76
|
203 // Push ignored word onto ignoredWords array.
|
Chris@76
|
204 if (ignoreall)
|
Chris@76
|
205 ignoredWords[misps[wordindex].word] = true;
|
Chris@76
|
206
|
Chris@76
|
207 // Update the index of all words we have processed...
|
Chris@76
|
208 // This must be done to accomodate the replaceAll function.
|
Chris@76
|
209 if (wordindex >= 0)
|
Chris@76
|
210 {
|
Chris@76
|
211 misps[wordindex].start += offsetindex;
|
Chris@76
|
212 misps[wordindex].end += offsetindex;
|
Chris@76
|
213 }
|
Chris@76
|
214
|
Chris@76
|
215 // Increment the counter for the array of misspelled words.
|
Chris@76
|
216 wordindex++;
|
Chris@76
|
217
|
Chris@76
|
218 // Draw it and quit if there are no more misspelled words to evaluate.
|
Chris@76
|
219 if (misps.length <= wordindex)
|
Chris@76
|
220 {
|
Chris@76
|
221 var divptr;
|
Chris@76
|
222 divptr = document.getElementById("spellview");
|
Chris@76
|
223 setInnerHTML(divptr, htmlspecialchars(mispstr).replace(/_\|_/g, "<br />"));
|
Chris@76
|
224
|
Chris@76
|
225 while (document.forms.spellingForm.suggestions.options.length > 0)
|
Chris@76
|
226 document.forms.spellingForm.suggestions.options[0] = null;
|
Chris@76
|
227
|
Chris@76
|
228 alert(txt['done']);
|
Chris@76
|
229 document.forms.spellingForm.change.disabled = true;
|
Chris@76
|
230 document.forms.spellingForm.changeall.disabled = true;
|
Chris@76
|
231 document.forms.spellingForm.ignore.disabled = true;
|
Chris@76
|
232 document.forms.spellingForm.ignoreall.disabled = true;
|
Chris@76
|
233
|
Chris@76
|
234 // Put line feeds back...
|
Chris@76
|
235 mispstr = mispstr.replace(/_\|_/g, "\n");
|
Chris@76
|
236
|
Chris@76
|
237 // Get a handle to the field we need to re-populate.
|
Chris@76
|
238 window.opener.document.forms[spell_formname][spell_fieldname].value = mispstr;
|
Chris@76
|
239 if (!window.opener.spellCheckDone)
|
Chris@76
|
240 window.opener.document.forms[spell_formname][spell_fieldname].focus();
|
Chris@76
|
241 else
|
Chris@76
|
242 window.opener.spellCheckDone();
|
Chris@76
|
243
|
Chris@76
|
244 window.close();
|
Chris@76
|
245 return true;
|
Chris@76
|
246 }
|
Chris@76
|
247
|
Chris@76
|
248 // Check to see if word is supposed to be ignored.
|
Chris@76
|
249 if (typeof(ignoredWords[misps[wordindex].word]) != "undefined")
|
Chris@76
|
250 {
|
Chris@76
|
251 nextWord(false);
|
Chris@76
|
252 return false;
|
Chris@76
|
253 }
|
Chris@76
|
254
|
Chris@76
|
255 // Clear out the suggestions box!
|
Chris@76
|
256 while (document.forms.spellingForm.suggestions.options.length > 0)
|
Chris@76
|
257 document.forms.spellingForm.suggestions.options[0] = null;
|
Chris@76
|
258
|
Chris@76
|
259 // Re-populate the suggestions box if there are any suggested spellings for the word.
|
Chris@76
|
260 if (misps[wordindex].suggestions.length)
|
Chris@76
|
261 {
|
Chris@76
|
262 for (var sugidx = 0; sugidx < misps[wordindex].suggestions.length; sugidx++)
|
Chris@76
|
263 {
|
Chris@76
|
264 var newopt = new Option(misps[wordindex].suggestions[sugidx], misps[wordindex].suggestions[sugidx]);
|
Chris@76
|
265 document.forms.spellingForm.suggestions.options[sugidx] = newopt;
|
Chris@76
|
266
|
Chris@76
|
267 if (sugidx == 0)
|
Chris@76
|
268 {
|
Chris@76
|
269 newopt.selected = true;
|
Chris@76
|
270 document.forms.spellingForm.changeto.value = newopt.value;
|
Chris@76
|
271 document.forms.spellingForm.changeto.select();
|
Chris@76
|
272 }
|
Chris@76
|
273 }
|
Chris@76
|
274 }
|
Chris@76
|
275
|
Chris@76
|
276 if (document.forms.spellingForm.suggestions.options.length == 0)
|
Chris@76
|
277 document.forms.spellingForm.changeto.value = "";
|
Chris@76
|
278
|
Chris@76
|
279 highlightWord();
|
Chris@76
|
280
|
Chris@76
|
281 return false;
|
Chris@76
|
282 }
|
Chris@76
|
283
|
Chris@76
|
284 function htmlspecialchars(thetext)
|
Chris@76
|
285 {
|
Chris@76
|
286 thetext = thetext.replace(/\</g, "<");
|
Chris@76
|
287 thetext = thetext.replace(/\>/g, ">");
|
Chris@76
|
288 thetext = thetext.replace(/\n/g, "<br />");
|
Chris@76
|
289 thetext = thetext.replace(/\ \ /g, " ");
|
Chris@76
|
290
|
Chris@76
|
291 return thetext;
|
Chris@76
|
292 }
|
Chris@76
|
293
|
Chris@76
|
294 function openSpellWin(width, height)
|
Chris@76
|
295 {
|
Chris@76
|
296 window.open("", "spellWindow", "toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=yes,resizable=no,width=" + width + ",height=" + height);
|
Chris@76
|
297 } |