Skip to content

Plugin Interface

Jae Sung Park edited this page Jun 14, 2023 · 5 revisions

Plugin Interface Design

a) Basic Usage

const chart = bb.generate({
    plugins: [
        new PluginA({ options }),
        new PluginB( ... ),
        ...
    ]
});

// Accesing plugin property
// [PluginA Instance, PluginB Instance, ...]
chart.plugins;
  • Basically, plugin's option should be completely isolated with the main chart option value.
  • The plugin instance will be reachable via .plugins property.

b) Lifecycle & Hooks

image

  • The call for every phase happens once, except the rendering.
  • Rendering phase, will be triggered as of chart.internal.redraw() is called.

c) Plugin class Interface

  • Every lifecycle hooks will be overridden if set.
  • At the $beforeInit, will be set $$ instance variable having the current chart.internal reference, which you can access from the plugin.
// ./src/plugin/Plugin.js
class Plugin {
    constructor(options) {
        ...
    }

    // chart.internal.beforeInit()
    // - The current chart instance will be set as `$$` instance member at this hook
    $beforeInit: function(){}
    
    // chart.internal.init()
    // the 'real' ininitialization happens here
    $init: function(){}
    
    // chart.internal.afterInit()
    $afterInit: function(){}
    
    // chart.internal.redraw()
    $redraw: function(){
        // will be called every re-rendering happens
    }
    
    // chart.destroy()
    $willDestroy: function(){}
}
  • Extending Plugin.js

    For all plugins are recommended(but not mandatory) to extend Plugin class (src/plugin/Plugin.js).

    If you want your plugin to be distributed with billboard.js official package, you must extend Plugin class.

    // importing from billboar.js cloned project
    import Plugin from "../Plugin";
    
    // importing from billbord.js npm package
    // import Plugin from "billboard.js/src/Plugin/Plugin";
    
    export default class MyPlugin extends Plugin {
        ...
    }

d) Plugin File structure

Directory

/src
    Plugin.js  # Plugin interface class
    ./PluginA   # Plugin directory
        index.js  # Plugin entry point
        ...

Build

/dist
    ./plugin
          billboardjs-plugin-stanford.js
          billboardjs-plugin-stanford.min.js

Writing a plugin

There're 2 options on writing plugin:

1) As being part of billboard.js

  • Must extend Plugins.js

    import Plugin from "../Plugin";
    
    export default class MyPlugin extends Plugin {
        ...
    }
  • The source code location should be:

    • ./src/plugin/$YOUR_PLUGIN_NAME
    • The entry point file name should be index.js

    ex) The file structure for myplugin plugin

    ./src/plugin
           ./myplugin
               index.js
  • An example outline of index.js

    class MyPlugin extends Plugin {
        constructor(options) {
            // plugin's option if necessary
            // calling 'super', will assign options as instance member
            super(options);
            
            // you can access options as instance member
            this.options;
    
            // NOTE:
            // Do not write business logic here, write within one of
            // lifecycle hook methods($beforeInit, $init, etc.).
            // At this point, chart isn't instantiated yet.
        }
    
        // will be executed at 'beforeInit' lifecycle
        // lifecycle hook is optional. Do not specify if isn't necessary
        $beforeInit() {
            // the current chart instance variable 'this.$$'
            // will be assigned by default as time of the initialization
            this.$$;  // access current chart instance's `chart.internal`
        }
    
        // 'init' hook (required)
        $init() {
            // write initial code for the plugin
        }
    
        // 'redraw' hook (required)
        $redraw() {
            // will be triggered as time of
            // "redraw"(resize, data toggle, etc.) happens
        }
    
        // 'willDestroy' hook (not mandatory, but highly recommended to implement)
        // will be triggered when '.destroy()' is called
        $willDestroy() {
            // write code releasing the resources used in this plugin
        }
    }
  • build & dev-server

    # Running below command will facilitate on plugin development
    
    # start dev-server
    $ npm run start:plugin
    
    # build plugin
    $ npm run build:plugin

    The plugin build will be output to ./dist/plugin/billboardjs-plugin-$PLUGIN-FOLDER-NAME.

    Checkout the nightly build as an example of build:

Example

As an example, take a look on below plugins implementation from master.

2) As being an independent plugin

Basically, there's no any restriction (except lifecycle hook) if you opt develop as an independent plugin.

import Plugin from "billboard.js/src/Plugin/Plugin";

export default class MyPlugin extends Plugin {
    ...
}

The package name for plugin can be any, but to be distinguished is recommended put billboardjs-plugin- as prefix.

billboardjs-plugin-$PLUGIN-NAME