tlfTextField - Highlight a part of text with "Code" - actionscript-3

I wonder how to set the text "Highlight" of a part of text inside tlfTextField with the code?
I tried "tf.backgroundColor = 0x990000" property, but did not help.
For instance, I can change the Font Color of any contents inside Parenthesis, by this code:
private function decorate():void {
var tf:TextFormat = new TextFormat();
tf.color = 0x990000;
var startPoint:int = 0;
while (startPoint != -1) {
var n1:int = textMc.tlfText.text.indexOf("(", startPoint);
var n2:int = textMc.tlfText.text.indexOf(")", n1 + 1);
if (n1 == -1 || n2 == -1) {
return;
}
textMc.tlfText.setTextFormat(tf, n1 + 1, n2);
startPoint = n2 + 1;
}
}
So I know "tf.color = 0x990000;" will change the Font color, however, don't know how to "highlight" some text, with code, as I do inside Flash manually.

You should have probably used tlfMarkup property to set the required format to the specific part of text. The attributes you seek are backgroundColor and backgroundAlpha of the span XML element that you should wrap your selection, however it should be much more difficult should there already be spans around words when you retrieve the property from your text field.
The problem with your solution is that you don't check if the two characters are located on a single line before drawing your rectangle, also you would need to redraw such rectangles each time something happens with the textfield. The proposed approach makes use of Flash HTML renderer's capabilities to preserve the formatting, however it will require a lot of work to handle this task properly.

Related

setAttributes does not apply foreground color, but bold and other formatting is retained

I want to replace a word "allowance" with "Some text", after running the code, It will remove word allowance and apply "Some text" with same formatting as that of "allowance" but foreground color property is not getting set as that of original.I want Some text also in red color as shown in the screenshot
function retainFormatting() {
var doc = DocumentApp.getActiveDocument();
var textToHighlight = 'allowance';
var highlightStyle;
var paras = doc.getParagraphs();
var textLocation = {};
var i;
for (i=0; i<paras.length; ++i) {
textLocation = paras[i].findText(textToHighlight);
if (textLocation != null && textLocation.getStartOffset() != -1) {
highlightStyle = textLocation.getElement().getAttributes(textLocation.getStartOffset());
textLocation.getElement().deleteText(textLocation.getStartOffset(),textLocation.getEndOffsetInclusive());
textLocation.getElement().insertText(textLocation.getStartOffset(),"Some text");
textLocation.getElement().setAttributes(textLocation.getStartOffset(),textLocation.getEndOffsetInclusive(), highlightStyle);
}
}
}
before setting attribute at offset
after setting attribute it turns out to be
getForegroundColor(offset)
Retrieves the foreground color at the specified character offset.
And
setForegroundColor(startOffset, endOffsetInclusive, color)
Sets the foreground color for the specified character range.
Here is a sample code :
Getting Color from text
highlightColor = textLocation.getElement().getForegroundColor(textLocation.getStartOffset());
Applying color to text
textLocation.getElement().setForegroundColor(textLocation.getStartOffset(),textLocation.getEndOffsetInclusive(), highlightStyle);
I hope it helps. Goodluck :)
Try
textLocation.getElement().editAsText().deleteText(textLocation.getStartOffset(),textLocation.getEndOffsetInclusive());
textLocation.getElement().editAsText().insertText(textLocation.getStartOffset(),"Some text");
The .editAsText() puts you into editing the contents of the rich text leaving the existing attributes as a 'wrapper'
Alternatively, try replacing the text rather than deleting and inserting
paras[i].replaceText("allowance", "some text") // the first attribute is a regular expression as string
I have just tested this and it seems that setting LINK_URL alongside other attributes interferes with FOREGROUND_COLOR.
The following results in a black text color:
var attrs = {
"FOREGROUND_COLOR": "#ff0000", // should be red
"LINK_URL": null
};
text.setAttributes(start, end, attrs);
The following results in a red text color:
var attrs = {
"FOREGROUND_COLOR": "#ff0000" // should be red
};
text.setAttributes(start, end, attrs);
In effect, if you don't need to set the link, remove the LINK_URL from the list of formatting options.
#JSDBroughton Gave me an idea, which worked.
Try setting the attributes of the rich text object you get when calling editAsText. So instead of:
highlightStyle = textLocation.getElement().getAttributes(textLocation.getStartOffset());
textLocation.getElement().setAttributes(textLocation.getStartOffset(),textLocation.getEndOffsetInclusive(), highlightStyle);
Do:
// Make sure you replace `asParagraph` with what you actually need
highlightStyle = textLocation.getElement().asParagraph().editAsText().getAttributes(textLocation.getStartOffset());
textLocation.getElement().asParagraph().editAsText().setAttributes(textLocation.getStartOffset(),textLocation.getEndOffsetInclusive(), highlightStyle);
Edit: after playing around with this, seems like this only sometimes works. I still haven't figured out the pattern for when it does work and when it doesn't.

Controlling Carat in as3 with setSelection

Ok I took some time and figured out to my surprise.
and unfortunately I couldn't just use standard arrow keys. Im making a simulator of a label maker and it has to work to the letter, arrow keys, and everthing.
var boop = textSelect.text.length;
var snoop = boop;
bbbutton.addEventListener(MouseEvent.CLICK, backBtns);
function backBtns(event:MouseEvent):void
{
snoop -= 1;
stage.focus = textSelect;
textSelect.setSelection( snoop,snoop);
}
You can accomplish this by using a textField's caretIndex property.
Assuming textSelect is a TextInput component, if it's a textField, just remove the .textField property from the lines below.
//this gets the current caret position, and subtracts one (if not already at 0)
var pos:int = textSelect.textField.caretIndex > 0 ? textSelect.textField.caretIndex - 1 : 0;
//this sets the selection to adjusted caret postion
textSelect.setSelection(pos,pos);

Modify TLF Text Field properties that is on stage

I have a TLF Text field on the stage. I am trying to test this out in simple flash document.
My code takes in some xml that I parse. The xml will vary and will not always change all the properties of the text field. For instance in one case I only want to change the size of the font. In another case I only want to change the alignment of the font.
I am using TLF Text fields because we will translating into Arabic and I already have gotten Right to Left text working with them.
These are some properties I will need to edit in code:
Font Size
Font
Alignment
Leading
Bold, Italic, Underline (weight)
Any coding help would be great. I have seen ideas out there for text flow and text layout but I am obviously not using it correctly because I can't get it to work.
Long ago before I give up and stop using TLF fields. I have a project that requests dynamic addind and removing tlf fileds from/to stage. This is a code from this project:
This will generate default format dynamically
var config:Configuration = new Configuration();
var defTextFormat: TextLayoutFormat = new TextLayoutFormat();
defTextFormat.textAlign = TextAlign.LEFT;
defTextFormat.fontFamily = m_strFontName;
defTextFormat.fontSize = m_nFontSize;
defTextFormat.fontWeight = FontWeight.BOLD
defTextFormat.paddingLeft = 3;
defTextFormat.paddingTop = 3;
defTextFormat.paragraphStartIndent = 3;
defTextFormat.paragraphSpaceBefore = 3;
config.defaultLinkActiveFormat = defTextFormat;
config.defaultLinkHoverFormat = defTextFormat;
config.defaultLinkNormalFormat = defTextFormat;
config.textFlowInitialFormat = ITextLayoutFormat( defTextFormat );
m_textFlow = new TextFlow( config );
member m_textFlow holds a ref to TLF field.
To add and remove elements use m_textFlow.addChild( p ); where p is paragraph element
see: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flashx/textLayout/elements/ParagraphElement.html
To change the FontSize and color an element for example :
var _p:ParagraphElement = ParagraphElement( m_textFlow.getChildAt( iChild ) );
for ( var iParChild: uint = 0; iParChild < _p.numChildren; ++iParChild )
{
_p.getChildAt( iParChild ).color = color;
_p.getChildAt( iParChild ).fontSize = nRatio;
...
Maybe this can help you.

How to get a RadioButton's label height - AS3

I want to get radioButton's label height in as3.
I have 5 radio buttons in my radioButton group. One of those radioButtons has a three line label, another has a single line etc...
When I try to access the radioButton.height, I always get same value regardless of the label height.
I need to know the height of the label, so I can set the radioButton y coordinate accordingly.
can I change the radioButton's label height?
spacing = 30;
rb.label = tempQQString //from xml. long or short string anyone
rb.group = myGroup;
rb.value = i + 1;
rb.x = answerX;
rb.y = questionField.height + (questionY+20) + (i * spacing); // here use rb.height or rb.textField.height
trace("rb height**" + rb.height) // always get velue 22;
addChild(rb);
RadioButton and any fl control that extends labelButton (all the ones that have a label), expose the actual text field with the .textField property.
So for your example, instead of using rb.height, you would use rb.textField.height to get the height of just the label portion of the control.
You can also set properties on the textField as well.
rb.textField.background = true;
rb.textField.backgroundColor = 0xDDDDDD;
rb.textField.multiline = true;
rb.textField.wordWrap = true;
rb.textField.autoSize = TextFieldAutoSize.LEFT;
now, for your scenario, you may be better off just using the radio button's bounds instead, as it will be the REAL height of the object.
rb.getBounds(rb).height; //this will be the true height of the component.
If your label was one line and your icon was taller than your label, you could potentially be getting a value from rb.textField.height that is smaller than the real height of the radio button.
Try this.
for(var i=0;i<rb.numChildren;i++){
if(rb.getChildAt(i) is TextField){
var txt:TextField = rb.getChildAt(i) as TextField;
trace(txt.height+":"+rb.height);//traces the height of text field and radio button
}
}

Flex container with HTML style floating

I am using Flex 4 with Spark components to build a mobile application and I have a HGroup that I am using to contain all of my elements. When the screen loads it pulls in a small amount of text that will be displayed and loops through all the words to see if any of them are a keyword. While it is looping I am putting each word into its own label element and if the word is a keyword it changes a few styles and adds a click event to show a description about the word.
Everything runs fine but when everything is appended to the HGroup, there ends up being only one line and most of the text completely cut off because it will not wrap the content.
My Question is - Is there a way to set or extend the HGroup to allow content wrapping on its child elements?
Below are some code snippets of what I have:
MXML containers:
<s:VGroup id="answerData" width="580" height="700" horizontalAlign="center" paddingTop="5">
<s:HGroup id="theLabel" color="white" width="580" fontSize="25" paddingBottom="20" />
<s:HGroup id="theText" color="white" width="580" fontSize="25" maxWidth="580" />
</s:VGroup>
AS to create labels:
public static function setKeyWords(someText:String, theGroup:Group, theDictionary:Array, theView:Object):void {
theGroup.removeAllElements();
var textArray:Array = someText.split(' ');
for(var i:int = 0, l:int = textArray.length; i < l; i++) {
if(checkForWord(theDictionary, textArray[i].toString())) {
var theLink:Label = new Label();
theLink.text = textArray[i].toString();
theLink.setStyle("color", "0xFFFF00");
theLink.setStyle("fontWeight", "bold");
theLink.maxWidth = 580;
var tmpDescrip:String = theDescription;
theLink.addEventListener(MouseEvent.CLICK, function(evt:MouseEvent):void {
showToolTip(tmpDescrip, theView);
});
theGroup.addElement(theLink);
} else {
var someLabel:Label = new Label();
someLabel.maxWidth = 580;
someLabel.text = textArray[i].toString();
theGroup.addElement(someLabel);
}
}
}
The issue that I was having is, I had multiple lables in a VGroup and needed them to wrap instead of extending past the containers set width. I was trying to integrate keywords into a dynamic paragraph of text. I could not use mx:Text because I needed each word to be its own component that allowed custom styling plus a mouse click even if the word was a keyword. Also the label max lines solution would not work because I am dealing with multiple lables in a VGroup and the VGroup needed to wrap its children not the label tags. I also could not use a TileGroup because it does not look right breaking a paragraph into a table looking component where each word is in its own column/row.
The solution I used was to count each character in the label being generated and add it to a variable to determine when I need to create a new HGroup that holds the labels and sits in a VGroup. I had to do this because I cannot determine the labels width until it renders because it is generated dynamically. This could not be done because as its render point is too late for me to move everything because the user can see all of this happening which is definitely not the desired effect.
Below is the code I used to solve this issue incase anyone else runs into this issue:
public static function setKeyWords(someText:String, theGroup:Group, theDictionary:Array, theView:Object):void {
theGroup.removeAllElements();
var textArray:Array = someText.split(' ');
var theCount:int = 0;
var theHGroup:HGroup = new HGroup();
var breakNum:int = 40;
theHGroup.percentWidth = 100;
for(var i:int = 0, l:int = textArray.length; i < l; i++) {
theCount += textArray[i].toString().length;
if(theCount >= breakNum) {
theGroup.addElement(theHGroup);
theHGroup = new HGroup();
theHGroup.percentWidth = 100;
theCount = 0;
}
if(checkForWord(theDictionary, textArray[i].toString())) {
theCount += 1;
var theLink:Label = new Label();
theLink.text = textArray[i].toString();
theLink.setStyle("color", "0xFFFF00");
theLink.setStyle("fontWeight", "bold");
theLink.maxWidth = 580;
//theLink.includeInLayout = false;
var tmpDescrip:String = theDescription;
theLink.addEventListener(MouseEvent.CLICK, function(evt:MouseEvent):void {
showToolTip(tmpDescrip, theView, 'keywords');
});
theHGroup.addElement(theLink);
} else {
theCount += 1;
var someLabel:Label = new Label();
someLabel.maxWidth = 580;
someLabel.text = textArray[i].toString();
//someLabel.includeInLayout = false;
theHGroup.addElement(someLabel);
}
}
if(theCount > 0)
theGroup.addElement(theHGroup);
}
This may not be the most effecient way to do this but it does work and takes little time to execute on the Iphone which is what I was aiming for.
Not fully sure I understand your question.
If you mean the Label's are truncated, you might want to set a percentWidth and wrap Labels with maxDisplayedLines:
someLabel.maxDisplayedLines = 10;
If you mean you want columns and rows to your Group layout, use TileGroup / TileLayout.
If the children of your group contain composite content that must float, some kind of includeInLayout=false might help.
If you want text to show in block of several lines, use mx:Text with width set.
To display something above HGroup, easiest way is to leave HGroup alone and just make transparent container (Canvas) above it. There you'll be free to display anything (just do the math to position it correctly.)