search in a textFiedl, a specific word - actionscript-3

I've got, in my AS3 code, a textfield that load sentences from a database (each sentences is a title.
How can I simply do a search bar for this TextField. When the user type the word "computer" (for exemple), it'll search in every sentences the word "computer".
Here's my current code :
function createListItem(index:int, item:Object):void {
var listItem:TextField = new TextField();
var myFormat:TextFormat = new TextFormat();
myFormat.size = 25
myFormat.color = 0x000000;
myFormat.font = "Mohave";
listItem.defaultTextFormat = myFormat;
listItem.text = item.title;
listItem.x = 10;
listItem.y = 140+ index * 40;
listItem.width = 160;
feedbackText.text = "createListItem" +item.title;
listItem.addEventListener(MouseEvent.CLICK, function(e:MouseEvent):void {
showDetails(item);
});
list.addChild(listItem);
}
and it displays a list like this:
"I sell a computer"
"I sell a desk"
"computer and apple"
(and know if I can do a search bar in order to display only the sentences with a specific word).
Thx for your help,

First convert your list into an array
var str: String = "first sentence. second sentence. third sentence. fourth sentence";
var arr: Array = str.split(".");/// to split the string into array items
function searching(val: String): String {
var collectedString: String = "";
for (var i: int = 0; i < arr.length; i++) {
if (arr[i].search(val) > -1) {
collectedString += arr[i].toString()+".";
}
}
return collectedString;
}
trace(searching("second")); /// input the key word
trace( searching("sentence")); /// another the key word

Related

How would i make the buttons pressed in my calculator show up in my dynamic text box

I am making a calculator with a dynamic text box, buttons from 0-9, and +,-,/,*,=, and clear button. but for some reason everytime I press the buttons on my calculator, they don't show up in my dynamic text box like I need them to. My problem specifically is how do I make it that when the number buttons on my calculator are pressed, the numbers show up in my dynamic text box, like a proper calculator. I would really appreciate your help.
Here is my code:
import flash.events.MouseEvent;
var numbers:Array= [btnNum0,btnNum1,btnNum2,btnNum3,btnNum4,btnNum5,btnNum6,btnNum7,btnNum8,btnNum9];
var operations:Array = [btnAdd_,btnSubtract_,btnMultiply_,btnDivide_,btnEqual_,btnClear_];
var o:String;
var number1:Number;
var number2:Number;
function addListeners():void
{
for(var i:uint = 0; i < numbers.length; i++){
numbers[i].addEventListener(MouseEvent.CLICK, pressNumber);
}
for(i = 0; i < operations.length; i++){
operations[i].addEventListener(MouseEvent.CLICK, pressOperations);
}
btnClear.addEventListener(MouseEvent.CLICK, clearAll);
btnDot..addEventListener(MouseEvent.CLICK, addDot);
}
function pressNumber(event:MouseEvent): void
{
// find name of button pressed
var instanceName:String = event.target.name;
// get the number pressed fom the instanceName
var getNum = instanceName.charAt(6)
if(output.text == "0"){
output.text = "";
}
output.appendText(getNum);
}
function pressOperations(event:MouseEvent): void
{
var instanceName:String = event.target.name;
var currentOperator:String;
currentOperator = instanceName.slice(3,instanceName.indexOf("_"));
trace(currentOperator)
}
function clearAll(event:MouseEvent): void
{
output.text = "";
number1 = NaN;
number2 = NaN;
}
function addDot(event:MouseEvent): void
{
if(output.text.indexof(".") == -1){
output.appendText(".");
}
output.text = "0";
addListeners();
}
You shouldn't try to store information in the instance name. Use objects stored in arrays for the buttons. This is how you can handle everything like this.
Using objects stored in arrays to handle your buttons, the basic code to make a new button and set its properties (store information about the button in the instance):
var aButtons:Array = new Array();var i: int = 0;
for (i = 0; i < 10; i++) {
var mcButton: McButton = new McButton();
mcButton.iButtonValue = i;
mcButton.sButtonName = "Button Number " + i;
aButtons.push(mcButton);
}
Then you can reference the buttons by
aButtons[i]
aButtons[i].iButtonValue
You have first to set a value to your text field, because appendText() method can't append text to an empty text field (nothing will appear).
At the begining of your code:
output.text = '0';
To use property "name" you must set this property after creating instance. Like this:
var btnNum0:Button = new Button();
butNum0.name = "btnNum0";
If you don't do this "name" property will be empty that looks like your case.
UPDATE:
Helloflash is right in his comment to question. At first time I did not see that but in code more mistakes than I thought.
First of all you need to put off your init code from function addDot() to the begining of the code. At now this code will be never called because you try to add listeners into listener addDot().
output.text = "0";
addListeners();
Also change indexof to indexOf and remove extra dot from statement btnDot..addEventListener(MouseEvent.CLICK, addDot);. And big advice/request: use some formatting rules when you write a code (specially about brackets). Your code will be more clean and readable.

Interaction isn't translating input Text to Strings

I'm in need of some help. To start with, what I have is an interaction where you fill out 5 text boxes in response to 2 questions. Each of the 5 answers must be filled out as input text and then checked against an array of acceptable responses when the done button is clicked. Also, there are two type differences in the fields. So the first three answer fields belong to a range of acceptable responses in the array: Type A and the next two questions to Type B. It's possible to fill out the correct responses in any order, so long as the typing is correct.
What I can't seem to figure out is why the textFields aren't translating to Strings.
import flash.text.TextField;
import flash.events.MouseEvent;
stop();
//*--------------------------------------------
//
// THINGS YOU CAN CHANGE
//
//*--------------------------------------------
var a_inputType:Array = new Array("Doggie Day Spa", "Deb's Dog Walking Service", "Pet Market", "Pampered Pet", "TLC Grooming"); //All recognized type responses, Type A listed before Type B
var n_typeA:Number = new Number(3); //Sets the range for Type A
//*--------------------------------------------
//
// PAGE SETUP
//
//*--------------------------------------------
var n_typeB:Number = new Number(a_inputType.length - n_typeA +1); //Finds the range of Type B
var a_testArray:Array = new Array(); //Holds push data from submit button
var a_correctArray:Array = new Array(); //Creates an array to run a final test against
for(var c = 0; c<=a_inputType.length-1; c++){ //Loop populates the array
a_correctArray.push(1);
}
var inputField1:TextField = new TextField(); //Creates the Text Fields
var inputField2:TextField = new TextField();
var inputField3:TextField = new TextField();
var inputField4:TextField = new TextField();
var inputField5:TextField = new TextField();
var txtString1:String = new String(); //Creates the strings for translating the input text
var txtString2:String = new String();
var txtString3:String = new String();
var txtString4:String = new String();
var txtString5:String = new String();
for(var f = 1; f<=a_inputType.length; f++){ //Assigns them properties, locations, and adds a listener for text
var fieldBuilder = "inputField"+f;
var fieldFinder = "txt_pos"+f;
addChild(this[fieldBuilder]);
this[fieldBuilder].border = false;
this[fieldBuilder].width = 290;
this[fieldBuilder].height = 25;
this[fieldBuilder].x = this[fieldFinder].x;
this[fieldBuilder].y = this[fieldFinder].y;
this[fieldBuilder].type = "input";
this[fieldBuilder].multiline = true;
this[fieldBuilder].text = "";
this[fieldBuilder].addEventListener(TextEvent.TEXT_INPUT, function (){
var stringBuilder = "txtString"+f;
this[stringBuilder] = this[fieldBuilder].text;
});
}
//*--------------------------------------------
//
// FUNCTIONS
//
//*--------------------------------------------
function SUBMIT(event:MouseEvent):void{
for(var t=1; t<=a_inputType.length; t++){ //Loop establishes checks for each String against an input type
if(t<=n_typeA){ //if/else divides the textfields into two ranges: typeA and typeB
checkTypeA(this["txtString"+t], a_inputType); //sends the array of correct responses and the captured String to checkTypeA
}else{
checkTypeB(this["txtString"+t], a_inputType); //sends the array of correct responses and the captured String to checkTypeB
}
}
var TEMPSELECT = a_testArray.toString(); //reduces the testArray recieving push data into a String
var TEMPCORRECT = a_correctArray.toString(); //reduces the correctArray from scene set-up into a String
if(TEMPSELECT == TEMPCORRECT){ //compares the strings and determines a trace response
trace("correct");
}else{
trace("incorrect");
}
}
function checkTypeA(value:String, arr:Array){ //Checks the String against all the array values within the specified range for type A
for (var a=1; a<=n_typeA; a++){ //determines the range
if (arr[a]==value){ //checks the value
a_testArray.push(1); //if true, generates a push value for a testArray to be checked later
}
}
}
function checkTypeB(value:String, arr:Array){
for (var b = n_typeA; b<=n_typeB; b++){
if (arr[b-1]==value){
a_testArray.push(1);
}
}
}
//*--------------------------------------------
//
// BUTTONS
//
//*--------------------------------------------
done_bttn.addEventListener(MouseEvent.CLICK, SUBMIT); //Launches the SUBMIT function when "Done" is pressed.
Upon further investigation I've noticed that the loop isn't terminating when it reaches 5. It keeps regurgitating TextFields over and over again with the same variable names and instancing. Because of this, the addChild is dumping input fields one on top of one another in the flash file (which makes editing a text field impossible since your always clicking on a new field positioned directly on top of the one you just edited).
The trace on the loop comes back like this:
inputField1
txt_pos1
inputField2
txt_pos2
inputField3
txt_pos3
inputField4
txt_pos4
inputField5
txt_pos5
inputField1
txt_pos1
inputField2
txt_pos2
inputField3
txt_pos3
inputField4
txt_pos4
inputField5
txt_pos5
inputField1
txt_pos1
inputField2
txt_pos2
and so on.... how can I stop this looping behavior. I've tried if/else breaking and that's not working.
The context of the this keyword changes when you call it from a local function. You can easily verify it if you add trace(this) to your anonymous function. It will trace out [object global]. Two solutions come to mind, store a reference of this in a variable:
var self:MovieClip = this;
for(var f = 1; f<=a_inputType.length; f++){
//...
this[fieldBuilder].addEventListener(TextEvent.TEXT_INPUT, function (){
var stringBuilder = "txtString"+f;
self[stringBuilder] = self[fieldBuilder].text;
});
}
Or declare a new function:
for(var f = 1; f<=a_inputType.length; f++){
//...
this[fieldBuilder].addEventListener(TextEvent.TEXT_INPUT, myFunction);
}
function myFunction(t:TextEvent){
var stringBuilder = "txtString"+f;
this[stringBuilder] = (t.target as TextField).text;
}

How to highlight static text background in AS3 dynamically?

If i can search a word in search box that word will find static text then highlight appear in flash as3. Any suggest please?
You can use .getCharBoundaries(), which returns a Rectangle encompassing a character at a given index in your TextField.
Using that Rectangle, you can create some highlight graphics. Here's a function that will simplify that process:
function highlightChar(textField:TextField, charIndex:int):void
{
var rect:Rectangle = textField.getCharBoundaries(charIndex);
var box:Shape = new Shape();
box.blendMode = BlendMode.MULTIPLY;
box.graphics.beginFill(0xFFCC33);
box.graphics.drawRect(textField.x + rect.x, textField.y + rect.y, rect.width, rect.height);
box.graphics.endFill();
if(textField.parent) textField.parent.addChild(box);
}
From here, you can create another function that will accept a phrase to highlight:
function highlightPhrase(textField:TextField, phrase:String):void
{
var start:int = textField.text.indexOf(phrase);
if(start >= 0)
{
for(var i:int = start; i < phrase.length; i++)
{
highlightChar(textField, i);
}
}
}
Combined, you'll find it easily to highlight a block of text like this:
var t:TextField = new TextField();
t.text = "This text is highlighted";
addChild(t);
highlightPhrase(t, "This text");

Length of a string in pixels

I'm populating a dropDownList with arrayCollection of strings. I want the width of the drop down list control to match with the size (in pixels) of the longest string in the array collection. The problem I'm facing is: the font width of the strings in the collection are different e.g. 'W' looks wider than 'l'. So I estimated the width of a character to be 8 pixels but that's not pretty neat. If a string that has many 'W' and 'M' is encountered the estimation is wrong. So I want precise pixel width of strings. How can i get the exact length of a string in pixels??
My solution that estimates all character to be 8 pixels wide is given below:
public function populateDropDownList():void{
var array:Array = new Array("o","two","three four five six seven eight wwww");
var sampleArrayCollection:ArrayCollection = new ArrayCollection(array);
var customDropDownList:DropDownList = new DropDownList();
customDropDownList.dataProvider=sampleArrayCollection;
customDropDownList.prompt="Select ...";
customDropDownList.labelField="Answer Options:";
//calculating the max width
var componentWidth=10; //default
for each(var answerText in array){
Alert.show("Txt size: "+ answerText.length + " pixels: " + answerText.length*9);
if(answerText.length * 8 > componentWidth){
componentWidth=answerText.length * 8;
}
}
customDropDownList.width=componentWidth;
answers.addChild(customDropDownList);
}
Any idea or solution is highly valued.
Thanks
To get a more accurate measurement, you can populate a TextField with the string, then measure the width of that TextField's text.
Code:
function measureString(str:String, format:TextFormat):Rectangle {
var textField:TextField = new TextField();
textField.defaultTextFormat = format;
textField.text = str;
return new Rectangle(0, 0, textField.textWidth, textField.textHeight);
}
Usage:
var format:TextFormat = new TextFormat();
format.font = "Times New Roman";
format.size = 16;
var strings:Array = [ "a", "giraffe", "foo", "!" ];
var calculatedWidth:Number = 50; // Set this to minimum width to start with
for each (var str:String in strings) {
var stringWidth:Number = measureString(str, format).width;
if (stringWidth > calculatedWidth) {
calculatedWidth = stringWidth;
}
}
trace(calculatedWidth);
I don't have edit priv on other people's post's so I'm posting this as a separate answer but credit should go to Cameron if this works:
function measureString(str:String, format:TextFormat):Rectangle {
var textField:TextField = new TextField();
textField.autoSize = TextFieldAutoSize.LEFT;
textField.defaultTextFormat = format;
textField.text = str;
return new Rectangle(0, 0, textField.textWidth, textField.textHeight);
}
If I see that it does and his is edited I'd delete this one for cleanliness.
Sorry for the garbage post initially was trying to answer the question just did so erroneously... anyhow tested this one and it appears to work. I did this in Flex but you should be able to just use the AS3 part no problem I just wrapped up the textfield in a UIComponent to get it on stage but using the autosize seems to work fine:
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<fx:Script>
<![CDATA[
import mx.core.UIComponent;
protected function textinput1_changeHandler(event:TextOperationEvent):void
{
// TODO Auto-generated method stub
var rect:Rectangle = measureString(event.target.text);
holderBox.graphics.clear();
holderBox.graphics.beginFill(0xFF0000);
holderBox.graphics.drawRect(rect.x,rect.y,rect.width,rect.height);
}
private function measureString(str:String):Rectangle {
var textField:TextField = new TextField();
textField.autoSize = TextFieldAutoSize.LEFT;
textField.text = str;
var uiComponent:UIComponent = new UIComponent();
uiComponent.addChild(textField);
holderBox.addChild(uiComponent);
return new Rectangle(0, 0, textField.textWidth, textField.textHeight);
}
]]>
</fx:Script>
<mx:VBox>
<s:TextInput text="" change="textinput1_changeHandler(event)"/>
<mx:Box id="holderBox"/>
</mx:VBox>
</s:Application>
This is a more polished version of some of the above code. Accounting for linebreaks (html break and \n) and nullifying the created Textfield object with some other optimizations. Hope this is helpful.
function measureString(str:String, font:String="Times New Roman", size:Number=12):Rectangle
{
var textField:TextField = new TextField();
textField.defaultTextFormat = new TextFormat( font, size );
textField.border = true;
textField.multiline = true;
textField.autoSize = TextFieldAutoSize.LEFT;
textField.htmlText = str;
// Grab with and height before nullifying Textfield.
var w:Number = textField.textWidth;
var h:Number = textField.textHeight;
//addChild( textField );// This will add the Textfield to the stage so you can visibly see it.
//if( contains( textField ) ) removeChild( textField );// If it exists onstage, remove it.
textField = null;//nullify it to make it available for garbage collection.
return new Rectangle(0, 0, w, h);
}
var str:String = "Jeremy is a good boy.<br>He also has a red bike. \nSometimes Jeremy rides his bike to the store to buy bread for his family.<br>He likes wholewheat.";
trace( measureString( str, "Times New Roman", 25 ).width );
If you prefer this in a class, check it out in my GIT framework:
https://github.com/charlesclements/as3-tools/blob/master/net/charlesclements/util/text/TextUtil.as
AS3-tools:https://github.com/charlesclements/as3-tools
Also, our Flash/JS brother Jack Doyle # GreenSock has some handy stuff to do with manipulating text. Well worth it to check it out:http://www.greensock.com/splittext/
Here is a routine I wrote for Java. I guess you can convert it to Javascript or whatever.
It is not exact, but gives an approximate answer. It assumes that a space is about 200 wide, and M and W is about 1000 wide. Obviously you'll need to scale that based on your particular font size.
static int picaSize(String s)
{
// the following characters are sorted by width in Arial font
String lookup = " .:,;'^`!|jl/\\i-()JfIt[]?{}sr*a\"ce_gFzLxkP+0123456789<=>~qvy$SbduEphonTBCXY#VRKZN%GUAHD#OQ&wmMW";
int result = 0;
for (int i = 0; i < s.length(); ++i)
{
int c = lookup.indexOf(s.charAt(i));
result += (c < 0 ? 60 : c) * 7 + 200;
}
return result;
}

Actionscript Child within parent within parent

I am trying to make a calculator where a user can select from a list of items. If a user clicks say "ITEM1", it should add the item to a "CONTAINER_MC". The problem i have is all my data is set inside an array containing names and prices like the code below.
var menuNames:Array = [
"Item1",
"Item2",
"Item3",
"Item4",
"item5",
"item6"
];
//price array
var menuPrices:Array = [
"0.99",
"1.99",
"2.99",
"5.99",
"6.99",
"10.99"
];
Now i have a sprite which creates a menu for each of these items by the use of a movie clip containing 2 input fields which i setup like the code below.
var menuSprite:Sprite = new Sprite();
var totalItems:Number = menuNames.length;
var item:menuItem; //new item field
var btn:add_btn;
for(var i = 0; i < totalItems; i++) {
item = new menuItem();
btn = new add_btn();
menuSprite.addChild(item);
item.addChild(btn);
item.x = 0;
item.y = i * 80;
btn.y = 45;
item.itemName.text = menuNames[i];
item.itemPrice.text = "$" + menuPrices[i];
}
addChild(menuSprite);
This all works fine so far, the problem is that i have a button inside my item and i need to add even listeners for these buttons, the problem is how to target these buttons. Since these buttons are added through the for loop they are not given instance names so notice how i targetted the input fields stored within the "item", i used itemName but how would i do it to the buttons stored inside item.
Thank you, really appreciate any help possible.
Something like this:
var menuSprite:Sprite = new Sprite();
var totalItems:Number = menuNames.length;
var item:menuItem; //new item field
var btn:add_btn;
for(var i = 0; i < totalItems; i++) {
item = new menuItem();
btn = new add_btn();
btn.addEventListener(MouseEvent.CLICK,clickHndlr);
menuSprite.addChild(item);
item.addChild(btn);
item.x = 0;
item.y = i * 80;
btn.y = 45;
item.itemName.text = menuNames[i];
item.itemPrice.text = "$" + menuPrices[i];
}
addChild(menuSprite);
public function clickHndlr(event:MouseEvent):void
{
((event.currentTarget as add_btn).parent as menuItem).itemName.text="Any of changes";
}
But also I'd like to change arrays to Dictionary instance, like this:
var menuData=new Dictionary();
//filling our Dictionary instead of weird arrays
for(var i:int=0;i<10;i++)
menuData["Item"+i]=Math.round(Math.random()*100);
var menuSprite:Sprite = new Sprite();
var item:menuItem; //new item field
var btn:add_btn;
for(var menuName:Object in menuData)
{
item = new menuItem();
btn = new add_btn();
btn.addEventListener(MouseEvent.CLICK,clickHndlr);
menuSprite.addChild(item);
item.addChild(btn);
item.x = 0;
item.y = i * 80;
btn.y = 45;
var menuPrice:int=menuData[menuName] as Number;
item.itemName.text = menuName as String;
item.itemPrice.text = "$" + menuPrice.toString();
}
addChild(menuSprite);
public function clickHndlr(event:MouseEvent):void
{
((event.currentTarget as add_btn).parent as menuItem).itemName.text="Any of changes";
}
And if to be very honest, I'll put away Flash, and prefer yo use Flex+Catalyst to create great code with great UI.
Ask more if you need more information.
Regards
Eugene