Tuesday, March 19, 2024

Reference External Resources from your Bookmarklets

Reference External Resources from your Bookmarklets

Since I first wrote about Bookmarklets a while back, my appreciation of their usefulness has only grown. Case in point, in my Automate Form Submissions using Bookmarklets article, I showed how they could be utilized to execute multiple form submissions, all without any user intervention. More recently, I was contacted by an attorney who wanted to populate US Social Security applications with data from a MySQL database. At first thought, one would think that this can’t be done on account of browser “sandboxing”. However, with an extra piece, it is possible to access all manner of external resources. In this tutorial, I’ll show you how to reference external resources from a bookmarklet.

What You’ll Need

What is the extra piece that I alluded to in the introduction, you might ask? It’s a web server. Although we tend to associate servers with something that runs on a hosting provider, web developers often run them locally as well. There are many excellent free small-scale servers available for local usage on a variety of platforms. The real deciding factor is what server-side language you want to write your resource access code in. If you’re not proficient in any other languages besides JavaScript, fear not! There are several JavaScript engines to choose from, including node.js, SpiderMonkey, and Rhino.

For the purposes of this tutorial, I’ll be using PHP, a widely-supported server language that most web developers are familiar with. For my server, I went with Wamp, a Windows server that specializes in web application creation with Apache2, PHP and MySQL databases.

The Bookmarklet Code

Unless your bookmarklet is ridiculously simple, it’s advantageous to place the bulk of the workload in a separate .js file. All you have to do is append your script file to the document like so:

javascript:(function(){
   var script=document.createElement('SCRIPT');
   script.src='http://localhost:8080/ajaxBookmarklet/ajaxBookmarklet.js';
   script.id='ajaxBookmarklet';
   document.body.appendChild(script);
})()

Notice that the path to the document is absolute and not relative. That’s because all scripts run as if they reside in the same directory as the currently loaded document. Hence, it’s root is prepended to all relative links.

Once, you’ve written your script appending code, use a bookmarklet minifier to remove whitespace. Mr Coles and subsimple are two good examples.

The ajaxBookmarklet.js File

Making Ajax calls is a lot easier using a good JS library like jQuery. I covered how to append it in the Automate Form Submissions using Bookmarklets tutorial under the Loading JS Libraries header, so I won’t belabor that point. The more interesting part to us is the fetchData() function that calls our PHP script.

Recall that our script runs as part of the document in which it’s embedded. Therefore we can only make Ajax calls to the host server. Attempting to call any other domain, including ours, will likely result in the familiar “No ‘Access-Control-Allow-Origin’ header is present on the requested resource.” cross-domain error. Sounds serious, until you realize that jQuery is very adept at making JSONP calls. JSONP (“JSON with Padding”) can bypass the cross-domain policies in web browsers by abstracting the difficulties associated with cross-domain requests. It does this by returning JSON data wrapped in a JS function. This “wrapped payload” is then interpreted by the browser as a function that we already defined in the JavaScript environment. It effectively unwraps the payload and can then work with the JSON object.

With respect to the Ajax call, all we need to do is set the dataType to “jsonp” and set the jsonpCallback method to the name of our function that will handle the JSON response. As par for the course, the expected contentType is JSON.

The jQuery library is referenced using its full name rather than the dollar sign ($) just in case the parent page called jQuery.noConflict().

if (window.jQuery === undefined) {
    var j = document.createElement('script');
    j.src = 'https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js';
    j.onload = fetchData;
    document.body.appendChild(j);
}
else {
    fetchData();
}

function fetchData() {
        var rootUrl = jQuery('#ajaxBookmarklet').attr('src');
        jQuery.ajax({
          url: rootUrl.substr(0, rootUrl.lastIndexOf('/') + 1) + "dbhelper.php",
          type: 'get',
          dataType: "jsonp",
          contentType: "application/json",
          jsonpCallback: "jsonCallback"
  });
}

function jsonCallback(json){
    alert("In jsonCallback! Got " + json.field1 + ", " + json.field2 + ", " + json.field3);
}

If you look at the url for our dbhelper.php script, you’ll notice that we’re using a trick to obtain the root of our local server. It is the same as the ajaxBookmarklet script that we appended earlier. We assigned it an ID so that we could refer to it later and read its src property. We can then lop off the file name and replace it with our php script.

The dbhelper.php Script

In the next instalment, we’ll be reading from a MySQL database from the dbhelper.php script. For now, let’s code the PHP script so as to test the communications between our bookmarklet and server. There are three key statements involved in returning JSONP data to the browser:

  1. Set the Content-Type to “application/json”.
  2. JSON-encode the data.
  3. Wrap the json-encoded string in a callback function whose name matches that of the function that you passed to the jQuery.ajax() call, which in turn matches the name of your function in the ajaxBookmarklet.js script.
<?php

header('Content-Type: application/json');
//return some sample data
echo 'jsonCallback('. json_encode( array("field1"=>"Maryland", "field2"=>"37", "field3"=>"43") ) .')';

Now when you run your bookmarklet you should see the output of the above object: “In jsonCallback! Got Maryland, 37, 43”.

Here are the files from today’s tutorial.

Conclusion

Being able to access external resources from your bookmarklets opens up a whole new world of possibilities. In the next instalment, we’ll use this technique to populate HTML5 form fields from a MySQL database.

Rob Gravelle
Rob Gravelle
Rob Gravelle resides in Ottawa, Canada, and has been an IT guru for over 20 years. In that time, Rob has built systems for intelligence-related organizations such as Canada Border Services and various commercial businesses. In his spare time, Rob has become an accomplished music artist with several CDs and digital releases to his credit.

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Popular Articles

Featured