The Keywords plugin
The last plugin I’m going to talk about during this initial period of RedFeather development is the keywords plugin. While the ability to add keywords to a resource is desirable enough to be a candidate for inclusion in the RedFeather core itself, I’ve decided to keep it separate for the time being since it serves as such an excellent demonstration of the plugin architecture. It acts as an example implementation of many of the different features a plugin might provide, in this case:
- Modifying the metadata schema.
- Adding field to input workflow.
- Adding field to output views.
- Adding a new page.
- Adding a new toolbar item.
So, let’s start by addressing the metadata schema. This is stored in the Advanced Configuration section of the RedFeather source and is defined in the $CONF as a simple string array called ‘fields’. However, this list by itself has no function and is merely a contract that defines what fields RedFeather will look for when it tries to perform actions involving metadata. In other words, it is the responsibility of a RedFeather plugin to provide support for each field specified – fields themselves provide literally zero functionality on their own. This is implemented using function pointers (like I mentioned in an earlier blog post, EVERYTHING is function pointers in RedFeather). All a plugin has to do is loop through the fields and call a different handler function for each field in the schema. In order to maintain code readability, each of these functions should be given a descriptive name following the RedFeather conventions.
The RDF plugin for example, provides individual functions that understand how to convert the field data into triples. This means that the function “generate_rdf_field_title” should return an RDF:description involving dc:title whereas the handler for processing the uploaded file needs to return both dct:hasPart and rdf:type. This perfectly illustrates exactly why the metadata definition is entirely abstract – there is literally no way to automatically determine how to process any given field, and the additional code required to implement a system flexible enough to support this level of description outweigh any possible benefit it may give.
In the case of the keywords plugin, this means implementing additional functions for the existing core modules: resource manager, browse/view, rdf and rss. The resource manager module is responsible for generating the edit workflow so this needs to be supported first. The workflow generator automatically looks for functions in the form ‘generate_input_field_xxx’, which it concatenates to the bottom of the form. There are no explicit restrictions on what these functions return as long as they include the required <input> elements for that field. In simple cases, such as for the title, this leads to an incredibly simple, single-line definition. However, the keywords field is actually a multifield (in that it can have more than one value) so is slightly more complicated. Fortunately, RedFeather also provides a simple way to automatically support multifields, which is also utilised in the creators field.
The browse/view module is responsible for actually displaying this data, since it provides the implementation for the metadata generator. This is implemented in a very similar way to the resource manager but instead looks for functions of the form ‘generate_output_field_xxx’. This consistency when dealing with plugins and fields exists throughout RedFeather and is vital in maintaining code readability in a swamp of functions. Output fields are much simpler than input fields and just have to return the html in the form of two-column table rows, which are combined to form the metadata table. The RSS and RDF field implementations are also impressively compact so I will move on.
That is all that is needed to implement the ‘data’ aspect of the keywords plugin. Appropriate input boxes now appear on the workflow and the fields manifest in the browse view, resource view, and alternative data views (RDF, RSS and JSON). However, no keyword system is complete without a pretty tagcloud to go with it. Implementing one requires us to create a whole new page (for the tagcloud itself) and a way to get to it from the main repository (in this case, a simple menu item).
As I mentioned in my earlier post on the RedFeather architecture, pages are implemented within RedFeather using function pointers. In this case, all we need to do is write a new function in the form ‘page_xxx’ (which is then automatically accessible at index.html?page=xxx). Page functions are used by RedFeather to output data or html to the web; this can be done either manually, or using the RedFeather templating system (which I talked about in great detail in a previous post). The tagcloud is intended to be normal page within the site, so it should use the template. The system then accesses the global resource data and builds the tagcloud by writing html to the $BODY global variable; this is then written to user by calling “render_template”.
Adding a menu item to allow users to access the tagcloud from the browse page is a case of simply writing a new function in the correct format. This is then processed by the toolbar renderer and added to the menu.
This consistent, concise architecture allows even intermediately skilled programmers to very quickly create exciting new plugins and features for RedFeather.
Alternative Data Views
It is important to make sure that a repository is accessible to machines as well as humans as this allows it to be indexed more efficiently and thus more discoverable on the web. RedFeather currently supports 3 alternative data formats: JSON, RSS and RDF. Additional representations, including schema.org markup, were considered during development but taken out of scope for this initial version of RedFeather. They do, however, make ideal candidates for further work.
Out of the formats mentioned, JSON is both the simplest and most versatile since it is easily understood by both humans and machines. Unfortunately, JSON support was only introduced in PHP v5 so it cannot be including in the core and so is only available as a plugin.
RSS is intended more for digesting the repository as a whole, and as a result is only accessible as a feed from the index page. Since there tends to be a lot of variance in terms of what different stream readers expect from RSS we decided to stick with a minimal entry format to try and maximise compatibility. However, the only truly critical important API is Nottingham Xpert, since that is one of the only feasible ways to make a small source of OER, such as an independent RedFeather installation, visible to the wider community.
Due to the inherent complexity of the format, the creation of an RDF export for RedFeather presented a few interesting challenges, most of which involved the ‘creators’ field. The first problem was that of URIs. Since RedFeather is implemented as a single php file, it’s not exactly overflowing with accessible URLs that can be used to resolve a URI. This is compounded by the fact that RedFeather doesn’t really have any concept of “people” as an entity – there are no profile pages for individuals and the user account system is ONLY used for authentication. In effect, a creator is just a single name field with an optional email address associated with it. Further problems occur if a certain name appears on multiple items in the repository – how do you tell if they are the same person or multiple entities? What if they are the same person but have changed their name or email? What happens if you delete all the resources by a certain author and re-add them? Will they still have the same URI?
Trying to solve all these issues and implement a complicated system which can deal with all the fringe cases above is ludicrous when you consider the elegant simplicity of the rest of RedFeather. A better solution would be to just assume that two creators with the same name and email are the same person. This will work in the vast majority of cases except in unusual instances where no email is known and their name is something incredibly common, like Bob. We can therefore pretty much just concatenate the name and email together to form the URI – however, the URI still needs to resolve to a page that makes contextual sense for a person. To solve this we just included a special page which contains a list of all the creators who have contributed to the repository. The names on this list are then linked to using an anchor tag to give a final URI that looks something like www.example.com/index.php?page=creators#matt
Reskinning RedFeather
The default RedFeather template has a very simple but modern style that can be used directly out-of-the-box. This allows less technical individuals to quickly deploy a site without having to worry about writing their own HTML or CSS. The template also gives the user the capability to customise the colour scheme at their own discretion. This can be done purely out of personal colour preferences (if you look fabulous in blue), or to try and match the colour scheme of an existing site. In my earlier post, Deploying RedFeather, I explored how one might integrate RedFeather into an existing site using this method. In this case, I was trying to add a RedFeather repository to the SLEP website, which has a fairly unusual magenta and indigo colour scheme. Simple recolouring RedFeather to match this gave very poor results due to the strange contrast, so I decided to average the colours instead and go with a uniform lilac theme. While this differentiated the site from a default ‘red theme’ RedFeather and would probably be acceptable to some users, I will be the first to admit that this wasn’t even close to a seamless integration.
It was obvious that it would not be possible to fully integrate RedFeather with another site unless you could replace the entire html template and stylesheet. This is a much more complex customisation than simply changing the banner colour and can only be done by writing a custom plugin. However, special consideration were made in the RedFeather core to make writing such a plugin much easier. The first was simple, enforcing a complete separation within the code between the template and content. This meant making sure that html elements making up the vital parts of the site (such as workflow items, or resource preview) were completely independent of the template and render properly even if all other styles are stripped out. Furthermore, they were all given unusual element ids and classnames (prefixed with “rf_”) to minimise the chance that any new css rules on the custom template will interfere with them.
The first step to writing the plugin is to override the ‘render_template’ function and completely replace the output HTML; this will cause RedFeather to render pages exactly like the target site, only without any RedFeather content. Adjusting the new template to include the required content is simply a case of inserting each element in the appropriate place. Each template needs to include the following compulsory elements:
- $BODY – the global variable containing the main content div for RedFeather.
- $TITLE – the title of the page.
- The global CSS and javascript (obtained by calling ‘generate_head_elements’) - should always be present in the html head element.
- The error message list (obtained by calling ‘generate_message_list’).
- The footer toolbar (obtained by calling ‘generate_toolbar_footer’) – contains a link to resource manager and RedFeather project page.
Depending on the structure of the new template, some of the RedFeather content might appear incorrectly. This is probably due to a mismatch in element types (for example, if the template expects <h2> elements instead of the <h1> RedFeather uses), or missing CSS. This is a problem that simply cannot be avoided, since we cannot make assumptions in the RedFeather core about the kind of templates people want to use. However, it is relatively straightforward to use jQuery to transform any incorrect elements so the are consistant with the template.
I’ve include a pair of photos below to demonstrate the versatility of the templating system. The first is a resource preview using the default RedFeather template, and the second is complete reskinning of RedFeather using a CC licensed template called “impeccable” by http://www.freecsstemplates.org. This template was chosen because it differs from the default in a number of significant ways with a two-column layout, dark colour scheme, and unusual header style (notice that the resource title includes an image). It also has a very narrow content area, so I’ve decided to install the vertical resource layout plugin, which switches the resource preview, metadata and comment widget into a single column layout.
Deliverable: RedFeather Core
The primary deliverable of this project is RedFeather itself, which provides an out-of-the box repository solution in a single php script. It distills the complexity of a full-scale repository platform to provide a feature set that we believe satisfies 90% of users who want to share OERs but don’t have the server infrastructure or expertise to do so. This includes independent teachers, those working for a university (or department) without an existing institutional repository, or small projects who only wish to share a small number of resources. In these instances it is very unlikely that the cost of setting up a repository can be justified so the resources are either never shared, or simply uploaded as simple files. This means that they won’t be properly annotated, attributed or indexed in any meaningful way. The RedFeather platform provides a solution that makes it feasible for almost anyone to benefit from the added value of OER without a significant initial investment.
By implementing the entire platform in pure PHP we eliminate the need for any additional software to be installed on the target server; it can even run without a database. Furthermore, the code is compatible all the way back to PHP 4 to truly maximise the number of webservers capable of running it. We feel this is approaching the theoretical minimum system requirements a repository could possibly have while still being locally hosted.
In the remainder of this post I’m going to describe the key features of RedFeather and talk a little about how they differ from those of a larger repository system.
Resource view
Arguably the most important part of a repository is the resource summary page, since this is what the consumers of OER will ultimately see. With a RedFeather resource, users are treated to a generous in-browser preview of the uploaded resource, a clearly layed-out metadata summary, and a variety of social networking options, including Twitter tools and a Facebook commenting widget.

An example RedFeather resource summary with in-browser preview, metadata and Facebook comment widget.
Like HumBox, there is a heavy emphasis on the resource itself being the focal point of the page as opposed to supporting metadata, which is usually of lesser importantance in a teaching and learning repository. The resource preview utilises the incredible powerful Google Docs Viewer, which allows us to embed a variety of file types, including Word documents, Powerpoint presentations and PDFs. Images are rendered as simple <img> html elements, while other media files type could potentially be supported with an additional plugin. Sadly, embedding rich media in html 5 isn’t currently feasible without browser plugins or server-side conversion tools, which would add unacceptable server side dependencies to the RedFeather core.
Index
The index page for RedFeather includes a customisable description of the repository, an ordered list of the uploaded documents, and links to the repository RSS and RDF. A simple resource filter is also provided so users can quickly find resources relating to a certain keyword or phrase. From here users can click the individual titles to visit the resource page for the item, or download the file directly using the link provided in the metadata box.
Resource Manager
Uploading a new file to the repository is remarkable straightforward and can be done directly from the RedFeather resource manager with only a few clicks. Once the file has been uploaded, the user is automatically taken to the annotation workflow where they can fill in the fields and make it immediately available. By streamlining the process of adding resources and employing an “upload first” workflow we hope to further reduce the barriers preventing uptake of OER sharing by inexperienced users. The resource manager also allows the user to delete or edit existing resources, and change the order that they will appear on the browse screen.
An alternative workflow is also available via FTP, which allows users to upload files directly to the webserver without using the browser. This is useful for extremely large files, or when first populating the repository (since you don’t have to upload each file individual). These unprocessed files appear in a seperate menu on the resource manager ready to be annotated at the administrator’s discretion.

Resource Manager – showing existing resources (with options to reorder, edit, view and delete), the list of currently unannotated files (uploaded via FTP) and the main resource upload options.
Default RedFeather Template, Customisation and Plugins
The default RedFeather template gives the repository a modern look-and-feel with an unintrusive single column design and bold headers. It also supports a certain amount of customisation and the standard Red theme can easily be changed to use the colours and font-style of the administrator’s choice – it is also possible to change the name, tagline and description of the repository. More significant customisations of RedFeather can be achieved by writing a plugin to overrides the template. I talk about RedFeather’s versatile plugin architecture in great depth in my series of posts on the subject.
RedFeather is an open-source project and is available on GitHub at https://github.com/mattrosstaylor/RedFeather.
Plugin Architecture
In this post I’m going to talk about how the RedFeather plugin system is implemented. I’m also give a rough overview on how the rest of RedFeather works and provide a rationale for the decisions I made regarding the design.
Given that the primary motivation behind RedFeather is the desire for simplicity I hat to make sure that the plugin system was just as simple. The first thing to consider was installation. This is a particular problem with EPrints, where a plugin is usually composed of many files which need to be individually copied in the correct directories in the source in order to work. While, the Bazaar package manager goes a long way towards making it easier for the user, it increases the complexity of both the plugin itself and the EPrints platform. With RedFeather each plugin is composed of a single php file which is can be installed by simply copying it into the webspace alongside the main repository. Depending on the complexity of the plugin, a small amount of additional configuration may be required but ultimately that’s all it takes. This simplicity also translates to the loading process; plugins are activated by appending their content to the main RedFeather file using a PHP include – this means that there is no need to parse or process the plugins in any way. It also maintains consistency within the system since there is absolutely no difference between a plugin and the RedFeather core itself. In effect, the main RedFeather source is really just a collection of the most useful plugins.
So, how does RedFeather work? Function pointers.
Literally everything in RedFeather is achieved via the clever use of functions: page loading, toolbar rendering, and workflow management. Furthermore, ever single function can be overridden in a plugin, allowing you to change the behaviour of almost any part of RedFeather. If you don’t like the layout of the browse page you can simply create a plugin that replaces that part of the system. The challenge then becomes one of code factorisation – how do I best break down the code into functions in order to facilitate code reuse? In the example where we’re editing the browse page there existing code is already broken down into various chunks; there is code to render individual fields, individual resources, the complete list of resources and the entire browse page itself. If you wanted to adjust the browse page to include a description at the top, you would only have to edit the “page_browse” function (which only consists of a few lines). Likewise, if you wanted to add an icon to each resource you might edit “generate_resource”.
This leads us onto a problem: too many functions reduces the readability of the code – made worse due to the fact that, as of the time of writing, the core RedFeather source code alone contains over 70 function. There is where good code structure and consistant naming conventions become critical. For example, functions prefixed with “render_” always write to the output buffer whereas functions beginning with “generate_” return html. However, functions names also serve a far more useful purpose in controlling program flow. The most obvious example is the prefix “page_”, which is used to denote the entry point for any URL access (for example, the url “index.html?page=resource_manager” will automatically call the function ‘page_resource_manager”). This makes it very easy to write plugins to define new pages, since all one must do is define a single function. I’ll talk more about function pointers in a future post.
In addition to the cunning function pointers there are also a number of global variables which are used to pass information around the program. The $BODY and $TITLE variables are used as output buffers for the html body and title when rendering a page using a inbuilt template system (which I will talk about in a future post). The $DATA variable is pre-loaded on every page with the metadata of all the resources in the repository and can be written back to persistance using the “save_data” function. The $CONF variable is the most important of all and contains all the configuration information – from the repository name itself, to the width of the resource preview widget. While it is generally considered “bad practise” to use global variables I felt they actually improved code readability in this case because they provide a consistent way to access frequently used values. Also, passing them around would just add unnecessary overhead to every single function call.
I think that’s enough background on the RedFeather implementation for now – I’ll go into more detail in future posts.
Learning from existing plugin systems
One of the other defining characteristics of RedFeather is the fact that the core implementation comprises of a single PHP file. Despite this, it still provides a highly extensible architecture capable of being customised and tweaked to suit different situations. Plugins can be written to add new fields to the workflow, introduce new pages and functionality, or change the site’s appearance. While the concept is nothing new, writing such an architecture while still maintaining the desired simplicity of RedFeather presents a distinct challenge. By looking at existing implementations of plugin environments it is easy to appreciate the potential complexity of such a system and identify ways to simplify.
The first architectural style I analysed was the ‘hook system’ of plugin management, as used in both WordPress and MediaWiki. In these programs, each plugin is associated with a special point within the code, known as a ‘hook’. Each hook corresponds to a different point in either the execution of the code (for adding additional processing), or a point in the rendering a page (for adding content). The advantage of this system is that is allows for the greatest possible flexibility while still maintaining complete control over how and where the program can be extended.
As you might expect, the code overhead associated with this system is considerable and would turn RedFeather into an unreadable mess of complexity. Framework code would need to be written to support the processing of plugins in general, then additional code to handle each category of hook. Furthermore, every page and feature in the system needs to be written in a specific way to support the plugin environment.
The EPrints platform utilises an entirely different system which relies largely on inheritance. Writing a new feature is done by creating a subclass of an existing one and adjusting the functionality as required. Plugins are loaded automatically on server startup and configured using additional scripts within the cfg.d directory. The main advantage of this system is that it is possible to entirely rewrite or extend any part of the platform, although a larger understanding of the core EPrints code.
In the interest of keeping these blog posts readable I shall continue this topic in my next post.
Lessons in dependency management
The approach I had to take when developing RedFeather was very different from my usual methodology due to the unusual motivations behind the system. As I mentioned in my earlier blog posts, the primary goal behind RedFeather is to provide a system with installation and usage barriers as low as possible. In this blog post I’ll be talking about how this affected the way I designed and implemented the system.
Limiting the amount of dependencies required to install and operate RedFeather was probably the biggest challenge during development. It is a well established ideology that you shouldn’t constantly reinvent the wheel – if somebody has already built a component, it is usually better to use it then to redevelop it yourself. This is why things like databases and software libraries exist; they have been developed to solve a very specific task and are usually mature, well documented, and proven technologies. For example, no sensible developer would program his own video codecs from scratch if something like ffmpeg would be adequate for their needs. However, every additional dependency included within RedFeather increases the overhead involved with installation and reduces the simplicity and self-containedness of the system.
The most important rule I imposed on RedFeather was to include zero server-side dependencies, thus eliminating any overhead associated with configuring the server environment. In practise, simple overheads (such as access to a database server) are usually acceptable but eliminating them entirely allows users to install RedFeather quickly without having to involve system administrators. However, programmers are accustomed to having access to these luxuries and often take them for granted. Having to develop without them requires us to take a step back and make the most of the facilities that are available. In the case of RedFeather, the most obvious alternative was to use the filesystem of the webserver itself which provides a convenient location to store both the resource metadata and files.
When you contrast this with a full-scale repository platform and you can see clear advantages. In EPrints, for example, resource metadata is stored in the database using a complex multi-table schema while the uploaded files are placed in a special data structure hidden on the server. Downloading a file involves first looking up the resource in the database, determining the file_id and then serving it using a custom file handler. In RedFeather, the resource metadata for the entire repository is stored in a single file in a schemaless human-readable format. The associated files are stored directly in the public webspace of the server and are therefore immediate accessible.
While the method utilised in EPrints is obviously far more flexible than RedFeather, I believe it is unnecessarily complex for 90% of cases and certainly over-specified for someone who just wants to share a handful of simple resources. Notably limitations of RedFeather in this respect are the lack of explicit collections and multi-file resources. However, neither of these features are precluded by this method of storage and could be added at a later date.
A harder lesson to learn was that certain features and functionality simply can’t be supported without external tools. This includes complex file processing or conversion, and media rendering (video and audio are particularly problematic since HTML 5 only supports a small number of formats). Exceptions had to be made for JQuery (which is indispensable for cross browser javascript) and the Google Docs Viewer (without which there would be no embedded previews). Fortunately, both of these dependencies are entirely web-based and therefore add no overhead to RedFeather’s installation process.
Deploying RedFeather
This week I deployed our first “real life” instance of RedFeather – to help manage the documents associated with the Southampton Learning Environment Project. Since our live demo of RedFeather was deployed as a standalone application this was the first time I’ve properly integrated with an existing site.
The first task for integration was giving RedFeather a suitable colour scheme. It was at this point that I discovered that a blue/magenta colour palette doesn’t look too great when applied to an entire site instead of just the header. As a result I decided to combine the two and give it a nice purple motif! After that, it was just a matter of setting a password for the resource manager, changing the header text, and providing a ‘go back’ link to navigate from RedFeather to the parent SLEP site. Then I simply moved all the existing SLEP documents to the RedFeather directory, annotated them using the resource manager, and redirected the hyperlinks to the resulting resource pages.
You can access the SLEP project page at http://slep.ecs.soton.ac.uk/, from there you can either go directly to the repository using the navbar link, or explore the Publications, Presentations, or Links sections to see how the resources are linked in to RedFeather directly.
This deployment represents the current progress with RedFeather and demonstrates completion of the first 3 work packages for the RedFeather project. Further deployments are planned for the near future which will be supported by additional blog posts.
RedFeather at Open Repositories
Last week I headed up to Edinburgh for Open Repositories 2012 and I took RedFeather along with me. While I didn’t have my own session or PechaKucha, my contacts in the EPrints community allowed me to get a short presentation as part of the EPrints user groups. This allowed me to talk about RedFeather as a way to introduce new users to the concept of repositories and allow them to discover the value of such systems. The eventual idea being to set them up with a full scale repository afterwards (I think of it as a gateway drug into repository platform addiction!). While the presentation was only short, it did give me a chance to talk about it afterwards with the user group members. I got some interesting feedback about how it might fit into the repository ecosystem.
My main mission, however, was to gratuitously talk about RedFeather as much as possible to anyone who would listen throughout the entire duration of the conference. I thought the best way to do this would be to enter the dev challenge and integrate RedFeather into my entry somehow. After bouncing some ideas off the other developers I eventually came up with a novel idea, Splinter Repositories, which utilised RedFeather without including any of the use cases RedFeather was originally intended for (it’s generally bad form to enter an existing project into the dev challenge).
A Splinter Repository is an offshoot of a larger repository that acts on its behalf, while still being an independent entity. Like its namesake, a Splinter Cell, it can later be reabsorbed into its progenitor or – if it was unsuccessful – simply disposed of. This makes it ideal for situations such as a conference or workshop, where there are a large number of unregistered, inexperienced or untrusted users who wish to contribute to a repository. Instead of unleashing them on your precious main repository, you can simply spawn a Splinter Repository to cater for this group. This reduces the administration overhead from supporting new users as well as acting as insulation between them and your existing content.
All a user has to do to join the Splinter Repository is visit a special page on the main site which allows them to spawn their own private instance of RedFeather. This microrepository instance (thanks to Mahendra Mahey for coining the term) will be automatically registered as part of the Splinter Repository and can be accessed via a special index. The allows it to act as a pseudopublic workspace – externally visible, but not part of the archive content. After the Splinter Repository has reached the end of its lifecycle, the repository admin then has the option to selectively absorb any of the content in the microrepository swarm into the main archive using SWORD. The entire Splinter Repository can then be trivially discarded or deleted without affecting the main repo.
Sadly, I didn’t win any prizes this year, but I feel it did introduce some interesting new concepts that might not have been considered before. Maybe next time…
Embedding Previews
One of the biggest challenges with RedFeather is providing users with the capability to preview OERs within their browser without requiring any specific browser extensions, plugins or server side conversion tools. When we were first scoping out the project we were aiming to support only simple media types such as PDF or images and embed them in a standards compliant fashion. Then we discovered the fantastic Google docs viewer, which allows us to embed a much greater number of media types, including the all important Word and Powerpoint.
This is actually quite a big deal, especially coming from an EdShare background where these document types cause huge problems. Going from a docx file to a embeddable html element involves first converting to PDF using OpenOffice and then converting the resulting PDF to images using ImageMagick. This two stage process performs quite well with simple documents but can fail quite badly if presented with complex content (e.g. unusual character sets or intricate vector based images).
The Google doc viewer seems to produce much more accurate conversions with the average content, but slightly worse with very complicated content (occasionally it fails to produce a preview at all). However, the main appeal of the Google converter is that, unlike the EdShare toolchain, it can run without requiring any additional dependencies on the server.
One downside of the viewer is that the conversion has to take place every single time you access the resource and it doesn’t seem possible to cache the result in any way. This isn’t really a huge problem but after accessing HumBox or LanguageBox it does seem slightly sluggish. While there is no way to speed up viewing Word or Powerpoint document, certain other media types could be rendered without using Google. Images are the most obvious, and implementing an image viewer was trivial. The next candidate was PDF but it was at this point that we started experiencing difficulties.
In order to embed a PDF in a webpage you need to use the object element and then delegate rendering to a specific browser plugin. You can also define some open parameters, which allow you to automatically skip to specific pages or scale the document to fit the element you place it in (which is an important usability factor in our case). Ironically, it was our previous saviour Google who thwarted our efforts. The Chrome browser has its own PDF viewer built in, which helps them avoid the many security problems associated with the standard. However, they haven’t implemented these critical open parameters – which means that every single PDF we embedded was loaded very fast, but at the incorrect size! We searched for a solution but sadly, there seems to be no work around.
The other problem we experienced with the Google doc viewer was a bug that caused the player not to appear in certain circumstances. After investigating the problem it appears to be a bug with API itself which occurs if your Google browser session has timed out. If you are currently logged into Google or were never logged in, the service work fine. However, if you have a valid but expired Google session ID – the embed code just fails without notification and you can’t use the previewer until log in again. This meant you would just get empty space on the RedFeather preview screen for every single resource. Since we can’t fix any problems with the Google API the best we can do is notify users how to fix the problem if it occurs. This proved surprisingly hard.
The main complication is that it is completely impossible to detect whether or not the bug has even occurred because the Google viewer is embedded using a cross-domain iframe. This means that the contents are totally invisible to the browser to prevent cross-site scripting attacks. No amount of javascript trickery will be able to detect whether or not the viewer has loaded since it will ALWAYS appear empty on the client side. Furthermore, it’s not possible to detect on the PHP server side since it is the client browser that is causing the problem.
We couldn’t detect when the error had occurred but at the same time we couldn’t ignore this fringe case, since it is absolutely catastrophic from a usability perspective. One solution would be to just warn the user that this might happen by putting a message somewhere on the site. However, this is unsatisfactory since it clutters the interface and makes it seem like the software is unreliable.
It turned out that the solution had been right in front of us the whole time: hide the message underneath the viewer. That way, if it fails to load you’ll be able to see the message through the empty iframe. If it succeeds, then the text will simply be obscured by the content! This allowed us to give the impression that the system was responding to the error without actually being aware of it at all.











