Custom HTML & JavaScript¶
AMI web is a highly customizable visual dashboard with its visual elements driven largely by HTML. 3forge supports multiple methods for implementing your own custom HTML for custom panel types, or JavaScript callbacks to invoke custom JavaScript libraries within AMI.
Within AMI¶
There are several areas within AMI that allow for the use of JavaScript and CSS out-of-the-box without the additional need for custom plugins. Where possible, we generally recommend avoiding custom HTML and opting to use inbuilt AMI functionality, however the following fields will accept frontend inputs.
-
Formulas
- Formatting and styling of individual cells, columns, tooltips, etc can be done using HTML where needed.
- Wrap any HTML statements in string quotations "".
-
HTML Panels
-
Custom CSS
-
For most use cases, using the style manager provides sufficient flexibility for visual customization.
-
To use custom styling for additional visual flare that AMI does not natively support, you can use the "Custom Css" field (Dashboard -> Custom Css) to write independent CSS.
-
We generally recommend using AMI inbuilt styles first.
-
Custom Panels¶
Overview¶
AMI's frontend is broken up into "panels," the primary visualizers in AMI. Each panel has a particular type, e.g: table, chart, heatmap, etc. In the rare instance you wish to implement your own custom panel type, you will need to use the Web Panel Plugin interface.
The Web Panel Plugin is a Java factory that generates an AmiWebPluginPortlet
which represents a panel instance. You will need to follow the general steps for setting up a custom Java plugin to get started.
Java interface¶
Properties¶
Custom JavaScript¶
Overview¶
JavaScript is not natively supported in AMI, however using the AmiGuiService
plugin, it is possible to have JavaScript code/methods to be accessible within AMI web in AmiScript. This is achieved using the bidirectional AmiScript API:
- Calls to JavaScript from within the browser can, in turn, invoke AmiScript callbacks
- Calls to AmiScript from within the dashboard can, in turn, call JavaScript within the browser.
In order to interact with AmiScript in the webserver and with JavaScript in the web browser, two blocks of adapter code must be written. Each of these two blocks of code are started as singletons which communicate over the AMI HTTP(S) transport (transparent to you when building these adapters).
The webserver's singleton is one per user session and the JavaScript singleton object is started when the browser loads. These two objects are responsible for communication between their respective environments and each other:
In-Depth¶
Initialization¶
- First, a Java plugin implementing the
com.f1.ami.web.guiplugin.AmiWebGuiServicePlugin
is initiated when the Ami Web Server starts up. The class name must be specified in theami.guiservice.plugins
property. Note, that only one instance is started up per JVM. - Each time a user logs in, the
AmiWebGuiServicePlugin::createGuiIntegrationAdapter
is called which returns a custom class implementing the AmiWebGuiServiceAdapter interface. - Each time the page is refreshed, including on initial login, the following methods are called on the
AmiWebGuiServiceAdapter
(These methods initialize the browser's JavaScript environment):
Methods | Description |
---|---|
getJavascriptLibraries() |
Your adapter returns a list of libraries to load. This tells the browser which libraries to load, if any, for this custom adapter. |
getJavascriptInitialization () |
Your adapter should return JavaScript to be executed in the browser at pageLoad and allows for any custom initialization. |
getJavascriptNewInstance () |
Your adapter must return the JavaScript necessary for generating a JavaScript singleton that will receive/send messages. This JavaScript must implement a function called registerAmiGuiServicePeer(peer) which, typically, just stores the peer argument in a member variable for later use. |
Registering AmiScript API¶
-
- Declaring methods that can be called from AmiScript
- Within the AmiScript environment, a single object will be available that represents the singleton. Similar to the session object which implements the Session AmiScript class, this object will have a predetermined name, class name, and available methods.
Methods | Description |
---|---|
AmiWebGuiServiceAdapter::getAmiscriptClassname() |
Your adapter should return the name of the class that is represented by the singleton (analagous to Session ). The singleton object will have the same name but prefixed with two underbars (__). |
AmiWebGuiServiceAdapter::getAmiScriptMethods() |
Your adapter should return a list of methods that can be called on the custom singleton. |
-
- Declaring AmiScript callbacks
- The callbacks allow for dashboard developers to declare their own AmiScript that gets executed when the callback is invoked. The dashboard developers can edit the callbacks under Dashboard -> Custom Gui Service Callbacks ->
<Your custom service>
Method | Description |
---|---|
AmiWebGuiServiceAdapter::getAmiScriptCallbacks() |
Your adapter should return a list of callbacks available for overriding. |
In Practice¶
- AmiScript to Javascript
- A user invokes an AmiScript method on your custom singleton.
- When a dashboard developer calls the custom AmiScript API, then
AmiWebGuiServiceAdapter::onAmiScriptMethod
is called. Any data validation, data massaging, etc should be specified here. - Call
executeJavascriptCallback
on the supplied peer.
Here is an example (with no additional validation):
- JavaScript to AmiScript
- A JavaScript function is called on the singleton.
-
The JavaScript singleton's method should then call:
Note
The peer is supplied on startup in the registerAmiGuiServicePeer function
-
The backend Java adapter's
AmiWebGuiServiceAdapter:: onCallFromJavascript(...)
is called. At this point, your adapter can do validation, data massaging, etc. before passing off to AmiScript. -
Call
executeAmiScriptCallback
on the supplied peer. Here is an example of steps 3 and 4, skipping validation, data massaging, etc: -
AmiScript call back is executed
Full JavaScript Example¶
This simple example shows a step-by-step breakdown of defining a method in JavaScript, calling that method in AmiScript, and then invoking a callback from the external JavaScript library.
We declare an AmiScript custom object called __GuiSample
of type GuiSample
with a single method getDate(String)
and a single callback called onDateDetermined(...)
.
When the getDate(...)
AmiScript is executed, the user is presented with a native JavaScript alert and then the current date from the browser is sent back to the AmiScript via the onDateDetermined(..)
callback.
The steps involved are as follows:
- Create a Java package for your plugin.
-
Create a
AmiWebGuiServicePlugin
and add that to yourlocal.properties
: -
Write your external JavaScript file and function containing the
getDate
prototype. - Create a
AmiWebGuiServiceAdapter
and define functionality to be called in AmiScript:- Add
getDate
togetAmiScriptMethods()
- Add the
"onDateDetermined"
callback togetAmiScriptCallbacks()
- Add the external JavaScript library to
getJavascriptLibraries()
- Add
AmiWebGuiServicePlugin_Sample.java
¶
For the plugin, ensure that you have your login.properties
configuration set to match your package and class, in this case:
For the adapter:
GuiSampleJavascript.js
¶
We write an external JavaScript library with the sample JavaScript function that will be called in our adapter. The function GuiSampleJavascript()
contains any methods that we want to call in AMI web, in this case getDate()
, and uts corresponding callback onDateDetermined(value)
.
AmiWebGuiServiceAdapter_Sample.java
¶
We specify in the adapter the how the JavaScript is passed and called to AMI. For a blank version of the AmiWebGuiServiceAdapter
class, see the end of this document.
Notes¶
getJavascriptInitialization
is run before the external library is loaded. Return an empty string here, unless you need to initialize something outside your javascript library.getJavascriptLibraries
expects a HTTP(S) connection. Either store your.js
file in your/amione/resources
folder, or host the library elsewhere.- If you want to perform some custom behavior or callback on startup, we recommend implementing it with the custom GUI callbacks (see method
onLayoutStartup()
) rather than as a custom callback within AMI.
In AMI Web¶
To test the functions, ensure you have exported your plugin and adapter, then launch AMI. Inside the dashboard, create a new HTML panel and add a button. Then, using the new custom object GuiSample
, set the AmiScript window to:
Notice how when initializing a GuiSample
object, the method will appear in the AmiScript wizard.
To set the callback, navigate to Dashboard -> Custom Gui Service Callbacks -> Gui Sample Callbacks
This will pull up the Custom Gui Service Callbacks which should contain a tab onDateDetermined(value)
. When invoked, this callback will return the function executed by the JavaScript singleton.
Input into the field:
Note
The default value returned will be a Unix timestamp. Here, we have parsed the date to be more legible. To further customize the format of the date to your preferences, please see the documentation on the formatDate()
method.
Exit editor mode (Ctrl+d), and click the button. You will get two pop-ups:
Blank AmiWebGuiServiceAdapter Java File¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
|