source: trunk/plugins/SpellChecker/spell-check-ui.js @ 987

Last change on this file since 987 was 987, checked in by ray, 11 years ago

#1179 minor html syntax changes

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