You can modify the behavior and create your own custom widgets to use inside of Control; the features added in version 1.4 make it especially easy to do so.
Prototype Inheritance
If you’re new to JavaScript, Prototype Inheritance is an important concept that takes a while to get used to if you’re coming from class based languages like C++ or Java. Basically, every object in JavaScript has a Prototype object that it inherits all methods / properties from. The big difference between a prototype and a class in C++ is that you can dynamically change prototypes at runtime. In Control, all Button widgets inherit from a single instance of the Widget prototype; this widget is stored in Button.prototype. If I modify some aspect of Button.prototype ALL BUTTONS are changed immediately. There is also a Widget prototype. By modifying this I can change the behavior of every widget instance at runtime.
This means we have three ways we can change widget behavior.
- Change the method of an individual widget. For example:
myWidget.event = function() { alert('here's an event!!!'); }
- Change the method of a prototype. This change will apply to all objects that inherit from the prototype. For example, to change every button widget:
Button.prototype.event = function() { alert('here's an event!'); }
- Change the method of the Widget prototype. This change will apply to EVERY widget in the interface, For example:
Widget.prototype.event = function() { alert('here's an event!'); }
Modification
For most modifications you'll need to view the javascript source of the widget you're modifying on GitHub to examine the method you want to override. Let's say we want to override the setValue method of a button widget. By looking at the Button.js file we know this method accepts one parameter: the new value for the button. To override it we can do the following (assume we've named the button myButton):
myButton.setValue = function(val) { alert('here's my new value: ' + val); }
Now when we press this button, nothing will happen except for an alert window that will pop-up. IMPORTANT: we can't override methods of objects until those objects are instantiated. If we place the above code in another function, we can then call that function from within the oninit
event handler to make sure the object has been instantiated. Example:
function initWidgets() { myButton.setValue = function(val) { alert('here's my new value: ' + val); } } pages = [[ { "name": "myButton", "type": "Button", "bounds": [0,0,.5,.5], "oninit": "initWidgets();", }, ]];
So now we've got a button with an overridden method. However, let's say we want to display an alert dialog (or execute some other arbitrary behavior) and then also have the standard button behavior occur. We can do this using the call method of the JavaScript function object. The call method allows us to invoke a method and define a particular scope for it. You should read more about it if you haven't been exposed to it before. Basically, we tell the call method to run with our button as the scope.
function initWidgets() { myButton.setValue = function(val) { alert('here's my new value: ' + val); Button.prototype.setValue.call(this, val); } }
Now the normal button behavior occurs after the alert menu has been displayed and dismissed.
Creating Widgets
User boblemarin is in the process of creating an excellent tutorial on how to create custom widgets. If there are further questions about this please ask in the forum.