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