Combining appendText and htmlText for dynamic text box in AS3 - actionscript-3

Hi I browsed the web and this web page for answer but can't seem to find solution for my problem. I've created a typewriter effect. It's being displayed through dynamic text box(tekst_txt). What I would like to achieve is to be able to use html tags to change specific word's font to bold or italic by just including i.e. < b > and < /b > but I can't seem to pull this of. I would really appreciate some advice.
That is code that shows up in first frame (text box doesn't exist on that frame):
import flash.events.MouseEvent;
stop();
var tekst:String = "";
var i:uint = 0;
var licznik:Timer = new Timer(20);
tekst_txt.htmlText = tekst_txt.text;
stage.addEventListener(MouseEvent.CLICK, klikaj);
function klikaj(event:MouseEvent):void
{
if (licznik.running == true)
{
tekst_txt.htmlText = tekst;
licznik.stop();
}
else if (licznik.running == false || licznik == null)
{
nextFrame();
tekst_txt.text = "";
}
}
And this is code from next frame(textbox already exist in this frame):
import flash.events.MouseEvent;
import flash.utils.Timer;
import flash.events.TimerEvent;
stop();
tekst="Tekst1Tekst1<i>Tekst1</i>Tekst1Tekst1Tekst1Tekst1Tekst1Tekst1Tekst1";
licznik.start();
licznik.addEventListener(TimerEvent.TIMER, odpalaj);
function odpalaj(e:TimerEvent):void
{
//tekst_txt.htmlText = tekst_txt.text;
tekst_txt.appendText(tekst.charAt(i));
//tekst_txt.htmlText=tekst_txt.text;
i++;
if (i >= tekst.length)
{
licznik.stop();
}
}

The problem you are facing is that any form of HTML formatting will take more than 1 character to describe, so when you try to do this animation character by character, you are really just setting the raw html markup into the text.
This may seem a bit messy, but here's something you can try...
You would create a temporary textfield and set the whole html markup text into its htmlText value first, then you can getTextFormat to copy the formatting for every character as you are appending... this allows Flash to process the html for you.
import flash.events.MouseEvent;
import flash.utils.Timer;
import flash.events.TimerEvent;
stop();
tekst="Tekst1Tekst1<i>Tekst1</i>Tekst1Tekst1Tekst1Tekst1Tekst1Tekst1Tekst1";
// shove your html markup text into the htmlText of a textfield
// this allows Flash to deal with parsing the html
var myTextField:TextField = new TextField();
myTextField.htmlText = tekst;
licznik.start();
licznik.addEventListener(TimerEvent.TIMER, odpalaj);
function odpalaj(e:TimerEvent):void
{
// get the text directly from the temp textfield
// you want to do this because it will have already processed the html markup
// and will give you the correct indexes and length of your text
tekst_txt.appendText(myTextField.text.charAt(i));
// copy the textformat
var format:TextFormat = myTextField.getTextFormat(i, i+1);
tekst_txt.setTextFormat(format, i, i+1);
i++;
if (i >= tekst.length)
{
licznik.stop();
}
}

Related

Delay text appearance animation when period appears

Flash/AS3 noobie here.
I'm attempting to display text letter-by-letter (which is working great). However, I want the animation to delay ~500 milliseconds each time a period/end of sentence is encountered. So far the relevant part of my code looks like this:
public function displayLoop(e:Event):void
{
if (pos == textToDisplay.length - 1)
{
stop();
return;
}
firstParagraph.appendText(textToDisplay.charAt(pos));
if (textToDisplay.charAt(pos) == String.fromCharCode(46))
{
//here's where I want to delay??
}
pos++;
}
In this case, firstParagraph is the name of my dynamic text object, textToDisplay is the String of text that is going to be displayed letter-by-letter, and pos is simply the position we're at when displaying the text, so we can keep track of it.
I'm guessing there's a simple solution to this problem, perhaps using a Timer EventHandler?
I appreciate any help anyone has to offer, thanks!
I think the following will be helpful for coding up what you want:
String.split() - This method will help you split up your paragraph into sentences and store them in an array. (Keep in mind that not all periods are full stops, so perhaps you will need to use some regular expressions to deal with special cases like when they are used as elipsis, or decimals.):
e.g.
textToDisplay.split('.');
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/String.html#split()
Array.shift() - This method will return to you the first element in the array, and then remove it from the array. If you have your sentences stored in an array, you can keep calling shift() to get the next sentence that needs to be shown:
e.g.
var sentences:Array = textToDisplay('.');
var next_sentence:String = sentences.shift();
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/Array.html#shift()
Timer - This object, like you mentioned, will help you create those delay intervals between appending the sentences:
e.g.
var myTimer:Timer = new Timer(1000, sentences.length);
myTimer.addEventListener(TimerEvent.TIMER, timerHandler);
myTimer.start();
function timerHandler(e:Event) {
firstParagraph.appendText(sentences.shift());
}
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/utils/Timer.html
No need to track position since the timer has a counter built into it.
import flash.text.TextField;
import flash.utils.Timer;
import flash.events.TimerEvent;
var textToDisplay:String = 'AB.CDE.FGHI.JKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
var tf:TextField = new TextField()
tf.width = 500
tf.wordWrap = true
tf.height = 400
addChild(tf)
var timer:Timer = new Timer(100)
timer.addEventListener(TimerEvent.TIMER, onTimer)
timer.start()
function onTimer(e:TimerEvent):void{
timer.delay = 100
tf.appendText(textToDisplay.slice(timer.currentCount-1,timer.currentCount))
if(timer.currentCount == textToDisplay.length){
timer.stop()
}
if(textToDisplay.slice(timer.currentCount-1,timer.currentCount) == '.'){
timer.delay = 500
}
}

embedded font flash.text.engine

I've completely run out of ideas on this. It follows, and is part of my previous question:
embedding a font in a swf using as3
I just don't seem to be able to get the flash.text.engine to use my embedded font. NB the font has to be loaded into the application (as embedded in swf) after the user has chosen the two languages (for translation to and from). There seems to be a little info implying that it is now necessary to use the fontswf application which is in the sdk. I have tried this and produced loadable swf files but I can't find any info on how these are then loaded (i.e. the getDefinition and registerFont bits below don't work as there are no classes in these swf) and applied to text.engine objects. The source for the embedding is in my answer to my question above. This is a test as3 which demonstrates how it doesn't work!
package
{
import flash.display.Loader;
import flash.display.Shape;
import flash.display.Sprite;
import flash.events.Event;
import flash.text.engine.ElementFormat;
import flash.text.engine.FontDescription;
import flash.text.engine.TextBlock;
import flash.text.engine.TextLine;
import flash.text.engine.TextElement;
import flash.net.URLRequest;
import flash.text.Font;
public class Main extends Sprite
{
private var loader:Loader;
private var tl:TextLine;
public function Main():void
{
loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE,fontLoaded);
loader.load(new URLRequest("EnglishF.swf"));
}
private function fontLoaded(evt:Event):void {
var FontClass:Class
FontClass = evt.target.applicationDomain.getDefinition("EnglishF") as Class;
try {
Font.registerFont(FontClass.myFont);
trace("successfully loaded " + FontClass);
// gives 'successfully loaded EnglishF'
} catch (err:Error) {}
var fontList:Array = Font.enumerateFonts();
for (var i:int = 0; i < fontList.length; i++) {
trace(fontList[i].fontName, fontList[i].fontType);
// gives 'EnglishF embeddedCFF'
}
var block:TextBlock = new TextBlock();
var font:FontDescription = new FontDescription("EnglishF");
var formt:ElementFormat = new ElementFormat(font, 30);
trace(FontDescription.isFontCompatible("EnglishF","normal","normal"), formt.fontDescription.fontName);
// gives 'true EnglishF'
formt.color = 0x882233;
var span:TextElement = new TextElement("Hello World. This is certainly NOT in the Font provided!", formt);
block.content = span;
tl = block.createTextLine();
tl.x = 10;
tl.y = tl.ascent + 10;
addChild(tl);
}
}
}
Am I doing anything wrong, or is this impossible?
Hopefully this will help. Under this line:
var font:FontDescription = new FontDescription("EnglishF");
add the following line:
font.fontLookup = FontLookup.EMBEDDED_CFF;
This will let the text framework know that you're using a CFF font (used in the new text framework), instead of a regular embedded font (used in TextFields).
Hope this helps.
Jordan

Flash Builder 4 + Flash Professional + FlashVars != WORKING

I have a Flash Builder 4 project that's hooked up to a Flash Professional CS5 FLA.
I do NOT use MXML, and all code is handled directly in Flash Builder. (Flash itself is used simply for the library, and its easier for our artists to use)
Everything's been going along without a hitch, everything runs off of dynamically generated XML from the site the SWF is embedded to. But up until now I've had the XML path hardcoded in the actionscript. I wish simply to not make it so.
I have followed minimum 45 tutorials on getting FlashVars into FB4/As3, and quite simply nothing seems to be working.
Old school < embed > method, using < object > method, and even using swfObject method, simply I cannot seem to access these flashvar properties.
here's the html that i currently have now:
<script>
var flashvars = {
xml: "/mapsystem/xml"
}; // yes that is definitely the correct path, its the same value as when it was hardcoded
$(function() {
swfobject.embedSWF("/flash/map.swf", "map", "960", "885", "10.0.0", "expressInstall.swf", flashvars);
});
</script>
<div id="map">
swfObject Aint Working
</div>
Heres the actionscript (this is in my Document class, first thing)
package
{
import flash.display.LoaderInfo;
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.events.Event;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import src.GlobalStage;
import src.Map;
import src.Styles;
public class map extends GlobalStage
{
public var xmlDoc = "map.xml";
public function map()
{
var test:TextField = new TextField();
test.x = 50;
test.y = 50;
test.autoSize = TextFieldAutoSize.LEFT;
test.text = "XML Doc: ";
this.addChild(test);
var test2:TextField = new TextField();
test2.x = 50;
test2.y = 80;
test2.multiline = true;
test2.border = true;
test2.autoSize = TextFieldAutoSize.LEFT;
test2.text = "Parameters: \n";
test2.appendText("Total Parameters: ");
this.addChild(test2);
var _params:Object;
if ( this.loaderInfo.parameters.length != null ) {
_params = this.loaderInfo.parameters;
} else {
// run alt code to init
}
for(var pItem:String in _params) {
test2.appendText("Name: " + pItem + " :: " + _params[pItem] + "\n" );
}
if(_params['xml'] != null) xmlDoc = _params['xml'];
test.appendText(xmlDoc);
var map:Map = new Map(xmlDoc);
Now, when i run this on my local test, nothing shows up as per expected, but when it comes to being on the site itself, with a passed flashvar, the xmlDoc remains "map.xml", my counter tells me there are 0 parameters, and of course nothing shows up in my list of parameters.
I have spent 8 hours trying to get this to work, quite frankly I'm losing hair and sleep over this.
loaderInfo.parameters is an Object, and so the condition in this if statement is never likely to be true (unless your flashVars had a param named 'length'):
if (this.loaderInfo.parameters.length != null) {
So instead of checking if the length is not null, just check if the parameters are not null:
if (loaderInfo.parameters) {
loaderInfo.parameters is an object, and it is never null. What you must do is check for your flashvar's existence like this:
if (loaderInfo.parameters.xml)
{
var xmlPath:String = loaderInfo.parameters.xml
// start using xml
}
else
// run alt code to init
}

I am trying to test if a text input box has focus

I am fairly new to AS3, so here is my problem.
I have two text input boxes p1 and p2. I want to do a conditional test to see if p1 has the focus. If it does not, then p2 must have the focus. Here is some code I am trying to get to work.
if ((Selection.getFocus()) == (p1totalScore.text)){
p1Score();
} p2Score();
Thanks for your help.
David
Without a FocusManager, you could test what the stage is returning for focus:
(If you have textInput1 and textInput2 on the art-board)
import flash.events.MouseEvent;
import fl.controls.TextInput;
var textInput1:TextInput;
var textInput2:TextInput;
stage.addEventListener(MouseEvent.CLICK, mouseClickHandler);
function mouseClickHandler(event:MouseEvent):void
{
if(stage.focus == textInput1.textField)
trace("text field 1 has focus.");
else if(stage.focus == textInput2.textField)
trace("Text field 2 has focus.");
}
I think a better approach than you're attempting is to add event handlers for focus change:
import fl.controls.TextInput;
import fl.managers.FocusManager;
import flash.events.FocusEvent;
var textInput1:TextInput;
var textInput2:TextInput;
var focusManager:FocusManager = new FocusManager(this);
textInput1.addEventListener(FocusEvent.FOCUS_IN, textInput1FocusHandler);
textInput2.addEventListener(FocusEvent.FOCUS_IN, textInput2FocusHandler);
function textInput1FocusHandler(event:FocusEvent):void
{
trace("textInput1 has focus.");
}
function textInput2FocusHandler(event:FocusEvent):void
{
trace("textInput2 has focus.");
}
Adobe will get you 99% of the way:
'http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/fl/managers/FocusManager.html'
I just changed the function to return the name of the control that has focus, instead of the instance name that their example returns.
private function focusChange(e:FocusEvent):void {
var ti_now:InteractiveObject;
ti_now = fm.getFocus();
trace("Focus now: ", ti_now.name);
}

how to write on screen in AS3

So I am creating a module and I have a screen that I need to be able to allow the users to write questions that they have on their screens in a text box. Does anyone know how to do this?
This is the basic setup that I use for every screen:
package screens
{
import flash.filters.*;
import flash.text.*;
import mapSystem.screenSystem.*;
import mapSystem.*;
import screens.*;
import caurina.transitions.Tweener;
public class screen4 extends screenBase
{
public function screen4(pSystem:mapManager)
{
super(pSystem);
numActions = 1;
}
public override function onAction()
{
if (actionStep == 1)
{
map.fID("54");
}
}
public override function onEnter()
{
map.zoomTo("full");
}
}
}
For users to input text, simply create a textfield and set its "type" property to TextFieldType.INPUT. When you go to retrieve this data, just access the textFields "text" prop.
Update -
Ok = simple google search on "AS3 textField tutorial", first hit was this tutorial, which I yanked and added a couple things to for you. Its fairly basic and well documented, so, depending on your level of experience, should prove illuminating.
//Creating the textfield object and naming it "myTextField"
var myTextField:TextField = new TextField();
//Here we add the new textfield instance to the stage with addchild()
addChild(myTextField);
//Here we define some properties for our text field, starting with giving it some text to contain.
//A width, x and y coordinates.
myTextField.text = "input text here";
myTextField.width = 250;
myTextField.x = 25;
myTextField.y = 25;
//#b99 addition
myTextField.type = TextFieldType.INPUT;
//This is the section for our text styling, first we create a TextFormat instance naming it myFormat
var myFormat:TextFormat = new TextFormat();
//Giving the format a hex decimal color code
myFormat.color = 0xAA0000;
//Adding some bigger text size
myFormat.size = 24;
//Last text style is to make it italic.
myFormat.italic = true;
//Now the most important thing for the textformat, we need to add it to the myTextField with setTextFormat.
myTextField.setTextFormat(myFormat);
Hope that helps!