Annotation of kupuMPIWG/common/kupuspellchecker.js, revision 1.1
1.1 ! dwinter 1: function KupuSpellChecker(buttonid, scripturl, spanstyle,
! 2: winwidth, winheight, skip_tags) {
! 3: this.button = document.getElementById(buttonid);
! 4: this.scripturl = scripturl;
! 5: this.spanstyle = spanstyle || 'color: red; ' +
! 6: 'text-decoration: underline;';
! 7: this.winwidth = winwidth || '600';
! 8: this.winheight = winheight || '400';
! 9: this.skip_tags = skip_tags || ['head', 'script'];
! 10: };
! 11:
! 12: KupuSpellChecker.prototype = new KupuTool;
! 13:
! 14: KupuSpellChecker.prototype.initialize = function(editor) {
! 15: this.editor = editor;
! 16: addEventHandler(this.button, 'click', this.check, this);
! 17: };
! 18:
! 19: KupuSpellChecker.prototype.check = function() {
! 20: var request = new XMLHttpRequest();
! 21: request.open('POST', this.scripturl, true);
! 22: request.setRequestHeader('Content-Type',
! 23: 'application/x-www-form-urlencoded');
! 24: request.onreadystatechange = new ContextFixer(
! 25: this.stateChangeHandler,
! 26: this,
! 27: request).execute;
! 28: var result = this.getCurrentContents();
! 29: result = escape(result.strip().replace('\n', ' ').reduceWhitespace());
! 30: request.send('text=' + result);
! 31: };
! 32:
! 33: KupuSpellChecker.prototype.stateChangeHandler = function(request) {
! 34: if (request.readyState == 4) {
! 35: if (request.status == '200') {
! 36: var result = request.responseXML;
! 37: result = this.xmlToMapping(result);
! 38: if (!result) {
! 39: alert(_('There were no errors.'));
! 40: } else {
! 41: this.displayUnrecognized(result);
! 42: };
! 43: } else {
! 44: alert(_('Error loading data, status ${status}',
! 45: {'status': request.status}));
! 46: };
! 47: };
! 48: };
! 49:
! 50: KupuSpellChecker.prototype.getCurrentContents = function() {
! 51: var doc = this.editor.getInnerDocument().documentElement;
! 52: var iterator = new NodeIterator(doc);
! 53: var bits = [];
! 54: while (true) {
! 55: var node = iterator.next();
! 56: if (!node) {
! 57: break;
! 58: };
! 59: while (this.skip_tags.contains(node.nodeName.toLowerCase())) {
! 60: node = node.nextSibling;
! 61: iterator.setCurrent(node);
! 62: };
! 63: if (node.nodeType == 3) {
! 64: bits.push(node.nodeValue);
! 65: };
! 66: };
! 67: return bits.join(' ');
! 68: };
! 69:
! 70: KupuSpellChecker.prototype.displayUnrecognized = function(mapping) {
! 71: // copy the current editable document into a new window
! 72: var doc = this.editor.getInnerDocument();
! 73: var docel = doc.documentElement;
! 74: var win = window.open('kupublank.html', 'spellchecker',
! 75: 'width=' + this.winwidth + ',' +
! 76: 'height=' + this.winheight + ',toolbar=no,' +
! 77: 'menubar=no,scrollbars=yes,status=yes');
! 78: if (!win) {
! 79: alert(
! 80: _('This feature requires pop-ups to be enabled on your browser!'));
! 81: return;
! 82: };
! 83: var html = docel.innerHTML;
! 84: // when Moz tries to set the content-type, for some reason leaving this
! 85: // in breaks the feature(?!?)
! 86: html = html.replace(/<meta[^>]*http-equiv="[Cc]ontent-[Tt]ype"[^>]*>/gm,
! 87: '');
! 88: win.document.write('<html>' + html + '</html>');
! 89: win.deentitize = function(str) {return str.deentitize()};
! 90: win.document.close();
! 91: if (!win.document.getElementsByTagName('body').length) {
! 92: addEventHandler(win, 'load', this.continueDisplay, this, win, mapping);
! 93: } else {
! 94: this.continueDisplay(win, mapping);
! 95: };
! 96: };
! 97:
! 98: KupuSpellChecker.prototype.continueDisplay = function(win, mapping) {
! 99: /* walk through all elements of the body, colouring the text nodes */
! 100: // start it all with a timeout to make Mozilla render the content first
! 101: timer_instance.registerFunction(this, this.continueDisplayHelper,
! 102: 1000, win, mapping);
! 103: };
! 104:
! 105: KupuSpellChecker.prototype.continueDisplayHelper = function(win, mapping) {
! 106: var body = win.document.getElementsByTagName('body')[0];
! 107: body.setAttribute('contentEditable', 'false');
! 108: var iterator = new NodeIterator(body);
! 109: var node = iterator.next();
! 110: timer_instance.registerFunction(this, this.displayHelperNodeLoop,
! 111: 10, iterator, node, win, mapping);
! 112: };
! 113:
! 114: KupuSpellChecker.prototype.displayHelperNodeLoop = function(iterator, node,
! 115: win, mapping) {
! 116: if (!node) {
! 117: return;
! 118: };
! 119: var next = iterator.next();
! 120: if (node.nodeType == 3) {
! 121: if (win.closed) {
! 122: return;
! 123: };
! 124: var span = win.document.createElement('span');
! 125: var before = node.nodeValue;
! 126: var after = this.colourText(before, mapping);
! 127: if (before != after) {
! 128: span.innerHTML = after;
! 129: var last = span.lastChild;
! 130: var parent = node.parentNode;
! 131: parent.replaceChild(last, node);
! 132: while (span.hasChildNodes()) {
! 133: parent.insertBefore(span.firstChild, last);
! 134: };
! 135: };
! 136: } else if (node.nodeType == 1 && node.nodeName.toLowerCase() == 'a') {
! 137: var cancelEvent = function(e) {
! 138: if (e.preventDefault) {
! 139: e.preventDefault();
! 140: } else {
! 141: e.returnValue = false;
! 142: };
! 143: return false;
! 144: };
! 145: addEventHandler(node, 'click', cancelEvent);
! 146: addEventHandler(node, 'mousedown', cancelEvent);
! 147: addEventHandler(node, 'mouseup', cancelEvent);
! 148: };
! 149: // using a timeout here makes Moz render the coloring while it's busy, and
! 150: // will make it stop popping up 'do you want to continue' prompts...
! 151: timer_instance.registerFunction(this, this.displayHelperNodeLoop,
! 152: 10, iterator, next, win, mapping);
! 153: };
! 154:
! 155: KupuSpellChecker.prototype.colourText = function(text, mapping) {
! 156: var currtext = text;
! 157: var newtext = '';
! 158: for (var word in mapping) {
! 159: var replacements = mapping[word];
! 160: replacements = replacements.entitize();
! 161: replacements = replacements.replace(/\'/g, "'");
! 162: var reg = new RegExp('^(.*\\\W)?(' + word + ')(\\\W.*)?$', 'mg');
! 163: while (true) {
! 164: var match = reg.exec(currtext);
! 165: if (!match) {
! 166: newtext += currtext;
! 167: currtext = newtext;
! 168: newtext = '';
! 169: break;
! 170: };
! 171: var m = (match[1] || '') + match[2];
! 172: newtext += currtext.substr(0, currtext.indexOf(m));
! 173: newtext += (match[1] || '') +
! 174: '<span style="' + this.spanstyle + '" ' +
! 175: 'onclick="alert(deentitize(\'' +
! 176: replacements + '\'));" ' +
! 177: 'title="' + replacements + '">' +
! 178: match[2] +
! 179: '</span>';
! 180: currtext = currtext.substr(currtext.indexOf(m) + m.length);
! 181: };
! 182: };
! 183: return currtext;
! 184: };
! 185:
! 186: KupuSpellChecker.prototype.xmlToMapping = function(docnode) {
! 187: var docel = docnode.documentElement;
! 188: var result = {};
! 189: var incorrect = docel.getElementsByTagName('incorrect');
! 190: for (var i=0; i < incorrect.length; i++) {
! 191: var word = incorrect[i].firstChild.firstChild.nodeValue;
! 192: var replacements = '';
! 193: if (incorrect[i].lastChild.hasChildNodes()) {
! 194: replacements = incorrect[i].lastChild.firstChild.nodeValue;
! 195: };
! 196: result[word] = replacements;
! 197: };
! 198: var attrs = [];
! 199: return result;
! 200: };
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>