Highlight string search string - apache-flex

I'm using the code below to search the text in a textarea for a string entered in a textinput. I'm trying to highlight the string in the textarea after it's been searched for. I assume the way to do this is selectRange(). I'm not sure how to find the endIndex for the second parameter of selectRange(). Below is what I have:
protected function searchBtn_clickHandler(event:MouseEvent):void
{
text = mainTextField.text;
search_Str = searchTxt.text;
var search_result:int = text.search(search_Str);
trace(search_result);
EDIT
<?xml version="1.0" encoding="utf-8"?>
<s:View xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark" title="HomeView">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<s:titleContent>
<s:TextInput id="searchTxt"/>
<s:Button label="Button" click="searchBtn_clickHandler(event)"/>
</s:titleContent>
<s:TextArea id="mainTextField" x="33" y="35" width="544" height="444"/>
<fx:Script>
<![CDATA[
public var text:String;
public var search_Str:String;
protected function searchBtn_clickHandler(event:MouseEvent):void
{
text = mainTextField.text;
search_Str = searchTxt.text;
var search_result:int = text.search(search_Str);
trace(search_result); // Traces correct int values
trace(mainTextField.selectRange(search_result,search_result+search_Str.length)); // Traces "undefined"
}
]]>
</fx:Script>
</s:View>

Can't you just calculate it based on the length of the search string?
The modified code would be like this:
protected function searchBtn_clickHandler(event:MouseEvent):void
{
text = mainTextField.text;
search_Str = searchTxt.text;
var search_result:int = text.search(search_Str);
trace(search_result);
mainTextField.selectRange(search_result,search_result+search_Str.length);
}
Update, In response to the original poster's code update; I went ahead and tested. A TextAre will not display an item as selected if it does not have focus. Therefore the solution to get the selected range to highlight is to set focus to the textArea after the button is clicked. Here is code demonstrating this:
<?xml version="1.0" encoding="utf-8"?>
<s:View xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark" title="HomeView">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<s:titleContent>
<s:TextInput id="searchTxt" text="Quick" />
<s:Button label="Button" click="searchBtn_clickHandler(event)"/>
</s:titleContent>
<s:TextArea id="mainTextField" x="33" y="35" width="544" height="444" text="The Quick Brown Fox Jumped Over The Lazy Dogs"/>
<fx:Script>
<![CDATA[
public var text:String;
public var search_Str:String;
protected function searchBtn_clickHandler(event:MouseEvent):void
{
mainTextField.setFocus();
text = mainTextField.text;
search_Str = searchTxt.text;
var search_result:int = text.search(search_Str);
trace(search_result); // Traces correct int values
trace(search_result+search_Str.length);
// trace(mainTextField.selectRange(search_result,search_result+search_Str.length)); // Traces "undefined"
mainTextField.selectRange(search_result,search_result+search_Str.length)
}
]]>
</fx:Script>
</s:View>

Related

Dynamically create an embedded image

I need to dynamically create a LinkButton with an icon. The names of files (icons) have the format images/icon_0.png, images/icon_1.png, ... images/icon_1000.png. But I don't know the specific image for this button. I only know the index of the icon.
I tried this, with no success:
var path:String = "#Embed(source='images/icon_" + imageindex + ".png')";
myButton.setStyle("icon", path);
I get a runtime error:
Type Coercion failed:
*cannot convert "#Embed(source='images/icons/icon_427.png')" to Class*
Sorry that will not work.
Since imageindex is a compile-time variable, then embedding tag will trigger an error message.
Why not to override the button and add extra property like 'iconPath' that will expect a string path instead of a Class object. This way you can manually set (inside extended Button) the icon.source = iconPath without having to use embed.
pls try this.
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" creationComplete="application1_creationCompleteHandler(event)"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600">
<fx:Script>
<![CDATA[
import mx.events.FlexEvent;
[Embed(source='icon_1.png')]
[Bindable]
private var linkButtonIcon:Class;
protected function application1_creationCompleteHandler(event:FlexEvent):void
{
lnkbutton.setStyle("icon",linkButtonIcon);
}
protected function button1_clickHandler(event:MouseEvent):void
{
[Embed(source='icon_2.png')]
var linkButtonIcon2:Class;
lnkbutton.setStyle("icon",linkButtonIcon2);
}
]]>
</fx:Script>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<s:VGroup>
<mx:LinkButton label="test" id="lnkbutton"/>
<s:Button label="change Icon" click="button1_clickHandler(event)"/>
</s:VGroup>
</s:Application>

How to pass and retrieve values to/from popup window in Flex?

I want to send some text value to my custom popup window when it pops up from main application which is having some text input and also I want to know how to retrieve data(of text input) which entered by a user in popup window. Any help is appreciated.
You can access popUp data using setter as example shows. Or make a popUp component as a global in your main application so you can refer component properties globally.
<!-- TitleWindow.mxml -->
<?xml version="1.0" encoding="utf-8"?>
<mx:TitleWindow xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/mx" layout="absolute" width="600" title="" height="160">
<fx:Script>
<![CDATA[
public function get UserTypedData():String
{
return tiSomeText.text;
}
]]>
</fx:Script>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<mx:TextInput id="tiSomeText" x="76" y="101"/>
<!-- Application.mxml -->
<mx:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/mx" layout="absolute" width="100%" >
<fx:Script>
<![CDATA[
public var popup:YourPopupWindow;
private function createPopUp():void
{
popup = YourPopupWindow(PopUpManager.createPopUp(this, YourPopupWindow, false));
}
private function getPopUpData():String
{
var retVal:String = "";
if (popUp != null)
{
// get data from setter
retVal = popUp.UserTypedData();
// of from TextInput
retVal = popUp.tiSomeText.text;
}
return retVal;
}
]]>
</fx:Script>
</mx:Application>
var popup:YourPopupWindow = PopupManager.createPopup(YourPopupWindow, true) as YourPopupWindow;
popup.someData = yourData;

Using [Bindable] in flex 4

I just don't get it with [Bindable] and updating a label
So here are my three pages, please tell me what I am doing wrong because when the listner sends the updated var to button2.mxml the var updates but the label does not redraw it.
application.mxml
<s:WindowedApplication
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:comps="components.*"
creationComplete="init();">
<fx:Script>
<![CDATA[
import mx.controls.Alert;
public function init(){
btn1.addEventListener(MouseEvent.MOUSE_OVER, myFunction);
}
public function myFunction(e:MouseEvent){
var myPage:button2 = new button2();
var ranNum = Math.floor(Math.random() * 40) + 10;
myPage.myValue("ABC "+ranNum);
}
]]>
</fx:Script>
<comps:button1 y="0" id="btn1" width="100"/>
<comps:button2 y="100" id="btn2" width="100"/>
button1.mxml
<?xml version="1.0" encoding="utf-8"?>
<s:Group xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" width="128" height="72">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<s:Button x="27" y="19" label="Button1" id="btn1" enabled="true"/>
</s:Group>
button2.mxml
<?xml version="1.0" encoding="utf-8"?>
<s:Group xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" width="400" height="300">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<fx:Script>
<![CDATA[
[Bindable]
public var myVal:String = "Button2";
public function myValue(mV:String)
{
myVal = mV;
}
]]>
</fx:Script>
<s:Button x="10" y="32" label="{myVal}" id="btn2" enabled="true"/>
</s:Group>
Your function should be:
public function myFunction(e:MouseEvent){
var ranNum = Math.floor(Math.random() * 40) + 10;
btn2.myValue("ABC " + String(ranNum));
}
In the function that you have, you are creating a new button (without adding it as a child to anything) and setting the label on that button rather than the one you have already defined in your application.
You also do not necessarily need a [Bindable] variable for the label in button2.mxml but this depends on what you are accomplishing. You could just do btn2.label = mV; in the myValue() function definition alternatively.
The simplest way to do this is to remove your setter for myVal in button2.mxml and just set the value in myFunction like you would any other public variable:
myPage.myVal = "ABC " + ranNum;
The reason your code is not currently working is that you have implicitly overridden the myVal setter and are not dispatching a data change event, which is what makes binding work. When you add the [Bindable] metadata tag to a variable, the compiler automatically generates a setter for that variable with the proper event dispatching for you.
Hope that helps.

Dynamic Flex Form Duplication

I'm designing a data entry app that allows multiple entries to its subject. For example, a person might have received education from multiple institutions. Each educational entry is a form and app user can click on a button to add another entry, which is a blank but identical form.
I figure it involves states and custom form components but not sure how everything fits together. Can someone shed some lights on how to accomplish that? Some sample codes would be greatly appreciated.
Thanks in advance,
Required flex version if there is a requirement? or just going with the newest available Flex 4 code? Generally speaking this is a very easy task in Flex, you create a class definition in MXML of AnEntry.mxml which is just a TextInput (or a label and TextInput or whatever you need for each entry). In the click handler of the a button you in Flex 3 call this.addChild(new AnEntry()) or in Flex 4 call this.addElement(new AnEntry());. To submit you'd do a loop starting at 0 and going to this.numChildren and for each TextInput pass along as params to an HTTPService.
Two files below compiled against Flex 3.4
[AnEntry.mxml]
<?xml version="1.0" encoding="utf-8"?>
<mx:Box xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Label text="Link:"/>
<mx:TextInput id="theTextInput"/>
</mx:Box>
[MainApplication.mxml]
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="vertical"
minWidth="955"
minHeight="600">
<mx:Script>
<![CDATA[
import mx.rpc.http.HTTPService;
protected function button1_clickHandler(event:MouseEvent):void
{
var params:Object = {};
var paramCount:Number=0;
// TODO Auto-generated method stub
for(var i:Number = 0; i<numChildren; i++)
{
var currentChild:DisplayObject = getChildAt(i);
if(currentChild is AnEntry)
{
params[paramCount++] = (currentChild as AnEntry).theTextInput.text;
}
}
var httpService:HTTPService = new HTTPService();
httpService.method = "POST"
httpService.url = "http://www.shaunhusain.com/somewhere.php";
httpService.send(params);
}
]]>
</mx:Script>
<mx:Button label="Add Entry" click="this.addChild(new AnEntry())"/>
<mx:Button label="Submit Info" click="button1_clickHandler(event)"/>
</mx:Application>
Please let me know if this gets you going in the right direction, if you're a beginner at Flex search for the Flex in a week videos, they're a great tutorial to get you started on Flex development.
Amendment for Flex 4:
[MainApplication.mxml]
<?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">
<s:layout>
<s:VerticalLayout/>
</s:layout>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<fx:Script>
<![CDATA[
import mx.rpc.http.HTTPService;
protected function button1_clickHandler(event:MouseEvent):void
{
var params:Object = {};
var paramCount:Number=0;
// TODO Auto-generated method stub
for(var i:Number = 0; i<numChildren; i++)
{
var currentChild:DisplayObject = getChildAt(i);
if(currentChild is AnEntry)
{
params[paramCount++] = (currentChild as AnEntry).theTextInput.text;
}
}
var httpService:HTTPService = new HTTPService();
httpService.method = "POST"
httpService.url = "http://www.shaunhusain.com/somewhere.php";
httpService.send(params);
}
]]>
</fx:Script>
<mx:Button label="Add Entry" click="this.addElement(new AnEntry())"/>
<mx:Button label="Submit Info" click="button1_clickHandler(event)"/>
</s:Application>
[AnEntry.mxml]
<?xml version="1.0" encoding="utf-8"?>
<mx:Box xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<mx:Label text="Link:"/>
<mx:TextInput id="theTextInput"/>
</mx:Box>

Remove child content from ViewStack in Flex 4

In my example below, when I click "Add Content", new stack content is loaded into the ViewStack as expected. But when I then click "Close Content", I'm expecting it to close the newly created content inside the ViewStack and switch to the "defaultContent" content.
Can anyone tell me where I'm going wrong please? Thanks in advance.
// TestProject.mxml (application)
<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx">
<s:layout>
<s:VerticalLayout/>
</s:layout>
<fx:Script>
<![CDATA[
import com.NewContent;
private function addContent():void
{
var content:NewContent = new NewContent();
var navContent:NavigatorContent = new NavigatorContent();
navContent.id = 'newContent';
navContent.label = 'newContent';
navContent.width = Number('100%');
navContent.height = Number('100%');
navContent.addElement(content);
viewStack.addElement(navContent);
viewStack.selectedChild = navContent;
}
]]>
</fx:Script>
<mx:ViewStack id="viewStack" width="100%" height="100%">
<s:NavigatorContent id="defaultContent"
label="defaultContent">
<s:Button click="addContent()" label="Add Content"/>
</s:NavigatorContent>
</mx:ViewStack>
</s:WindowedApplication>
// NewContent.mxml (component)
<?xml version="1.0" encoding="utf-8"?>
<s:Group xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
width="100%" height="100%">
<fx:Script>
<![CDATA[
import mx.core.FlexGlobals;
private function closeContent():void
{
FlexGlobals.topLevelApplication.viewStack.removeChild('newContent');
FlexGlobals.topLevelApplication.viewStack.selectedChild = 'defaultContent';
}
]]>
</fx:Script>
<s:Button click="closeContent()" label="Close Content"/>
</s:Group>
selectedChild expects the child itself, not the label.
Instead - try this:
public function removeContent():void
{
Viewstack(this.parent).selectedIndex = 0;
this.parent.removeChild(this);
}
Note - it's generally reccomended to avoid using FlexGlobals.topLevelApplication, as it leads to a very tightly coupled & fragile application.
Sorted it...
// TestProject.mxml (application)
private function addContent():void
{
var content:NewContent = new NewContent();
content.addEventListener("removeMe",onRemove,false,0,true);
var navContent:NavigatorContent = new NavigatorContent();
navContent.id = 'newContent';
navContent.label = 'newContent';
navContent.width = Number('100%');
navContent.height = Number('100%');
navContent.addElement(content);
viewStack.addElement(navContent);
viewStack.selectedChild = navContent;
private function onRemove(event:Event):void
{
var content:NewContent = event.currentTarget as NewContent;
content.removeEventListener("removeMe",onRemove,false);
viewStack.removeChild(content.parent.parent.parent);
}
// NewContent.mxml (component)
public function removeContent():void
{
dispatchEvent(new Event("removeMe"));
}

Resources