Archive

Archive for November, 2009

Prompt TextInput with ignore text

November 15, 2009 5 comments

There are cases in which we need more than text input, which should let the user to notify with some custom text  in text input whenever it is empty. i.e. prompt text input. But there are special cases in which we should even treat some text as empty and should show the prompt text in text input. I went through this need when my client asked me to show a prompt text in text input whenever it is zero. We could restrict zero in text input by using conditional expression in text property, provided we must ensure wherever we are setting the text input.

So i have decided to extend the text input component so that i could restrict zero in one place called set text(value : String) method. when i wanted to implement, i needed prompt text input and i asked myself why should not i do that too. I went ahead did at last.

You can find the implemented component code below which allows you to set ignore text (the text you want to treat as empty text) and you can also enable/disable the prompt text input. If it is disabled, it would function as normal text input.

Click here to download sample application

package
{
	import flash.display.DisplayObject;
	import flash.events.Event;
	import flash.events.FocusEvent;

	import mx.controls.TextInput;
	import mx.utils.StringUtil;
	[Style(name="promptStyleName", type="String")]
	public class PromptIgnoreTextInput extends TextInput
	{
		[Bindable] private var textEmpty : Boolean;
		public function PromptIgnoreTextInput()
		{
			super();
			this.addEventListener(FocusEvent.FOCUS_IN, handleFocusIn);
			this.addEventListener(FocusEvent.FOCUS_OUT, handleFocusOut);
			this.addEventListener(Event.CHANGE, handleChange);
		}
		[Bindable] private var _prompt : String;
		public function set prompt(value : String):void
		{
			_prompt = value;
		}
		public function get prompt():String
		{
			return _prompt;
		}
		[Bindable] private var _ignoreText : String;
		public function set ignoreText(value : String):void
		{
			_ignoreText = value;
		}
		public function get ignoreText():String
		{
			return _ignoreText;
		}
		[Bindable] private var _enablePrompt : Boolean;
		public function set enablePrompt(value : Boolean):void
		{
			_enablePrompt = value;
		}
		public function get enablePrompt():Boolean
		{
			return _enablePrompt;
		}
		override public function set text(value:String):void
		{
			value = StringUtil.trim(value);
			if(value != null && value != "")
			{
				if(value == ignoreText)
				{
					textEmpty = true;
				}
				else
				{
					textEmpty = false;
				}
			}
			else
			{
				textEmpty = true;
			}

			super.text = value;
			invalidateDisplayList();
		}
		override public function get text():String
		{
			return super.text;
		}
		override protected function updateDisplayList(unscaledWidth:Number,
		unscaledHeight:Number):void
		{
			if(_enablePrompt)
			{
				if(textEmpty && !isCurrentlyFocussed())
				{
					super.text = prompt;
					this.styleName = getStyle("promptStyleName");
				}
				else if(textEmpty && isCurrentlyFocussed())
				{
					super.text = "";
					this.styleName = "";
				}
				else
				{
					this.styleName = "";
				}
			}
			super.updateDisplayList(unscaledWidth, unscaledHeight);
		}
		protected function isCurrentlyFocussed():Boolean
		{
			var focussedComponent : DisplayObject;
			focussedComponent = focusManager.getFocus() as DisplayObject;
			if(focussedComponent)
			{
				if(focussedComponent == this || this.contains(focussedComponent))
					return true;
			}
			return false;
		}
		protected function handleFocusIn(event : FocusEvent):void
		{
			invalidateDisplayList();
		}
		protected function handleFocusOut(event : FocusEvent):void
		{
			text = super.text;
			invalidateDisplayList();
		}
		protected function handleChange(event : Event):void
		{
			textEmpty = (super.text.length == 0 || super.text == _ignoreText) ?
			            true : false;
		}

	}
}

Please let me know if you find any problem or have any suggestion about this component so that i could refine this code when i find time. Thank you for reading this post.

Advertisements

Dont re-invent Datefield when it needs to be editable

November 14, 2009 6 comments

Hi guys, we always look for customization if the feature we are looking,  is not available in the flex framework. But  if the same thing is possible with  minor tweaks, what is the need of re-inventing the wheel. I have experienced this scenario when i needed to implement a DateField which should allow the users to edit it as well as it has to display a DateChooser when they edit it, which is not quite possible even if you make editable property of  DateField is true.  As usual i went for google search and found couple of developers created their own component using Grid. I dint have enough time to test and use their component, i stumbled upon dateField public functions named open() and close().

Atlast I found the way of how to show a DateField dateChooser when i make editable property to true ( normally DateChooser wont show up if we make editable true). I extended the DateField component , invoked open() in focus-in event handler and i have done what i wished to be done without spending much time. further if you are not compromised with the position in which DateChooser shows up, you could change the x and y values of dateChoooser of DateField in  its open event.

Check out the below code for reference.

package
{
import flash.events.FocusEvent;
import flash.geom.Point;

import mx.controls.DateField;
import mx.events.DropdownEvent;

public class EditableDatefield extends DateField
{
public function EditableDatefield()
{
super();
this.addEventListener(DropdownEvent.OPEN, onOpenDropDown);
this.addEventListener(FocusEvent.FOCUS_IN, onFocusIn);
}

protected function onFocusIn(event : FocusEvent):void
{
this.open();
event.stopImmediatePropagation();
}

protected function onOpenDropDown(event : DropdownEvent):void{
var point : Point = new Point(this.textInput.x, this.textInput.y);
var targetCoordinates : Point = this.localToGlobal(point);
dropdown.x = targetCoordinates.x - dropdown.width/2 + textInput.width/2;
dropdown.y = targetCoordinates.y + textInput.height + 5;
}
}
}

I hope this post would atleast help one flex developer and would save his/her time. If you find any problem with above code, please let me know i will try to resolve it as much as possible. Thank you for reading this post!