|
|
|
|
File: [home] / javascript / spell.html
(download)
/
(as text)
Revision: 1.8, Sun Apr 24 06:37:31 2005 UTC (5 years, 4 months ago) by ws Branch: MAIN CVS Tags: HEAD Changes since 1.7: +148 -189 lines faster, correct, less compatible -_- |
<html>
<head>
<title>a realtime spellcheck using javascript</title>
<style type="text/css">
span.miss {
border-bottom: 2px #f00 solid;
}
</style>
<!--[if IE]>
<style type="text/css">
span.miss {
border-bottom: 1px #f00 solid;
}
</style>
<![endif-->
<script type='text/javascript' src='dict.js'></script>
<script type='text/javascript' src='logging.js'></script>
<script type='text/javascript'>
<!--
// realtime JS spellchecker
// by Tony Chang
// BSD License, like always: http://www.opensource.org/licenses/bsd-license.php
//
// Notes
// - So this doesn't work in safari, but it has built in spell checking as
// you type for text fields. No need for this client/server technology.
// TODO:
// - better protocol for returning misspelled words (index rather than whole word)
// - handling correction? might be too bandwidth intense, we'll see
var isIE = (document.all) ? true : false;
function httpRequest(spellerObject) {
if (isIE)
this.http = new ActiveXObject("Msxml2.XMLHTTP");
else
this.http = new XMLHttpRequest();
this.words = {}; // the set of words being sent
this.spell = spellerObject; // pointer to the speller object
}
httpRequest.prototype.response = function() {
if (4 == this.http.readyState && 200 == this.http.status) {
var misspelled = new Array();
if (this.http.responseText) {
var text = this.http.responseText.substring(0,
this.http.responseText.length - 1);
misspelled = text.split(' ');
}
// check which words this impacts
for (var w in misspelled) {
this.spell.misspelled[misspelled[w]] = true;
}
for (w in this.words) // any remaining words are correct
this.spell.dictionary[w] = true;
this.spell.updatepreview();
}
};
httpRequest.prototype.send = function() {
var sendStr = '';
for (var w in this.words)
sendStr += w + ' ';
if ('' == sendStr)
return; // nothing to send, abort
// make a closure
var self = this;
this.http.onreadystatechange = function() {
self.response(self);
};
this.http.open('POST', 'spell.py', true);
this.http.send(sendStr);
}
httpRequest.prototype.addWord = function(w) {
this.words[w] = true;
}
function MapToTextNodes(root, f) {
var len = root.childNodes.length;
for (var c = 0; c < len; c++) // walk the dom
MapToTextNodes(root.childNodes[c], f);
if (3 == root.nodeType) {
f(root);
}
}
// supports for multiple text areas and outputs would be nice (with shared dictionary)
var speller = {
dictionary: {}, // seen words
newWords: {}, // unseen words
misspelled: {}, // words that are known to be misspelled
lastUpdate: 0,
updateInterval: 500,
keyupdate: function(ev) {
this.updatepreview();
},
updatepreview: function() {
// updatepreview is an expensive operation. we try to rate limit it.
var st = (new Date()).getTime();
if (st - this.lastUpdate < this.updateInterval)
return;
this.lastUpdate = st;
var text = document.getElementById('in').value;
text = text.replace(/\n/g,"<br />\n");
var preview = document.getElementById('preview');
// now process the tree
var hidden = document.createElement('div');
hidden.innerHTML = text;
this.findAndReplace(hidden);
preview.innerHTML = hidden.innerHTML;
/* // for debugging
//var raw = document.getElementById('raw');
preview = document.getElementById('preview');
var tmp = preview.innerHTML.replace(/</g, "<");
raw.innerHTML = tmp.replace(/>/g, ">");
//*/
var et = (new Date()).getTime();
this.updateInterval = Math.max((et-st) * 2, 200);
},
findAndReplace: function(root) {
var self = this;
MapToTextNodes(root, function(node) {
var words = node.nodeValue.split(/(\W+)/);
for (var w = 0; w < words.length; w++) {
if (self.misspelled[words[w].toLowerCase()])
words[w] = "<span class='miss'>" + words[w] + "</span>";
}
var newNode = document.createElement('span');
newNode.innerHTML = words.join('');
node.parentNode.replaceChild(newNode, node);
});
},
updateDictionary: function() {
// determine what words are new and send a request
var text = document.getElementById('in').value;
var elt = document.createElement('div');
elt.innerHTML = text;
var req = new httpRequest(this);
var self = this;
MapToTextNodes(elt, function(node) {
var newWords = node.nodeValue.split(/\W+/);
var len = newWords.length;
for (var i = 0; i < len; i++) {
var word = newWords[i].toLowerCase();
if (!self.dictionary[word] && word.length > 1) // ispell always says that 1 letter words are correct
req.addWord(word);
}
});
req.send();
}
}
window.onload = function() {
initDict(speller.dictionary);
window.setInterval("speller.updateDictionary()", 2000);
if (isIE)
{
tb = document.getElementById('in');
tb.style.width = document.body.clientWidth - 280;
}
}
// -->
</script>
</head>
<body>
<div style='float: right; margin: 0 0 0 10; background: #b0ffb0; width: 200px; padding: 0 4px;'>
<p style='text-align: center; margin: 0;'>NOTES</p>
<p>This is a demo of a real time spell checker. It uses xmlhttp request to
get spelling corrections. It works in Firefox, but not in IE and Safari due
to incomplete regular expression implementations.</p>
<p>You're welcome to take the <a href="http://ponderer.org/cvs/index.pl/javascript/">souce
code</a>.</p>
</div>
<div id='container' style='text-align: center; margin: 0 210 8 0; border: 0px; background: #ffb0b0;'>
<p style='margin: 0 0 0 0;'>ENTER TEXT (or html) HERE</p>
<textarea style='width:90%; background: #f0f0f0; margin: 0 5 5 5; height: 200px; padding: 2 2 2 2;border: 1px #808080 solid;' id='in'
onkeyup='speller.keyupdate()'></textarea>
</div>
<div style='text-align: center; margin:0 210 0 0; border: 0px; background: #b0c0ff;'>
<p style='margin: 0 0 0 0;'>PREVIEW</p>
<div id='preview' style='padding: 5 5 5 5; text-align: left; background: #d0e0ff; border: 1px #000000 dashed;'></div>
</div>
<!-- for debugging html
<div style='text-align: center; margin:6 210 0 0; border: 0px; background: #b0c0ff;'>
<p style='margin: 0 0 0 0;'>RAW</p>
<div id='raw' style='padding: 5 5 5 5; text-align: left; background: #d0e0ff; border: 1px #000000 dashed;'></div>
</div>
-->
</body>
</html>
| tony at ponderer dot org |
Powered by ViewCVS 0.9.2 |