[Greasemonkey] XPCNativeWrappers and Deer Park compatibility

Jed jedsbugs at gmail.com
Wed Jul 27 17:39:17 EDT 2005


Ouch.

I think one of the beauties of GM, is the standard 'js' that you could
write, and get results, no need for re-learning or developing work
arounds.

Now with GM-TNG, we are now presented with a new 'flavor' where the JS
we are used to won't work out of the box.

I can see the fustration by future developers thinking...
Why the hell does... var elmForm = document.getElementById('foo');
elmForm.bar.value = '...';
not work.

I'm not trying to complain, just that it seems this is a step in the
wrong direction.

my 2 worthless cents
-Jed


On 7/27/05, Mark Pilgrim <pilgrim at gmail.com> wrote:
> Simon and I have been furiously working on updating all the scripts in
> "Greasemonkey Hacks" to work with GM-TNG and Deer Park alpha 2.  Here
> are the most frequent problems I've encountered so far.
> 
> Every element you get from document.anything(), including new elements
> you create with document.createElement, or elements you get from
> document.getElementById or document.getElementsByTagName, is a "deep
> wrapper" (technically, an XPCNativeWrapper object) around the real
> element.  XPCNativeWrappers have several limitations that will
> frustrate you, and you will be tempted to say "screw it" and just use
> unsafeWindow/contentWindow where "everything just works."  Resist this
> temptation!  Take the time to learn about XPCNativeWrappers.
> 
> 1. You can't access form elements by name.  For the form <form
> id="foo"><input name="bar"></form>, the following code no longer
> works:
> 
> var elmForm = document.getElementById('foo');
> elmForm.bar.value = '...';
> 
> Instead, you need to to do this:
> 
> var elmForm = document.getElementById('foo');
> elmForm.elements.namedItem('bar').value = '...';
> 
> 2. Scripts often create new elements (like links) and assign onclick
> or other event handlers to them directly.  Setting
> elementWrapper.onclick = 'javascript code' does not work; neither does
> setting elementWrapper.onclick = functionRef, as explempfied by the
> following non-working code:
> 
> function my_click_handler() { ...; return false; }
> var elmLink = document.createElement('a');
> elmLink.onclick = my_click_handler;
> 
> Instead, you need to use addEventListener and call
> event.preventDefault() inside your event handler if you want to
> prevent the event from bubbling, like this:
> 
> function my_click_handler(event) { ...; event.preventDefault(); }
> var elmLink = document.createElement('a');
> elmLink.addEventListener('click', my_click_handler, true);
> 
> This applies to any element, not just new ones you create, and any
> event handler, not just onclick.  If you are defining an onkeypress
> handler for an input element you get by ID, this is the only variation
> that works in Deer Park:
> 
> function my_keypress_handler(event) { ...; event.preventDefault(); }
> var elmInput = document.getElementById('foo');
> elmInput.addEventListener('keypress', my_keypress_handler, true);
> 
> 3. Scripts often create brand new properties on elements to reference
> them later.  For example my Zoom Textarea script (
> http://diveintogreasemonkey.org/download/zoomtextarea.user.js )
> inserts a button before each <textarea> and "associates" each button
> with its <textarea> by creating a new _target property on the button
> (and then referencing that property later in the button's onclick
> handler).  This simply doesn't work at all in Deer Park; you just
> can't create new properties on XPCNativeWrappers.  You will need to
> refactor your code to remove the custom property, and pass it to the
> event handler (or whatever) some other way, like with a closure.
> 
> Non-working code (violates #2 and #3 above):
> 
> function my_button_click(event) {
>   var elmTextarea = event.currentTarget._target;
>   ...
>   return false;
> }
> var elmTextarea = document.getElementById('foo');
> var elmButton = document.createElement('a');
> elmButton._target = elmTextarea;
> elmButton.onclick = my_button_click;
> 
> Refactored code that works in Deer Park:
> 
> function my_button_click(event, elmTextarea) {
>   ...
>   event.preventDefault();
> }
> var elmTextarea = document.getElementById('foo');
> var elmButton = document.createElement('a');
> elmButton.addEventListener('click', function(event) {
>   my_button_click(event, elmTextarea);
> }, true);
> 
> All of these techniques also work in GM-TNG under FF 1.0.6, so you
> don't need to sacrifice backward compatibility to gain forward
> compatibility.
> 
> I have been notifying individual developers as I fix their scripts.
> If we're using one of your scripts in "Greasemonkey Hacks" and you
> don't hear from either me or Simon in the next few weeks, chances are
> your script works without modification in Deer Park.
> 
> Once "Greasemonkey Hacks" is done, I will be updating Dive Into
> Greasemonkey to include a chapter on Deer Park compatibility, as well
> as updating all the examples, patterns, case studies, and the rest of
> my own scripts.  Until then, keep watching this mailing list, and I'll
> report any new stumbling blocks as I, er, stumble over them.
> 
> Many thanks to Aaron Boodman, who patiently explained all this to me,
> and even went to the trouble of fixing one of my book's scripts.  His
> efforts served as a starting point in my own education, and now your
> education as well.
> 
> --
> Cheers,
> -Mark
> _______________________________________________
> Greasemonkey mailing list
> Greasemonkey at mozdev.org
> http://mozdev.org/mailman/listinfo/greasemonkey
>


More information about the Greasemonkey mailing list