This is a rather unique use of Fabrik. Code snippets are linked to separate pages. To view the source while reading the description right click on the link and select Open in new Tab.
We use
Community Builder to manage our users. Originally we had a text field where our users would type their interest and this text field could be searched from the User
Lists. The problem we were having is that one user would input Golf and another would input Golfing. During a search, the member who entered Golf would get both Golf and Golfing, but the member who searched for Golfing would only get the members who used Golfing in their interests. We needed some way to standardize on the naming of interests.
Some members suggested that a pick list of interests would be preferable, in this way they would always choose the standard name.
Community Builder does not offer a picklist field type, nor a field type where a member can add a new item to the list. But wait! Fabrik has this!
In order to accomplish this functionality a number of components in addition to Fabrik are used. These include NoNumber Modals, NoNumber Sourcerer, custom HTML and
Javascript, and a custom
Community Builder plugin. I am including the source for the entire plugin which can be reviewed to see what is happening.
General Design
Since the CB search facility searches only text fields we must use a text field for the actual field withing CB. Furthermore, CB searches any words so a search for "Line Dancing" will return "Line Dancing" as well as "Ballroom Dancing". As a result we need to ensure the search terms are unique.
In order to ensure uniqueness we will use two (2) versions of the same interest. One we will call the Value and one we will call the Label. The Label version will be the user readable version, in our example "Line Dancing". The Value version will be modified by replacing spaces, dashes and slashes with underscores. This means the Value version would be "Line_Dancing".
The system will display the Label version to the members but the Value version will be used for the actual search. The member will never see the Value version. The words Value and Label will be used throughout this discussion.
In order to accomplish our goal we will create a new type of CB field through the use of a CB Field Plugin. The underlying field type will be text but we will add some extra stuff outside of CB itself.
The pieces are:
- a field plugin for CB
- a fabrik database table and form with pick list
- a joomla article to close the fabrik form modal window
Other items used in the system are:
- NoNumber Sourcerer to insert HTML and Javascript into the article closing the fabrik window
- NoNumber Modals to display the fabrik form
Each of these will be described in more detail.
Workflow
The following briefly describes the user experience of using this system.
We start with a member who has not selected any interests.
When the member views their profile they will see neither the title for their interests or any interests on their profile.
In order for the member to add interests they will go in and edit their Profile. At the bottom of the profile fields is a grayed out box which at this point is empty. Beside this box is a link "Click to change". A pop-up window opens when the member clicks on this link which displays some instructions along with the picklist. The member drags and drops interests from the From column to the To column and then clicks Save. When the pop up window closes they will see their selections inside the grayed out box. They will then click on Update. Upon returning to their profile they will now see the Interests row and the selected interests displayed. Other members will also see these interests when they view this member's profile.
The member can go back at a later date and add/subtract from this list in the same way.
Members may also add new interests to the list.Instructions for doing so are included on the pop up form.
When a member wishes to search the member community for like minded people, they will do so by accessing the Members List from the User Resources menu. Clicking on the Search Users button will open the search criteria selections. To search for a particular interest the member will select the desired interest from a drop-down list and then click on Find Users. The list of other members with the interest defined in their profile will then display.
Fabrik List/Form
Fabrik provides the PickList functionality and database of member interests.
The
Picklist element of Fabrik has 2 parts for each pick, a Value and a Label (isn't that convenient!). For our purposes the Value is what will be stored in the CB database and the Label is what will be displayed to the user.
The underlying table is called member_interests. The key parts of this table are the user_id and the member_interests. A unique record is maintained in this table for each user who elects to select his/her interests. The Joomla User Id of the user is stored in the user_id column. The actual chosen interests, the Value part, is stored JSON encoded in the member_interests column.
The User ID is stored by placing {$my->id} in the default of the element.
Member Interests Element
As mentioned above, this is a Fabrik
Picklist element. The PickList has a list of Labels from which the member may select by dragging them from the From column to the To column on the Fabrik form. Initially a few items were included in the list when the system was created. Over time this list will expand as members add their own interests to the list.
The underlying structure of the PickList item contains a Value/Label pair for each item. We only display the Label in the form for the user to choose, but it is the Value that is stored in the member_interests table and CB database for the user.
As indicated previously, the Value text is modified for uniqueness.
The
Picklist element is configured to allow members to add new values to it.
For additions the element is configured to present an entry field for the Label only. As a result, the element will set the Value the same as the Label. This of course is not what we want but we will fix this in the form submission plugin.
The element runs a
PHP validation script when the form is submitted. The purpose of the script is to validate additions. It performs a
Validation to ensure that the addition does not conflict with an exiting interest or even with another addition. If this happens the
Validation fails and the user is presented with an error message indicating the problem.
Picklist element Validation plugin source code
here.
Fabrik Form
The name of the Fabrik form is "Update Your Interests"
The form has a single element and that is the
Picklist element described above. The form also includes introduction text to advise the member on how to choose their interest, how to add new interests, and describes some restrictions on naming any additions.
The form has 2 form submission plugins, an onBeforeProcess PHP plugin and a redirect plugin. These plugins run once the user clicks on Save and there are no
Validation errors. See the Element description for
Validation details.
The form itself is displayed when the user clicks on the "Click here to change" link when they are editing their profile. This link creates a modal window using the NoNumber Modals plugin and the link inside the modal is to the Fabrik form. More details on this will be presented in the CB Field Plugin discussion.
OnBeforeProcess Form PHP Plugin
Source code
here.
The purpose of this plugin is to massage any additions that a member may provide.
Once
Validation passes, Fabrik runs the onBeforeProcess PHP plugin. The code for this plugin can be found by opening the form in the Administration interface under Components->Fabrik->
Forms, clicking on the Plugins tab, and then clicking on the PHP plugin. This plugin performs a number of steps:
- It gets the interests and additions from the form data. If there are no additions it simply returns.
- It massages the additions, changing the Value part to replace the spaces, dashes, slashes etc to underscores. It also changes the Value and Label to uppercase words.
- It verifies the addition wasn't entered twice.
- It adjust the additions for a bug in the Picklist element. Details are in the code.
- It puts the revised additions back into the form
At this point any addition will be in upper case word format and the Value part of it will have been made unique with the replacements.
Fabrik will now store the information into the member_interests table for the user, and it will insert any additions into the
Picklist element list of available items.
The purpose of this plugin is to cause Fabrik to redirect to a specific page after form submission.
Once the form is submitted there is no way to close the modal window. Normally it would redirect back to the home page with the affect we have a copy of the home page in the modal window. Not optimal.
We use a redirect plugin to causes Fabrik to redirect to a specific page on the website rather than the home page. This page is a special article created for the purpose as described next.
Note: Fabrik always runs the redirect plugin as the very last thing it does upon form submission completion. You may see the redirect plugin listed before the php plugin when you open the
Forms plugin tab. This is OK, it is simply the order I created them.
The jump page is very straightforward, you just need the article ID and any valid menu ID (check authorizations): index.php?option=com_content&view=article&id=275&Itemid=864
Redirect Article
Source code
here.
The purpose of this article is to update the CB Profile edit values and the close the modal window.
This article performs 2 very special functions. It does this using NoNumber Sourcerer which allows to insert PHP and
Javascript code into the article. The name of the article is: "Dummy article to close the member interests ajax window"
Its first function is to update the CB fields in the edit profile page with the selections the member made. There are 2 text fields on the edit profile page, one is displayed and one is hidden. The hidden one is the standard CB text field for the interests which should have the Value texts for the selected interests, and a display field which needs to have the Label texts for the selected interests.
The PHP code does the following:
- it gets a list of the interests the member has selected from the member_interests table based on the user ID. These are Value texts.
- it gets the corresponding Label texts from the actual Fabrick Picklist element
- it stores the values into the CB table for the user ** see note below
- it then creates some Javascript and echo's it out. When this Javascript is processed by your browser the 2 fields are updated with the correct text.
The final part of the Javascipt is to close the modal window which returns the member to the CB edit profile page.
Note: The CB database is updated here for a reason. The Fabrik table will have the new Values stored in it. If we do not update the CB database then if the user cancels the profile edit the CB database and Fabrik table will be out of sync. Instructions are provided to the member advising them that once they Save the Fabrik form their profile is updated.
Note: what you see below is php code inserted into an article using NoNumber Sourcerer. Please visit the NoNumber site for details on usage.
CB Plugin
View source
here.
This is where a lot of the magic is for this system. I am not going to go into any detail on how to build a CB plugin, but I will describe what is happening in each part of it.
One of the challenges this project faced is how to have searchable text strings that are unique but that also can be displayed for the user to read. For example, we have "Line Dancing" and "Ballroom Dancing". We would like to see them displayed in this manner to the user, but if we use them as is for searching, and we enter "Line Dancing" into the search box we will get both results. This is because the search engine searches on individual words and the word Dancing matches both.
We solve this by storing a massaged version of the name in the database. In the above example we store Line_Dancing and Ballroom_Dancing. Now when we search for Line_Dancing only one matches.
We have already discussed how the PickList does the massaging for us of the Value/Label pairs. The Plugin will make this all seamless to the member when they view and search for interests.
General
When CB needs to render a field it calls the field type plugin. CB provides many core field types such as text, a textarea, email, password, etc. CB can be extended by developers by adding their own field types.
I have developed a CB field plugin called cbfabrikitem. As far as CB is concerned it is a text field, but the plugin inserts additional HTML around the field when displaying it to the user. There are three basic types of display: html text, html edit, and html edit search. What is inserted differs for each of these and will be described in more detail.
HTML Text
This request by CB is to render the text field for display in the member profile. CB does not care what we render here. It passes us the current values stored in the CB database. Remember these values are the PickList Values so have been massaged for searching, they will include the underscores.
Since we do not want to show the Values to the user we go get the Labels for these Values from Fabrik
Picklist element and return the string of Labels for display.
All very straightforward.
HTML Edit
This one is a little more complicated. CB wants us to return a field that will allow the user to edit the values and when the user clicks the Update button CB will store these new values in the database. This is not good for us for a number of reasons. First we want massaged Values stored in the database and the user is sure to enter Label type text, and secondly if the user was able to change these then the Fabrik table would be out of sync. We want changes kept in one place.
When CB asks for this type of rendering we do the following:
- create the html for the edit field normally, then insert a hidden attribute. In this way the field does not display to the user.
- we create a new html field and set it to disabled. We insert into this field the Label text of the Values given us by CB. So now the user sees the Interests (or none) that they chose previously.
- We insert a link beside the new html field. This link is a modal using NoNumber Modals which opens the Fabrik Form.
Now, as described under the Fabrik Form redirect article, when the form closes the article
Javascript pushes new Values to the hidden field and new Labels to the field the user sees.
HTML Edit Search
If you look at the code you will actually see that this type of render actually comes in the same way as the HTML Edit type, but there is a reason code sent along which tells us it is for a search.
We are going to do some similar magic as for the HTML Edit type.
We decided we did not want the member typing in a search term as they were likely to get unpredictable results. This is because the search function of CB is pretty trivial and searches on any words. Searching for "Board Games" would return Board Games, Boogie Board, Card Games, etc., not useful. So the decision was made to provide a dropdown list where the member would choose a specific interest.
When CB asks for this type of rendering we do the following:
- create the html for the edit field normally, then insert a hidden attribute. In this way the field does not display to the user.
- create a drop-down list-box of all the available interests from the Fabrik Picklist element. Since the Element has Value/Label pairs we use these in the Value/Text of the select Options. The member sees the Labels in the drop-down.
- we insert an onchange function call on the drop-down box to call a pushInterest Javascript function
- we insert Javascript with this function. The purpose of the function is to push the Value of a selection change to the field we have hidden from step one. We also check that if the member has selected the "Please Select" option we clear the hidden field.
Now when the member selects an interest, the
Javascript pushes the Value of the selected interest to the hidden field, and when the member clicks on Find Users CB uses the text in the hidden field (the Value) to search the database.
All works wonderfully.