Widget JavaScript file

A widget JavaScript (.js) file contains specific JavaScript code that implements a widget as an element of the user interface. This page shows examples of how to extend existing widgets and implement changes by registering them as new widget classes.

The widget JavaScript (.js) files contain functions for rendering the widget template file (.tpl.html) and dynamically building the DOM element. To customize a widget, you need to extend the standard widget class in a new widget .js file contained in your customization project directory.

The widget JavaScript (.js) file is associated with a template file. If the widget JavaScript (.js) file and the template file are in the same directory and have the same name (for example, MyEditWidget.js and MyEditWidget.tpl.html), they are associated automatically. If the template file does not have the same name as the widget JavaScript (.js) file, you can associate them by setting the __templateName value in the .js file.

Simple widget

This sample code shows the minimal code you need to extend a simple widget in JavaScript:

"use strict";

modulum('newWidget', ['baseWidget', 'WidgetFactory'],
  function(context, cls) {

    cls.newWidget = context.oo.Class(cls.baseWidget, function($super) {
      return {
        __name: "newWidget",
        __templateName: "newTemplate",

        /* your custom code */
      };
    });
    cls.WidgetFactory.registerBuilder(parentSelector nodeSelector, cls.newWidget);
  });

where:

  • newWidget is your custom widget.
  • baseWidget is the built-in widget that it extends.
  • newTemplate (optional) is the template file to associate with the widget. If the .tpl.html file has the same name as the .js file, you do not need to specify the template name.
  • parentSelector (optional) designates one of the targeted node's ancestors.
  • nodeSelector designates the targeted node.

    parentSelector and nodeSelector are both types of selector. A selector takes the following format:

    nodeName.4stStyleName [4stAttribute=value] ... 
    • nodeName is the AUI node name. It is optional.
    • 4stStyleName is the AUI node style name. It is mandatory if nodeName is omitted but optional if nodeName is present. If 4stStyleName is omitted, the leading dot is also omitted.
    • [4stAttribute=value]... is a list of zero to N items. For each item in the list:
      • 4stAttribute is the name of an attribute belonging to one of the Genero presentation styles of this node.
      • value is the targeted value for this Genero presentation style attribute.
Note:

In most cases, you would use the simplest form of the cls.WidgetFactory.registerBuilder function:

cls.WidgetFactory.registerBuilder(nodeName, cls.newWidget)

However, you would specify extra parameters when you want to provide a widget that responds to an object that uses a specific Genero presentation style and Genero presentation style attribute.

Example 1:

cls.WidgetFactory.registerBuilder('Stack Group', cls.StackGroupWidget);

The StackGroupWidget is used for the Group AUINode if one of its ancestors is Stack AUINode.

Example 2:

cls.WidgetFactory.registerBuilder("CheckBox[customWidget=toggleButton]", cls.MyToggleButtonWidget);

The MyToggleButtonWidget is used for any CheckBox AUINode where the form object (the CheckBox) specifies the Genero presentation style attribute customWidget with the value toggleButton.

Container widget

For container widget customization, you can set a file gbc-project-dir/customization/customization-project-dir/js/myComposedWidget.js:

"use strict";

modulum('MyComposedWidget', ['WidgetGroupBase', 'WidgetFactory'],
  function(context, cls) {
    cls.MyComposedWidget = context.oo.Class(cls.WidgetGroupBase, function($super) {
      /** @lends classes.MyComposedWidget.prototype */
      return {
        __name: "MyComposedWidget",

        _label: null,
        _edit: null,

        constructor: function() {
          $super.constructor.call(this);
          this._label = cls.WidgetFactory.createWidget('Label');
          this._edit = cls.WidgetFactory.createWidget('Edit');
          this.addChildWidget(this._label);
          this.addChildWidget(this._edit);
        },

        [...]
        destroy: function() {
          this.removeChildWidget(this._label);
          this.removeChildWidget(this._edit);
          this._label.destroy();
          this._label = null;
          this._edit.destroy();
          this._edit = null;
          $super.destroy();
        },
        [...]
      };
    });
    cls.WidgetFactory.registerBuilder('MyComposed', cls.MyComposedWidget);
  });

For a Container widget, the root base widget is always WidgetGroupBase. You add the child elements with this.addChildWidget and remove child elements with this.removeChildWidget.