Cambridge University Library

Getting started with Widgets

puzzle

Widgets are small packages of code which put information from external sources onto regions of webpages. Typically they comprise small collections of HTML, CSS, Javascript and (sometimes) XML.

In their simplest form widgets contain only an "iframe" which is a window onto a website hosted on another machine. More complex widgets contain code which is to be embedded and run actually within the outer page.

Widgets can usually be written in a day in a text editor, including the time spent to learn a new widget technology, if you have the appropriate services feeding you data. Widgets use services, detailed here to perform queries on underlying systems. A widget may, or may not, have access to further information from the container such as the current user, their permissions and so on.

For more general information on web services and widgets see our project blog here. For the full range of tools, services and gizmos provided by Cambridge University Library see our Library Toolbox.


Basic Principles

  • Widgets sit inside a widget container (aka portal). This can be as simple as a static webpage or as complex as Facebook, iGoogle, or a VLE. For most of the different containers which you will target, you will need to write a separate widget. However, writing a widget should be quick, and you can reuse a lot of your code.
  • Widgets execute entirely in the browser of the user. Any interactions which they need to make with your own systems takes place through the use of services.
  • Widgets can either use iframes or not (not using them is usually called using HTML fragments). You need to decide how yours are to be implemented (see below). But changing your mind later on isn't painful.
  • If you eschew iframes and use HTML Fragments, you write HTML and CSS to lay the widget out as you intend. Then use AJAX in your javascript to call services and then update the webpage.
  • Using iframes is simpler. You write a small fragment of code to be hosted on the container, containing the iframe "window", and then write the rest of your code on your own server.
  • If using HTML Fragments, a container will typically help you with the javascript by providing you with libraries to perform common tasks (such as calling a remote URL for services). These may well include the jQuery or trimpath libraries of useful javascript methods. Do check particularly if jQuery is installed as, if so, it can save a lot of bother. If using iframes, we strongly recommend using jQuery in your pages.
  • A container may provide you with a means of storing a user's preferences, or you could use client-side cookies. This is useful for things like preferred layout and usernames.
  • Because widgets run entirely in the user's browser, you cannot rely on what is returned for security purposes, as a user can intercept and change messages between widgets and services. (see below for help on security).

To iframe or not to iframe?

As described above, an iframe tag is like a window in one web page onto another, often on another site altogether. One use of iframes is for widgets. By placing only an iframe into the widget code for the container, the content of the widget can come from your own server, and will be put inside the iframe by the browser.

Some widget containers require the use of iframes. Others don't allow iframes, your widget must hosted on the site of the widget container as HTML fragments. Many containers allow both. If your container only allows one approach or the other, then you have no choice.

If both are available, I would recommend trying HTML fragments first, and only moving to iframes if you need to. The exception is Facebook, where iframes are generally easier. This blog post is a good discussion of an alternative perspective on the iframe vs fragments issue.

Typically, access to services will become the deciding factor in whether or not to use iframes.

An iframe widget is running on your server, and so can be given complete access to whatever else is running on your server with little difficulty. However, the widget is at some remove from the container, and so you will find it harder to access facilities provided by the container (for example, it may be harder to determine which user is using the widget).

The opposite is true of HTML fragments: they are closely embedded in the container, but further from your own services and systems.

Trying one method, and being prepared to change if you run into trouble, is probably the best approach, until you get an instinct for this decision.

Writing Your Own

If you are interested in widgets in general, but have no specific target in mind, start off by trying to write a widget for iGoogle Gadgets. This will help clarify the issues discussed in this document, ready for when you write widgets in anger.

To write an iGoogle Gadget start here. This describes writing an iGoogle gadget as an HTML fragment. The "Include Gadget" on this page is an example of an iframe-based iGoogle gadget.

If you are in Cambridge and want to write a CamTools widget, starting in iGoogle can be helpful as a CamTools start page widget is like an iGoogle Gadget, and can be written and tested as such in iGoogle. Some extra facilities are available within CamTools - for details contact the Camtools team.

To write a Facebook application start here. See here for a discussion of iframe vs fragment issues in relation to Facebook in particular.

To embed a widget into a normal web page, all you need to understand is how the iframe tag works. Write your widget as for any other iframe widget and then write the relevant iframe tag and encourage others to embed it on their page. One way to encourage this is to make the code copy-and-pastable from your site. An example of how to do this is available at talks.cam views. Instructions on embedding the Cambridge Libraries Widget in a web page can be found here.

If at all possible, use a library like jQuery to help you write your javascript. This is always possible with iframe widgets, and often provided with HTML fragments. jQuery helps you write javascript by providing common methods for manipulating a webpage which have been extensively tested and debugged. Whilst the javascript language itself is quite simple (adding two numbers, calling a function, and so on), interacting with browsers (making something green, implementing tabs), whilst superficially simple, is very subtle if you want it to work on most browsers, and best left to the experts.

Integrating With Web Services

As described in our document on web services, services are presented at a particular URL. To consume a service you need to connect to that service as if a web client. You can do this from javascript running on a user's web browser. This is known (formally erroneously) as AJAX.

However, AJAX can only issue a request to the page's originating server. In the case of HTML Fragment widgets this will be the widget container's domain (eg google for an iGoogle widget). This would make HTML Fragment widgets almost worthless were it not for the additional ability to "proxy" your request through the container: a javascript function is provided by the container to allow it to issue any requests on behalf of the widget. For iGoogle these methods are detailed here.

For iframe widgets, the originating server will be the server from which the content of the frame was served - i.e. your server. If this is the same server your web services are hosted on this may make life a lot easier when connecting to your services. Iframe widgets also allow you to implement server-side code to issue HTTP requests to any site of your choice.

Security

Computer security is very difficult. The difficulty is not only in the coding, but in reasoning correctly. Almost everyone believes their concepts are watertight, only to be surprised by an unanticipated attack. But you will probably need to think about security when writing widgets.

There are three main approaches to staying safe:

  • First, don't use security, unless you have to, and then use it as little as possible. This may sound counterintuitive at first, but the fewer things there are to go wrong, the less vulnerable your system is. Do you really need to protect this data? Also, do you really need to be so fine-grained in your control? Keeping a simple undifferentiated circle of trusted individuals is likely to lead to better security than complex fine-grained restriction in many cases. The chances of one of the trusted team betraying the others is usually less likely, or has less of an impact than, the risk of a faulty complex system revealing details to the whole world.
  • Secondly, if you do use security, use a known technique. The best are those you copy from APIs at well-regarded, popular sites. Discover the techniques they use and copy them.
  • Thirdly, apply strength in depth. Implement as many techniques as make sense, even if they seem redundant. However, beware of unnecessarily complex systems (see first point).

Useful toolkits in your armoury include: shared secrets, salts, hashes, HMACs, OAuth, Raven, Shibboleth, IP-range restriction. Google for these for details.

And always remember, a user can change anything which is sent from their browser!

Guidelines

  • Keep the widget as simple as possible: make it do one thing well. Don't dump lots of functionality into a single widget, users can install multiple widgets matching functions they choose to use.
  • Let users customise their widget. Your widget will be a part of their page. Issues as simple as title bars, multiple branding, and different colour schemes can be irritating in a page containing many widgets and, more importantly, needlessly consume a lot of screen space.
  • Consider Context. Where will your widget go? Make sure you include enough information for the user to understand what the widget does but to reduce the amount that they will already know from surrounding context. If it is to be installed in Facebook don't say "Library Widget" say which library. On your library's internet, however, say nothing.

This site has excellent general advice about designing widgets.