Creating Custom Widgets with JavaScript in Wakanda

by Saad Mousliki on June 5, 2014

The modern web is always changing, and this article is more than two years old.

By Saad Mousliki

4D, a company known for launching the first graphical relational database for the Macintosh 30 years ago, unveiled a full-stack JavaScript platform for developing business web applications in 2010 named “Wakanda”. Wakanda is an open-source platform allows you to develop Web and mobile business applications using web standards: HTML, CSS, HTTP/REST, JSON-RPC, and JavaScript. Moreover, Wakanda uses JavaScript on both the client-side and the server-side.

Wakanda recently released its 8th version. A new version is typically released every four to five months and a public roadmap is maintained based, in large part, on suggestions made by the community via the company’s website. Thanks to the community’s input, Wakanda has developed connectors for 4D, SQL Server, MySQL and ODBC, a server-side Web socket, a Git client for collaborative development, data bridges between 4D and Wakanda, and a new widget architecture.

In this article, we’ll learn the basics of getting started building widgets using the new widget architecture. This new widget architecture is probably one of the greatest advances Wakanda has made in Wakanda 8. The new Widgets API allows you to develop a custom widget (either using a third-party widget or using your own JavaScript code) and using it in your Wakanda project as if it were a built-in Wakanda widget. You can use any front end JavaScript framework like KendoUI, Sencha, Select2 JS, or jQuery to create a custom widget in Wakanda.

I’ve found the new Widgets API easy-to-use and have been able to create four custom widgets in a short amount of time. These widgets are on my GitHub repository.

The New Widgets Architecture

In previous versions of Wakanda, the process for creating and deploying a custom widget was manual. In Wakanda 8, creating a custom widget is automated in Wakanda Studio. Not only can you create your custom widget, but you can also develop and debug it in Wakanda Studio directly. Custom widgets are fully integrated into Wakanda so that they work just like any of the built-in widgets. You can create the properties (as well as data binding properties) and events as well as style sections to display in the Properties area for the widget in the GUI Designer (the tool you use to create your Pages in Wakanda).

In the example for this article, I will show you how to create a custom Wakanda widget using a third-party JavaScript widget that allows the capture of the user signature from a mobile web app or a desktop web app. For more detailed information, you can refer to the Wakanda documentation.

Getting Started

Obviously, for creating a widget (or using Wakanda in general), you’ll need experience in web development and a good knowledge of JavaScript.

For the widget that we will create in this section, I used the following:

  • I worked on a Windows 7 machine with 64xbit and 4G RAM but basically the same steps should work on a Mac.
  • I used Wakanda v8 production (64-v8-159169), which you can download here ). There are a variety of all-in-one installers or zip archives depending on your preference.

Creating a Custom Widget Using the Template

After installing the Wakanda All in one, go to the Wakanda Studio folder and run the Wakanda Studio .exe file, you can now create your solution by clicking “Create New Solution”

wakanda-widgets-1

 

At the bottom of the Solution Explorer Panel you will find the “WIDGETS” folder which will contain the list of all custom widgets that you have. right click this folder and create a new custom widget, give your widget a name, for example “My_Custom_Widget.”

wakanda-widgets-2

You could also use the “File” menu, point to “New” and then click on “Custom Widget.” In addition, you can right click on the “WIDGETS” folder, click on “New Custom Widget,” give it a name (for example “my_Widget”),  click on “Create,” and, once created, expand the “WIDGETS” folder to see the custom widget template.

wakanda-widgets-3

The newly created custom widget folder contains the following files and folders:

  • README.md: The Markdown file where a portion of the documentation of the widget’s API (properties, methods and events) is described; this is the GitHub repository description.
  • designer.js: This is the file that defines the appearance of the widget in Wakanda Studio. You could also add advanced behaviors to your widget via Wakanda Studio.
  • widget.js: This file is where we can add the code that creates our widget: the creator function, the properties and methods, and the events.
  • icons: This folder contains the widget icon which will be visible in the widgets toolbox in Wakanda Studio.
  • css: This folder contains the widget.css file where we define the custom widget’s style.
  • package.json: In this JSON file we define the widget metadata and many other details. The most important part of this file is the loadDependencies array where we add references to all of the JavaScript or CSS files that should be loaded when creating the widget.

For more details about the custom widget template take a look to this doc.

As I mentioned in the previous section, I’ll create a custom widget based on a jQuery Plugin, for this part, I have chosen to use the signature_pad plugin, which allows visitors to sign on a web page (using a smartphone, tablet or desktop) like signing on paper. Go to the GitHub repository for this jQuery Plugin and download the latest minified version signature_pad.min.js.

Create a subfolder within the widget folder by right clicking on the widget folder and choosing “New Folder…” Give it a name – for example “js” or “lib.” After that, copy the signature_pad.min.js file into this folder.

wakanda-widgets-4

Now, we need to add this dependency to the package.json file. Here we can also modify the widget name, author, collaborators and other metadata if we choose. You can add a new icon for the custom widget by replacing the by default icon by a new .png file that is sized 16×16.

wakanda-widgets-5

Tips

  • In the package.json, you should add the dependency of each file js and css, and respect the loading order. For example, if we have integrated a third party library that uses Raphael.js, we should first add the Raphael dependency and then, after that, add the library dependency which will use Raphael.js. At the end add the widget.js dependency where we will use the previous files. The same sort of order should be respected for CSS files.
  • If you have a JavaScript library or CSS file that is used by many widgets, you don’t need to add the same files for each widget. You could add it for one widget and refer to its path on the other widgets that use it.

Now, we have finished preparing the template and we will move on to the next step where we will add code that creates the widget and defines its properties.

Adding Properties and Methods to a Custom Widget

The custom widget inherits directly from the widget object, which provides a common API used by all Wakanda widgets. The widget.js file contains template code to create a widget. The code has many comments that help the developer add the code which can initiate the widget and define its properties and events. For our custom widget we will need to add code tp initiate the widget DOM within the init() function:

init: function() {
    var $node = $(this.node);
// Add a canvas DOM element to the custom widget
    this.node.innerHTML = '<canvas></canvas>';
// Customize the canvas attributes using JQuery
    $node.find("canvas").attr('id', 'canvas_' + this.node.id),
                        .attr('width', this.node.clientWidth),
                        .attr('height', this.node.clientHeight);

    if (!window.Designer) {
        var that = this;
        this.signaturePad = new SignaturePad($node.find('canvas')[0], {

            minWidth: this.minWidth(),
            maxWidth: this.maxWidth(),
            penColor: this.penColor(),
            dotSize: this.dotSize(),
            backgroundColor: this.backgroundColor(),
            velocityFilterWeight: this.velocityFilterWeight(),
// Add events using the fire() methos of the custom widget API
            onBegin: function() {
                that.fire('begin');
            },
            onEnd: function() {
                that.fire('end');
            }
        });
    }
}

The init() function code is responsible of creating the DOM element of the custom widget on the page when dragging and dropping the widget from the Widgets tab to the web page in Wakanda Studio. In our code, we need to add the canvas element to our custom widget DOM, which is necessary to instantiate our custom widget as described in the documentation for the signature_pad JQuery plugin API. To create a drawing area, we need to pass the already created HTML5 Canvas element as the first argument to the SignaturePad() function and the options (minWith, maxWith, penColor, etc.) as the second argument.

In our custom widget code, we have used jQuery, which is loaded by default as a part of the WAF. To select the widget using jQuery you should use $(this.node), which is the equivalent of document.getElementById(my_Widget_ID).

After instantiating and adding events to our custom widget, we should add some properties that will be visible in the custom widget properties panel within Wakanda Studio. Let’s add the same properties as defined in signature_pad API docs. The plugin has 6 options: dotSize, minWidth, maxWidth, backroundColor, penColor and velocityFilterWeight. These same options are presented as properties of the widget using the following code:

dotSize: widget.property({
    type: 'number',
    defaultValue: 0.2,
    bindable: false
}),
minWidth: widget.property({
    type: 'number',
    defaultValue: 0.5,
    bindable: false
}),
maxWidth: widget.property({
    type: 'number',
    defaultValue: 2.5,
    bindable: false
}),
backgroundColor: widget.property({
    type: 'string',
    defaultValue: "#fff",
    bindable: false
}),
penColor: widget.property({
    type: 'string',
    defaultValue: 'black',
    bindable: false
}),
velocityFilterWeight: widget.property({
    type: 'number',
    defaultValue: 0.7,
    bindable: false
})

For more details about how to add properties to a custom widget using the property() method, take a look to this doc ).

The properties are now visible in the Wakanda Studio and could be customized. At this point, our custom widget could be added to a web page, and debugged to verify that the added properties and events work as expected.

wakanda-widgets-6

Tips

    • Use a render() function to initiate and update your custom widget, so that each time some of the widget properties are updated by the user, the onChange() event is raised causing the render() function to execute with the new property value.
    • If you need to separate the Studio and runtime behavior of your widget, you could use the window.Designer which returns true if we are in the Studio and false on runtime. In our custom widget, we have used this tip to not allow the writing of a signature at design time in Wakanda Studio.
    • If you are using a more recent version of jQuery in your widget than the version in Wakanda, you can restore the original version of jQueryby placing this code at the top :
      var $ = JQuery.noConflict(true);

An example of using a property’s getter and setter:

var propertyValue = this.propertyName(); /* get the widget’s property value */
this.propertyName(newPropertyValue); /* update the propertyName to be    newPropertyValue */
    • The custom widget could have private properties and events that are only used in the internal code of the widget and not returned in the widget object via the JavaScript Module Pattern.

To manage the update of the custom widget when a property is changed at runtime, the custom widget API offers us the onChange() event, which is fired when a widget’s property changes. For more details about this event, take a look to this doc.

Defining Custom Widget Events

In the init() function, two events are added to our custom widget: onBegin, which is fired when the user begins the signature process; and onEnd, which is fired when the user ends the signature process. To add an event to the custom widget, the custom widget API offer the fire() method. For more details about the two events from signature_pad, take a look its documentation.

Events added to the custom widget via the widget.js file should be referenced in the designer.js file as follows:

/* Define custom event for your widget */
My_Widget.addEvent('begin');
My_Widget.addEvent('end'); 

Next, we will add three methods to the custom widget API for clear(), isEmpty() and toDataURL():

clear: function() {
    this.signaturePad.clear();
},
isEmpty: function() {
    return this.signaturePad.isEmpty();
},
/* This API method convert the SignaturePad canvas to an image that could be opened in the browser */
toDataURL : function(){
    return this.signaturePad.toDataURL();
}

The events are now visible in the Wakanda Studio and the user could add code that executes when the event is fired.

wakanda-widgets-7

After clicking on the plus button to right of the event name, we can add code for the event. For example, we could fire an alert when the user finishes writing his/her signature.

my_Widget1.end = function my_Widget1_end (event)
{
    alert("You can save your signature as an image file !");
};

Tips

  • The whole custom widget’s code is loaded each time you open a page in Wakanda Studio. So, if you are developing a custom widget and you have a page that is already open, you will be notified by Studio that this page doesn’t have the latest code for your widget. You should close and re-open it to load in the new changes.
    wakanda-widgets-8
  • The designer.js code is executed first when loading the custom widget in Wakanda Studio. After that widget.js is executed. At runtime only the widget.js code is executed. In fact, the widget code is minified and loaded with all other widgets on the page using the loader.js.

Preview and Debug a Custom Widget

As we have seen, there are several steps involved in creating a custom widget you are ready to preview and debug the custom widget. However, debugging and previewing can obviously be done at the same time along with the previous steps to fix and check the code as you develop it.

To preview a custom widget, you should open a new page, go through the list of the custom widgets in the bottom of the widgets tab, and drag your widget over to the page.

wakanda-widgets-9

Tips

  • If Studio notifies you that the page has an error and cannot be opened via the “Unable to load your document” message, you shouldn’t save the page. Open the source code of your page and then delete the tag element of the custom widget which is causing the issue.
    wakanda-widgets-10
  • To debug the widget code, for example to check the value of a variable when the widget is thrown in the Wakanda Studio, you could use alert() and pass it the value. For example, we’ll verify the value of the penColor property when dragging our custom widget over the page:
    alert(this.penColor());

    wakanda-widgets-11

Reusing the Custom Widget

Reusing and sharing the custom widget with other developers is one of the important steps, because it could help others gain time and also help you receive feedback that can improve your widget.

To share the widget in the official custom widgets repository in GitHub you can follow the steps described in this guide.

In order to facilitate the export and import of custom widgets, the development version of Wakanda has a new extension called Add-Ons which allows the importing of custom themes, custom widgets and custom Wakanda Studio extensions. At the time of writing this article, the extension has 28 custom widgets that are classified by popularity, with the most downloaded listed first.

wakanda-widgets-12

To get more details about how to install a custom widget using the Add-On extension, take a look to this discussion.

Conclusion

After completing this tutorial, we have a custom widget that integrates a third party library/jQuery plugin. Our widget has many use cases including storing a user signature in a remote database ) or using it for a mobile application that allows you to write or draw pictures. The point is, the JavaScript community is creating amazing libraries: graphs, select boxes, maps, grids, panels, menus etc. The new Custom Widget architecture allows us to turn these third party libraries into native Wakanda widgets.

In this tutorial, we saw how you can turn a useful library into a drag-and-drop Wakanda widget that can be re-usable in all your projects. You can even add customized properties, multiple events and data-binding that can greatly extend the capabilities of the original 3rd party library.

Additional Resources