Hello. I have a new blog.

I've moved this blog to the following URL Kerkness.ca. Thank you for visiting, please update your bookmarks.

Showing posts with label components. Show all posts
Showing posts with label components. Show all posts

Wednesday, October 1, 2008

Flex Component : ButtonPanel puts a button in your panel header

It's always a joy when you need something and after writing a few lines of code, you have it. Such is the beauty of nice extendable components and the Flex architecture.

Today I needed a panel which had a button in the top right corner of the header. Where the 'status' text is normally is. I wanted to put a 'save' button there. One problem, the mx.containers.Panel component does not have a button in the header.

Solution. Make a new component which extends all the functions of the Panel and stick a button in the top corner where I want.

Click here to see a demo

Click here to view the source

My new ButtonPanel component extends Panel and adds 2 new properties and 1 event.

Properties

buttonLabel : String - Defines the label for the button in the top corner
buttonPadding : Number - Defines how much padding to provide in the header

Event

buttonClick : Event - Dispatched when the button is clicked

Thursday, July 31, 2008

Updated Flex Qwerty Component

I've made some updates and improvements to my Flex Qwerty Keyboard Component.

This version of the component is a little more tailored for a touch screen kiosk and is modled a little after the soft-touch keyboard you see on Apples' iPhone. The main new features are shortcut buttons for typing '.com' and '.ca' (cause I'm Canadian) as well as a 'Tab' button for tabbing through form fields.

You can view a demo of the updated component here.

You can view the source code for the updated component here.

How to Customize this Component

I've had a few comments and questions about how to customize this component. It should be fairly straight forward to do if all you want to do is add or modify how a button works. Here are instructions on how to add an 'Enter' or 'Return' button to the keyboard.

  1. First step is to physically add the button to the keyboard. This can be done by adding a new object to one of the keyRow arrays in the qwerty.mxml file. Adding the following object to the end of the keyRowC array will add the button to the end of row 3 of the keyboard.
    {label:'Return',w:100}
    The property 'w' specifies that the button should be 100 pixels wide. Alternatively you could set the property 'flex' to 'true' which would make the button take up as much available space as is available.

  2. Next you need to instruct the component on how to handle the click event for this new button. You do this by adding a condition to the switch statement in the function handleKeyClick(). Add the following condition for the new Return button.
    case 'Return': this.inputControl.text += "\n";break;
  3. Finally we need to modify the function which handles toggling between Upper and Lower case on the keyboard. We don't want our new button to be affected by this toggling so we will adjust this function to bypass our new button.

    In the function toggleUpperLower() edit the following line from this...
    if ( kidLabel == 'Tab' || kidLabel == 'Delete' ) continue;
    to this...
    if ( kidLabel == 'Tab' || kidLabel == 'Delete' || kidLabel == 'Return' ) continue;
There you go, you should have a functional return button. If you have any problems with this example please let me know in the comments.

Thursday, June 26, 2008

Flex Component : Yet Another Flex File Upload Component

There are several Flex upload components floating around and I gave most of them a good look over but I was not able to find one which suited my needs so I decided to make my own. Here it is for you to enjoy.

Click here to view a demo
(demo lets you upload up to 3 files at a time with a max size of 4 megs each)

Click here to view the source

The usage of the component is pretty straight forward. You can set some properties to define what types of files can be uploaded and you direct the 'upload' towards a server side script. In my demo I send the files to a basic PHP script ( which I've included below ). The script handles one file at a time and is expected to report back either the string 'successful' or an error message which is displayed.

Properties

The following public properties can be set to customize the use of this component

  • uploadButtonLabel : String = 'Upload'
    This is the label used for the 'upload' button.

  • selectButtonLabel : String = 'Select File(s)'
    This is the label used for the 'select' button.

  • removeButtonLabel : String = 'Remove Selected File'
    This is the label used for the 'remove' button.

  • maxFileCount : Number = 3
    This sets the number of files a user is allowed to upload

  • maxFileSize : Number = 1
    This sets the maximum file size (in megs) for each individual file. Default is 1 meg.

  • requestUrl : String = ''
    This is the URL for your PHP/ASP/ColdFusion/Other script which you will send the uploaded files to. THIS PROPERTY MUST BE SET !

  • allowOnlyImages : Boolean = false
    If set to 'true' the user will only be able to select image files

  • allowOnlyText : Boolean = false
    If set to 'true' the user will only be able to select text files.

  • allowAllFiles : Boolean = true
    If set to 'true' the user can upload images or text files.

  • barColor : String
    Allows you to style the progress bar
Events

The component has one event 'uploadComplete' which is triggered if all files are uploaded successfully.

The PHP Handler

Following is the source for the simple PHP script which I am using in the demo. In this script I am just confirming that the file was uploaded successfully and then I am deleting it. Since this is a public demo I don't want people filling up my server with unwanted images. In your script you would most likely copy the FILE to a more permanent location and possibly do a little more validation. The script needs to echo the string 'success' or echo an error message.
$hasError = false;
foreach( $_FILES as $i=>$file ){
if ( $file['error'] ){
$hasError = true;
}
/**
* Because this is a public example. I am just going to immediately delete
* the file which was uploaded. In a regular application you would copy the file
* from it's temporary location to it's permament location.
*/
unlink( $file['tmp_name'] );
}

if ( ! $hasError ){
echo('success');
} else {
echo('Stick custom error message here');
}

Wednesday, June 4, 2008

Something I need to remember about ItemRenderers and the TileList control

From a high level perspective, scrolling is moving data through fixed itemRenderers, not by actually moving renderers off the visible area of
the screen.
I found this little bit of information hidden in this thread. After trying to extensively use my PageList component in a large application and with a dataProvider that had the potential of providing hundreds of items needing rendering I was noticing a very bad side effect. My application would continue to create a new instance of the itemRenderer for every item in the dataProvider and if the dataProvider was emptied ( ie: arrayCollection.removeAll() ) the itemRenderers would remain.

Back to the drawing board on that one. I hope to post a new PageList component soon as my application is not usable in it's current state.

Monday, March 17, 2008

Flex SuperLabel Component : An Easy How To on Extending Flex Components with Custom Events and Effects

Since I switched from developing XUL/Javascript based RIAs using the Mozilla platform to programming in Flex and Actionscript one of the things I have been most impressed with is how easy it is to extend existing components and customize them to fit my needs perfectly.

Recently (as in 10 minutes ago) I was working on laying out the interface for a new application which displays some dynamically changing content. One part of the interface which was dynamically changing was the page title which I was displaying as a Label component. I thought it would be nice to add a small effect every time the text property for Label changed. Looking at the language reference documentation for the Label component I noticed there was no built in event or effect which could be triggered when the text property is updated.

No problem, I thought. I'll just add that in. So with less than 25 lines of code and in less time than it is taking to type this post I was done.

Here is a summary of the steps I took to create my new SuperLabel Component.

  • Created a new Actionscript Class
  • Added Metatags for the new Event and new Effect
  • Created a function which overrides the text property setter function
  • done.
Here is the source code for the new component.
package claire.com
{
import mx.controls.Label;
import flash.events.Event;

[Event(name="textChange", type="flash.events.Event")]
[Effect(name="textChangeEffect", event="textChange")]

public class SuperLabel extends Label
{
public function SuperLabel()
{
super();
}
public override function set text(value:String):void
{
if ( value != this.text )
{
this.dispatchEvent( new Event('textChange') );
}
super.text = value;
}
}
}
There you go. It really is that easy.

Just to finish off here is how you use the new component in MXML.
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:com="claire.com.*">
<mx:WipeRight id="myEffect" duration="750" />
<com:SuperLabel textChangeEffect="{myEffect}"/>
</Application>

Friday, March 7, 2008

Control Access to Flex Components with Group Based Permissions

When building a large application which has many different views it's likely that you'll want to grant some users more access than others. You might have some components that all guests are permitted to view and also have other components that only admin users are allowed to use.

A common way to accomplish this is to assign all users to different user groups and then control what user groups are allowed to view certain parts of your application.

The example I show here focuses only on controlling the 'visible' property of a component and therefore only addresses what interface elements the user is allowed to see. I plan to expand on this example in the future to also address the user's ability to access specific sets of data.

Permit and PermitCondition Classes

In order to have a central repository of permissions and information on the current user I created a singlton class called Permit and another class called PermitCondition. Using a singlton ensures that only one instance of the class will be created and can still be easily accessible anywhere in your application.

The Permit class keeps information on the current user and is responsible for creating instances of the PermitCondition class.

Each instance of PermitCondition defines a single permission requirement for a single component by declaring if a specific user group is allowed to view the component or is explicitly blocked from viewing the component. Components can have multiple PermitConditions allowing for more complex permissions.

Summary of Example Application

View the demo : View demo source

In my example application I define permissions for 3 sample components in the main MXML application file. I then use a LogIn component which sets the user's group memberships. Both the main MXML application and the LogIn component use the same singlton instance of the Permit class.

For the purpose of keeping this example simple my LogIn component manually sets users group permissions from a couple of simple functions. In a more complete application you would want your LogIn component to accept a username and password and define user groups after calling an HTTPService and likely querying a database.

Creating and Accessing the Permit Class

Use the following code to get access to the Permit singlton.

import claire.libs.Permit;
private var appPermit:Permit = Permit.getInstance();
Defining Component Permissions

Use the following code to define permissions for individual components
appPermit.applyPermit('adminaccess',Permit.ALLOW,'admin',box3);
appPermit.applyPermit('adminaccess',Permit.BLOCK,'guest',box3);

The applyPermit method accepts 4 properties
applyPermit( permitname:String, condition:String, group:String,component:UIComponent)
  • permitname : A unique identifier for the declared permit.
  • condition: Accepted values are Permit.ALLOW or Permit.BLOCK. Determines if the supplied group name is granted or blocked access to component.
  • group: Name of a user group checked in the condition.
  • component: a UIComponent which the permit is applied against.

Adding User Details to the Permit Class

Use the following code to add user details to the Permit class after successfully validating the user's username and password.
appPermit.loggedIn = true;
appPermit.addGroup('guest') // Adds user to group 'guest'
When a user is added to a group the Permit class will automatically check PermitConditions and update the visible property of components.

Tuesday, March 4, 2008

Updated Flex PageList Component and Demo with Google JSON API

I've had a chance to completely re-write my PageList component so it runs much smoother and provides easier more flexible use.

The PageList component let's a user horizontally page through a TileList. The component binds with a HTTPService to provide a continual flow of data.

Click here to view a demo of the component

Click here for full source code

Things to make note of:

Because the component dynamically adjusts it's own X position it needs to be the child of either an Application, Canvas or Panel.

The component at the moment has a single results handler which handles a JSON response from a Google API. To use this component you can easily add your own handler functions to handle data specific to your own application.

Google JSON API

The demo I've put together for this component makes use of a Google JSON API which is really handy and easy to access if your Flex project uses the Adobe Corelib library.

The Google JSON API can be accessed via the following URLs.

http://www.searchmash.com/results/images:[query]
http://www.searchmash.com/results/blogs:[query]
http://www.searchmash.com/results/video:[query]

The full url I used in the demo is

http://www.searchmash.com/results/images:Apple

In order to access the API remotely and not run into any Flex security issues I used a php proxy. Click here for details

Thursday, February 28, 2008

Flex PageList Component Adds Paging Support to TileList

Using the Flex TileList component is a nice way to display a list of products. The one thing the component lacks is the ability to easily display multiple pages of content which is a typical design requirement of most web based stores or product catalgues. For this reason I extended the TileList component into a PageList component.

The PageList Component works very similar to the TileList but adds PREV/NEXT buttons to the bottom of the list and automatically calls a HTTPService to load it's data. When the User clicks 'next' to view more items the PageList component automatically fetches more records and appends them to the list. This allows the user to browse an entire catalogue of items with a very smooth and transparent process. Page count is calculated based on the viewable area and the width of list items.

UPDATE 2: I've completely re-written this class which works much better. The new PageList component has been published along with source code and demo. Click here for more details

Wednesday, February 20, 2008

Flex On Screen Qwerty Keyboard Component

NOTE:  I've updated this component. To see the latest version click here.

One of the Flex applications I work on is a touch screen application primarily used to browse a product catalog. Because there is no keyboard physically attached to the touch screen display and it was necessary to have some input from users (primarily for signing up to a mailing list) I built a Qwerty keyboard component for flex.

The component displays a nearly full set of keys found on your standard Qwerty keyboard with a limited set of special characters. You can assign TextInput and TextArea controls to accept the output from the component and there is a handy method for changing focus to different input fields.

Click here to view the example application

Click here to view source

Basic Usage

<mx:Form width="100%">
<mx:FormItem label="Field 1" width="100%">
<mx:TextInput id="field1" focusIn="myQwertyKeypad.newFocus(field1)" width="100%"/>
</mx:FormItem>
<mx:FormItem label="Field 2" width="100%">
<mx:TextInput id="field2" focusIn="myQwertyKeypad.newFocus(field2)" width="100%"/>
</mx:FormItem>
<mx:FormItem label="Field 3" width="100%">
<mx:TextInput id="field3" focusIn="myQwertyKeypad.newFocus(field3)" width="100%"/>
</mx:FormItem>
</mx:Form>
<claire:Qwerty id="myQwertyKeypad" inputControl="{field1}" width="100%"/>


While probably a pointless component for most Flex Applications this component is very handy for touch screen input requirements.

Tuesday, February 19, 2008

AlertTimer Flex Component

The Flex AlertTimer component displays a pop up alert window which automatically closes and displays a countdown timer to the user.

Click here to view an example
(right click application to view source)

The alert can be called from a 'show' method which accepts the following properties:

  • parent:DisplayObject = The component the alert displays over most likely the parent application

  • alertText:String = The message to display in the alert window

  • alertTitle:String = The title of the alert popup

  • modal:Boolean = If true the user will not be able to interact with the rest of the application until the alert closes
Example usage
var myAlert:AlertTimer = new AlertTimer();
myAlert.show(this, "my alert message", "my alert title", true);

You can further customize the AlertTimer by setting more properties.
var myAlert:AlertTimer = new AlertTimer();
myAlert.duration = 10;
myAlert.buttonText = "Click here to close now";
myAlert.alertWidth = 200;
myAlert.counterText = "This window will self destruct in ";
myAlert.show(this, "my alert message", "my alert title", true);

While this component serves my purpose just fine it can certainly be expanded upon to include the full set of features available in a regular Flex Alert. For starters I'm pretty new to ActionScript and Flex so I wasn't able to figure out how to actually extend the current Alert class. So instead I just created my own component and therefore their isn't the ability to use multiple buttons like you can with an Alert. That said, if you were going to use multiple buttons you may not want to automatically close the alert on a timer.

I do realize that you can easily close a regular alert using the setTimeout() function and the PopUpManager, but then you can't display a dynamic countdown which I think is more user friendly.

Sunday, February 17, 2008

Flex / JSON / PHP Example Application

While trying to teach myself how to best use PHP and Flex together I build the following example application. Source code and details on how the application works are included.

The example application uses JSON (JavaScript Object Notation) to facilitate a smooth and simple way of providing PHP Arrays that can be used by a Flex Application. A more complete HowTo is included in the application.

Click here to launch the application
(right click to view source)

Requirements

This application requires a php class called json.php which encodes a PHP array and the corelib libraries available from Adobe Labs used to decode the array in Flex. You'll also need a mysql database with a single table called 'people' with the fields 'firstname','lastname' and 'category'.

To install the corelib libraries I used a post at Mike Chambers blog.
The json.php class originally comes from M. Migurski.

MXML Summary

Right click the example application to view the MXML source

  • FlexPhp.mxml : Main Application file. Contains a navigation tab and loads the components PhpDataGrid.mxml and PhpForm.mxml
  • PhpDataGrid.mxml : Contains a simple DataGrid and ActionScript for calling read.php
  • PhpForm.mxml : Contains a simple Flex form and ActionScript for calling write.php
Description of PHP Files

read.php : File queries the database and returns a JSON encoded array to the Flex application.
write.php : File accepts data posted from Flex form, updates the database and sends a JSON encoded response back to the flex application.
json.php : Class file used to encode PHP arrays into a JSON formatted string.
mysql.php : Class file for accessing and updating the database.
conf.php : Simple configuration file for keeping database access information and debugging.


Friday, February 15, 2008

Flex Hint Bubble Component

Flex makes it very easy to display tooltips associated with buttons, form fields and other interface components in your application. However sometimes a tooltip isn't enough because they only display themselves when a user mouses over a specific button or object. Well what if the user doesn't know where to point their mouse?

For this purpose I created a custom component called a HintBubble. The HintBubble can be triggered by any event using a function called toggleHintBubble. When toggled the Hint Bubble will fly into view displaying whatever hint message you like and then Fade out of view after XX number of seconds have passed. In one of my applications I'm using this remind users of a search button on the screen.

The component is effective for these purposes but could be easily expanded or customized to suit many purposes. Transitions and styles are hard coded but could also easily be customized to suit different needs.

HintBubble.mxml

<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="init()"
backgroundAlpha="0.0" horizontalScrollPolicy="off" verticalScrollPolicy="off">
<mx:Script>
<![CDATA[
import mx.effects.easing.Cubic;
import flash.events.TimerEvent;
import flash.utils.Timer;
// duration = Number of seconds to display hint bubble
[Bindable]
public var duration:Number = 4;
// hintText = Main text for hint bubble
[Bindable]
public var hintText:String;
[Bindable]
// hintTitle = Title for the hint bubble
public var hintTitle:String;
[Bindable]
// leftTo = Left position to move hint bubble to on display
public var leftTo:Number;
[Bindable]
// hintIcon = Icon to use for hint bubble.
public var hintIcon:String;
// Hint Timer Object
private var hintTimer:Timer = new Timer(1000,duration);
// Initiate function adds event to close hintbubble when timer ends
public function init():void
{
hintTimer.addEventListener(TimerEvent.TIMER_COMPLETE, closeHintBubbleOnTimer);
}
// opens hint bubble and starts timer
public function toggleHintBubble():void
{
hintTimer.reset();
hintTimer.start();
openHintBubble();
}
// opens hint bubble without starting timer
public function openHintBubble():void
{
this.currentState = 'ShowHint';
}
// closes hint bubble without transitions. Returns to base state
public function closeHintBubble():void
{
this.currentState = '';
}
// closes hint bubble with transition. Resets timer.
public function hideHintBubble():void
{
hintTimer.reset();
this.currentState = 'HideHint';
}
// closes hint button from event timer
public function closeHintBubbleOnTimer(event:TimerEvent):void
{
this.currentState = 'HideHint';
}
]]>
</mx:Script>
<mx:states>
<mx:State name="ShowHint">
<mx:SetStyle target="{this}" name="left" value="{leftTo}"/>
</mx:State>
<mx:State name="HideHint" basedOn="ShowHint">
<mx:SetProperty target="{myHintBubble}" name="visible" value="false"/>
</mx:State>
</mx:states>
<mx:transitions>
<mx:Transition fromState="" toState="ShowHint">
<mx:Parallel>
<mx:Move duration="1250" target="{this}" easingFunction="{Cubic.easeOut}"/>
</mx:Parallel>
</mx:Transition>
<mx:Transition fromState="ShowHint" toState="HideHint">
<mx:Parallel>
<!-- ** After HideHint state completes it's transition state is immediately set to default ** -->
<mx:Dissolve duration="1000" alphaFrom="1.0" alphaTo="0.0" target="{myHintBubble}"
effectEnd="this.currentState=''"/>
</mx:Parallel>
</mx:Transition>
<mx:Transition fromState="HideHint" toState="">
<mx:Parallel>
<mx:Dissolve duration="1000" alphaFrom="0.0" alphaTo="1.0" target="{myHintBubble}"/>
</mx:Parallel>
</mx:Transition>
</mx:transitions>
<mx:Canvas backgroundAlpha="0.0" visible="true" id="myHintBubble">
<mx:HBox backgroundColor="#F6E285" cornerRadius="16" verticalAlign="middle"
borderStyle="solid" borderColor="#FFFFFF" themeColor="#FFFFFF" alpha="0.85"
paddingTop="20" paddingLeft="15" paddingBottom="15" paddingRight="20">
<mx:Image source="{hintIcon}" scaleContent="true" width="50" height="50"/>
<mx:VBox backgroundAlpha="0.0">
<mx:Text color="#000000" text="{hintTitle}" id="myHintTitle" paddingBottom="-10"/>
<mx:Label color="#000000" fontSize="20" id="myHintText" text="{hintText}"/>
</mx:VBox>
</mx:HBox>
</mx:Canvas>
</mx:Canvas>


HintBubble Usage Example
To use the HintBubble place the component somewhere in an accessible namespace for your application and place a tag similar to the following in your mxml file.

<HintBubble id="myHint" hintIcon="theme/arrow.png"
hintText="Click 'Search' to find more products." duration="5"
hintTitle="Help Tip" leftTo="40" bottom="65" left="1200" />

HintBubble Properties

  • hintIcon : An icon to display in your hint bubble
  • hintText : Main text of your hint
  • hintTitle : Title for your hint bubble
  • left : Starting position of bubble ( ideally set somewhere off screen )
  • leftTo : Position the hint bubble slides to when toggled
  • bottom/top : fixed verticle position of bubble
  • duration : Seconds to display hint before automatically hiding