![]() |
Xataface
2.0alpha2
Xataface Application Framework
|
The previous sections have been laying the foundation for this section, in what will be our first "useful" module. Xataface comes with a set of built-in widgets that are quite useful, but once in a while, you will likely find yourself in need of a widget that doesn't yet exist. The internet is full of jQuery plugins that can easily be converted into Xataface widgets with very little effort.
Some Javascript plugins that have already been adapted into Xataface widgets include:
The general strategy for creating a widget is:
For this tutorial we will be creating a Color Picker widget based on the eyecon colorpicker.
Xataface forms are based on HTML_QuickForm for its base set of widgets, but it uses a Widget Handler as a wrapper around these widgets as a means of configuring them. These wrappers are known as Widget handlers and they are managed by the Dataface_FormTool class.
A widget handler has to be able to do at least three things:
In most cases you can get by with only defining a single method (buildWidget()) in the widget handler and let Xataface just use its default handler to load and store the values in the widget.
There is no set place where the widget handler needs to go. Let's just add it to the root directory of our module, and call it colorpicker_widget.php. Add the following content to this file:
The above widget handler doesn't do anything fancy yet. It simply creates a plain text field. After we have our widget working as a plain text field, we'll go back and transform it into a color picker.
Before we can use our new widget, we need to register the widget handler with the form tool. We'll make use of the Dataface_FormTool::init event that is fired when the form tool is first created. This allows us to avoid loading the FormTool into memory unnecessarily. We'll do all of this in our module class's constructor as this is guraranteed to be executed at the beginning of every request that the module is enabled for.
Now that we have registered our widget, we should be able to use the widget. Let's set up a simple table in the database for this purpose:
And we'll create a fields.ini file for this table in the myapp directory:
We will use our new colorpicker widget as the widget for both the foreground_color and background_color fields:
Now that all of the pieces are in place, let's load up a new record form for the color_profile table and see what it looks like.
color_profile table by pointing your web browser to your application's index.php page with the GET parameters -table=color_profile and -action=new
If everything is working correctly, you should see regular text fields for the foreground_color and background_color fields. This may be slightly disappointing, but this is what we want. We'll convert these into more interactive color-picker widgets in the next few steps. At this point we just want to be sure that our custom widget handler is working.
Before we can convert our text fields into color pickers, we need to make sure that the javascripts, CSS files, and images for the colorpicker widget that we are planning to use are accessible to our project. Specifically we need to add these files to our project in such a way that the Dataface_JavascriptTool and Dataface_CSSTool can work with them.
We start by downloading the Color Picker source files from the EyeCon website. After unzipping the ZIP file we should have the following directory structure:
So we have 3 types of content to contend with:
The first thing we'll do is to add the Javascript files to our module. In order to keep things separated, we'll place them inside our namespace inside the js directory. A good location might be
jquery.js because we have our own version of jQuery with the Xataface distribution that we'll be using instead.Once we have copied all of the javascript files we should have the following directory structure inside our module:
Similarly, we'll add the CSS files in a namespaced directory structure so that we can reference them uniquely. We'll place both the css and images directories inside the
directory.
When we're done copying these files, the directory structure of our module will look like:
Now that we've added all of the necessary javascript and CSS files for the colorpicker widget, we need to create our own thin bootstrap code that converts our text fields into color pickers.
Before we can do this, however, we need to add a CSS class or attribute to our text fields so that we are able to identify the colorpicker widgets in Javascript. We modify our Widget handler (colorpicker_widget.php) in order to accommodate this:
All we've done here is create an $atts array where we specify a class attribute that is to be added to all color picker fields. We then add this as the 4th parameter of the $factory->addElement() call (a call to HTML_QuickForm::addElement).
In short, all this does is add the css class xf-colorpicker to all instances of our colorpicker widget. This will allow our Javascript bootstrap code that we're about to write to identify which fields are colorpicker fields, and hence which ones should be "decorated".
We'll place our Javascript bootstrap code into a new file. It's location doesn't matter as long as it is located somewhere inside the module's js directory. We'll place it at
Place the following code inside this file:
There isn't much in ths bootstrap file, but there's a lot going on.
registerXatafaceDecorator function so that it will be executed for any part of the page that is added even after page load. This is important if you want your widget to work properly inside compound widgets like the grid widget.ColorPicker() jQuery plugin to all elements with the xf-colorpicker CSS class.Now that we have created the Javascript bootstrap we need a way to ensure that it will be run whenever a form is rendered. Essentially, this just requires us to import the colorpickier_widget.js using Dataface_JavascriptTool::import(), but we would prefer to do this in the most efficient way possible, such that the file is only imported if the colorpicker is going to be rendered. And taking an additional step back, we also need to ensure that our module's js and css directories are registered with the application when necessary. Otherwise our import won't work.
In the previous section we used Dataface_JavascriptTool::addPath() method to register our js directory. However we only did this inside the hello_world action. This code is only executed for that one action and won't be executed for the edit form or other Xataface actions that may require the colorpicker widget to be rendered. A simple solution would be to perform this registration inside our module's constructor, but then we may be adding unnecessary overhead to our application since most of the application has no need for our scripts.
To succinctly rephrase, our problem is:
Properties of the ideal solution to this problem are outlined in the wording of the problem itself. Namely, the ideal solution should:
css or Javascript directories with Dataface_JavascriptTool unless they are needed.To achieve this goal we will encapsulate the code that registers these files into our module's class as a method, and use a flag to ensure that they are loaded at most once.
hello_world.php:
Having this functionality encapsulated in a single method of our module makes it a simple matter to register the module's javascript and css assets on demand.
Now to complete our solution, let's add load our bootstrap javascript code from our widget handler (hello_world_widget.js):
All we've done here is to call our loadJs() method on the hello_world module class to load our javascript and css directories. Then we imported the bootstrap code so that it will run on page load. Notice that we do all this inside the buildWidget() method of our widget handler. This ensures that it will only run the bootstrap code if a colorpicker widget has been built (and thus likely will exist on the final page output).
Now if you reload the new record form for the color_profile table and click on one of the colorpicker fields, you should see something like:
If you don't see anything like this, there see module_developer_guide_widget_troublueshooting
If you run into problems along the way in this tutorial it really helps to have a good Javascript development tool so that you can easily check things like attributes and classes on HTML elements on the page. In addition you will want to keep an eye on the Javascript error log to see if any errors are reported. Especially in a tutorial such as this, with multiple parts, there are many places where you can go wrong. If a file is miss-named you may not see an error message - but the file will just not be picked up at all.
If you get really stuck, the best thing to do is seek help in the forum.
You can download the source for this module here.
1.8.1.2