//////////////////////////////////////////////////////////////////////////////// // // Copyright (c) 2008 Josh Tynjala // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. // //////////////////////////////////////////////////////////////////////////////// package com.joshtynjala.text { import flash.events.Event; import flash.events.TimerEvent; import flash.text.TextField; import flash.utils.Timer; //-------------------------------------- // Events //-------------------------------------- /** * Event that is fired when the DecryptingTextField has finished decrypting all of * its characters. * * @eventType flash.events.Event.COMPLETE */ [Event(name="complete",type="flash.events.Event")] /** * A TextField that starts out displaying garbage text, but letter by letter * the desired text is displayed. Similar to hacking decryption in the movies. :) * * @author Josh Tynjala */ public class DecryptingTextField extends TextField { //-------------------------------------- // Constructor //-------------------------------------- /** * Constructor. */ public function DecryptingTextField() { super(); this._typingTimer = new Timer(this.delay); this._typingTimer.addEventListener(TimerEvent.TIMER, timerUpdateHandler); } //-------------------------------------- // Properties //-------------------------------------- /** * @private */ private var _typingTimer:Timer; /** * @private */ private var _position:int; /** * @private * Storage for the delay property. */ private var _delay:Number = 30; /** * The number of milliseconds before a new character is decrypted. */ public function get delay():Number { return this._delay; } /** * @private */ public function set delay(value:Number):void { this._delay = value; } /** * @private * Storage for the text property. */ private var _text:String = ""; /** * @copy flash.text.TextField#text */ override public function get text():String { return this._text; } /** * @private */ override public function set text(value:String):void { this._text = value; super.text = this.randomChars(value); this._position = 0; if(value.length > 0) { this._typingTimer.delay = this.delay; this._typingTimer.start(); } } /** * @private * Storage for the keepSpaces property. */ private var _keepSpaces:Boolean = false; /** * If true, the DecryptingTextField will always choose a space * during randomization when it encounters a space in the original * text. This can help the aesthetics when displaying multiple lines. */ public function get keepSpaces():Boolean { return this._keepSpaces; } /** * @private */ public function set keepSpaces(value:Boolean):void { this._keepSpaces = value; } //-------------------------------------- // Private Methods //-------------------------------------- /** * @private */ private function timerUpdateHandler(event:TimerEvent):void { //it might change during the typing this._typingTimer.delay = this.delay; this._position++; if(this._position > this._text.length) { //if we've typed the full text, we can stop this._typingTimer.stop(); this.dispatchEvent(new Event(Event.COMPLETE)); return; } super.text = this._text.substr(0, this._position) + this.randomChars(this._text.substr(this._position)); } /** * @private * * Generates a string of the specified length containing random * characters in the character code range 33 to 126. */ private function randomChars(value:String):String { var result:String = ""; var count:int = value.length; for(var i:int = 0; i < count; i++) { //for best results on word wrapped textfields, //spaces should be kept in the same locations. //a monospaced font makes it even better. if(this.keepSpaces && value.charAt(i) == " ") { result += " "; } else { result += String.fromCharCode(int(33 + Math.random() * 93)); } } return result; } } }