// 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) + '' + misps[wordindex].word + '' + htmlspecialchars(strend); setInnerHTML(divptr, newValue.replace(/_\|_/g, '
')); // 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, "
")); 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(/\n/g, "
"); 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(); }