I'm having a strange problem with WebKit's Javascript engine. Please help. Copious explanation inside.
I have a live inline comment preview feature, much like MetaFilter's, on my blog. It works great in Opera and Firefox (and MSIE). However, it doesn't seem to work in Safari, OmniWeb, or even the WebKit nightly build-I downloaded it in the hope that this was a WebKit bug that's fixed upstream in the nightlies, but if it
is their bug, it doesn't look like it's been fixed. I'm asking this question in the hope that it's something
I can fix.
Here's how my comment preview code works:
1. There's a textarea with the id "comment-text" which you type your comment into. It has an onKeyUp event handler that calls doCommentPreview() in my javascript file. There's a preview field underneath the textarea with the id "comment-preview", which doCommentPreview() fills with the preview HTML.
2. I have a blacklist of disallowed words, as a spam prevention measure. The comment engine will refuse any comment that contains any of these words or phrases.
3. At the top of the document (not in the javascript file), I fill a javascript array called spams[] with the contents of the blacklist, using php, on the server side.
4. I have two String prototype functions: showSpams() and regExEscape(). I use showSpams() to highlight items in the blacklist that a commenter might have typed in, to alert them right in the inline previewer that their comment is likely to be rejected before they hit post. It just tests the comment against each element of the spam[]array, and if the comments contains that particular word, it turns red and is surrounded by a border.
5. I've enabled the Debug menu using
defaults write com.apple.Safari EnableDebugMenu 1
Safari's Javascript console, in the debug menu, shows the following error:
Value undefined (result of expression re.compile) is not object. bloggie_05.js
on line 16.
The line that WebKit complains about is the first line inside the for-loop in String.prototype.showSpams():
re.compile(spams[i].regExEscape(),'gim');
6. Here's all the code, in context:
6-a. At the top of the document, in the <head> section:
<script language="javascript">var spams = new Array();spams[0] = 'casino';spams[1] = 'craps';spams[2] = 'backgammon';spams[3] = 'cash advance';</script>
<script src="bloggie_05.js" language="javascript" type="text/javascript"></script>
[I abbreviated the blacklist (the spams[] array) because this question is already way too long.]
In the textarea used for writing comments, I have this:
<textarea tabindex="1" id="comment-text" name="comment_text_body" style='width:95%;height:300px;' onKeyUp="javascript:doCommentPreview();"></textarea>
And here's the empty div underneath it, which is filled by the doCommentPreview() function above:
<div class="ientrycomment_body" id="comment-preview" name="prevu"></div>
Finally, here's the code in the external (bloggie_05.js) javascript file:
function doCommentPreview(doc){
doc=(typeof(doc)=="undefined"?document:doc);
field=doc.getElementById("comment-text");
preview_field=doc.getElementById("comment-preview");
preview_field.innerHTML = "<p>" + field.value.split(/\n\n/).join("</p><p>").split(/\n/).join("<br />").showSpams() + "</p>";
}
String.prototype.showSpams = function(){
despammed=this;
re = new RegExp();
for (var i=0; i < spams.length; i++) {
re.compile(spams[i].regExEscape(),'gim');
despammed=despammed.replace(re,"<span style=\"color:red;border:1px dotted;\" title=\"you can't say that here!\">" + spams[i] + "</span>");
}
return despammed;
}
String.prototype.regExEscape = function() {
text=this;
if (!arguments.callee.sRE) {
var specials = [ '/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\' ];
arguments.callee.sRE = new RegExp(
'(\\' + specials.join('|\\') + ')', 'g'
);
}
return text.replace(arguments.callee.sRE, '\\$1');
}The line that WebKit has a problem with is in bold, in the String.prototype.showSpams() above.
What's going on here?
Why don't you just pass the pattern to 'new RegExp(pat)'?
posted by MonkeySaltedNuts at 1:46 PM on September 23, 2006