1 // Spell Checker Plugin for HTMLArea-3.0
2 // Implementation by Mihai Bazon. Sponsored by www.americanbible.org
4 // htmlArea v3.0 - Copyright (c) 2002 interactivetools.com, inc.
5 // This notice MUST stay intact for use (see license.txt).
7 // A free WYSIWYG editor replacement for <textarea> fields.
8 // For full source code and docs, visit http://www.interactivetools.com/
10 // Version 3.0 developed by Mihai Bazon for InteractiveTools.
11 // http://students.infoiasi.ro/~mishoo
15 // internationalization file was already loaded in parent ;-)
16 var SpellChecker = window.opener.SpellChecker;
17 var i18n = SpellChecker.I18N;
19 var is_ie = window.opener.HTMLArea.is_ie;
20 var editor = SpellChecker.editor;
22 var currentElement = null;
23 var wrongWords = null;
27 function makeCleanDoc(leaveFixed) {
28 // document.getElementById("status").innerHTML = 'Please wait: rendering valid HTML';
29 for (var i in wrongWords) {
30 var el = wrongWords[i];
31 if (!(leaveFixed && /HA-spellcheck-fixed/.test(el.className))) {
32 el.parentNode.insertBefore(el.firstChild, el);
33 el.parentNode.removeChild(el.nextSibling);
34 el.parentNode.removeChild(el);
36 el.className = "HA-spellcheck-fixed";
37 el.parentNode.removeChild(el.nextSibling);
40 // we should use innerHTML here, but IE6's implementation phucks up the
41 // HTML to such extent that our poor Perl parser doesn't understand it
43 return window.opener.HTMLArea.getHTML(frame.contentWindow.document.body, leaveFixed);
46 function recheckClicked() {
47 document.getElementById("status").innerHTML = i18n["Please wait: changing dictionary to"] + ': "' + document.getElementById("f_dictionary").value + '".';
48 var field = document.getElementById("f_content");
49 field.value = makeCleanDoc(true);
53 function saveClicked() {
55 editor.setHTML(makeCleanDoc(false));
61 function cancelClicked() {
64 ok = confirm(i18n["QUIT_CONFIRMATION"]);
72 function replaceWord(el) {
73 var replacement = document.getElementById("v_replacement").value;
74 modified = (el.innerHTML != replacement);
76 el.className = el.className.replace(/\s*HA-spellcheck-(hover|fixed)\s*/g, " ");
78 el.className += " HA-spellcheck-fixed";
79 el.__msh_fixed = true;
83 el.innerHTML = replacement;
86 function replaceClicked() {
87 replaceWord(currentElement);
88 var start = currentElement.__msh_id;
92 if (index == wrongWords.length) {
95 } while ((index != start) && wrongWords[index].__msh_fixed);
98 alert(i18n["Finished list of mispelled words"]);
100 wrongWords[index].onclick();
104 function replaceAllClicked() {
105 var replacement = document.getElementById("v_replacement").value;
107 var spans = allWords[currentElement.__msh_origWord];
108 if (spans.length == 0) {
109 alert("An impossible condition just happened. Call FBI. ;-)");
110 } else if (spans.length == 1) {
115 var message = "The word \"" + currentElement.__msh_origWord + "\" occurs " + spans.length + " times.\n";
116 if (replacement == currentElement.__msh_origWord) {
117 ok = confirm(message + "Ignore all occurrences?");
119 ok = confirm(message + "Replace all occurrences with \"" + replacement + "\"?");
123 for (var i in spans) {
124 if (spans[i] != currentElement) {
125 replaceWord(spans[i]);
128 // replace current element the last, so that we jump to the next word ;-)
134 function ignoreClicked() {
135 document.getElementById("v_replacement").value = currentElement.__msh_origWord;
140 function ignoreAllClicked() {
141 document.getElementById("v_replacement").value = currentElement.__msh_origWord;
146 function learnClicked() {
147 alert("Not [yet] implemented");
151 function internationalizeWindow() {
152 var types = ["div", "span", "button"];
153 for (var i in types) {
155 var els = document.getElementsByTagName(tag);
156 for (var j = els.length; --j >= 0;) {
158 if (el.childNodes.length == 1 && /\S/.test(el.innerHTML)) {
159 var txt = el.innerHTML;
160 if (typeof i18n[txt] != "undefined") {
161 el.innerHTML = i18n[txt];
168 function initDocument() {
169 internationalizeWindow();
171 frame = document.getElementById("i_framecontent");
172 var field = document.getElementById("f_content");
173 field.value = editor.getHTML();
175 document.getElementById("f_init").value = "0";
177 // assign some global event handlers
179 var select = document.getElementById("v_suggestions");
180 select.onchange = function() {
181 document.getElementById("v_replacement").value = this.value;
184 select.attachEvent("ondblclick", replaceClicked);
186 select.addEventListener("dblclick", replaceClicked, true);
189 document.getElementById("b_replace").onclick = replaceClicked;
190 // document.getElementById("b_learn").onclick = learnClicked;
191 document.getElementById("b_replall").onclick = replaceAllClicked;
192 document.getElementById("b_ignore").onclick = ignoreClicked;
193 document.getElementById("b_ignall").onclick = ignoreAllClicked;
194 document.getElementById("b_recheck").onclick = recheckClicked;
196 document.getElementById("b_ok").onclick = saveClicked;
197 document.getElementById("b_cancel").onclick = cancelClicked;
199 select = document.getElementById("v_dictionaries");
200 select.onchange = function() {
201 document.getElementById("f_dictionary").value = this.value;
205 function wordClicked() {
206 if (currentElement) {
207 var a = allWords[currentElement.__msh_origWord];
208 currentElement.className = currentElement.className.replace(/\s*HA-spellcheck-current\s*/g, " ");
211 if (el != currentElement) {
212 el.className = el.className.replace(/\s*HA-spellcheck-same\s*/g, " ");
216 currentElement = this;
217 this.className += " HA-spellcheck-current";
218 var a = allWords[currentElement.__msh_origWord];
221 if (el != currentElement) {
222 el.className += " HA-spellcheck-same";
225 document.getElementById("b_replall").disabled = (a.length <= 1);
226 document.getElementById("b_ignall").disabled = (a.length <= 1);
229 txt = "one occurrence";
230 } else if (a.length == 2) {
231 txt = "two occurrences";
233 txt = a.length + " occurrences";
235 document.getElementById("statusbar").innerHTML = "Found " + txt +
236 ' for word "<b>' + currentElement.__msh_origWord + '</b>"';
237 var select = document.getElementById("v_suggestions");
238 for (var i = select.length; --i >= 0;) {
242 suggestions = this.nextSibling.firstChild.data.split(/,/);
243 for (var i = 0; i < suggestions.length; ++i) {
244 var txt = suggestions[i];
245 var option = document.createElement("option");
247 option.appendChild(document.createTextNode(txt));
248 select.appendChild(option);
250 document.getElementById("v_currentWord").innerHTML = this.__msh_origWord;
251 if (suggestions.length > 0) {
252 select.selectedIndex = 0;
255 document.getElementById("v_replacement").value = this.innerHTML;
260 function wordMouseOver() {
261 this.className += " HA-spellcheck-hover";
264 function wordMouseOut() {
265 this.className = this.className.replace(/\s*HA-spellcheck-hover\s*/g, " ");
268 function finishedSpellChecking() {
269 // initialization of global variables
270 currentElement = null;
274 document.getElementById("status").innerHTML = "HTMLArea Spell Checker (<a href='readme-tech.html' target='_blank' title='Technical information'>info</a>)";
275 var doc = frame.contentWindow.document;
276 var spans = doc.getElementsByTagName("span");
279 for (var i = 0; i < spans.length; ++i) {
281 if (/HA-spellcheck-error/.test(el.className)) {
283 el.onclick = wordClicked;
284 el.onmouseover = wordMouseOver;
285 el.onmouseout = wordMouseOut;
287 var txt = (el.__msh_origWord = el.firstChild.data);
288 el.__msh_fixed = false;
289 if (typeof allWords[txt] == "undefined") {
290 allWords[txt] = [el];
292 allWords[txt].push(el);
297 if (sps.length == 0) {
299 alert(i18n["NO_ERRORS_CLOSING"]);
302 alert(i18n["NO_ERRORS"]);
306 (currentElement = sps[0]).onclick();
307 var as = doc.getElementsByTagName("a");
308 for (var i = as.length; --i >= 0;) {
310 a.onclick = function() {
311 if (confirm(i18n["CONFIRM_LINK_CLICK"] + ":\n" +
312 this.href + "\n" + i18n["I will open it in a new page."])) {
313 window.open(this.href);
318 var dicts = doc.getElementById("HA-spellcheck-dictionaries");
320 dicts.parentNode.removeChild(dicts);
321 dicts = dicts.innerHTML.split(/,/);
322 var select = document.getElementById("v_dictionaries");
323 for (var i = select.length; --i >= 0;) {
326 for (var i = 0; i < dicts.length; ++i) {
328 var option = document.createElement("option");
330 option.appendChild(document.createTextNode(txt));
331 select.appendChild(option);