Developer Guide
This page discusses building your first widget, adding and interacting with it on a web page. It also gives hints, tips, and best practices to making your widgets awesome.
Introduction
Currently with data visualization on the web, you have two options. Go with a high level charting library, which in many cases have their own limitations, making customization difficult or impossible. The other option is go with a low level visualization library like D3, which comes with a steep learning curve and a time cost to implement.
Svidget bridges the gap between those two options by allowing you to express your visualizations as simplistic or as specialized as your application requires. The beauty of Svidget is you can use these libraries in your widgets. You want a pretty pink bar chart with flowers instead of bars? Not a problem. You can combine Svidget with D3 or any charting library, or both, and produce stunning visualizations, then package them as nice friendly widgets!
Architecture
The stated goal for Svidget.js is to cleanly separate visualization SVG from its host HTML page. This means that the page has a DOM,
and a Svidget widget has its own DOM. Contrast this with the fact that most JavaScript visualization libraries manipulate the DOM directly.
There are advantages and disadvantages in both approaches.
The primary advantage of a single DOM is perceived performance and ease of manipulation.
However, due to JavaScript's single threaded nature any performance gains are minimal.
Coming soon, there will be some sample pages to demonstrate Svidget's performance capabilities.
Design Goals
The design goals of the Svidget framework are:
Clean Separation. You can build and test your widgets as standalone SVG files before integrating them with a page.Ease of Use. Consuming a widget on a web page only requires minimal HTML and JavaScript knowledge.Encapsulation. Neatly encapsulting data visualization components making reuse clean and easy to use.Isolation. JavaScript errors within the widget do not interfere with the page in most cases, and vice versa.Customization. Working within an SVG file allows you make as specialized a visualization as you need.
Library Design
Some Uses
- A real-time view into your IoT assets.
- A blog or content-oriented site that wants to quickly integrate a chart without the hassle of picking and coding against a charting library.
- A live dashboard or infographics page that contains multiple charts, graphs or other visual assets that is constantly refreshing its data.
- An interactive game, puzzle, or activity that reuses a lot of similar graphical components (like ABC blocks for example).
Building a Widget
This section describes building a widget.
A Simple Hello World Widget
Here is a simple widget with a single text element. This illustrates the basic layout of a widget.
Widget Properties
We can communicate with the widget through the three facets - params, actions, and events. If you are familiar with component architecture (i.e. control, jQuery plugins, etc) this should already feel familiar.
Params - Params are the data endpoints for a widget. They can be read from and set at any point during the widget's lifecycle.Actions - Actions are the functional endpoints (i.e. methods). They are abstractions to underlying functionality in the widget.Events - Events represent notifications from the widget.
Declarative Syntax
Types and Subtypes
The Svidget framework defines a series of types and subtypes that mostly correspond to JavaScript native types. These types and subtypes are referenced in params and actionparams. When using a widget, it is important (although not critical) to adhere to the types.
Type | Description | Subtypes |
---|---|---|
string | Represents a JavaScript string. The default type in most cases. | regex, color, choice |
number | Represents a JavaScript numeric value. | integer |
bool | Represents a JavaScript boolean. Can also be expressed as 0 or 1. | |
object | Represents a JavaScript object. Can be expressed as JSON. | |
array | Represents a JavaScript Array type. Can be expressed as a JSON array. |
The object and array types can be represented as JSON when declaratively setting a param using a <param> tag inside of a <object> tag. Svidget has a bit more relaxed approach to parsing JSON syntax than you would see when using JSON.parse(). Specifically, Svidget allows the use of single quotes in JSON. This is so you can specify JSON in the value attribute without the need to escape double quotes.
CSS Selectors + Attributes Syntax
Svidget uses CSS selector syntax to bind a param to one or more elements or attributes within the SVG document.
However, the W3C spec for CSS selectors does not currently provide support for selecting attributes directly.
Because of this, Svidget as added an additional capability on top of the standardized selector syntax, the use of @attr to select the attribute.
Consider this example:
The backgroundColor param is bound to the fill attribute of the <rect id="rect1"> element. We normally couldn't select the fill attribute directly, but using Svidget's +Attributes syntax, we now can. Note that this syntax may change in the future if the W3C spec is updated to allow direct attribute selection.
Working with Other Libraries
Svidget plays nice with almost any charting or other visualization library that allows itself to be embedded in an SVG file. These libraries have been tested and proven to play nice with Svidget.js:
- jQuery 2.x and above
- D3.js
- svg.js
- snap.svg
Making Your Widget Mobile Friendly
1. Handle click and tap/touchstart/touchend separately. Since a user can't typically hover over an element on a touch-only device, using tap/touch to simulate this behavior is the best approach.
2. Use Chrome's built in emulator to emulate different mobile devices.
The Chrome developer tool allows you to test your widget in different resolutions and orientations, and includes emulating tap/touch capabilities, so you can for example handle click and tap events separately.
Best Practices
Tips
Using a Widget
This section discuss embedding a widget on a page.
Loading on a Page
The best way to add a widget to a page is to use the <object> tag.
You can also add a widget programatically using svidget.load().
Interacting with the Widget
With our widget up and running, the next things to think about are how to interact with the widget.
A widget is a living component, which means that its params can be set at any time.
Here is an example of setting the data param on our Hello World widget:
The next thing you can do is invoke actions on the widget. Our Hello World widget defines a spin action that doesn't take any params.
The final thing you can do is listen for events on the widget. Our Hello World widget defines a spinComplete event.
Note: For a live example of params, actions, and events in action, see the Spinning Star example.
Lifecycle
Because of the asynchronous nature of loading web pages and assets, sometimes the widget completes its loading before the page, and vice versa. Svidget handles this by attempting to communicate with the widget as soon as its loaded. When the widget finally responds, the bidirectional relationship between the page and widget is established, and the params are passed to the widget. If the widget is instantiated in standalone mode, then the relationship is terminated after the params are passed. This is discussed in the next section.
Connected vs Standalone
By default, widgets are loaded in connected mode. This means that the communication between page and widget is always on, and the page can send action commands and receive events, and the widget can trigger events. A widget can be declared as standalone using the data-standalone attribute. When true, once the params are passed to the widget from the page, communication is terminated. This is useful for widgets that have no actions or events, or for scenarios when the page doesn't have any need to invoke actions or handle events from the widget.
Cross Domain
Widgets can be loaded cross domain. However, Svidget has to take a couple extra steps to make that happen. A widget declared as an <object> element has to be converted into an <iframe>. This is so it can access the widget's window in order to communication with the widget and vice versa via cross domain messaging. If you know that you are loading a widget in another domain, you can speed up this process by setting the data-crossdomain attribute to true.
Best Practices
Load a widget from the same domain as the page. Use the data-crossdomain attribute to hint to Svidget that the widget is on another domain. This will speed up the loading process.
Downgrading
Downgrading for non HTML5 browsers is easy, and is the same as using the <object> tag for other purposes such as a Flash object.