Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Excerpt

The custom widgets JavaScript API provides a number of properties and methods. Some of these are mostly used to access data, but others are explicitly provided as extension points to overwrite.

Table of Contents

Table of Contents
outlinetrue
excludeTable of Contents

Widgets.Base

All widgets – in-built as well as custom – inherit from the base widget. For a full list of the available widgets to extend from, see Base Widgets.

Methods and properties that are not defined by default, but instead provided purely for extension purposes, are highlighted as follows:

Status
colourBlue
titleExtend
.

The examples in the reference omit the boilerplate that is needed. For example if you are inheriting from the text widget and setting the customEl property, the code would look like this:

Code Block
languagejs
titlewidget.js
return Widgets.Text.extend({
    customEl: '.widget-content',

    ... // Other code inside the class here
}) 

For conciseness this is abbreviated below as follows:

Code Block
languagejs
titleExample
customEl: '.widget-content',

Life cycle

The widget life cycle is split into a number of stages in order:

  1. Initialization
    1. External module management
    2. Data prefetching
  2. Data loading
  3. Rendering
  4. Interaction
  5. Destruction

The methods and properties are all documented in their respective stage.

Properties that are set by the base widget (as for example model) are documented in the stage where they become available. These properties are only available in stages after the one that set it.

Initialization

In this stage the widget is wired up with the basics, configuration options, visual options (if needed).

The stage is executed once when creating the widget (once in the life cycle of a dashboard).

If models or collections are required, they should be initialised here. By default, a widget extending Base widget (without visuals or logic) gets a initialized Squirro Item collection. Extending other widgets gets their respective collections.

afterInitialize()

widget.afterInitialize(/* no arguments */)    

Status
colourBlue
titleExtend

This method is called after the class has been initialized. It is a good place to set up preloading , event listeners, etc.

...

titleExample
Code Block
languagejs
titleExample
afterInitialize: function () {
    this.updateTime();
},

External module management

It is possible to bundle a custom widget together with additional JavaScript modules, for example 3rd party libraries. The API provides support for managing such modules on several levels.

At the very least, a customResources object is constructed, mapping module (file)names to script load Promises. The load Promise, when executed, will asynchronously download the module and execute it in global context, resolving itself when done, and therefore allowing followup code to be executed afterwards.

Code Block
languagejs
titleExample
this.customResources['my-module.js']

To execute code after module is loaded, execute the promise and chain a followup function as you would with Promises.

Code Block
languagejs
titleExample
this.customResources['my-module.js']().then(function () {
    // Module has been loaded, do something.
});

A further level of management is available (and recommended to use) in the API. A custom widget may request registration of JavaScript modules on the dashboard level, to ensure modules are:

  • reused across widgets, if same modules are required.
  • reused across instances of one custom widget, if more than one exists in any given dashboard.
  • loaded before stages following initialization are reached (in beforeSetup stage already).
  • if required, can loaded before any widget renders (global dashboard modules)

It also helps to reduce code complexity by reducing the need to create chained, nested code.

Registration of modules should happen in the initialization stage, and can be done using the dashboard model's registerPreloadedResource method as follows:

registerPreloadedResource()

dashboard.registerPreloadedResource(name, resourcePromise, context)

Used to register custom dashboard JavaScript modules.

Code Block
languagejs
titleExample
afterInitialize: function () {
    this.dashboard.registerPreloadedResource('my-module', this.customResources['my-module.js'], this);
},

In this example, we've simplified the entire module management to one call, during the widget's initialize stage, to dashboard models' registerPreloadedResource method.

The method takes three parameters:

  • name - the unique identifier for the module. If more than one widget requests modules of the same name, it will be loaded only once and its load promise shared with the views that require it.
  • resourcePromise - promise of asynchronously loading and executing the script in global context
  • context - determines whether loading of the module should block only the widget defined by passing its view reference here; or the entire dashboard, when the context is not passed.
    • Useful when loading a module is essential to the correct rendering of the dashboard, and it is inconvenient for one reason or another, to ensure loading on a per-widget basis.

Guarantees:

  • The module will be fetched asynchronously only on demand (by calling directly customResources promise and/or the registerPreloadedResource method).
  • The module is ready and available during the beforeSetup stage already, so before collection initialisation.

Data prefetching

The API supports loading additional data via Backbone Models/Collections using the registerPrefetch() pattern. Prefetching should be registered during the initialization stage, and ensures the data objects are ready to use in beforeSetup stage already.

registerPrefetch()

widget.registerPrefetch(model)

Used to register custom Backbone models/collections.

Code Block
languagejs
titleExample
afterInitialize: function () {
    // Ensure user object is prefetched before
    this.registerPrefetch(this.user);
},

Any Backbone Model/Collection can be registered in this way. For more information about Backbone.js, please consult its documentation.

Code Block
languagejs
titleExample
afterInitialize: function () {
	this._customModel = new Backbone.Model({
		url: '/my/custom/api'
	});
	this.registerPrefetch(this._customModel);
},

Setup

In this stage the collection is set up to prepare for data to be loaded from the Squirro backend.

This stage is executed once, when the widget is created.

beforeSetup()

widget.beforeSetup(/* no arguments */)     

Status
colourBlue
titleExtend

This method is called before the setup phase happens.

afterSetup()

widget.afterSetup(/* no arguments */)     

Status
colourBlue
titleExtend

This method is called after the setup phase happens. This is a useful place to attach events to the collection, as it's initialised here (but not yet loaded).

...

titleExample
Code Block
languagejs
titleExample
afterSetup: function () {
    this.collection.on('add', this.itemAdded, this);
},

collection

widget.collection

A Backbone.js collection as instantiated by the base widget. This contains all the data that the widget needs for rendering. It is fetched before the rendering stage.

...

titleExample
Code Block
languagejs
titleExample
afterRender: function () {
    console.log(this.collection.length);
},

dashboard

widget.dashboard

A Backbone.js model that represents the currently rendered dashboard. See dashboard store for the main usage of this model.

getCustomCollectionParams()

widget.getCustomCollectionParams(/* no arguments */)     

Status
colourBlue
titleExtend

Returns an object with key/value pairs of parameters which should be passed into the widget's collection constructor.

Currently supported parameters:

...

  • Allows presenting different datasets in different widgets
  • Note, produces more requests. Always take care to ensure the overall performance is not affected.

...

  • Supports both absolute (ISO format) dates and relative strings, e.g. '24h', '3months'

...

titleExample
Code Block
languagejs
titleExample
getCustomCollectionParams: function () {
	return {
		additionalQuery: 'Company:Squirro',
		createdBefore: '24h',
		createdAfter: '2011-01-01T00:00:00',
	};
},

Rendering

In this stage the widget content is rendered into its container. The container is managed by the Squirro Dashboard automatically. So after this stage the widget is fully in the page's DOM tree and displayed to the user.

This stage is executed each time the widget is rendered - usually when the dashboard query changes as a result of a search or a filter interaction.

afterRender()

widget.afterRender(/* no arguments */)    

Status
colourBlue
titleExtend

This method is called after the rendering has been done (after renderContent). When this is executed, the widget is guaranteed to have injected itself into the DOM, and thus normal techniques of manipulating DOM elements apply (jQuery can be used for example).

The default implementation of afterRender appends the custom template to the widget and also installs any custom events (see customEvents).

...

titleExample
Code Block
languagejs
titleExample
afterRender: function () {
    this.$el.append(this.customTemplate());
},

customEl

widget.customEl    

Status
colourBlue
titleExtend

A special property of the widget that defines the element into which the custom template is rendered. This is a CSS selector that is executed against the root node of the current widget.

...

titleExample
Code Block
languagejs
titleExample
customEl: '.widget-content',

customTemplate()

widget.customTemplate(/* no arguments */)

Renders the custom template and returns the resulting HTML code. The default behavior of this method is to call the customWidgetTemplate function with the return value of getCustomTemplateParams method.

customWidgetTemplate()

widget.customWidgetTemplate(params)

This is a templating function that returns a HTML string templated from the given params hash.

This is assigned automatically by Squirro to be a Underscore.js template function rendering the widget.html file.

getCustomTemplateParams()

widget.getCustomTemplateParams(/* no arguments */)    

Status
colourBlue
titleExtend

Returns a hash of all the parameters that are passed into the custom template. The return value of this method is used as input for the customWidgetTemplate call.

customResources

widget.customResources['myTemplate.html'](parameters)

If any additional (apart from widget.html) HTML templates have been uploaded with the widget, they can be accessed trough this property.

Contains a dictionary with keys being the template file names, and values the preconfigured template functions, which will return the correct HTML string upon execution.

Optional parameters can be passed in and accessed in the template.

widget.customResources['myStylesheet.css']()

If any additional (apart from widget.css) CSS stylesheets have been uploaded with the widget, they can be accessed trough this property.

Contains a dictionary with keys being the template file names, and values the functions which will ensure the CSS is in the document for the lifecycle of the widget (and will be unloaded afterwards).

DISABLE_FULL_GRID

widget.DISABLE_FULL_GRID (default: false)

Controls whether the Full Grid functionality should be supported by the custom widget. When set to a true value, the expanding button will not be shown on the widget.

expanded

widget.expanded (default: false)

Contains the expanded state of the widget (true / false) if the Full Grid functionality has been turned on. Gets passed automatically to the template under the same name.

renderContent()

widget.renderContent(/* no arguments */)

This renders the content of the widget. In the base widget, this method does nothing - but in all the other widgets it contains the logic for displaying the widget content in the dashboard.

To prevent the default rendering of a widget completely, replace this function with noop:

Code Block
languagejs
renderContent: _.noop

In that case rendering can be fully customized and overwritten in the afterRender method.

Interaction

Squirro Widgets provide interaction by subscribing events to its DOM elements and handling them. All of these events fall into the interaction stage.

The recommended way to install custom events is customEvents. To add the event handlers manually, for example by using jQuery listeners directly, attach them in the afterRender method.

customEvents

widget.customEvents    

Status
colourBlue
titleExtend

The customEvents hash can be used to specify a set of DOM events that will be listened for and delegated to methods in the widget view. This is an extension to the default events hash of Backbone.js and behaves very similarly.

Expand
titleExample

This is an example that extends the facets table with an additional click handler.

Code Block
languagejs
return Widgets.FacetsTable.extend({
    customEvents: {
        'click tr': 'onRowClicked',
    },
 
    onRowClicked: function () {
        this.dashboard.store.set({'additionalInfo': true});
    },
});

See dashboard store for information on the store property being used here.

onStoreChange()

widget.onStoreChange(model, options)    

Status
colourBlue
titleExtend

Called when a store variable changes (see Dashboard Store).

The model argument can be used to access the exact property or properties that have changed by accessing model.changed. That property is a hash containing all the attributes that changed in the last set call.

Destruction

In this stage, the widget views are destroyed, its events unbound and its content removed from the DOM.

This stage is executed once, when destroying the widget.

afterClose()

widget.afterClose(/* no arguments */)    

Status
colourBlue
titleExtend

This method is called when the widget is being removed from the document. It is a good place to clean up, such as removing event listeners.

...

titleExample
Code Block
languagejs
titleExample
afterClose: function () {
    this.cancelTimer();
},

Widgets.FacetsTable

Additional customisation options are available in the API for the Facets Table widget. 

Rendering

customCellTemplate

Specifies that a custom HTML template for the table cells should be used instead of the default one. Any of the custom templates uploaded with the custom widget can be assigned to this property directly.

...

titleExample
Code Block
languagejs
titleExample
afterInitialize: function () {
	this.customCellTemplate = this.customTemplates['myTemplate.html'];
},

customHeaderTemplate

Equivalent technique as for the cell templates can be used to customize the table headers.

customDetailTemplate

Equivalent technique as for the cell templates can be used to customize the table item detail panels.

getCustomCellTemplateParams()

widget.getCustomCellTemplateParams(/* no arguments */)        

Status
colourBlue
titleExtend

The method is called when the HTML for table cells is being generated out of the custom cell template. It is expected to return an object with parameters which will be present in the scope of the template (passed into the template function).

...

titleExample
Code Block
languagejs
titleExample JavaScript
getCustomCellTemplateParams: function () {
	return {
		myParam: 'squirro',
	};
},
Code Block
languagexml
titleExample HTML
<div>
	Welcome to the parametrised custom template.
	Value passed in: <%- myParam %>
</div>

getCustomHeaderTemplateParams()

widget.getCustomHeaderTemplateParams(/* no arguments */)      

Status
colourBlue
titleExtend

The method is called when the HTML for table cells is being generated out of the custom header template. It is expected to return an object with parameters which will be present in the scope of the template (passed into the template function).

getCustomDetailTemplateParams()

widget.getCustomDetailTemplateParams(/* no arguments */)      

Status
colourBlue
titleExtend

The method is called when item body is being generated. It is expected to return an object with parameters which will be present in the scope of the template (passed into the template function).

Additional variables exposed in the custom cell Facet Table templates

item

A Backbone model containing information about current item (row). Contains properties describing the item (e.g. title), as well as a few helper methods.

getThumbnailURL()

Returns the URL of the item thumbnail image, if present.

generateMailLink()

Returns a mailto: link containing basic information about the item ready for sharing.

getDisplayTime()

Returns the formatted creation date/time of the item.

getItemLink()

Returns a link to the item source, if present.

toggleStar()

Toggles the starred mode on the item.

markAsRead()

Marks item as read.

escape(property)

Mimics Backbone.Model.get(), but escapes the value to be displayed in HTML.

column

A Backbone model containing information about current table column.

name

Contains the column name, which is equal to the facet the column was configured with.

title

Contains the column title, which is a formatted version of the name.

widget

Contains a reference to a Backbone model with configuration of the custom widget.

Additional variables exposed in the custom header Facet Table templates

column

A Backbone model containing information about current table column. See "Additional variables exposed in the custom cell Facet Table templates" for more information.

Additional variables exposed in the custom item detail Facet Table templates

item

A Backbone model containing information about current item (row). See "Additional variables exposed in the custom cell Facet Table templates" for more information.

Widgets.Connection

The Connection widget (Heatmap) draws a matrix of integral values, and automatically calculates the background for each cell, according to its value (intensity).

Data postprocessing

postProcessData

The method will be called just before the data is about to be displayed, allowing the cells to be changed, new rows and columns to be added, and sorting to be performed.

...

titleExample
Code Block
languagejs
titleExample
postProcessData: function (payload) {
	payload.labelsX.sort();
	payload.matrix[0][1] = 1;
	payload.matrix.push([1, 2, 3, 4]);	
	return payload;
},

Widgets.DoubleSided

The DoubleSided widget is a composite widget, allowing composing of two other widgets, with separate configurations, with the option to 'flip' between the views in runtime.

The widget expects its configuration passed in as JSON trough the widgets property.

...

titleExample
Code Block
languagejs
return Widgets.DoubleSided.extend({
    widgets: [
        {
            type: 'Facets',
            options: {
                facets: [
                    {
                        facet: 'language',
                    },
                ],
                title: 'Language Pie Chart',
            },
        },
        {
            type: 'Search',
            options: {
                title: 'Result List',
            },
        },
    ],
});

The options for each composed widget depend on the widget type. If a widget requires one or more facets to visualize, the facets configuration should be passed in as shown in example above.

Widgets.Search

Rendering

itemTemplate

Specifies that a custom HTML template for each item should be used instead of the default one. Any of the custom templates uploaded with the custom widget can be assigned to this property directly.

...

titleExample
Code Block
languagejs
titleExample
afterInitialize: function () {
	this.itemTemplate = this.customTemplates['myTemplate.html'];
},

getItemTemplateParams

widget.getItemTemplateParams()

If implemented, and if itemTemplate is defined, the returned value of getItemTemplateParams() will be passed onto the HTML side.

...

titleExample
Code Block
languagejs
getItemTemplateParams: function () {
    return {
		external_id: 1234,
	};
},

...

The dashboard store is accessible in the widget using the widget.dashboard.store property (usually this.dashboard.store). This model is the recommended way for custom widgets to talk to each-other. The dashboard store is a Backbone.js model though without persistence.

Custom widgets should implement the onStoreChange method to listen for changes to the store.

Architecture

A good example for when to use the store is when there are two widgets on a dashboard that have to communicate with each-other.

For example a navigation widget can be implemented which presents the user with a number of menu options. When clicking on one of the options, the store is updated by setting a attribute. A second widget reacts to that store value and changes the content to be displayed depending on the set attribute.

Methods

get()

store.get(attribute)

Get the current value of the store attribute.

...

titleExample
Code Block
languagejs
onStoreChange: function () {
    if (this.dashboard.store.get('additionalInfo')) {
        this.$el.addClass('additional-info-requested');
    }
},

set()

store.set(attribute, value)
store.set(attributes)

Set one attribute to the given value or - in the secondary form - update all the key/value pairs from the hash.

If any attribute changes, a change event is triggered. The easiest way to subscribe to those in the widget is by implementing the onStoreChange method.

...

titleExample
Code Block
languagejs
onRowClicked: function () {
    this.dashboard.store.set({'additionalInfo': true});
},

unset()

...

If any attribute changes, a change event is triggered. The easiest way to subscribe to those in the widget is by implementing the onStoreChange method.

...

titleExample
Code Block
languagejs
onRowClicked: function () {
    this.dashboard.store.unset('additionalInfo');
},

Property Pages

Most widgets require configuration to function correctly. The widget configuration panels are exposed in the API, and can be leveraged and/or extended freely. To define a custom property panel, add a config.js file to the custom widget, and use the widget upload tool to bundle it.

The property page configuration file is a JavaScript file which is expected to return an extension on one of the objects in globally scoped object Pages.

Simplest form of the file would just return an existing configuration page (from one of the basic widgets), like so:

...

titleExample
Code Block
languagejs
// Use the property page of Result List widget
return Pages.Search;

Extending the property page is done in same fashion as extending the base widget views.

The extended property page can implement any (or both) of two properties, customNormal and customAdvanced - depending which configuration section should be extended.

Each of the two properties is an array of objects, one per defined property. The objects are expected to contain the properties 'view' and 'config', The 'config' property should contain at minimum, 'inputName' and 'infoText', plus can define additional options, some global (available for all properties), some available for selected properties only.

  • view
    • Specifies the type of property and is represented in the type of property view used. The properties available are exposed under the globally scoped 'Property' object:
      • Property.Bool
        • Defines a checkbox.
        • Serializes to a boolean model property type.
      • Property.Color
        • Defines a colorpicker.
        • Serializes to a string model property type containing the color hashcode.
      • Property.DateFormat
        • Defines a control allowing to customize the format of a data.
        • Serializes to a string model property containing the date formatting string.
      • Property.Dictionary
        • Defines a dynamic key/value pair picker control.
        • Serializes to an object model property containing the chosen values.
      • Property.Facet
        • Defines a multi-facet selector control, which allows selecting one of the facets defined in the system.
        • Serializes to an array of strings model property, corresponding to the names of facets chosen.
        • Property specific options:
          • min
            • Defines how many facets minimum should the property allow to configure and serialize under one model property.
          • max
            • Defines how many facets maximum should the property allow to configure and serialize under one model property.
          • colorPicker
            • Whether the control should allow choosing a color for each facet, by integrating a colorpicker control.
          • typeRestriction
            • Restricts type of facets which should appear in the control.
          • aggregate
            • Whether to provide aggregation options for the facet.
          • aggregateFunctions
            • Which mathematical functions to allow aggregation over. By default, min, max, sum and avg (average) are exposed.
      • Property.Language
        • Defines a language control, which allows selecting a language from all languages list.
        • Serializes to a string model property containing the language identifier.
      • Property.MultilineText
        • Defines a multiline text input control.
        • Serializes to a string model property containing the text.
        • Property specific options:
          • maxLines
            • Defines how many lines of text should the control allow.
      • Property.Multiselect
        • Defines a radio control.
        • Serializes to a string model property containing the selected value.
        • Property specific options:
          • options
            • Defines the options for the radio control
            • Is an array of objects, each containing at least string properties label and value, as well as optionally boolean property default.
      • Property.Number
        • Defines a number input control.
        • Serializes to an integer model property containing the selected number.
        • Property specific options:
          • min
            • Defines the minimum number that can be selected
          • max
            • Defines the maximum number that can be selected
      • Property.Percentage
        • Defines a percentage slider control.
        • Serializes to an integer model property containing the selected percentage.
      • Property.Text
        • Defines a singleline text input control.
        • Serializes to a string model property contaning the text.
      • Property.Trend
        • Defines a trend entity picker control.
        • Serializes to a string containing the trend entity id.
      • Property.URL
        • Defines a URL input control.
        • Serializes to a string containing the URL.
        • Property specific options:
          • hideDocs
            • Hides the section explaning the usage of URLs within Squirro widgets
  • inputName
    • Specifies the name of model property to which the value should be serialized.
    • Can be accessed in the custom widget code by this.model.get(inputName).
  • infoText
    • Specifies the information text (title) that is displayed just above the property, providing additional instructions or description of the parameter to the user.

Additional options all properties support:

  • defaultValue
    • Specifies the default value the property should use (for example when widget has been freshly added to the dashboard and thus not configured yet).
    • Value type depending on the property type.
  • denyValidate
    • Allows to skip validation on fields. By default basic form validation is performed, depending on the property type.

...

titleExample
Code Block
languagejs
// Use the base (empty) property page and extend it with new fields
return Pages.Base.extend({
	customNormal: [
		{
			view: Properties.Number,
			config: {
				inputName: 'myNumber',
				infoText: 'Select a number from 3 to 7',
				min: 3,
				max: 7,
				defaultValue: 5,
			},
		},
	],
});

Utils

queryParam

A utility for handling query string parameters.

parse()

Utils.queryParam.parse(/* no arguments */)

Returns a hash of all the query string parameters in the current URL.

...

titleExample
Code Block
languagejs
var params = Utils.queryParam.parse();
// returns a hash of parameters, example:
// {"q": "Apple"}
console.log(params.q);

facetParser

A utility for parsing arbitrary query strings into key/value facet/value pairs.

Factories

Factories expose an additional level of control over the internal Squirro objects. They can be used to mock, and create arbitrary data collections.

Collections

Items

Creates a Squirro Items collection.

Factories.Collections.Items.create(search, project)

...

titleExample
Code Block
languagejs
getCollection: function () {
	return Factories.Collections.Items.create(this.options.search, this.options.project)
},

Facets

Creates a Squirro Facets collection.

Factories.Collections.Facets.create(search, project, options)

...

titleExample
Code Block
languagejs
getCollection: function () {
	return Factories.Collections.Facets.create(this.options.search, this.options.project, {
		facet_fields: [ 'custom_facet' ], // custom facets to fetch
		nof_facets: 100, // maximum number of facet values returned
		itemsCollection: Factories.Collections.Items.create(this.options.search, this.options.project), // associate (optionally) a custom Items collection
	});
},

MockItems

Creates a Squirro Items collection. It is possible to throw a JSON object with mocked items at it, to be used as an alternative data source to Squirro backend.

Factories.Collections.MockItems.create(search, project, items)

...

titleExample

...

languagejs

...

Child pages (Children Display)