Thursday, August 16th, 2007

Purple Include 1.9

In July, Brad Neuberg and a group of talented hackers released Purple Include, a library that does transclusions.

Now there is a new version which is a major refactoring that simplifies working with the library and now works across all major browsers.

Brad tells us more:

Purple Include is a client-side JavaScript library that allows you to do client-side transclusions.

What the heck does that mean?

It means that you can include and display fragments of one HTML page in another without copying and pasting any content. For example, you could quote the second paragraph from another person’s blog entry by embedding something like:

  1. <div href="[2])"></div>

in your blog page. The expression following the explanation point in the URL is an XPath expression.

If the page you want to transclude has a fragment identifier or a purple number, you can transclude that directly:

  1. <div href=" "></div>

In fact, all you have to do is add an ‘href’ attribute to any of the following types of HTML tags in order to have that URL transcluded right into the page when the page loads:

  1. <p href=""></p>
  3. </blockquote><blockquote href="[2])"></blockquote>
  5. <div href="includeme.html#foobar"></div>
  7. <span href="../../relativefile.html#foobar"></span>
  9. <q href=""></q>

Here’s the great thing about this new release — there’s nothing to install! We do some magic (see the Release Notes below to see how) to make it so that you have absolutely no server to install. I host everything on my webserver now, at, even the inclusion service and JavaScript, so all you have to do is add the following JavaScript to the top of your page:

<script src=””></script>

Plus, Purple Include now works across Safari, Internet Explorer, and Firefox (Opera probably too — I just haven’t tested). The client-side JavaScript is now just about 9K.

See the example page for examples and usage. Also see the README file. You can view the JavaScript file as well if you want.

This is all beta stuff, so as usual, if you see bugs, tell me — or even better, fix it ;)

RELEASE NOTES for August 15th, 2007 Purple Include 1.9

This is a pretty radical refactoring of the Purple Include code. The big highlights in this version:

* Now works cross-browser: Internet Explorer, Firefox, and Safari (Opera should work but has not been tested)

* There are no server-side requirements anymore. Instead, the inclusion service is hosted on my web site at and we do a trick in the JavaScript (the JSONP/Script tag trick) in order to do transclusions through a third-party web site. All you have to do is drop the JavaScript into your page and start using it.

* We no longer have an tag; instead, you can simply add an ‘href’ attribute to many different HTML types and have that type transclude it’s contents:

  1. <p href="[@id='table_of_contents'] ")</p>

This works for the following tags: P, BLOCKQUOTE, Q, PRE, DIV, SPAN

* The client-side script has gotten vastly smaller and simpler — the script is now only about 9K.

* We now use the notation #xpath(//p) around an XPath expression rather than using an exclamation point, such as #xpath!//p. This is in keeping with the pseudo-standard that has developed around this practice, such as #xpointer() — it also opens up the possibility of chaining together expressions in the future, such as #xpath(//expression1)xpath(//expression2), which would return the results of both expressions.

* The little roller image, roller.gif, used to be a pain in the butt to configure because it was always relative to the page you are using transclusions on, which therefore required you to specify a relative path or something using a META tag. To cut down on configuration, I now just host this image on my web server — you can set it to your own path using the META tag ‘purple.include.rollerURL’ but we default it inside the code to my webserver. This means that all you have to do now to use Purple Include is have the JavaScript file — that’s it.

Posted by Dion Almaer at 9:47 am

2.8 rating from 46 votes


Comments feed TrackBack URI

Nice work Brad! I am happy to see JSONP in use, I have been hoping that would gain momentum. Just of curiosity, did you move the xpath processing to the server (perhaps that’s how you decreased the size and added cross browser support)?

Comment by Kris Zyp — August 16, 2007

Sounds interesting. It however breaks validation on most elements except perhaps blockquote which has the cite-attribute – but this script uses the non-existent href-attribute on blockquote elements anyway – why? Wouldn’t it be more semantically correct to use cite?

For the other objects – really nice, but what if I have turned of my javascript? Shouldn’t I be informed about the texts anyway?

Perhaps instead of having a href on an element not supporting it, one could assign a class to that element and add the href to a link within the container. That link could then be replaced by the fetched text and this would all be a bit more unobtrusive :)

Comment by Pelle — August 16, 2007

How do they handle the non-technical issues?
* They are putting load on the targeted page. The page owner might not want their information embedded in this way. How do they handle attribution?
* The targeted person could change their content – remember the microsoft / goatse insident?

Comment by Steve Brewer — August 16, 2007

Thx a lot from Ushuaia, Argentina [end of the world].

Comment by Matias — August 16, 2007

You can only include each item once on your page. E.g.

Item 1:

Blah blah blah
Item 1 again:

One of the two above spans will get stuck with the twirly and not the target content.

Comment by Mark — August 16, 2007

The examples link didn’t come through in the post:

Also, it works on the iPhone as well, even on the Edge network!


Comment by Brad Neuberg — August 16, 2007

I’ve said it before, and I’ll say it again: Brad’s the man.

Comment by Ryan Breen — August 16, 2007

Thanks for the nice comments Ryan and Kris!

@Kris: All the processing is now on the server, but rather than the classic client vs. server debate it’s a new debate ;) Now, we can have thick servers without having to have thick clients, but the server is a hosted solution so the developer/end-user never has to setup a server. The server is hosted at, so the client-side is just a thin layer of JavaScript to prepare the arguments and send them over using JSONP by adding a dynamic script tag to the document, getting the results back as a bit of JavaScript. The server actually implements XPath 2.0 processing, btw. You could imagine other kinds of addressing schemes on the server as well, such as a #line(55) scheme which would let you grab a certain line of a text/source code file; #line(55)-line(100) would grab a chunk of lines; etc. Since this is all on the server-side now (Java), it’s much easier than it would be on the client-side and makes support more broad.


Comment by Brad Neuberg — August 17, 2007

Ug. First hot-linking images, now every browser is going to be a scraper?

Though I do see how it would be personally fun to use. But would Brad want me to put this on millions of page views a day, grabbing a paragraph from his blog? (Maybe!)

Comment by Steven — August 17, 2007

Hi Steven — I like to hit scalability limits when they actually happen, versus theoretical ones — get the functionality right first. If you deploy this on a huge site, just host it yourself (you can override all the defaults). Also, in the future, I might look at using Amazons Elastic Compute service to host this. But, I want to wait until there is actually a scalability need for something like that.


Comment by Brad Neuberg — August 17, 2007

Oh, you meant someone grabbing a paragraph from my site with a million visitors. Well, that is a scalability wall too that we’ll solve when we actually hit it — I’m sure that we could engineer the Purple Include service hosted on my site to simply cache a page for a given period of time, perhaps 30 minutes.

Comment by Brad Neuberg — August 17, 2007

Similar to XHTML 2 where “any element may have a src attribute, which specifies a resource (such as an image) to load instead of the element”.

Comment by rvm — August 25, 2007

Any possibility to make transclucion on demand (i.e event based) rather than load event?

Comment by Alixe — October 4, 2007

I’ve tried to use the script for grabbing some daily bible verses from this site : and including them in our pages, but the formatting and special fonts are not coming through.

This is the result:
Jes 55,6-7

6 S�k Herren mens han er � finne,
��������kall p� ham den stund han er n�r!
��� 7 Den ugudelige skal forlate sin vei
��������og ugjerningsmannen oppgi sine tanker
��������og vende om til Herren,
��������s� vil han vise barmhjertighet,
��������til v�r Gud, for han er rik p� tilgivelse.

Comment by Vidar Bøe — October 26, 2007

I really like the idea behind this. I had been assuming that XQuery would be the vehicle since it include the doc() function that pulls an XML/XHTML from anywhere, not just the same domain. This is as opposed to the Javascript cross site scripting issue (XSS).

I think that you should be more upfront about this and recommend a server side replacement for your workaround, for example, having a URL proxy system (like a redirect, but instead a proxy that grabs external web docs by just appending the external to a proxy URL). This way the work done by your Javascript can be carried by sites that want to have a dependable process and not burden the one you use.

The second issue is the use of the href attribute. I know that this is similar to some HTML friendly templating languages, however the href attribute is not allowed for valid XHTML in the elements you use. XInclude cant be used yet. To be valid, I might suggest using the “a” element with the href attribute and a specific class attribute. The other positive about this technique is that it gently degrades to a link (and with xpointer, some browsers might even go to the right part). Another work around is to use the object element (ok, not so good, but I think it was the element that was supposed to be used for this).

Comment by citizencontact — April 25, 2009

Leave a comment

You must be logged in to post a comment.