Ticket #204: spell-check-ui.js

File spell-check-ui.js, 13.9 kB (added by spell-check-ui.js, 7 years ago)

Revised file

Line 
1// Spell Checker Plugin for HTMLArea-3.0
2// Sponsored by www.americanbible.org
3// Implementation by Mihai Bazon, http://dynarch.com/mishoo/
4//
5// (c) dynarch.com 2003.
6// Distributed under the same terms as HTMLArea itself.
7// This notice MUST stay intact for use (see license.txt).
8//
9// $Id: spell-check-ui.js 60 2005-04-05 13:22:31Z niko $
10
11// internationalization file was already loaded in parent ;-)
12var SpellChecker = window.opener.SpellChecker;
13
14var HTMLArea = window.opener.HTMLArea;
15var _editor_url = window.opener._editor_url;
16
17var is_ie = HTMLArea.is_ie;
18var editor = SpellChecker.editor;
19var frame = null;
20var currentElement = null;
21var wrongWords = null;
22var modified = false;
23var allWords = {};
24var fixedWords = [];
25var suggested_words = {};
26
27var to_p_dict = []; // List of words to add to personal dictionary.
28var to_r_list = []; // List of words to add to replacement list.
29
30function _lc(string) {
31  return HTMLArea._lc(string, 'SpellChecker');
32}
33
34function makeCleanDoc(leaveFixed) {
35  // document.getElementById("status").innerHTML = 'Please wait: rendering valid HTML';
36  var words = wrongWords.concat(fixedWords);
37  for (var i = words.length; --i >= 0;) {
38    var el = words[i];
39    if (!(leaveFixed && /HA-spellcheck-fixed/.test(el.className))) {
40      el.parentNode.insertBefore(el.firstChild, el);
41      el.parentNode.removeChild(el);
42    } else
43      el.className = "HA-spellcheck-fixed";
44  }
45  // we should use innerHTML here, but IE6's implementation fucks up the
46  // HTML to such extent that our poor Perl parser doesn't understand it
47  // anymore.
48  return window.opener.HTMLArea.getHTML(frame.contentWindow.document.body, false, editor);
49};
50
51function recheckClicked() {
52  document.getElementById("status").innerHTML = _lc("Please wait: changing dictionary to") + ': "' + document.getElementById("f_dictionary").value + '".';
53  var field = document.getElementById("f_content");
54  field.value = makeCleanDoc(true);
55  field.form.submit();
56};
57
58function saveClicked() {
59  if (modified) {
60    editor.setHTML(makeCleanDoc(false));
61  }
62
63  if(to_p_dict.length || to_r_list.length && editor.config.SpellChecker.backend == 'php')
64  {
65    var data = {};
66    for(var i = 0;i < to_p_dict.length;i++)
67    {
68      data['to_p_dict[' + i + ']'] = to_p_dict[i];
69    }
70    for(var i = 0;i < to_r_list.length;i++)
71    {
72      data['to_r_list[' + i + '][0]'] = to_r_list[i][0];
73      data['to_r_list[' + i + '][1]'] = to_r_list[i][1];
74    }
75    // var win = window;
76    window.opener.HTMLArea._postback(_editor_url + '/plugins/SpellChecker/spell-check-savedicts.php', data);
77    window.close();
78  }
79  else
80  {
81    window.close();
82  }
83  return false;
84};
85
86function cancelClicked() {
87  var ok = true;
88  if (modified) {
89    ok = confirm(_lc("This will drop changes and quit spell checker.  Please confirm."));
90  }
91  if (ok) {
92    window.close();
93  }
94  return false;
95};
96
97function replaceWord(el) {
98  var replacement = document.getElementById("v_replacement").value;
99  var this_word_modified = (el.innerHTML != replacement);
100  if (this_word_modified)
101    modified = true;
102  if (el) {
103    el.className = el.className.replace(/\s*HA-spellcheck-(hover|fixed)\s*/g, " ");
104  }
105  el.className += " HA-spellcheck-fixed";
106  el.__msh_fixed = true;
107  if (!this_word_modified) {
108    return false;
109  }
110  to_r_list.push([el.innerHTML, replacement]);
111  el.innerHTML = replacement;
112};
113
114function replaceClicked() {
115  replaceWord(currentElement);
116  var start = currentElement.__msh_id;
117  var index = start;
118  do {
119    ++index;
120    if (index == wrongWords.length) {
121      index = 0;
122    }
123  } while ((index != start) && wrongWords[index].__msh_fixed);
124  if (index == start) {
125    index = 0;
126    alert(_lc("Finished list of mispelled words"));
127  }
128  wrongWords[index].__msh_wordClicked(true);
129  return false;
130};
131
132function revertClicked() {
133  document.getElementById("v_replacement").value = currentElement.__msh_origWord;
134  replaceWord(currentElement);
135  currentElement.className = "HA-spellcheck-error HA-spellcheck-current";
136  return false;
137};
138
139function replaceAllClicked() {
140  var replacement = document.getElementById("v_replacement").value;
141  var ok = true;
142  var spans = allWords[currentElement.__msh_origWord];
143  if (spans.length == 0) {
144    alert("An impossible condition just happened.  Call FBI.  ;-)");
145  } else if (spans.length == 1) {
146    replaceClicked();
147    return false;
148  }
149  /*
150  var message = "The word \"" + currentElement.__msh_origWord + "\" occurs " + spans.length + " times.\n";
151  if (replacement == currentElement.__msh_origWord) {
152    ok = confirm(message + "Ignore all occurrences?");
153  } else {
154    ok = confirm(message + "Replace all occurrences with \"" + replacement + "\"?");
155  }
156  */
157  if (ok) {
158    for (var i = 0; i < spans.length; ++i) {
159      if (spans[i] != currentElement) {
160        replaceWord(spans[i]);
161      }
162    }
163    // replace current element the last, so that we jump to the next word ;-)
164    replaceClicked();
165  }
166  return false;
167};
168
169function ignoreClicked() {
170  document.getElementById("v_replacement").value = currentElement.__msh_origWord;
171  replaceClicked();
172  return false;
173};
174
175function ignoreAllClicked() {
176  document.getElementById("v_replacement").value = currentElement.__msh_origWord;
177  replaceAllClicked();
178  return false;
179};
180
181function learnClicked() {
182  to_p_dict.push(currentElement.__msh_origWord);
183  return ignoreAllClicked();
184};
185
186function internationalizeWindow() {
187  var types = ["div", "span", "button"];
188  for (var i = 0; i < types.length; ++i) {
189    var tag = types[i];
190    var els = document.getElementsByTagName(tag);
191    for (var j = els.length; --j >= 0;) {
192      var el = els[j];
193      if (el.childNodes.length == 1 && /\S/.test(el.innerHTML)) {
194        var txt = el.innerHTML;
195        el.innerHTML = _lc(txt);
196      }
197    }
198  }
199};
200
201function initDocument() {
202  internationalizeWindow();
203  modified = false;
204  frame = document.getElementById("i_framecontent");
205  var field = document.getElementById("f_content");
206  field.value = HTMLArea.getHTML(editor._doc.body, false, editor);
207  var dict = document.getElementById("f_dictionary");
208  if(typeof editor.config.SpellChecker.defaultDictionary != "undefined"
209     && editor.config.SpellChecker.defaultDictionary != "") {
210    dict.value = editor.config.SpellChecker.defaultDictionary;
211  } else {
212    dict.value = "en_GB";
213  }
214  if(editor.config.SpellChecker.backend == 'php')
215  {
216    field.form.action = _editor_url + '/plugins/SpellChecker/spell-check-logic.php';
217  }
218
219  field.form.submit();
220  document.getElementById("f_init").value = "0";
221
222  // assign some global event handlers
223
224  var select = document.getElementById("v_suggestions");
225  select.onchange = function() {
226    document.getElementById("v_replacement").value = this.value;
227  };
228  if (is_ie) {
229    select.attachEvent("ondblclick", replaceClicked);
230  } else {
231    select.addEventListener("dblclick", replaceClicked, true);
232  }
233
234  document.getElementById("b_replace").onclick = replaceClicked;
235  if(editor.config.SpellChecker.backend == 'php')
236  {
237    document.getElementById("b_learn").onclick = learnClicked;
238  }
239  else
240  {
241    document.getElementById("b_learn").parent.removeChild(document.getElementById("b_learn"));
242  }
243  document.getElementById("b_replall").onclick = replaceAllClicked;
244  document.getElementById("b_ignore").onclick = ignoreClicked;
245  document.getElementById("b_ignall").onclick = ignoreAllClicked;
246  document.getElementById("b_recheck").onclick = recheckClicked;
247  document.getElementById("b_revert").onclick = revertClicked;
248  document.getElementById("b_info").onclick = displayInfo;
249
250  document.getElementById("b_ok").onclick = saveClicked;
251  document.getElementById("b_cancel").onclick = cancelClicked;
252
253  select = document.getElementById("v_dictionaries");
254  select.onchange = function() {
255    document.getElementById("f_dictionary").value = this.value;
256  };
257};
258
259function getAbsolutePos(el) {
260  var r = { x: el.offsetLeft, y: el.offsetTop };
261  if (el.offsetParent) {
262    var tmp = getAbsolutePos(el.offsetParent);
263    r.x += tmp.x;
264    r.y += tmp.y;
265  }
266  return r;
267};
268
269function wordClicked(scroll) {
270  var self = this;
271  if (scroll) (function() {
272    var pos = getAbsolutePos(self);
273    var ws = { x: frame.offsetWidth - 4,
274         y: frame.offsetHeight - 4 };
275    var wp = { x: frame.contentWindow.document.body.scrollLeft,
276         y: frame.contentWindow.document.body.scrollTop };
277    pos.x -= Math.round(ws.x/2);
278    if (pos.x < 0) pos.x = 0;
279    pos.y -= Math.round(ws.y/2);
280    if (pos.y < 0) pos.y = 0;
281    frame.contentWindow.scrollTo(pos.x, pos.y);
282  })();
283  if (currentElement) {
284    var a = allWords[currentElement.__msh_origWord];
285    currentElement.className = currentElement.className.replace(/\s*HA-spellcheck-current\s*/g, " ");
286    for (var i = 0; i < a.length; ++i) {
287      var el = a[i];
288      if (el != currentElement) {
289        el.className = el.className.replace(/\s*HA-spellcheck-same\s*/g, " ");
290      }
291    }
292  }
293  currentElement = this;
294  this.className += " HA-spellcheck-current";
295  var a = allWords[currentElement.__msh_origWord];
296  for (var i = 0; i < a.length; ++i) {
297    var el = a[i];
298    if (el != currentElement) {
299      el.className += " HA-spellcheck-same";
300    }
301  }
302  // document.getElementById("b_replall").disabled = (a.length <= 1);
303  // document.getElementById("b_ignall").disabled = (a.length <= 1);
304  var txt;
305  if (a.length == 1) {
306    txt = "one occurrence";
307  } else if (a.length == 2) {
308    txt = "two occurrences";
309  } else {
310    txt = a.length + " occurrences";
311  }
312  var suggestions = suggested_words[this.__msh_origWord];
313  if (suggestions)
314    suggestions = suggestions.split(/,/);
315  else
316    suggestions = [];
317  var select = document.getElementById("v_suggestions");
318  document.getElementById("statusbar").innerHTML = "Found " + txt +
319    ' for word "<b>' + currentElement.__msh_origWord + '</b>"';
320  for (var i = select.length; --i >= 0;) {
321    select.remove(i);
322  }
323  for (var i = 0; i < suggestions.length; ++i) {
324    var txt = suggestions[i];
325    var option = document.createElement("option");
326    option.value = txt;
327    option.appendChild(document.createTextNode(txt));
328    select.appendChild(option);
329  }
330  document.getElementById("v_currentWord").innerHTML = this.__msh_origWord;
331  if (suggestions.length > 0) {
332    select.selectedIndex = 0;
333    select.onchange();
334  } else {
335    document.getElementById("v_replacement").value = this.innerHTML;
336  }
337  select.style.display = "none";
338  select.style.display = "block";
339  return false;
340};
341
342function wordMouseOver() {
343  this.className += " HA-spellcheck-hover";
344};
345
346function wordMouseOut() {
347  this.className = this.className.replace(/\s*HA-spellcheck-hover\s*/g, " ");
348};
349
350function displayInfo() {
351  var info = frame.contentWindow.spellcheck_info;
352  if (!info)
353    alert("No information available");
354  else {
355    var txt = "** Document information **";
356    for (var i in info) {
357      txt += "\n" + i + " : " + info[i];
358    }
359    alert(txt);
360  }
361  return false;
362};
363
364function finishedSpellChecking() {
365  // initialization of global variables
366  currentElement = null;
367  wrongWords = null;
368  allWords = {};
369  fixedWords = [];
370  suggested_words = frame.contentWindow.suggested_words;
371
372  document.getElementById("status").innerHTML = "HTMLArea Spell Checker (<a href='readme-tech.html' target='_blank' title='Technical information'>info</a>)";
373  var doc = frame.contentWindow.document;
374        var spans = doc.getElementsByTagName("span");
375        var sps = [];
376  var id = 0;
377        for (var i = 0; i < spans.length; ++i) {
378                var el = spans[i];
379                if (/HA-spellcheck-error/.test(el.className)) {
380                        sps.push(el);
381      el.__msh_wordClicked = wordClicked;
382      el.onclick = function(ev) {
383        ev || (ev = window.event);
384        ev && HTMLArea._stopEvent(ev);
385        return this.__msh_wordClicked(false);
386      };
387      el.onmouseover = wordMouseOver;
388      el.onmouseout = wordMouseOut;
389      el.__msh_id = id++;
390      var txt = (el.__msh_origWord = el.firstChild.data);
391      el.__msh_fixed = false;
392      if (typeof allWords[txt] == "undefined") {
393        allWords[txt] = [el];
394      } else {
395        allWords[txt].push(el);
396      }
397                } else if (/HA-spellcheck-fixed/.test(el.className)) {
398      fixedWords.push(el);
399    }
400        }
401  wrongWords = sps;
402  if (sps.length == 0) {
403    if (!modified) {
404      alert(_lc("No mispelled words found with the selected dictionary."));
405      // window.close();
406    } else {
407      alert(_lc("No mispelled words found with the selected dictionary."));
408    }
409    return false;
410  }
411  (currentElement = sps[0]).__msh_wordClicked(true);
412  var as = doc.getElementsByTagName("a");
413  for (var i = as.length; --i >= 0;) {
414    var a = as[i];
415    a.onclick = function() {
416      if (confirm(_lc("Please confirm that you want to open this link") + ":\n" +
417            this.href + "\n" + _lc("I will open it in a new page."))) {
418        window.open(this.href);
419      }
420      return false;
421    };
422  }
423  var dicts = doc.getElementById("HA-spellcheck-dictionaries");
424  if (dicts) {
425    dicts.parentNode.removeChild(dicts);
426    dicts = dicts.innerHTML.split(/,/);
427    var select = document.getElementById("v_dictionaries");
428    for (var i = select.length; --i >= 0;) {
429      select.remove(i);
430    }
431    var activeDictionary = document.getElementById("f_dictionary").value;
432    for (var i = 0; i < dicts.length; ++i) {
433      var txt = dicts[i];
434      var option = document.createElement("option");
435      if(txt == activeDictionary) {
436        // The line below removes the selected item instead
437                //txt = RegExp.$1;
438        option.selected = true;
439      }
440      option.value = txt;
441      option.appendChild(document.createTextNode(txt));
442      select.appendChild(option);
443    }
444  }
445};