JavaScript: Extended

Important JavaScript classes

UIControl

UIControl is meant to be the base type for all JavaScript widget classes. These classes manage and attach behavior to an element. Examples of classes that extend from UIControl include DataTable (the base of all report visualization JavaScript classes) and VisitorProfileControl (used to manage the visitor profile).

UIControl allows descendants to clean up resources, provides a mechanism for server side code to send information to the UI and provides a method for listening to dashboard widget resize events.

Extending UIControl

The actual extending is straightforward:

(function (require, $) {

    var UIControl = require('piwik/UI').UIControl;

    var MyControl = function (element) {
        UIControl.call(this, element);

        // ... setup control ...
    };

    $.extend(MyControl.prototype, UIControl.prototype, {
        // ...
    });

    var exports = require('MyPlugin');
    exports.MyControl = MyControl;
})(require, $);

UIControl's constructor takes one argument: the HTML element that is the root element of the widget.

Creating controls that extend UIControl

Control instances should be created through the initElements() static method:

MyControl.initMyControlElements = function () {
    UIControl.initElements(this, '.my-control');
};

This will find all elements with the my-control class, and if they do not already have a MyControl instance associated with them, it will create an instance with that element. MyControl.initMyControlElements should be called when your control's HTML is added to the DOM. This is often done in Piwik by including a <script> element in HTML returned by AJAX, for example:

<div class="my-control">
</div>
<script type="text/javascript">require('MyPlugin').MyControl.initMyControlElements();</script>

Cleaning up after your control

When the selected page changes or when a popover is closed, Piwik will call the UIControl.cleanupUnusedControls() static method. This method will automatically collect all control instances that are attached to elements that are not part of the DOM and call the controls' _destroy() method.

When creating your own control, if you need to do some extra cleanup, you can override this method:

$.extend(MyControl.prototype, UIControl.prototype, {

    _destroy: function () {
        UIControl.prototype._destroy.call(this);

        this.myThirdPartyLibWidget.destroy();
    }

});

Sending information from PHP to UIControl

If you need to pass information from PHP code to UIControl instance, you can set the data-props HTML attribute of the root element of your control to a JSON string. This data will automatically be loaded and stored in the props attribute of a UIControl instance.

So if you create HTML like the following:

<div class="my-control" data-props="{&quot;title&quot;: &quot;My Control&quot;}">
</div>
<script type="text/javascript">require('MyPlugin').MyControl.initMyControlElements();</script>

then this.props.title will be set to 'My Control':

var MyControl = function (element) {
    UIControl.call(this, element);

    alert(this.props.title); // will say 'My Control'
};

Listening to dashboard widget resize

To redraw or resize elements in your control when a widget is resized, call the onWidgetResize() method when setting up your control:

var MyControl = function (element) {
    UIControl.call(this, element);

    var self = this;
    this.onWidgetResize(function () {
        self._resizeControl(); // private method not shown
    });
};

Piwik_Popover

Creating popovers

To create a popover, use the createPopupAndLoadUrl() method:

(function (require) {

    var Piwik_Popover = require('Piwik_Popover');
    Piwik_Popover.createPopupAndLoadUrl("?module=MyPlugin&action=getMyPopover", "The Popover Title", 'my-custom-dialog-css-class');

})(require);

Creating a popover will close any popover that is currently displayed. Only one popover can be displayed at a time.

Closing popovers

To close the currently displayed popover, call the close method:

(function (require) {

    var Piwik_Popover = require('Piwik_Popover');
    Piwik_Popover.close();

})(require);

Note that the Piwik_Popover object is stored directly in the window object and contains popover creation and management functions. Popovers created directly through this object are not persistent. To create persistent popovers, see the next section.

Loading Persistent Popovers

To load a popover that will be displayed even if the page is reloaded, you'll need to call two functions. Piwik makes a popover persistent by adding a popover query parameter. The parameter value will contain a popover ID and another string (separated by a ':'). Piwik will see this ID and execute a function that displays the popover.

The first method you need to call is named addPopoverHandler(). It associates a function with the popover ID. The function will be passed the rest of the popover query parameter. For example:

(function (require) {

    var broadcast = require('broadcast');
    broadcast.addPopoverHandler('myPopoverType', function (arg) {
        Piwik_Popover.createPopupAndLoadUrl("?module=MyPlugin&action=getPopup&arg=" + arg, _pk_translate('MyPlugin_MyPopoverTitle'));
    });

})(require);

Then, when you want to launch a popover call the propagateNewPopoverParameter() method:

(function (require, $) {

    var broadcast = require('broadcast');

    $('#myLink').click(function (e) {
        e.preventDefault();

        broadcast.propagateNewPopoverParameter('myPopoverType', 'myarg');

        return false;
    });

})(require, jQuery);

To learn more about the object, see the documentation in the source code (located in plugins/CoreHome/javascripts/popover.js).

ColorManager

If your control uses color values to, for example, draw in canvas elements, and you want to make those colors theme-able, you must use the ColorManager singleton.

JavaScript colors are stored in CSS like this:

.my-color-namespace[data-name=my-color-name] {
    color: red;
}

In your JavaScript, you can use ColorManager to access these colors:

(function (require) {

    var ColorManager = require('piwik').ColorManager;

    // get one color
    var myColorToUse = ColorManager.getColor('my-color-namespace', 'my-color-name');

    // get multiple colors all at once
    var myColorsToUse = ColorManager.getColor('my-color-namespace', ['my-first-color', 'my-second-color']);

})(require);

To learn more about the singleton, read the source code documentation (located in plugins/CoreHome/javascripts/color_manager.js).

Learn more about theming in our Theming guide.

DataTable

The DataTable class is the base of all JavaScript classes that manage report visualizations. If you are creating your own report visualization, you may have to extend it.

To learn more about extending the class, see our Visualizing Report Data guide.

Learn more

  • To learn about creating new report visualizations read our Visualizing Report Data guide.
  • To learn more about the asset merging system read this blog post by the system's author.
  • To learn more about theming read our Theming guide.