Using the GMail Greasemonkey API and Succeeding: My Workaround
The new GMail interface is a giant mass of frames and obfuscated JavaScript. Knowing this, Google released an API for Greasemonkey authors to use, called the GmailGreasemonkey10API. Isn’t that nice of them?
Well, don’t get too excited. First, it is fairly limited in what it can do. Its greatest advantage for you is that it can give you handles to the various frames that it loads things into. It does also give you some convenience methods for adding elements to the navigation box as well as other methods.
For performance reasons Google doesn’t load the API on every call to GMail. It is only loaded if a script asks the API to initialize through a call to gmonkey.load. This function takes a callback function as the first parameter which according to Google will be called when the API has successfully loaded. My mileage has varied. Greatly.
Even testing their ultra-simple example script I had serious issues with it not running much more often than it did run. My own scripts would usually bomb at the same rate.
The issues were generally something to the effect of “vN is undefined” (calls to getCanvasElement, an undocumented function) or “a is undefined” (calls to registerViewChangeCallback). Pretty much any short alpha-numeric combination coming up as “is undefined” is likely caused by this issue.
After much trial and error I seem to have found a viable work-around to the issue. Instead of immediately making calls to the API functions when the load function completes, have it set a window timeout of 500ms. This seems to resolve nearly all of the problems, though you will still occasionally get a hiccup. For those occasions, simply catch the error and reload the page. Is it an ugly hack? Yes. Does it work? Seems to.
Here’s a quick example:
var gmail = null; window.addEventListener('load', function() { if (unsafeWindow.gmonkey) { unsafeWindow.gmonkey.load('1.0', init); } }, true); function getCanvas() { try { gmail.getCanvasElement().addEventListener('click', function() { GM_log('Worked'); }, true); // Could also be a call like: gmail.registerViewChangeCallback(function() { GM_log('Also works'); }); } catch (ex) { GM_log('3:'+ex.message); // This seems like a brutal hack, however the call to getCanvasElement // will sometimes fail when the page loads. If that happens this seems // to resolve it eventually. window.location.reload(); } } function init(g) { try { gmail = g; // Calls to the gmail API seem to fail far less often if you wait // for a bit to actually start using it. window.setTimeout(getCanvas, 500); } catch (ex) { GM_log('1:'+ex.message); } } |
I used this trick in my GMail Multiple From Address Extensions Greasemonkey script available at Userscripts.org. I went through several different revisions on that site and probably a dozen more locally before I found this workaround. So far it seems to work, though I’d love to hear if anyone has a different experience.
I’ve also experienced issues with Google’s scripts not honoring my calls to stopPropagation and preventDefault. If anyone has any advice there I’m sure we’d all be interested.
[...] generally do, this one wound up being a really good learning experience for me, as chronicled in this earlier post. So, thanks “wmblewett”. I hope you enjoy the script as much as I enjoyed the experience [...]
I couldn’t get the Gmail API to work until I stumbled upon this method, thanks.
This, I used to run into similar issues with my script — gmailAutoBcc. It was very annoying when the script failed to bcc my sent emails! This hack seems to help so far, I’m keeping my fingers crossed.
[...] example by Google Gmail View Watcher runs once in a while. On my search for a solution I found a blog post about using the GMail Greasemonkey API by Eric [...]