Widget Framework Technical Overview
This document covers technical aspects of how widgets work and some possible ways to use them. Familiarity with HTML, Javascript and the browser loading process will be very helpful in understanding this document, particularly the Widget Script section.
Widget Lifecycle
The widget lifecycle begins when a browser loads an HTML page containing the widget’s script block. The script NewsGator sends to the browser bootstraps the widget. First the script document.write()’s out another script block to load the widget framework Javascript, and also write()’s an empty placeholder <div> that will later contain the widget’s HTML.
The initial loading script also contains the widget’s HTML template encoded in a Javascript string, and the code from the widget’s script section in Editor’s Desk. Notice that this means the widget’s Javascript is interpreted before the widget’s data is loaded, before the widget is rendered, and possibly even before the widget framework code is loaded. Your widget’s scripting code must be developed with this in mind.
The widget now appends a <LINK> element to document to load the widget’s styles, and requests the widget’s data from the NewsGator server. The widget then waits for the data to load. Once the data is loaded the widget’s HTML is rendered (see Widget Template section below) and inserted into the placeholder <div> that was created earlier. Finally, any callbacks registered via AddPostRenderCallback() are invoked, and a view event is logged to the NewsGator servers.
At this point the out-of-the-box widget framework is basically done. Of course the widget is still visible, and there may still be Javascript running for things like tabs or accordions. But the framework won’t do anything else, except for logging attention events as requested by the widget’s HTML and script code.
Widget Template
The widget template is written for a Javascript templating engine called TrimPath Javascript Templates, which is similar to other templating engines such as JST, ASP or Velocity. If you are a developer with a scripting background, you can gain a lot of insight by reading the TrimPath JST documentation, in particular the Syntax page. http://code.google.com/p/trimpath/wiki/JavaScriptTemplates.
In essence the TrimPath JST library turns your widget’s HTML template into a Javascript function that does a bunch of string concatentation. Control constructs such as {for} and {if} are turned into their Javascript equivalents. Tokens such as ${Post.Description} are turned into property accesses, with the properties converted into strings. Because the template is inside a function the Tokens and BuiltIns from Editor’s Desk are not automatically available to Javascript code outside the HTML template. However, it is possible to call out to other Javascript functions and pass tokens to them.
Note that you should not generally put <style> or <script> blocks inside your widget’s HTML template. Your widget’s HTML is inserted into the document using innerHTML and some browsers will not handle <style> or <script> tags correctly. Instead, you should always use the CSS and JavaScript panes in Editor’s Desk for these code elements.
Widget Styles
The widget styles are loaded in via a dynamic <LINK> tag appended to the head. Again, this means they’re on the same playing field as all the other styles on the page. Therefore, you need to think carefully about how you structure your selectors so that they don’t conflict with any other styles on the page. See the KB article on designing widgets for more details.
The widget framework sends your styles to the browser almost verbatim. The only exception is that we look for the ${BuzzId} token and replace it with your widgets actual numeric BuzzId (eg, 90213). This is just a straight string replacement – none of the other tokens or modifiers is available. Using the ${BuzzId} token on CSS selectors is a great way to ensure one widget’s style does not collide with another’s, since without it the two widgets would be very likely to have selectors with identical names.
Widget Script
Generally the widget’s script is loaded into the page as part of the initial widget script block. Note that the widget script is not modified at all, so it’s essentially the same as putting the script straight onto the page. This means that all the functions and variables in the widget script go into the global scope. Therefore, you need to be careful what function and variable names you use so they don’t conflict with the page’s Javascript or other widget’s scripts.
A simple approach to preventing collisions is to put all your Javascript inside one object with a unique name. For example:
var fakeCo_NewsWidget = {
myVariable : 1234,
myFunction : function(){
//do stuff
}
};
Referencing the widget object
Also note that your scripts do not automatically get a reference to the widget object or data. If you need that reference for any reason you should make a Javascript call from within the HTML template to pass that value, as in the following example:
From the Javascript pane:
var fakeCo_NewsWidget = {
buzzObj : null,
initialize : function(buzzObj){
this.buzzObj = buzzObj;
}
};
From the HTML pane:
{eval}
fakeCo_NewsWidget.initialize(BuzzObj);
{/eval}
Note that you can also pass other values out from the HTML template, for example the Posts array or the UniqueName token.
Saving objects into the widget
Sometimes it can be helpful to save references to other Javascript objects into the widget object. For example, some tabbed widgets create an object to handle hiding and showing the tabs, and it can be useful to call methods on that object later.
Javascript allows you to create new properties on objects as you go. For example:
From the HTML pane:
{eval}
BuzzObj.tabHandler = new TabHandler();
{/eval}
Widget Data
Most widgets load data from Editor’s Desk. The data is a Javascript array of objects representing posts. Exactly which posts you get is determined by the settings of the Content section of Editor’s Desk. Note that the posts are loaded from NewsGator’s database – they are not pulled from the source feed each time a widget loads.
The Data token is nothing more than a Javascript array of objects. This means that you can manipulate the posts before rendering them. For example, the NewsBar default template throws out posts with bad FeedNames before rendering them. You could also do things like reorder the posts to group them by feed before showing them. For example:
From the Javascript pane:
function sortByFeedId(a, b){
if(a.FeedId != b.FeedId){
return (a.FeedId - b.FeedId);
} else {
return (a.Title < b.Title ? -1 : 1);
}
}
From the HTML pane:
{eval}
Data.sort(sortByFeedId);
{/eval}
{for Post in Data}
<!-- Render post here -->
{/for}