Tutorial8: Creating Rich
Clients Using jQuery
Tutorial
Creating
the Structure of the Contact and Initial Texts
Respond
to the Mouse Moving Over the Contact
Write
the Expand and Collapse Functionality.
Associating
the jQuery Library with the Page
Associating
the Client Script with the Page
A
Closer Look at the JavaScript
What
are the main participants?
See also: All Tutorials, Client Javascript and Rich Client Features
The aim of this tutorial is to take you through the steps needed to add some dynamic behaviour to a web page, scripted using client-side Javascript together with the jQuery library.
We will be creating a simple contact such as you might find in an address book. The contact has a name, a job position, start date and an email address. To save space on the screen and in order to fit as many future contacts in as possible, we only want to show the contact’s name. When the mouse is moved over the contact we want the extra details to be presented.
To satisfy this we will create a page which will initially present:
Moving the mouse pointer over it will reveal the content.
And then moving the mouse away will hide the content again.
(right
click on the project Tutorials, then select Properties).
drag a Text control 1 into that panel and enter title of the contact CEO,
drag a Text control 2 and enter Co-Founder (1983) and
drag a Text control 3 and enter Email: ben.harper@notarealcompany.com
The WYSIWYG View now looks like this:
click on the ContentPanel Panel Control in the Outline View or WYSIYG View and in the Control’s Properties View, change its Layout type property to Vertical Box.
right-click on the ContactPanel Panel Control in the Outline View or WYSIYG View and open the Styling Assistant:
Now fill in the properties to match those in the pictures below:
The WYSIWYG View of the designer now looks like this. Note that the Border Radius property we just set above to give us rounded corners is a runtime only property so doesn’t show up in the designer.
The ContentPanel Panel Control also needs this padding, to give it space and to line up with the text in the HeaderPanel.
The ContentPanel Panel Control’s Styling Assistant should now look like this:
The WYSIWYG View now looks like this – much better than before we started styling!
Now we will make the contact more interesting, here is where we add the ‘expand and collapse’ feature where only the header is visible until
the mouse hovers over it when the content is revealed.
We want to be able to identify the ContentPanel panel in the browser DOM, as that is the panel we want to expand and collapse.
We do this in the ContentPanel panel’s HTML Element Properties Assistant. There is a choice of two Locators: Id and Class.
We could use the Id locactor, but this needs to be unique on the page which is great if all we want is to show one contact, but we will probably end up showing more than one,
and means we will have to be careful every time we add a new contact to make sure it’s different.
Class locators are good for this as many HTML elements can use the same class name and it means we can then easily manipulate all these elements as a group;
which is what we want, as any more contacts we add will need the same functionality.
!!!important: Html Element
Properties Assistant settings apply to ContentPanel!
For ContentPanel: add a Class Locator: content.
When the user moves the mouse over the contact we want it to expand, showing the content, and when the mouse moves away from the contact
we want it to collapse back down to the header (the name), hiding the content. We have yet to write functions that actually do the expanding and collapsing (that comes next),
but we can prepare for that here.
We are interested in two types of event that the jQuery library generates as a user moves
the mouse across the screen: mouseenter and mouseleave.
The mouseenter event is generated when the mouse is moved into an element, and the mouseleave event is generated when the mouse is moved out of an element.
The element we are interested in is the ContactPanel panel, so we will set up some custom Event Handlers on the ContactPanel panel to respond to these events.
Now set up the two jQuery Event Handlers as shown below, along with the contact Class Locator.
This Class Locator is used by the system to register these Event Handers to the ContactPanel element for you.
<IMMMMMMMMMMMMM image3>
For ContactPanel:
· add a Class Locator: contact.
·
Select mouseenter from Jquery Event drop down list and add Code: expand(this);
· Select mouseleave from Jquery Event drop down list and add Code: collapse();
·
!!!important: Html Element
Properties Assistant settings apply to ContactPanel!
Let’s have a quick look at the first Event Handler. It says: on a jQuery mouseenter event execute the script: expand(this). As we are adding this Event Handler to the contact panel,
this event is generated when the user’s mouse enters the contact panel. Again, as we are adding this to the contact panel, the this in the expand(this) code is the contact panel itself
(technically it is the HTML element that represents the contact panel – the div element).
See: Client Script Editor
We have now added Event Handlers which respond to the mouse entering and leaving the contact panel, calling either expand or collapse as appropriate.
These functions currently do not exist, so we now need to create them. This is the hard bit as writing the expand and collapse functionality requires knowledge about JavaScript
and jQuery. JavaScript is (and the jQuery library is as close as makes little difference) an industry standard for writing scripts for the Browser.
This Client Javascript needs to provide two functions: expand and collapse.
When we created the Event Handlers for mouseenter and mouseleave we called these functions and passed in the contact panel that the event was raised on, so these functions must accept a parameter
where the contact panel can be passed in. One of the contact panel’s children is the content panel to which we have just added the Class Locator content (above).
Both of these functions can use this Locator to find the contact panel’s content panel.
In the collapse function, once the content
panel has been found, we need to collapse it (i.e. shrink it until it
disappears). To do this, the Client Javascript
can make use of the jQuery function slideUp,
which decreases the size of the element it is called on until it is completely hidden. Therefore in the collapse function, we need to find the contact panel’s content panel and then call slideUp() on it.
JQuery also provides a function called slideDown that does the opposite of slideUp; it makes an element visible and then increases it to its full size.
Thus in the expand function, once it has found the content panel, calling slideDown() on it will expand it.
The Javascript code to do this can be found here. You can see the two functions collapse and expand, both of which accept a parameter called element.
The functions then look through the given element’s children to find the one with a content class, and they call slideUp or slideDown on that element as appropriate.
Copy the Javascript into the Script Editor and save it.
The editor should now look like this:
See: Form Properties, Adding External Scripts, Configuring Web Resources
Our Client Javascript uses the jQuery library, so we must associate this library with the Page (either directly or indirectly through a Form or Presentation Template).
If we don’t add it to the Page, the Browser will not be able to find any of the jQuery functions we have used.
In this case we are going to add the jQuery
library to the Form, which means it
will be available to all the Pages of
this Form. This saves adding it to every page
individually (although for this form there is only one page).
Now we will configure the jQuery library. Google is one of several public hosts of the jQuery Library and as it’s convenient, we’ll use that.
Click on the … button to the right of Client Javascript, then click on the ‘add script’ button (green plus).
Enter the URL: https://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js - be aware though if you are not connected to the internet then your browser
will not be able to follow the link and therefore will not be able to load the library).
See: Page Properties, Client Script Configuration Dialog, Configuring Web Resources
To make the functions we have written in our Client Javascript file PanelExpander available, we must associate it with the Page (either directly or indirectly through a Form or Presentation Template).
Let’s associate it with the Page directly:
Note that this property already shows the jQuery library added at form level in the previous step.
Press the ‘add script button’ (the green plus) then click on the Browse… button, select the Configure from workspace tab and select PanelExpander.
This dynamic behaviour we have created is only shown using a browser; the WYSIWYG View does not show it. So to see it all work.
Initially you will see:
Moving the mouse pointer over it will reveal the content.
And moving the mouse pointer away will fold the content back up so just the name is shown. This achieves our aims as stated in the introduction.
We can do this by copying and pasting the contact panel twice using the Outline View. Then double click the Texts controls to change them:
And as the mouse pointer is moved:
If you had a database table full of contacts, then the original ContactPanel panel could be placed into a Repeater Control, backed by this table.
The fields of this table could then be mapped in order to replace our hardwired Text Controls and so all of the contacts could be added without having to change our Client Javascript, Locators and Event Handlers.
1. The ContactPanel panel is the element the user is interacting with – when the mouse moves over it, the content must expand and collapse accordingly.
2. The ContentPanel panel is the element that is being expanded / collapsed (shown / hidden).
The ContactPanel panel contains the both HeaderPanel panel and the ContentPanel panel.
The HTML representation of the ContactPanel panel is as follows (removing system generated items used for styling and the Text Controls which don’t play any role in this example):
<div> (the contact panel)
<div></div> (the header panel)
<div></div> (the content panel)
</div>
As you can see each panel is represented by a single div element. Notice that the names we are using - ContactPanel, ContentPanel and HeaderPanel - do not appear in the HTML representation;
they are designer aids. This means we need a way of telling the ContentPanel and the HeaderPanel div elements apart in the Browser. This is why we have added a Locator to the ContentPanel panel (above);
we gave it a Class Locator of content, which in turn adds a class to the ContentPanel panel’s div element:
<div> (the contact panel)
<div></div> (the header panel)
<div class=”content”></div> (the content panel)
</div>
For this exercise, the jQuery Library helps us in two ways:
Firstly, whenever the mouse is moved around the page, jQuery generates an event every time the mouse enters and leaves an element. Actually, jQuery generates a suite of events to cover all user interactions from clicking
the mouse to typing into text fields, all of which complement or enhance the HTML events the Browser generates. But in this example, we are only interested in when a mouse enters or leaves the contact panel (or rather its div element).
We used this feature when we created the two Event Handlers in the contact panel’s Html Element Properties Assistant above. The Event Handlers listen for mouseenter and mouseleave events on the contact panel’s div element
and call a function when the event is triggered, passing the contact panel’s div element (i.e. the element that generated the event) into the function.
It should be noted that there is no reason why these Event Handlers couldn’t have implemented these functions themselves, rather than relying on them being defined elsewhere; the Event Handler’s code can be written in Javascript (as we have done)
and can use any Javascript library like jQuery (as long as the library is associated with the page, like we did here). The reason we didn’t define these functions in the Event Handlers comes down to a question of reusability – if the Event Handlers defined the functions, then only those Handlers can use them, so if we want to use the expand and collapse functionality elsewhere we would have to re-implement it. However, using a Client Javascript file, all we have to do is associate it with the Page in question (like we did here) and the functions can be used straight away.
The second reason we are using the jQuery library is that its API (http://www.jquery.com) provides two functions we can use to achieve the expanding and collapsing effect: slideUp() and slideDown(). slideUp() decreases the size of an element until it is completely hidden and slideDown() does the opposite. Because the jQuery library has been tested to be compatible with all browsers supported by Verj.io, it removes the headache of having to code in any incompatibility workarounds into our Client Javascript.
We already know the signature of the expand function as we considered this in the code of our mouseenter jQuery Event Handler, where we passed in the contact panel’s div element into a function called expand.
So in Javascript, our function definition looks like:
expand = function(element)
{
}
We want to use the jQuery slideDown() function to expand the content panel, so we need to start by finding the jQuery object representing this element: $(element). $ is an alias into jQuery.
It is the same as writing jQuery(element) which is the main entry point function into the jQuery library.
Now we have a jQuery object for the contact panel we need to find its child content panel and we can do this with the jQuery library function find(). This function accepts an optional selector parameter,
which is a way of identifying which specific children you are looking for (calling find() without a selector returns all the children – in this case both the header and content panels’ div elements).
As we have given the content panel a Class Locator of content we can use this as the selector. So $(element).children(".content") will give us the jQuery object representing the content panel (or technically its div element).
All that remains if to call the jQuery slideDown function: $(element).find(".content").slideDown();
And that’s it! To recap, we have created a function called expand which accepts an element which the Event Handler uses to pass in the contact panel’s div element (the element the mousesenter event was triggered on). Using jQuery we then found the content panel’s div element via its Class Locator, and then called slideDown() on it.
Putting all of this Javascript together we get:
expand = function(element)
{
$(element).find(".content").slideDown();
}
Now we have created the Javascript for expanding the content panel, writing the Javascript for the collapse function is easy. It is exactly the same as the expand script, but apart from calling the jQuery function slideDown, we call slideUp:
collapse = function(element)
{
$(element).find(".content").slideUp();
}
As it stands, when the page first loads in the Browser, all the content panels will be visible because we haven’t done anything to hide them yet. There are two ways these panels can be hidden:
1. Advanced styling can be used to add a display:none CSS style to the content panel. This is probably not the best solution, as it will hide the content panel in both the Browser and
in the Designer. This might be ok if you have finished
designing and styling the page, but if you need to come back to it you will
have to remove the style before you can see the panel again.
2. Use Javascript to hide the content panel. This means that it is still visible in the Designer but not in the Browser. However, as the content is still shown in the Designer, it becomes difficult to see what the page might look like when the content panel is hidden (as it will be in the Browser), especially when there are several contacts on the page.
So both these methods have problems and it really comes down to how you set about designing the page. As this tutorial is about using Javascript and jQuery, we will use the Javascript method here.
When a page loads in a Browser, the jQuery library generates a ready() event on the document as soon as the DOM is ready for scripts to manipulate it. In our Client Javascript we can hook into this event with the following code: $(document).ready(function(){ });. Here, we are calling ready() on the jQuery object representing the document and passing in a function (an anonymous function more precisely; i.e. one that has not been assigned a name which can then be referred to elsewhere). This function will then be executed by the jQuery library when it generates the ready event.
The first thing we need this function to do is find the content panel. We have already done something like this for the expand and collapse functions, but the difference here is that the Event Handler passed in the contact panel, and we then looked for the content panel within it using the Class Locator we gave it. We can use this Locator again here: $(“.content”) to find all the elements with a content class. Now we have found all the content panels we can hide them using the jQuery hide function. So to hide all content panels we can use this JavaScript: $(“.content”).hide();.
The complete JavaScript to hide all the content panels on the page when it is opened by the Browser is:
$(document).ready(function()
{
$(".content").hide();
});
Pulling in both expand and collapse functions and the code to hide the content panel, we arrive at the final code for our Client Script:
$(document).ready(function()
{
$(".content").hide();
});
expand = function(element)
{
$(element).find(".content").slideDown();
}
collapse = function(element)
{
$(element).find(".content").slideUp();
}
Instead of defining Event Handlers to call functions in our Client Script we can register events directly in it:
$(document).ready(function()
{
$(".content").hide();
$(".contact").hover(function () {
$(this).find(".content").slideDown(); },
function () { $(this).find(".content").slideUp();
} );
});
The first few lines are the same as before; all the content panels on the page are hidden when it loads in a Browser. We then register a hover event to all the contact panels on the page.
This hover event is configured with two functions: the first is called when a mouse enters the contact panel and the second one is called when it leaves.
Both of them use the jQuery find function on the current element (the contact panel the mouse is moving into/out of) to get all of its content panels.
Then the first function calls slideDown() to expand them whereas the second one calls slideUp() to collapse them instead.
Important: This eliminates the need for our custom jQuery Event Handlers for mouseenter and mouseleave, but we still need to add the contact
and content Class Locators to the Html Element Properties of the contact and content panels respectively.