javascript


After an hour or two of sleuthing I’ve discovered that jQuery 1.2.6 does not set the Content-Type header for HTTP GETs even if you explicitly use the contentType parameter. My understanding of the jQuery rationale is that GETs don’t contain data and therefore a Content-Type header is not required. Unfortunately, Microsoft reckons that GETs returning JSON provide a security risk and that a Content-Type header must be specified. Scott Guthrie explains it here http://weblogs.asp.net/scottgu/archive/2007/04/04/json-hijacking-and-how-asp-net-ajax-1-0-mitigates-these-attacks.aspx.  

After reading documentation from both camps I can fully understand their opposing views.  Ultimately it is yet another indicator that the responsibility of user protection lies in the browser is blatantly wrong!  If the browser raised a message asking the user if they are ok with a cross domain request and acted according to the response it would render both jQuery’s and Microsoft’s approaches obsolete.

So now I am caught between a rock and a hard place.  I love jQuery and I love Microsoft ASP.NET webservices and I am going to use both in my current projects.  But, if I can not explicitly set the Content-Type header for an .ajax() GET then I have just one choice and that is to use POSTs instead.  Unfortunately this contradicts the notion of using the correct HTTP verbs and removes the possibility of a RESTful API. 

It’s always about compromise.

Advertisements

Here is a slightly updated version of the code from my previous post. The alert box that appears will also display the title and url for the current page. Try the bookmarklet on different pages and you will see it has access to the current document.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
   <title>Hello World</title>
</head>
<body>
   <a href="javascript:{alert('Hello World!\n\nFrom ' +     
      document.title + ' @ ' + document.location.href);}">
      Hello World!</a>
</body>
</html>

About a year and a half ago I had to create a simple bookmarklet for a work project that captures the url and title of the current page. While there was a lot of information scattered about the internet there was no single step-by-step guide that I could find. As I started to learn more about bookmarklets I gained a greater understanding of their potential. Many new ideas came to mind that I never had time to explore until now.

This series of posts is intended to provide that simple step-by-step guide as well as offer some new and exciting bookmarklets ideas.

How does a bookmarklet work?

A bookmarklet is simply a bookmark that uses the javascript: protocol instead of the more usual http(s): protocol. When you click on a bookmarklet from your Bookmarks toolbar the javascript is executed within the context of the current document.

Since a bookmarklet is just another url it can be presented in a webpage just like any other link. Adding a bookmarklet to the browser Bookmarks toolbar is just a matter of dragging and dropping the link. A bookmarklet can even be put into a folder on the Bookmarks toolbar for less frequest access.

Bookmarklets also have access to any other Uri and are not limited by the same-origin policy. Bookmarklets often inject into the current tab a script tag that points to a completely different domain. Since the script tag has access to both the current document and the remote domain it can pass information between them.

Of course, passing information between domains has security implications. Users adding bookmarklets to their toolbar should do so only in trusted situations. Since there is no universal code signing mechanism for javascript, bookmarklets should be treated with the same caution as any other website.

Known Issues

  • Javascript is required. It goes without saying that any link that uses the javascript protocol is going to require that javascript be enabled in the browser.
  • Framesets present a challenge too since there is no DOM element to attach a child script element to.

Hello World

Lets create the simplest of bookmarklets. No web server is required and the IDE of choice can be as simple as notepad. Copy the following code block into a new text document and save it with an appropriate name. I named mine helloworld.htm but you can choose whatever you like as long as the extension is recognized by your web browser.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
   <title>Hello World</title>
</head>
<body>
   <a href="javascript:{alert('Hello World!');}">Hello World!</a>
</body>
</html>

After you have saved the file open up your web browser and navigate to the file or double click it from within Windows Explorer or the Mac Finder. You should see a plain white page with a single link. Drag that link to your Bookmarks toolbar and when you drop it you should see a new button labelled Hello World!

Navigate to a totally unrelated page then click the button.

Assuming there were no accidental typos you should see an alert box with the Hello World! text in it.

Congratulations. You have created your first bookmarklet. In part II of this series I will show you how to do something a little more useful than hello world. I will demonstrate how to manipulate some information from an existing page and present it in an embedded iFrame.

I have been using xml and xslt for over a decade now and find it a great format for exchanging data between systems.  I used to use it for sending data between a web server and browser in my “corporate” days.  All of my work back then was for various fortune 500’s where the browser was dictated to be IE so transforming xml using the msxml libraries was a cinch.  Fast forward to now where I’m designing Ajaxified cross platform web applications and suddenly xml can’t be used.  The cross-domain issues and non-standard transformation support make xml consumption a nightmare at best.

This is becoming a bigger issue for me (and many others I suspect) as I try to dynamically load and consume RSS feeds cross-domain.  So now I am investigating a simple solution – JSON.  JSON data can be easily obtained from other domains and it can be queried in a similar fashion to xpath by simply walking the object/property structure. 

Today almost all RSS syndicators are publishing in the traditional XML format so it is necessary to parse RSS to JSON somehow.  Hopefully this will change and a complimentary javascript format will emerge.  In the mean time I am going to find/build some tools that will perform this transfer on the fly.

My first such tool uses Yahoo Pipes to grab the headlines from the Ajaxian RSS feed.  I have published a stupidly simple Pipe that can be found at http://pipes.yahoo.com/pipes/pipe.info?_id=_osFeI7W2xGPFy3cqGIyXQ.  It takes one parameter; the URI of a feed and simply retrieves and returns the contents of the feed.  The cool thing is Pipes can be forced to output in JSON format rather than XML by simply setting the _render querystring variable to “json”.

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>
<html xmlns=”http://www.w3.org/1999/xhtml” >
<head>
<title>Untitled Page</title>
</head>
<body>

</body>
</html>
<script language=”javascript” type=”text/javascript”>
var pipeCallback;
var data;
function pipeCallback(d) {
data = d;
console.debug(d);
var arts = d.value.items;
for (var i=0; i<arts.length; i++)
{
var a = document.createElement(“a”);
a.setAttribute(“href”, arts[i].link);
a.innerHTML = “<h1>” + arts[i].title + “</h1>”
var dv = document.createElement(“div”);
dv.innerHTML = arts[i].description;
document.body.appendChild(a);
document.body.appendChild(dv);
}
}
</script>
<script type=”text/javascript”src=”http://pipes.yahoo.com/pipes/pipe.run?urlinput1=http%3A%2F%2Fwww.ajaxian.com%2Findex.xml&_id=_osFeI7W2xGPFy3cqGIyXQ&_render=json&_callback=pipeCallback”></script>

Next I am going to build an XSLT to transform an RSS file to its JSON equivalent.

An interesting article that introduces a useful function called graft().  graft() takes a JSON string defining a serious of DOM elements and returns a DOM fragment that can be inserted into the document element.  Now I haven’t tried the code in this article yet and some of the comments indicate that there maybe some truncation so be forewarned.

Making Javascript DOM a Piece of Cake with the graft() Function

This article from Jonathan Snook is a great primer for JavaScript objects. It describes how to create and use functions, templates and the prototype keyword. It also talks about singletons and object factories.

Digital Web Magazine – Objectifying JavaScript