/////////////////////////////////////////////////////////////////////////////////////////////////////// // Copyright (c) 2010, Blogagic (http://blogagic.com/) // All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, // are permitted provided that the following conditions are met: // // - Redistributions of source code must retain the above copyright notice, this list of // conditions and the following disclaimer. // - Redistributions in binary form must reproduce the above copyright notice, this list // of conditions and the following disclaimer in the documentation and/or other materials // provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER // IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT // OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /////////////////////////////////////////////////////////////////////////////////////////////////////// /* FadingInjector - Animate background color of a modified text control. Copyright (C) 2010 Blogagic (http://blogagic.com/) Version 0.2 FadingInjector fades background color of a control when it loses focus while its content has been changed. It can also be configured such that it changes the background color of the monitored control into the editingColor as soon as it gains focus. In this case, the fading effect is applied only when the value has changed; if it hasn't the standard background color is restored immediately (no fading effect). FadingInjector can be associated to any UIComponent as long as there is a String property providing the value for comparison as well as a backgroundColor style that we can fade. Notes: Uses AnimateColor by Darron Schall (refer to http://www.darronschall.com/weblog/2007/01/animate-color-flex-2-effect-updated-for-201.cfm) Licensed under the Creative Commons BSD Licence http://creativecommons.org/licenses/BSD/ */ package com.blogagic.controls { import com.blogagic.core.IDisposable; import com.darronschall.effects.AnimateColor; import flash.events.FocusEvent; import mx.controls.TextArea; import mx.controls.TextInput; import mx.core.EventPriority; import mx.core.UIComponent; /** * The FadingInjector fades background color of a control when it loses focus * while its content has been changed. * *

It can also be configured (using highlightOnFocus) such that * it changes the background color of the monitored control into the editingColor * as soon as it gains focus. In this case, the fading effect is applied only when * the value has changed; if it hasn't the standard background color is restored * immediately (no fading effect).

* *

FadingInjector can be associated to any UIComponent (specified using * control) as long as there is a String property (specified using * valuePropertyName) providing the value for comparison as well as a * backgroundColor style that we can fade.

* *

It also automatically selects the control's content when clicking on the * control (only available for TextInput and TextArea).

* * @mxml * *

The <mx:FadingInjector> tag supports the following tag * attributes:

* *
	 *  <mx:FadingInjector
	 *    Properties
	 *    control=""
	 * 	  highlightOnFocus="false|true"
	 *    editingColor="0xf9faa1"
	 *    valuePropertyName="text"
	 *    fadeColorEffectDuration="1600"
	 *
	 *  />
	 *  
* */ public class FadingInjector implements IDisposable { //-------------------------------------------------------------------------- // // Properties // //-------------------------------------------------------------------------- /** * @private * Storage for the control to monitor (on which Fading is to be applied). */ protected var _control:UIComponent; /** * Specifies the monitored control. * */ [Bindable] public function get control():UIComponent { return _control; } /** * @private */ public function set control(value:UIComponent):void { if (value != _control) { unmonitorControl(_control); _control = value; monitorControl(_control); } } //---------------------------------- // Text property name //---------------------------------- /** * @private */ protected var _valuePropertyName:String = "text"; /** * Specifies property name of a String property of the monitored control. * The property value is stored when focus is gained by the monitored control; * on focus out, it is compared with the current property value and, if * different, the fading effect is triggered. * * @default text */ [Bindable] public function get valuePropertyName():String { return _valuePropertyName; } /** * @private */ public function set valuePropertyName(value:String):void { if (value != _valuePropertyName) { _valuePropertyName = value; } } //---------------------------------- // Fading Effect duration //---------------------------------- /** * @private * Storage for the Fade Color Effect duration. */ protected var _fadeColorEffectDuration:Number = 1600; /** * Specifies the duration of the Fade Color effect. * * @default 1600 */ [Bindable] public function get fadeColorEffectDuration():Number { return _fadeColorEffectDuration; } /** * @private */ public function set fadeColorEffectDuration(value:Number):void { if (value != _fadeColorEffectDuration) { _fadeColorEffectDuration = value; if (_fadeColorEffect) _fadeColorEffect.duration = _fadeColorEffectDuration; } } //---------------------------------- // Editing Color //---------------------------------- /** * @private * Storage for the editing color. */ protected var _editingColor:Number = 0xf9faa1; /** * Specifies which editing color to use (when the control gains focus). * * @default f9faa1 */ [Bindable] public function get editingColor():Number { return _editingColor; } /** * @private */ public function set editingColor(value:Number):void { if (value != _editingColor) { _editingColor = value; if (_fadeColorEffect) _fadeColorEffect.fromValue = _editingColor; } } /** * @private * Storage for the editing color. */ protected var _highlightOnFocus:Boolean = true; /** * Specifies which editing color to use (when the control gains focus). * * @default f9faa1 */ [Bindable] public function get highlightOnFocus():Boolean { return _highlightOnFocus; } /** * @private */ public function set highlightOnFocus(value:Boolean):void { if (value != _highlightOnFocus) { _highlightOnFocus = value; /* if (_fadeColorEffect) _fadeColorEffect.fromValue = _editingColor; */ } } /** * @private * Storage for the normal background color of the control. */ private var _backgroundColor:Number; //-------------------------------------------------------------------------- // // Constructor // //-------------------------------------------------------------------------- /** * Constructor. */ public function FadingInjector() { super(); } //-------------------------------------------------------------------------- // // Cleanup // //-------------------------------------------------------------------------- /** * Use the dispose method to explicitly release unmanaged resources in conjunction * with the garbage collector. * Call this method when the control is no longer needed. */ public function dispose():void { unmonitorControl(_control); if (_fadeColorEffect) { _fadeColorEffect.stop(); _fadeColorEffect = null; } } //-------------------------------------------------------------------------- // // Variables // //-------------------------------------------------------------------------- /** * @private * Control content before editing. */ protected var _previousText:String; /** * @private * Effect based on AnimateColor class made by Darron Schall * Note: This is now natively available in Flex 4. */ protected var _fadeColorEffect:AnimateColor; //-------------------------------------------------------------------------- // // Methods // //-------------------------------------------------------------------------- /** * @private * Monitor a control by listening to focus in and focus out events */ protected function monitorControl(control:UIComponent):void { if (control) { control.addEventListener(FocusEvent.FOCUS_IN, focusInHandler, false, EventPriority.EFFECT, true); control.addEventListener(FocusEvent.FOCUS_OUT, focusOutHandler, false, EventPriority.EFFECT, true); if (_fadeColorEffect) _fadeColorEffect.target = control; } } /** * @private */ protected function unmonitorControl(control:UIComponent):void { if (control) { control.removeEventListener(FocusEvent.FOCUS_IN, focusInHandler, false); control.removeEventListener(FocusEvent.FOCUS_OUT, focusOutHandler, false); if (_fadeColorEffect) _fadeColorEffect.end(); } } /** * @private * Effect based on AnimateColor class made by Darron Schall. * Note: This is now natively available in Flex 4. */ protected function configureFadeColorEffect():void { if (!_fadeColorEffect) { _fadeColorEffect = new AnimateColor(_control); // Hardcoded! _fadeColorEffect.property = "backgroundColor"; _fadeColorEffect.isStyle = true; _fadeColorEffect.duration = fadeColorEffectDuration; _fadeColorEffect.fromValue = editingColor; } if (_highlightOnFocus) _fadeColorEffect.toValue = _backgroundColor; else { // Trick: using NaN for the target color allows to use control's backgroundColor _fadeColorEffect.toValue = NaN; } } //-------------------------------------------------------------------------- // // Handlers // //-------------------------------------------------------------------------- /** * @private * Retrieve the initial value from the control, * change backgroundColor to editingColor * (and select text for TextInput and TextArea). */ protected function focusInHandler(event:FocusEvent):void { if (!control) return; if (_fadeColorEffect && _fadeColorEffect.isPlaying) { // Need to interrupt any on-going fading to not mess the background color _fadeColorEffect.end(); } // No check regarding the property type (supposed to be a String) // Anyway, if it's not a string, the toString() will be implicitely called. if (_control.hasOwnProperty(valuePropertyName)) _previousText = _control[valuePropertyName]; if (_highlightOnFocus) { _backgroundColor = _control.getStyle("backgroundColor"); _control.setStyle("backgroundColor", editingColor); } if (_previousText) { if (_control is TextArea) TextArea(_control).setSelection(0, _previousText.length); else if (_control is TextInput) TextInput(_control).setSelection(0, _previousText.length); } } /** * @private * Compare control current value with initial value and trigger fading * if they are different. * If not, just restore the initial background color without fading. */ protected function focusOutHandler(event:FocusEvent):void { if (!control) return; if (_control.hasOwnProperty(valuePropertyName) && (_control[valuePropertyName] != _previousText)) { configureFadeColorEffect(); _fadeColorEffect.end(); _fadeColorEffect.play(); } else if (_highlightOnFocus) _control.setStyle("backgroundColor", _backgroundColor); } } }