UI extensibility example: calculator bundle
This documentation shows how to use extensibility scenarios that are experimentally deployed in update 9. The APIs described here are manually deployed, which currently prevents installation in the Cloud. They are usable only in an Early adopter program context.
This article explains how you can add a custom action button at the top of every SAFE X3 web page.
To keep things simple we will add a simple button that opens up a popup with a calculator.
Before writing our JavaScript code we must create a bundle's directory and a package.json file.
Our bundle will have the following structure:
xa1-calculator/package.json public/calculator-widget.jsplugin/jquery.calculator.jsjquery.calculator.css
package.json
file contains:CODECODE CODE json{"name": "xa1-calculator","description": "Calculator widget extension","version": "1.0.0","author": "ACME Inc.","private": true,"sage": {"x3": {"extensions": {"shell-widgets": [{"module": "xa1-calculator/public/calculator-widget"}]}}}}
shell-widgets
extension key indicates that the package contains a UI shell extension. The module
value gives the path to the JavaScript module which implements the extension.We will not write the calculator ourselves. Instead, we will use the calculator jquery plugin.
The calculator-widget.js
file provides the glue between the SAFE X3 web framework and the jquery plugin:
CODECODE CODE javascript"use strict";require('./plugin/jquery.plugin');require('./plugin/jquery.calculator');// load CSS files['/xa1-calculator/public/plugin/jquery.calculator.css'].forEach(function(href) {$("<link/>", {rel: "stylesheet",type: "text/css",href: href,}).appendTo("head");});exports.create = function(container) {// add a 'calculator' button to the container var $button = $('<div>').text('calculator').appendTo($(container.div)).click(function() {$popup.toggle();}).css({color: 'white',});// create the calculator popup which is toggled by the buttonvar $popup = $('<div>').appendTo($(container.div)).calculator().css({position: 'fixed',margin: '7px 0px',}).hide();// return our widget's API (empty)return {};};
CODECODE CODE javascriptrequire('./plugin/jquery.plugin');require('./plugin/jquery.calculator');
CODECODE CODE javascript['/xa1-calculator/public/plugin/jquery.calculator.css'].forEach(function(href) {$("<link/>", {rel: "stylesheet",type: "text/css",href: href,}).appendTo("head");});
create
function that the UI framework will call to create our widget. This create
function is defined as follows:CODECODE CODE javascriptexports.create = function(container) {var $button = ....;$button.appendTo($(container.div));return {// our widget's interface}}
container
parameter of the create
function is the interface that the widget can use to interact with its container. This interface contains the following members and functions:div
: the <div>
HTML element of our container. The create
function should append the widget's root element to this div.Note: the container API is very limited at this stage. It will be enhanced in the future.
Important: your widget should only use the container interface to interact with the rest of the UI framework. JavaScript is very permissive and you could bypass this interface and interact directly with internal APIs of the UI framework. Even if this is technically possible, this is forbidden. If you do so, your code may break at any point when the UI framework is upgraded. Instead you should file a request for an API enhancement if you have needs that are not covered by the current API.
The widget that you create will be displayed in the application's top bar. You should design it as a small button or icon that opens your widget as a popup.
The calculator button is created by:
CODECODE CODE javascriptvar $button = $('<div>').text('calculator').appendTo($(container.div)).click(function() {$popup.toggle();}).css({color: 'white',});
CODECODE CODE javascriptvar $popup = $('<div>').appendTo($(container.div)).calculator().css({position: 'fixed',margin: '7px 0px',}).hide();
Note that you do not need to require the core jQuery library. It is already loaded by the SAFE X3 UI framework.
The last line of the create
function returns the API that the UI framework will use to interact with your widget. For a shell widget, this API is empty. But for other extension scenarios the widget will need to expose some functions to its container. See the color picker extension for example.
The create
function is designed as an API or interface handshake: the container passes its API and receives the widget's API in return.
Deployment is easy: add your extension directory under the node_modules
directory of the SAFE X3 'node.js' server, and restart the 'node.js' server.
Do not forget to restart the 'node.js' server everytime you make a change to your bundle. Otherwise it won't pick up the latest code.