Pathfinder Blog
Topic Archive: BJAX

Bjax: Make it Play MP3’s

It's nice to know you've inspired someone and it was very nice of Chris Anderson to drop us a note on his own Bookmarklet: Make it Play. Basically, this bookmarklet will scan a page for mp3 links and then insert a little semi-transparent media player interface at the bottom of the page.

It's not SongBird, but it's a good demonstration of the power of Bjax -- injecting user interface to improve an existing web interface. Based on JQuery.

Technorati Tags: , , , ,

Parsing HTML with innerHTML

Yes, yes, innerHTML is "the debil." Direct DOM manipulation is much to be preferred. It's faster, smells less, and gives you shiny white teeth. But innerHTML, when combined with XHR, can allow you to scrape data from the existing HTML pages of a site.

var div = document.createElement(div);// do the XHR thing...div.innerHTML = response.responseText; // contains the full html of a page// voila, div now is the Root of an HTML DOM tree that can be traversed for screen scraping

Now remember, don't hook the div node into the page with appendChild. Yes, it is a hack that makes use of the browser's built-in parser, but it is a useful hack nonetheless. I have seen only a few mentions of this technique (see the references). Maybe it's because this seems like such a contrary thing to do. If you are in control of an application or site, you have control of the server and what runs on it, after all. You could just write a quick XML service that can be requested and parsed by an Ajax client, right?

Well, that's not always possible when integrating widgets with third-party or other closed source packages. A common solution has been to proxy and scrape an application with a combination of XQuery and TagSoup (to fix the ugly, broken HTML, dontcha know), but it is possible to do this purely in the browser. And browsers don't need TagSoup as they are masters on wrangling broken HTML.

Another use of this technique is for injecting a new user interface on top of web sites and applications via bookmarklets or Greasemonkey. I've been tinkering with SuperCraig, a makeover of the Craig's List interface that makes use of this technique.

There are limits to this technique. For example, scripts are ignored and images are not loaded when the div is not hooked into the document, so a site that depends heavily on Javascript for its content. may withhold it's secrets from the screen scraper. That sort of site is likely to have HTTP requests that produce XML, however, so it will give up it's secrets in other ways.

Anyhow, that's the story on tinkering with bookmarklets and interface injection. I wanted to finish SuperCraig for today, but the grind of work sometimes gets in the way.

References

    Topics: ,

    BJAX: A Quick Hack for Using GWT with Bookmarklets

    BJAX = Browser Extensions + Ajax

    I've continued my explorations on how to use GWT in unconventional ways, starting with how to load a GWT application through a bookmarklet. That's been made much easier with GWT 1.4 through the introduction of a "cross site" feature:

    Cross-site script inclusion is now supported. The compiler produces a "-xs" (meaning "cross-site") version of your module's startup script that can be included without being restricted by the same-origin policy. Be careful, though. Including scripts from other sites that you don't fully trust is a big security risk.

    There has been some confusion about this "option." Some developers thought that "-xs" was a command-line flag you had to pass to the GWT compiler. In fact, the GWT compiler produceds a file with "-xs" in its name as a part of its normal workings -- no special flags necessary. This file, when included in a page via a script tag, loads the GWT application as a Javascript (a ".js" file) into the current browser window. That's opposed to the iframe/html way it's been up to now.

    Obviously iframe/html way is not suitable for things like bookmarklets, as the cross-domain thing gets in the way. With the pure Javascript approach, our problem is solved, right? Not so fast. If you try including the "-xs" Javascript file into a page via a bookmarklet, you get the dreaded hanging page with a perpetual "Loading..." message in the status bar. Why is that?

    A little tour through an "-xs" file reveals that GWT assumes that the Javascript file is loaded during the normal loading/rendering of the page. Specifically, it uses document.write to insert script tags and uses an onload event handler to kick off the application code.

    var $wnd = window, $doc = document, external = $wnd.external, gwtOnLoad, bodyDone, base = '',metaProps = {}, values = [], providers = [], answers = [], onLoadErrorFunc, propertyErrorFunc;[...]var oldOnLoad = $wnd.onload;$wnd.onload = function(evt){    if (oldOnLoad) {      $wnd.onload = oldOnLoad;      $wnd.onload(evt);    }    bodyDone = true;    maybeStartModule();}[...]$doc.write('<\/script>');

    Of course this doesn't work so well with a bookmarklet. For one, the onload event is already long gone by the time we run our code, and for another, document.write after a page has rendered will cause precisely the "hanging page" behavior we see when we try to load the GWT app via a bookmarklet. Really, this is less of a specific bookmarklet problem and more of a general "how do I get GWT to load after a page has already rendered" problem. So, what can we do to remedy this it?

    First, we can simply use document.appendChild to insert the script tag, second, we can assume that the body has finished loading, and third, we will have to tell GWT where to find the application code. Why this last step? Because GWT uses a "marker script" to figure out the source URL of the GWT application:

    function computeScriptBase(){    var thisScript, markerScript;    $doc.write('<\/script />');    markerScript = $doc.getElementById('__gwt_marker_MyApp');    if (markerScript) {      thisScript = markerScript.previousSibling;    }    function getDirectoryOfFile(path){      var eq = path.lastIndexOf('/');      return eq >= 0?path.substring(0, eq + 1):'';    }
    
        ;    if (thisScript && thisScript.src) {      base = getDirectoryOfFile(thisScript.src);    }    if (base == '') {      base = getDirectoryOfFile($doc.location.href);    }     else if (base.match(/^\w+:\/\//)) {    }     else {      var img = $doc.createElement('img');      img.src = base + 'clear.cache.gif';      base = getDirectoryOfFile(img.src);    }    if (markerScript) {      markerScript.parentNode.removeChild(markerScript);    }}

    When you use document.appendChild, this code stops working. Now there's probably a way to make this code work with appendChild, but I haven't noodled about it enough. That's why this post is termed a "Quick Hack."  We do some simple surgery with the "-xs" file as follows:

    function insertScript(src) {    var script = document.createElement("script");    script.type = "text/javascript";    script.src = src;    $doc.body.appendChild(script);}[...]function computeScriptBase(){    base = "http://labs.pathf.com/MyApp/";    bodyDone = true;}[...]insertScript(base + strongName);

    With these changes, the GWT app can now be load via a bookmarklet.

    Next week, I hope to demonstrate a few interesting hacks using GWT and bookmarklets. Maybe I'll even give the dowdy Craig's list a much needed overhaul. Stay tuned...

    Technorati Tags: , , ,

    Topics: ,

    Google Gears Security Thoughts

    The new Google Gears comes with a long set of security warnings and disclaimers. Nitesh Dhanjani over at O'Reilly's ONLamp.com had some initial thoughts about the security of Google Gears:

    If I had to pick ..., I’d guess that we are most likely to hear of existing XSS or browser vulnerabilities being abused to steal (or manipulate) Gears databases.

    I agree with Nitesh: the attack vectors will remain the same, but the consequences will be much greater. Some folks, such as those working on the Dojo framework, are addressing some of the offline storage issues with encryption:

    Right now Dojo offline adds a DES encryption library with functions to encrypt and decrypt. The example used encrypting/decrypting SSNs. He also pointed out that doing this in javascript can be computationally intensive and hasn’t been that feasible before. Right now though using Google Gears worker threads they can encrypt/decrypt in javascript at about 80k/second.

    You could also roll your own from  this implementation of AES, RC4, RSA and a number of other algorithms. While this approach solves the stolen laptop problem, it doesn't solve the XSS problem, i.e. as long as you can inject Javacript into a page, you can bypass this security. After all, the plain text has to pass through the sandbox, where it is fair game. In this case, Google Gears just papers over the shortcomings of browsers.

    It is possible that WorkerPool could be used to limit the kinds of modifications that are made to the encrypted data:

    The WorkerPool behaves like a collection of processes, rather than threads. Workers do not share any execution state.  Changing a variable in one worker has no effect in any other worker.  And created workers do not automatically inherit script code from their parents.

    Members of a WorkerPool interact with each other only by sending message strings. Workers can also pass richer data types, by first converting objects to strings using JSON.

    We can hide the encryption details in a WorkerPool member and communicate with it via messages. We still pass plain text data through the main browser execution context, but we can at least regulate the access to the encrypted database -- i.e. no bulk downloads or modification.

    As a final thought, what's bad for ActiveX is also bad for Google Gears. The fact that the project is open source and thus not a black box, mitigates this criticism only somewhat. To make me comfortable with Google Gears, all of the XSS volnerabilities will have to be closed first.

    Technorati Tags: , , , ,

    BJAX - Hacking Google Maps with Bookmarklets

    How many of us have passively watched a film or read a book or used a web site and said to ourselves, "That could have been better. If only they had changed this aspect or that, it would have been so much better." Then we leave the theatre, close the book or navigate away from the web site and go on about our vaguely dissatisfied lives.

    While many of us won't be able to edit films or adapt books anytime soon (sure, sure, some people are mashing up films, and fan fiction has been around for a while, but it's actually kind of hard and time consuming to do), but people have been hacking web sites with tools like Greasemonkey for a while now, but it's starting to get easier to achieve powerful results with the adoption of Ajax.

    One of the neat things about Ajax apps that use a well defined API is that it is pretty easy to modify their behavior using BJAX -- Browser Extensions and Ajax. Google maps is an excellent example of this sort of API; if you can predictably get ahold of a reference to a Google maps object, you can manipulate it in a myriad of ways.

    One of the things I hate about many mapping sites -- those that display information on real estate, restaurants and coffee shops -- is that they don't display important navigation information, such as the locations of subway stops. Trulia is a representative example of such a site. It's a handy way to search for realestate that is for sale, by Zipcode and various other parameters. One of the things I found myself wishing for over and over again was a visual display of El stops.

    preline.png

    The elevated lines in the map above are barely visible as little gray hash lines, and forget about seeing the stations. But adding lines and markers to this map is pretty simple if you know the Google Maps API.

    Drag the following link, CTAMap (see this entry to see how the Javascript for the bookmarklet is done) to your toolbar (or bookmark it if you are using IE). Now search again on Trulia for properties in Chicago (try 60660 for a Zipcode), then click on the bookmarklet. You should see El lines and stations now on this map (see below). Until Trulia adds this sort of functionality, this is one way of making their service more useful.

    postline.png

    The Javascript that populates the map can be found here. Note that this code searches the global scope object for a GMap2 object to a depth of one property (variable and variable.child) and uses this object to manipulate the map. This bookmarklet works with Trulia, HousingMaps, but not maps.google.com itself. I'll have to do a little bit more spelunking to find the object there and in a few other recalcitrant site.. Below is a sample of the code that is included.

    map.addOverlay(new GPolyline([
    new GLatLng(41.794771, -87.618222)
    , new GLatLng(41.780238, -87.615488)
    , new GLatLng(41.780415, -87.605783)
    ], "#006400", 5));
    map.addOverlay(new GPolyline([
    new GLatLng(41.794771, -87.618222)
    , new GLatLng(41.779229, -87.644781)
    , new GLatLng(41.778943, -87.664221)
    ], "#006400", 5));
    map.addOverlay(CTAMap.createMarker(41.910821, -87.649403, "North & Clybourn Station: 1599 N. Clybourn Ave., Chicago, IL 60622"));
    map.addOverlay(CTAMap.createMarker(42.019375, -87.672232, "Howard Terminal: 1649 W. Howard St., Chicago, IL 60626"));
    map.addOverlay(CTAMap.createMarker(41.874265, -87.627675, "Harrison Station: 608 S. State St., Chicago, IL 60605"));
    map.addOverlay(CTAMap.createMarker(41.97327, -87.658443, "Argyle Station: 1118 W. Argyle Ave., Chicago, IL 60640"));
    map.addOverlay(CTAMap.createMarker(41.891447, -87.628078, "Grand Avenue Station: 521 N. State St., Chicago, IL 60610"));
    map.addOverlay(CTAMap.createMarker(41.868119, -87.627398, "Roosevelt Station: 1167 S. State St., Chicago, IL 60605"));
    map.addOverlay(CTAMap.createMarker(41.883696, -87.627891, "Washington Station: 128 N. State St., Chicago, IL 60602"));
    

    The same thing could be done with the train lines of other cities, bus lines, or other important geographic features.

    So, the next time you find a web site or application you think comes up short, don't just throw up your hands, make it better with BJAX.



    Technorati : , , ,

    Topics: ,

    Using Bookmarklets to Disruptive Effect

    But any big change is more likely to result if there is a disruptive event such as new technologies or platforms that have a surprising effect on market share. -- Trip Hawkins

    My consulting company is relatively small, so I love disruptive technologies. I see them as opportunities to sneak up on the big boys. I suppose that if I were one of the big boys, I wouldn't be so enthusiastic about disruptive technology. But there it is. Bookmarklets and Greasmonkey are just such disruptive technologies. They let you create mashups and manipulate pages in ways that were not intended by the original authors. They are a way to make content and sites work better for you.

    While Greasemonkey lets you automatically execute scripts after page has loaded and allows you to make XHR requests to other domains, it requires a user to install a plug-in that isn't easily available for all browsers. Bookmarklets, on the other hand, are as easy to install as a bookmark, but they require a user to click or select a bookmark in order to work.

    Last time, we saw how to load additional JavaScript into the browser in order to exceed the size limits of the bookmarklet itself. This time we're going to hack the front page of the New York Times with our own news. First, we need a bookmarklet that will load our actual script. We simply adapt our code from last time to load our nyt.js script.

    javascript:(function(){var s,d=document,a=function(o){d.body.appendChild(o)};s=d.createElement('script');s.type='text/javascript';s.src='http://labs.pathf.com/bm101/nyt.js';a(s)})();

    The code simply inserts a script element that points to our JavaScript file. You can see the live link below.

    Drag the following link to your toolbar or bookmark it:
    NYT Hack

    If you now navigate to the New York Times home page and click on the link, you should be able to see some stories about Iraq inserted above the fold.

    nythack.jpg

    How did I do this? Well, it's all about what I packed into that nyt.js file. What's in there? Well, first I added in JQuery, my favorite Javascript library of the moment. Since the New York Times site doesn't use Prototype or anything that declares a $ function, we don't have to take any special precautions. Next, I defined a utility function to load in a script from a URL:

    // NYT Funcs
    
    var NYTHack = new Object();
    
    NYTHack.addScript = function(url) {    var scr = document.createElement("script");    scr.type = "text/javascript";    scr.src = url;    $("body").append(scr);}

    This is the same trick as earlier. Instead of performing an XHR, we inject Javascript which is executed withing the context of the current page. And what do we inject?

    NYTHack.insertYahooNews = function() {    // insert the yahoo news script tag with a callback    NYTHack.addScript('http://api.search.yahoo.com/NewsSearchService/V1/newsSearch?appid=YahooDemo&query=iraq&results=5&language=en&output=json&callback=NYTHack.callBack');}
    
    // run me$(document).ready(function(){    NYTHack.insertYahooNews();});

    We load from Yahoo's News Search Service. Why Yahoo? Because they let you specify JSON as the output format and further specify a callback function, to which the JSON object is passed as a parameter. Our callback (along with a utility function) looks as follows:

    NYTHack.buildStories = function(div, json) {    var stories = json.ResultSet.Result;    for (var i = 0; i < stories.length; i++) {         div.innerHTML += '<h4><a href="' + stories[i].Url + '">' + stories[i].Title + '</a></h4><p>' + stories[i].Summary + '</p>';    }}
    
    NYTHack.callBack = function(json) {    var div = document.createElement("div");    div.id = 'nythack';    div.style.border='1px solid #ff0000';    div.style.padding='5px';    var hl = document.createElement("h2");    hl.innerHTML = "Iraq News from Yahoo!";    div.appendChild(hl);    NYTHack.buildStories(div, json);    $("#mainTable").before(div);}

    Nothing fancy. We just pull titles, summaries and url's out of the JSON object and construct a set of headlines and links. Then we insert it ahead of the main content section of the NYT home page.

    Now we don't do any error checking and you can run this bookmarklet in other pages than the NYT home page. Adding those in wouldn't have been too onerous, but it would have distracted from the main focus of the bookmarklet and cluttered the code. Ideally we would check in the bookmarklet itself to see whether we had already loaded it once by looking for a hidden div element with a particular id.

    Next time we will actually use the information on the page to drive what our bookmarklet does and we will use the site itself as a web service using Sarissa.

     
      Technorati : , ,

    Topics: ,

    Bookmarklets 101

    Today I want to build the "Hello World!" of bookmarklets. Actually, I'm going to build two versions, the second of which will allow us to do bigger and better things than the first. So, what exactly is a bookmarklet? It's a bookmark that points to javascript instead of a web page -- javascript:... instead of http:.... This Javascript then runs in the context of the current page -- sort of a Greasemonkey script that you invoke by clicking or selecting a bookmark.

    If you're using Firefox, this is going to be a whole lot easier than if you're using IE, Opera or Safari. In Firefox, you can drag a link to your toolbar and have it easily available for use. In IE and Opera, you can bookmark the Javascript link and have it available in your bookmarks dropdown menu. As far as Safari goes, not all bookmarklets work in it -- as we'll find out, there's not really enough space in a bookmarklet to do much cross browser support --, but this won't really be a problem for us given this bookmarklet's code and the direction we are going with the second version.

    OK, here's the first version. It's about a simple as it gets:

    javascript:alert("Title: " + document.title);

    You can try out this bookmarklet below.

    Drag the following link to your toolbar or bookmark it:
    Title

    IE will complain (provided your system has the latest security patches) about adding an unsafe bookmark. Browse to a different page and select the bookmarklet and you will see that it correctly displays the page's title. So far so good.

    What if we want to do something more substantial, say write a bookmarklet that would inspect the DOM of a page and modify it based on some sort of algorithm? Well, bookmarklets can only be so large -- no more than 255 characters in some older browsers, a few thousand characters in the case of the newer ones. If you're going to write bookmarklets that do interesting things, where are you going to put the code? One approach, is to use an Ajax technique known as DOM-based on-demand Javascript. That's just a fancy name for inserting a script element into the DOM of the current page. There are lots of bells and whistles we will add in future examples, but for the moment we will keep it simple.

    The second version looks like this:

    javascript:(function(){var s,d=document,a=function(o){d.body.appendChild(o)};s=d.createElement('script');s.type='text/javascript';s.src='http://labs.pathf.com/bm101/hello.js';a(s)})();

    At the top level we are declaring an anonymous function and calling it, all in one step -- (function() { .....})();. The code creates a script element, sets its type and source and appends it to the document. We've used lots of dereferencing to save characters, such as assigning d=document. Now, on the server-side, we create a little JavaScript file that contains our familiar alert statement:

    alert("Title: " + document.title);

    Try out our new example:

    Drag the following link to your toolbar or bookmark it:
    Title2

    OK, so what's the big deal? Didn't we just do the exact same thing in a more complicated way? Yes and no. Yes, the new bookmarklet does exactly what the old bookmarklet did but in a different way. It included a JavaScript file into the context of the current page. Into that file we could have put as much other JavaScript as our hearts desired. We could even, with some precautions, have included our favorite Ajax library to manipulate the DOM and make asynchronous requests. The bookmarklet thus becomes just the leading wedge that allows us to load in more substantial program logic.

    For a Web 2.0 example of a bookmarklet, have a look at Blummy, which allows you to share useful bookmarklets with other users. A word of warning, however, about bookmarklets: you're inviting someone else's code into your browser. Once in, they can do a great deal of mischief. When evaluating bookmarklets ask yourself, "how much do I trust this company or individual?"

    Next time we'll go beyond the mere "Hello World!" and try to be a little bit more disruptive.

     
      Technorati : ,

    Topics: ,

    Blummy - Bookmarklets with A Whole Lot of Ajax

    Another way to add Ajax functionality to a third party web page is a bookmarklet -- little snippets of Javascript that can modify the current page. Blummy takes this concept a step farther by allowing you to combine many different bookmarklets into a single dropdown, saving precious space on your browser toolbar.

    blummy.com_config.php.png

    You can drag and drop "blumlets," the individual bookmarklets that Blummy aggregates, into your drop down via the blummy.You can even write your own blumlets, if the madness takes you. As one might expect, many of the blumlets available are one for social bookmarking sites.All of your configuration information is stored with the blummy service, so in theory you can carry your blummy configuration to a different browser.


    Technorati : , , ,

    Topics: ,

    BJAX With Greasemonkey for Firefox and IE

    A few weeks ago I put together a BJAX example using Greasemonkey (BJAX = Browser Extensions and AJAX). The idea behind BJAX, of course, is that you can use AJAX widgets on third party sites and do cross domain scripting with ease. Two examples of BJAX apps are Book Burro,

    burro.jpg

    which will get you book prices from competing retailers, and MyStickies,

    stickies.png

    Which will let you put stickies on pretty much any web site and use them on any computer where you have the MyStickies plugin installed. These BJAX applications go quite a bit beyond the original intent of Greasemonkey. They don't just enhance a few link but rather let you insert little mini-applications into someone else's webapp. This is potentially very disruptive to site owners, as they can no longer control their message. Amazon and Barnes and Noble can't be happy that people can seamlessly comparison shop, and the upcoming shareable feature of MyStickies could reduce the ability of community sites to moderate their own content.

    My own BJAX application was built just for demo purposes in response to all the people who asked for a concrete example and thus wasn't particularly useful. It put the current weather in downtown Chicago, updated every minute, in a translucent box and floated it over the google.com search page. I decided to update it so it worked both with Firefox and IE and could run in the Greasemonkey clone for IE, Turnabout (get the advanced version, otherwise you won't be able to load your own scripts). The new, updated script can be found here. Three things have changed. Two of the changes are merely dealing with cross browser xml parsing and event handling. The third change is that clicking on the box now will toggle it from maximized to minimized.

    www.google.com_search.png

    Next steps are to port a client side AJAX framework so it uses GM_xmlhttpRequest, can handle being loaded after the page loads in Greasemonkey's sandbox, and doesn't have namespace conflicts with other AJAX frameworks. The mind races. Could GWT be adapted to build BJAX applications?

    One potential issue with Greasemonkey and BJAX is that Greasemonkey runs after the page has loaded and all of the page's Javascript has run. What will happen with a true AJAX application that controls its DOM much more closely. Could our inserted DIV get deleted or munged? Should Greasemonkey fire after every DOM update or XMLHttpRequest?

    Update 1: Johan Sundström takes me to task for being lazy. I've changed the test for GM_xmlhttpRequest to

    typeof GM_xmlhttpRequest != 'function'



    Technorati : , , , , , ,

    Topics: ,

    BJAX With Greasemonkey

    I've had a number of people write me wanting to know how to do BJAX (Browser Extension and AJAX) with Greasemonkey on Firefox. I thought I'd give a simple little example here. The example will show a small box in the top left corner of a google page. This box will display the weather in Chicago as served up by a Yahoo! RSS feed, refreshed every 30 seconds. Yes, yes, this isn't terribly useful, but that's not the point. Also, this is a quick hack. It won't work on IE or probably most versions of browsers.


    www.google.com_search.png


    OK, having dispensed with preliminaries, let's get started. First you'll need to install Greasemonkey. Once you've done that, download the example script here. You'll need to load it in a browser window and install it.


    There are a couple of differences in programming Javascript in Greasemonkey as opposed to a regular browser environment. We'll only touch on a few of these here, but you should have a look at Dive Into Greasemonkey for a more complete treatment.


    OK, the first step in our extension involves looking for a particular method:


    if (typeof GM_xmlhttpRequest != 'function') {
    return;



    As you can probably guess, GM_xmlhttpRequest is a special version of XMLHttpRequest that allows you to access any remote site. It isn't present in all versions of Greasemonkey, so you have to check for it. Next, we check that we have the top window. We don't want the box showing up in IFrames.


    if (window == top) {



    The next bit looks pretty standard; we create a div, give a few of the elements id's and insert it at the beginning.


    var mybox = document.createElement("div");

    mybox.innerHTML = '<div id="bjax_box" style="margin: 0 auto 0 auto; ' +
    'position:absolute; left:15px; top:15px; width:175px; opacity: .75; filter: alpha(opacity=75); z-index:100; ' +
    'margin: 5px; padding: 5px; overflow: hidden; height: auto; ' +
    'font-size: 8pt; font-weight: bold; font-family: arial, sans-serif; background-color: #ccffcc; ' +
    'color: #000000;"> ' +
    'BJAX in Action! <br/> Chicago weather: <br/> ' +
    '<p id="bjax_weather"></p>' +
    '</div>';


    document.body.insertBefore(mybox, document.body.firstChild);



    There remains the periodic call to GM_xmlhttpRequest. We parse the RSS XML and grab the second description. It's an example. In an actual app you would want to be a little more careful.


    window.setInterval(function() {
    GM_xmlhttpRequest({
    method: 'GET',
    url: 'http://xml.weather.yahoo.com/forecastrss?p=60602',
    headers: {
    'User-agent': 'Mozilla/4.0 (compatible) Greasemonkey',
    'Accept': 'application/atom+xml,application/xml,text/xml',
    },
    onload: function(responseDetails) {
    // convert string to XML object
    var xmlobject = (new DOMParser()).parseFromString(responseDetails.responseText, "text/xml");
    var condition = xmlobject.getElementsByTagName('description')[1];
    var weather = document.getElementById('bjax_weather');
    weather.innerHTML = condition.firstChild.nodeValue;
    }
    });
    }, 30 * 1000);



    A few quirks you may want to watch out for (see also this pitfalls articles):


    • When you get a DOM element in Greasemonkey, it will be a XPCNativeWrapper. That type doesn't have many properties you've come to expect, such as onclick. You can add event listeners using document.addEventListener('click',... instead.
    • The scope of functions and variables. Greasemonkey wraps your code in an anonymous functions, so you variables and functions are not available to other Javascript in the file. Use anonymous functions where you have to pass a function pointer.


    Now that you've been through this little example, you may want to uninstall the example BJAX component. Who, after all, wants weather hanging over their google search?


    One additional interesting feature of Greasemonkey is that once you've written your script, you can compile it into a Firefox extension.



    About Pathfinder

    • We design and build extraordinary applications for companies looking to make the next great idea a reality.
    • learn more

    Topics

    WordPress

    Comments about this site: info@pathf.com