PERGOLA JavaScript Library for SVG
The framework that swings SVG into action. Easy. Flexible. Innovative.

OVERVIEW

Pergola's API allows you to build from the simplest presentation to the most complex web app of systemic type. It is class based and defines an OOD model designed to be used by its classes, internally, and by the developer, in a consistent manner throughout all the develoment phases.

  1. DOM
  2. Contexts (SVG – HTML)
  3. Classes
  4. Libraries
  5. Look & Feel
  6. System logic and hierarchy
  7. Interactivity and accessibility readiness
  8. Compatibility

DOM

Pergola does not define any pseudo-language or proprietary representation of the DOM and its methods. Instead it exposes the SVG library (the browser's implementation) directly thanks to its progressive DOM helper (see article svgmagazine.com/jul2011/dom-helper.html) which is at the core of all the building blocks of the Pergola classes as well as the user's objects. This is done through the method pergola.createSVGElement and its sibling method pergola.createHTMLElement, with shortcuts $C and $html respectively. The idea of leveraging directly on the vocabulary and grammar of SVG (and HTML) voids any need to replicate classes that already exist.

The method expects an object literal, or reference, containing that which is expected by the implementation: an element name and a collection of attributes. The required property element and the utility property appendTo are processed. The properties designating attributes are not processed:

var pacman = $C({
  element: "circle",
  r: 50,
  transform: "rotate(160 100 100)",
  fill: "none",
  stroke: "yellow",
  "stroke-width": "100px",
  "stroke-dasharray": "150,50",
  appendTo: pergola.user
});

The method returns a reference to the newly created element. If the appendTo property is not set and the call is referenced, the element remains available for manipulation at a later stage.

The method is designed to process one other optional utility property: textNode. Its value is a string and it can be set while creating <text> or <tspan> elements. The text node will be automatically created and appended to the element. In HTML it can be used with any element that can have a text node.

Contexts

Pergola runs equally well in a standalone SVG context or in HTML. All the examples are shown in HTML and you will find the same examples 100% SVG in the package. The selection is done in the configuration file bound to each project:

pergola.container = document.getElementById("svg");
pergola.doc = $C({
  element: "svg",
  width: "600px",
  height: "400px",
  appendTo: pergola.container
});

This presupposes that an html element with id "svg" exists (you can use other selection methods), or you can define one on the fly:

pergola.container = $html({
  element: "div",
  style: "width: 600px; height: 400px; overflow: hidden;",
  appendTo: document.body
});

In all cases you select a suitable HTML container and then override the property pergola.doc, initially set to document.documentElement. Pergola uses an OOD model where the critical objects of the DOM are referenced, as well as all those that are intended or likely to be manipulated. This allows interactivity and dynamic manipulation without the tedious work of selection and referencing. You will be able to focus entirely and right away on the development of your application.

Classes

One of the core components of Pergola is a comprehensive collection of classes specializing in the production of system objects, widgets and other utilities. Classes are bound to the pergola namespace, and most of them inherit from the Class superclass which defines prototype methods and other generic properties. The classes define prototype extensions, basically specific properties and methods. Classes are broadly divided in two categories, those (the majority) which build interface controls and other graphical constructions, and those which accomplish particular tasks. Some utility classes from the second category are: pergola.Load for loading SVG fragments; pergola.Layout which defines layout methods; pergola.Dragarea, a smart class with several options for which one unique and reusable instance is created; pergola.Timer (see article http://www.svgmagazine.com/nov2011/js_timer.html).

Instantiation of a class in the first category is made using a split method: 1) call to constructor for inheritance; 2) call to the build() method of the class. This technique opens a few opportunities like defining properties in between the two calls (instance methods for example), placing the call to the build() method in a distant file or execute it dynamically, self-referencing of the object with access to its prototype.

The constructor expects one optional argument, a string that is assigned to the property name, useful for visible strings and for debugging, and from which an XML ID is derived and assigned to the property id. If no name is passed, a unique XML name is generated:

var myWindow = new pergola.Button("My Window");

The call to the build() method is consistent with the technique used for the DOM helper, and for all the classes of the first category. The function expects one object, with the difference that the properties become properties of the instance. Here you can override prototype properties and define instance properties for your own usage. To reduce memory footprint Pergola deletes properties that are only necessary for the initial configuration of the object.

var button = new pergola.Button();
button.build({
  parent: g,
  x: 80,
  extra: {
    rx: 3,
    transform: "rotate(-45)"
  },
  symbol: {
    symbol: pergola.symbols.arrow.large.left,
    x: 5,
    y: 5
  },
  quickTip: {tip: "this button is rotated but|its symbol is straight"},
  ev: "mouseup",
  target: legend.tip6,
  fn: legend.hilight
});

The example shows how the framework let's you activate some of the class's features for a particular instance. The documentation contains a quick reference guide of the properties for each class, clearly showing which properties can be overridden, which ones are user define, and which ones relate to the physical structure of the object (referenced DOM nodes). The properties and techniques are reviewed in the example pages.

Some classes are enabled to process the text property. For example you could define it for a button, like this:

text: {
  x: 44,
  y: 36,
  textNode: "TALK",
  fill: "none",
  stroke: "#FFFFFF",
  'stroke-width': 1.5,
  'font-family': "'Arial Black'",
  'font-size': 22,
  'font-weight': "bold",
  transform: "scale(1 .5)",
  'text-anchor': "middle",
  'letter-spacing': 2,
  kerning: 0,
  'pointer-events': "none"
}

i.e., you define the text element in the usual format (but without the element property). In all cases the text property mutates to become a reference to the newly built text element. On some event you could then say: button.text.firstChild.data = "SILENCE!";.

Most proptotype methods are intended for internal use. Pergola defines hardly any utility functions or Object extensions, leaving that task to specialized libraries which can be used in conjuntion with Pergola. For instance, the mapping application example uses a custom version of Polymaps.

However, some utility functions, all bound to the pergola namespace, are available and more will be added. They count: pergola.mousePoint returning an object with x and y properties set to evt.clientX and evt.clientY, which are subject to the matrixTransform method if Pergola is embedded in a HTML container; pergola.width and pergola.height which use window.getComputedStyle if available or the non standard window.innerWidth and window.innerHeight; pergola.use, a simulation of the SVG <use> element for using shapes from the library; pergola.symbol which is inherently used by the class constructors when you define a library symbol for an object (like a button), and which you can use directly for placing symbols anywhere or for building icons, for example; pergola.message (shortcut $M) which expects a string (can contain the "\n" escape sequence), and an optional object defining x and y properties. It displays the reusable pergola.notification dialog box as an alternative to the system alert. Functions for extensive operations on colors among which: pergola.colorConvert for parsing and conversion of any format to rgb, hex, or array of rgb values depending on the parameters passed; pergola.shade which expects deviation (or neutral) and brightness parameters and returns a computed variant in hex format based on the theme reference color specified in the config file. The algorithm manages well extreme zones of the spectrum; pergola.luminosity which expects three parameters (r, g, b) and returns a Number in the range 0 - 255; pergola.rgbToHex; pergola.hexToRGB;

Libraries

Pergola libraries define essentially SVG objects. A library is an object bound to the pergola namespace. The libraries defined by Pergola are:

Look & Feel

Pergola has a versatile skin library. A skin is a function, and the name of the skin to use for a project is set as a property of the pergola.settings object in the config file: skin: "rubber". There you also set the base color for the skin: theme: "nürburgring".

The function creates the pergola.presentationAttributes object, where initial values for the prototype properties of all classes are defined. Those prototype properties are then simply references, the values are hardcoded in the skin file, so you don't need to go through the headache of hacking a class. You edit the skin instead. So far then the skin behaves much like a style sheet for SVG presentation attributes. Where it becomes interesting is that you can have multiple definitions of the same classes in one unique file. This means that different projects can share the same sheet. Unlike what happens for style sheets, the new class definitions do not override the previous ones.

To create a new skin you simply copy and paste the default skin and tweak it to your taste and needs. The artist in you will know how to appreciate this low level control. The names of the properties are very explicit, they're simply the same as the classes.

The function also builds gradients and patterns referenced by the skin properties, and any other gradient or pattern that you may need to define for your objects.

gradient = $C({
  element: "linearGradient",
  id: "sliderPatternGrad",
  x1: "0%",
  y1: "0%",
  x2: "100%",
  y2: "100%",
  gradientUnits: "objectBoundingBox",
  appendTo: defs
});
$C({element: "stop", offset: "0%", "stop-color": shade([100, 100, 100], 20), appendTo: gradient});
$C({element: "stop", offset: "100%", "stop-color": shade([100, 100, 100], -20), appendTo: gradient});

System logic and hierarchy

At runtime Pergola establishes layers hierarchy: pergola.desktop is a reference to the outmost <g> element, created and appended to pergola.doc (document.documentElement); the <g> elements pergola.user and pergola.system are then created and appended to pergola.desktop.

The layer pergola.user is a safe residence for your objects, but this is in no way a requirement, you can append Pergola objects or other elements anywhere in the document, knowing however that they might partially mask some higher ranking layers which carry preemptive system objects (dragarea, dialog and message boxes in particular).

All system classes implement system logic. The system is unobtrusive and transparent, and you keep total freedom over whether to use it or not. If you do use any of its components you have the insurance of proper functioning. For example, The handleEvent method of the Menu class registers a “mousedown” event listener on the pergola.desktop group on activation of any menu instance. A “mousedown” event triggered by any object in the interface will propagate and cause an opened menu to close. The event listener is then removed. Note that an object with systemic behavior doesn't mean that it's necessarily appended to the pergola.system layer, naturally you append your menus anywhere you like.

Some system objects like pergola.dragarea or pergola.colorpicker are instantiated at runtime and you just use them.

Interactivity and Accessibility readiness

User events and functions are implemented in all the low level component classes. They are defined during instantiation by setting the instance properties ev and fn. The property ev gets an array of one or more event types which are all registered with the same handler assigned to fn. The property fn gets multiple types, function/method name, function literal, or string, to cope with a variety of situations. This consistent and powerful feature is well documented and widely used throughout the examples. This, together with the possibility of overriding properties and methods, allows the addition of accessibility extensions by developers with the right know how. They may also find interesting the possibility of defining a global accessibility “skin” in the skin.es file.

Compatibility

Pergola is compatible with all the major SVG implementations: Firefox, Opera, Safari, IE 9, Chrome, ASV *.

*Compatibility with ASV is ensured up to version 1.3.7, except for mapping extensions. It was abandoned definitively from version 1.3.8.