Subversion-Projekte lars-tiefland.content-management

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

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