As a little follow up to my post last week about starting to play with the Flex, I took my last.fm user application a little further to include more of the information they expose throught the audioscrobbler site.
Have a play: last.fm flex app v2
As a little follow up to my post last week about starting to play with the Flex, I took my last.fm user application a little further to include more of the information they expose throught the audioscrobbler site.
Have a play: last.fm flex app v2
Spry blog posts seem a little thin on the ground, so I thought I'd start a series of Spry related posts covering some of the issues that we've come across in the rebuild of the HostelBookers site (yet to be launched). Spry was the AJAX framework of choice for the project before I arrived at HostelBookers and as I'd had a little experience with it in my last job we decided to carry on with it. I've since been named "SpryMan/Guy". Not sure whether to be proud of that or not. Spry seemed to fit nearly all of our AJAX-type needs especially in the data display/filtering/sorting capacity, but it is lacking in some other areas, so we had to draft in jQuery for a nice datepicker and other UI bits and bobs. I think if I got a chance to start from scratch I'd stick to one framework completely, and I think it would be jQuery (mainly for the size of the community).
So my first example will be on conditional validation. We have a section of the site that has a little survey. The very first question decides whether you need to answer further questions or not. If you get the futher questions displayed those fields need to be validated, if they're not, the validation is unnecessary. This will be a generic example, not quite as large as our actual page:
First you'll need to include the required Spry librarys and validation CSS in the <head> for the functionality we're going to use (if you haven't got Spry yet, it's available from Adobe Labs, but the download below includes all the files used in this example). For this example we'll use:
<link rel="stylesheet" type="text/css" href="spry/SpryValidationTextField.css">
<link rel="stylesheet" type="text/css" href="spry/SpryValidationRadio.css">
<style type="text/css">
.hide {display:none;}
</style>
<script type="text/javascript" src="spry/SpryUtils.js"></script>
<script type="text/javascript" src="spry/SpryDOMUtils.js"></script>
<script type="text/javascript" src="spry/SpryValidationTextField.js"></script>
<script type="text/javascript" src="spry/SpryValidationRadio.js"></script>
The Spry CSS covers the validation indicators by hiding the messages by default and colouring fields when they meet certain criteria. The ".hide" class is added to hide the optional questions in our form. Of the Spry JavaScript, the first two are helper utilities, the second two are for the form input validation. We're only going to validate text fields and radio buttons in this example, but you can add select, textarea and/or checkbox valdiation as required. I tend to use the minified versions of the JS files. Packed ones are usually smaller, but the decompression of them can add an overhead.
Our XHTML form will be:
<form name="frmQuestions" id="frmQuestions" action="index.html" method="post">
<div id="valMoreQuestions">
<p>1. Would you like some more questions?</p>
<label for="moreQuestionsYes">
<input type="radio" name="moreQuestions" id="moreQuestionsYes" value="true" />
Yes please.
</label>
<br />
<label for="moreQuestionsNo">
<input type="radio" name="moreQuestions" id="moreQuestionsNo" value="false" />
No thanks.
</label>
<br />
<span class="radioRequiredMsg">Please select</span>
</div>
<div id="valExtraQuestion1" class="hide optionalQ">
<p>2. Extra question one.</p>
<label for="extraQuestion1">Who is your daddy?</label>
<input type="text" name="extraQuestion1" id="extraQuestion1" />
<br />
<span class="textfieldRequiredMsg">Please enter an answer for question 2.</span>
</div>
<div id="valExtraQuestion2" class="hide optionalQ">
<p>3. Extra question two.</p>
<label for="extraQuestion2">And what does he do?</label>
<input type="text" name="extraQuestion2" id="extraQuestion1" />
<br />
<span class="textfieldRequiredMsg">Please enter an answer for question 3.</span>
</div>
<br /><br />
<input type="submit" name="submitAnswers" id="submitAnswers" value="Submit Answers" />
</form>
The form is pretty basic with a few things to note. Each question is wrapped in a <div> with an id. This is so Spry can reference <input> tag it contains and apply the appropriate validation. The <div> tags that wrap the optional questions are given 2 extra classes; "hide", to make sure they're not visible from the offset and "optionalQ" so we can easily select just the optional questions later. Each question's <div> also includes a validation message within a nested <span> tag. The class name of this determines which validation error has occured and so which message to display (these can be found in the Spry Documention, or customised with your own class names when constructing the validation object). The <br />'s are just to make it a little tidier to view.
And finally out custom <script> to make it work:
<script type="text/javascript">
var valMoreQuestions = new Spry.Widget.ValidationRadio("valMoreQuestions", {validateOn:["change"]});
var valExtraQuestion1;
var valExtraQuestion2;
Spry.$$("#valMoreQuestions input").addEventListener("click", toggleAdditonalQuestions, false);
function toggleAdditonalQuestions(e) {
if(e.currentTarget.value == "true") {
//loop over all elements with a class of "optionalQ" and REMOVE the class of "hide"
Spry.$$(".optionalQ").forEach(function(qs){Spry.Utils.removeClassName(qs,"hide");})
//...and set up radio validation...
valExtraQuestion1 = new Spry.Widget.ValidationTextField("valExtraQuestion1", "none", {validateOn:["change"]});
valExtraQuestion2 = new Spry.Widget.ValidationTextField("valExtraQuestion2", "none", {validateOn:["change"]});
} else {
//loop over all elements with a class of "optionalQ" and ADD a class of "hide"
Spry.$$(".optionalQ").forEach(function(qs){Spry.Utils.addClassName(qs,"hide");})
//destroy all the validation (if they were set up)
if(valExtraQuestion1) {
valExtraQuestion1.reset();
valExtraQuestion1.destroy();
}
if(valExtraQuestion2) {
valExtraQuestion2.reset();
valExtraQuestion2.destroy();
}
}
}
</script>
So this JavaScript block is where all the magic happens. First we set up our variables, "valMoreQuestions" can be set up with Spry Radio Validation straight away as it's always displayed. The next 2 are just set up as placeholders to be filled if they need to be shown.
Next we add event listeners to the 2 radio buttons, so both fire the function "toggleAdditonalQuestions" when clicked. This is where the included SpryDOMUtils comes in very useful. "Spry.$$(CSS Selector)" allows you to select any elements from the DOM from their CSS selectors, so you can be as specific or generic as you need. In the case of adding the event listeners to the radio buttons we've selected "#valMoreQuestions input", so all <input> tags under an element with the id of "valMoreQuestions". This powerful little utility makes selecting and manipulating DOM objects a breeze. In addtion to their selection we use the .addEventListener() method to attach the listener.
Now the event listeners are set up the last part is the function that called when these event are fired, "toggleAdditonalQuestions". This function first tests to see that the value of the currentTarget of the fired event is true (the value of the radio button clicked). If it is, we use another DOM selector to get all the elements with a class of "optionalQ". On this selection of objects we call the forEach() method with fires a function for each element it's found in the selection phase. Each object is passed to the function as an argument so we can then remove the class of "hide" for each one using the SpryUtils function "Spry.Utils.removeClassName(qs,"hide")" (qs being a single element found in the DOM selector). This displays the 2 optional questions. We then add the validation to these options.
If the "No thanks" radio option is clicked the reverse happens. The ".optionalQ" classed elements are selected again and have a class of hide added to them to make them disappear. We then check if the 2 optional validation variable are set with an if statement (we do this becuase the user may have clicked "No thanks" first and the following functions wouldn't be available. If the variables are defined we use the reset() and destroy() methods on the validation object to remove it.
Spry automatically does the rest of the work to trigger the appropriate validation on clicking the submit button. We also added the additional "validateOn:["change"]" to all the validation so they will also validation on the change event.
Download the example files. Also the Spry API is an invaluable reference for all the methods and options.
Finally got around to installing Flex Builder 3 to have a play. I've watched a few tutorials over the last few nights and thought tonight was about time to start coding. Within 10 minutes I've got a very very basic application that will take your last.fm username, consume the audioscrobbler webservice feed of your top 50 albums and display them in a tile list. 10 minutes! Why haven't I played with this before?
Anyway I've put my little app up (it's my first go, and does very little, but I'm chuffed with it). Flex is definitely something I want to become proficient at!
A slightly quirky idea in Gmail labs, but I know it would of helped me in the past... Mail Goggles sets times that it will give you a maths quiz to confirm you're sure you want to send the email. E.g. late nights/weekends when you may be a little worse for wear and think it's a good idea to email the ex telling her of your undying love. Fairly useless, but I like the thinking behind some of these widgets.
Another, which I've always thought should be standard in every email client, is that if you mention "attached" or "attachment" in your email it should check that you have attached something. Very handy.
To get to Gmail labs go to "Settings" then the "Labs" tab in your Gmail account.
...Blog-wise that is.
It's been a while since I posted but work's calming down a bit so I think I'll be on a bit of a blogging mission soon. In the meantime I've migrated from BlogCFC to Mango Blog.
I'm a fan of BlogCFC, it's served me well, although after having a quick play with Mango Blog I wanted to switch. Coming from a design/CSS background, the chance to easily create themes for my blog was one of the deciders. BlogCFC has always been a bit of a mission to style and more effort maintaining that style after updates. I look forward to seeing what BlogCFC 6 brings in that respect.
Mango installation and migration is an absolute breeze, very much a "is that all I need to do?" kind of procedure. Although, I did have a couple of teething problems while testing. I started with version 1.2.2, but the BlogCFC import would throw an error. A quick post to the Mango Blog Forums and within hours (including the time zone differences) Laura had 1.2.3 on RIAForge. And the import was fixed. But then I noticed all the imported comments (not that I have that many) had been given a date/time of the import, not their original. Seems I was the first to spot it (doesn't look like Mark Drew did in his recently migration, oops). But another quick post to the forums and Laura delivers the goods again this morning with 1.2.4. So that was the decider and I put my blog live in Mango. And here it is :)
A big thanks to Laura Arguello for all her fantastic work and help!
Expect themes and plugins from me soon...
P.S. if you're migrating from BlogCFC don't forget to recreate the rss.cfm in the root pointing to the new feed file: <cfinclude template="feeds/rss.cfm" />. To maintain any existing subscribers.
Recent Comments