How to uninstall Firefox add-on using javascript?

WebKit Javascript Woes

  • 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?

  • Answer:

    re.compile is not a standard Javascript method. Why don't you just pass the pattern to 'new RegExp(pat)'?

evariste at Ask.Metafilter.Com Visit the source

Was this solution helpful to you?

Other answers

Javascript code (for pages) rarely needs to be optimized. This is absolutely not true. Since JavaScript is not compiled, there are dozens and dozens of optimization routines that can speed up script execution. Just for example, take this loop in the code you quote: for (var i=0; i ... > You're calculating the length of the spams array every time you iterate through the loop. You could optimize it by declaring a variable in the for...loop that holds the value of the length as such: for (i=0, j=spams.length; i < j; i++) { ... When you have large datasets that you need to perform operations on, like looping through a allowed-words filter, for instance, there are a number of real-world performance benefits to these relatively simple optimizations. That's just a simple, small example. There are much larger issues looming in your routine. For example, this is abhorrant: preview_field.innerHTML = "<p>" + field.value.split(/\n\n/).join("</p><p>").split(/\n/).join("<br />").showSpams() + "</p>"; Why are you calculating the entire field value for every single keystroke? You could have a function in between your expression tester that checks whether a space or enter has been hit, and only then run the expression tester.

Civil_Disobedient

MonkeySaltedNuts-For performance reasons. I don't want to create a new RexExp object for each of the some-80ish blacklisted terms in a loop. Reusing the same RegExp instance seemed wiser. OTOH, maybe that was a premature optimization, since I didn't actually check to see if it was causing performance problems, I just assumed it would and factored it out of the loop. compile isn't a standard method of RegExp objects? Damn...I guess that's my problem then. Too bad, it worked in every browser but WebKit ones. I'll try it without re.compile.

evariste

Is there anywhere out there that has a Javascript compatibility chart, like the CSS browser compatibility charts that show which browsers can do what?

evariste

check to see if safari supports the compile method with a try/catch, and if nottry {re.compile(spams[i].regExEscape(),'gim');}catch {alert('guess we found the problem');// write a longer method of doing the same thing without use of the compile method}or just detect if (!re.compile) alert('this browser doesn't support compile');

Señor Pantalones

That was it, Safari doesn't support the compile method. Thanks, Monkey and Señor!

evariste

Javascript code (for pages) rarely needs to be optimized. If you really need to optimize I would pre-compute the REs for 'spams' into 'spamREs' rather than re-compute them everytime you invoke .showSpams on a string.

MonkeySaltedNuts

If you really need to optimize I would pre-compute the REs for 'spams' into 'spamREs' rather than re-compute them everytime you invoke .showSpams on a string. Duh. *smacks forehead* As it turns out, there's no need to optimize, so I'm not going to worry about it for now. Thanks again.

evariste

Hi, I'm a Safari developer and I'd love it if you could file this bug at http://bugzilla.opendarwin.org/ in product WebKit. Even if "compile" is not a standard RegExp method, we prefer to support common extensions of other browsers.

maciej

oh awesome, maciej is part of the hive mind! now fix my filed bugs! ;) (j/k). civil_disobedient: crapping in the ice cream machine at a Dairy Queen is "abhorrent." poorly optimized javascript is "poorly optimized" :)

Señor Pantalones

Just Added Q & A:

Find solution

For every problem there is a solution! Proved by Solucija.

  • Got an issue and looking for advice?

  • Ask Solucija to search every corner of the Web for help.

  • Get workable solutions and helpful tips in a moment.

Just ask Solucija about an issue you face and immediately get a list of ready solutions, answers and tips from other Internet users. We always provide the most suitable and complete answer to your question at the top, along with a few good alternatives below.