Table of contents
- Find Cursor Position in a HtmlText Object (RichTextEditor, TextArea, TextField)
- Find Cursor Position in a HtmlText Object (RichTextEditor, TextArea, TextField) - UPDATE
In the previous article I came out with a function that calculates the position of the cursor in the htmlText which is different than the position in the normal text. Rick draw my attention in his comments to some flaws which are correct: the & and other similar special chars are not counted correctly and the new lines are replaced by <p> and not counted.
For this new article I studied the problem and remodeled the calculateHtmlPosition function from the previous post and now more than one type of tag opening and ending are possible (see openTags and closeTags arrays). Here it is (comments are in the code):
public function calculateHtmlPosition(htmlstr:String, pos:int):int { // we return -1 (not found) if the position is bad if (pos <= -1) return -1; // characters that appears when a tag starts var openTags:Array = ["<","&"]; // characters that appears when a tag ends var closeTags:Array = [">",";"]; // the tag should be replaced with // ex: & is & and has 1 as length but normal // tags have 0 length var tagReplaceLength:Array = [0,1]; // flag to know when we are inside a tag var isInsideTag:Boolean = false; var cnt:int = 0; // the id of the tag opening found var tagId:int = -1; var tagContent:String = ""; for (var i:int = 0; i < htmlstr.length; i++) { // if the counter passes the position specified // means that we reach the text position if (cnt>=pos) break; // current char var currentChar:String = htmlstr.charAt(i); // checking if the current char is in the open tag array for (var j:int = 0; j < openTags.length; j++) { if (currentChar == openTags[j]) { // set flag isInsideTag = true; // store the tag open id tagId = j; } } if (!isInsideTag) { // increment the counter cnt++; } else { // store the tag content // needed afterwards to find new lines tagContent += currentChar; } if (currentChar == closeTags[tagId]) { // we ad the replace length if (tagId > -1) cnt += tagReplaceLength[tagId]; // if we encounter the </P> tag we increment the counter // because of new line character if (tagContent == "</P>") cnt++; // set flag isInsideTag = false; // reset tag content tagContent = ""; } } // return de position in html text return i; }
The modified working example is bellow (pressing “Add _” button an underscore will be added at the cursor position):
Rick thanks for you comments and credit goes to you.
Future development can be done to be able to add over a selected part of text.
UPDATE: JBI had special situation and he explained it in his comment bellow, so please take a look - it may save you much trouble.
Popularity: 69%
| ||
|
Tags: ActionScript, htmltext, positioning, RichTextEditor
This post was written by Andrei Ionescu
Views: 5616



















I’ve been using a function similar to this at work for a few months now (shame on me for not sharing). You’ve also got to watch out for the LI tags (there are no ULs in flash’s htmlText, so you’re safe there) and BR tags (a lot of times these get converted to P tags, but they’re technically legal so if the HTMLtext is explicitly set they can persist). I can pass my function along if you’re interested in peeking at it (though it’s not nearly so well commented).
public static function getHtmlCaretPosition( target:UIComponent, caret:int ):int{
var range:TextRange = new TextRange( target, false, 0, caret );
var pattern:RegExp = /(.*?)(< \/([^<>]*>< \/[^<>]*)*>)/gm;
var cleanHtml:String = range.htmlText.replace( pattern, “$1″);
var htmlLength:int = cleanHtml.length-1;
return htmlLength;
}
His original comment is here.
Can u drag a UI control such as a Grid or canvas…etc and drop it in the RTE?
I’m just beginning my Flex experience, and was curious as to how you calculated the normal position? I’m working in a TextArea, not a RichTextEditor if that makes a difference. Thanks in advance.
For Justin: As you can see in the source file you cand use selection.beginIndex property of the RTE like this:
RTE.selection.beginIndexFrom what I can tell the values for norm pos and pos are incorrect. Maybe I’m interpreting these incorrectly?
If you place your cursor after the first “a” you will see pos is “1″ and norm pos is “118″, now turn on HTML view and count the number of characters including whitespace.
Am I missing something?
Maybe I don’t understand what you mean in you comment and if so please give me more info.
Hi. This is a great piece of code. I have one small ‘fix’ though.
I have the following tag:
<span class="charo_u68" id="txsr_a:2:{s:4:"bnlt";s:6:"e_LTnm";s:4:"bncp";s:3:"b_f";}">
Don’t ask why, it’s a complicated story
But this tag gets broken off, in the middle. Why? Because the code it recognizes a new tag and focuses on that.. So I’ve added two lines of code;
public function calculateHtmlPosition(htmlstr:String, pos:int):int
{
// we return -1 (not found) if the position is bad
if (pos < = -1)
return -1;
// characters that appears when a tag starts
var openTags:Array = ["<","&"];
// characters that appears when a tag ends
var closeTags:Array = [">“,”;”];
// the tag should be replaced with
// ex: & is & and has 1 as length but normal
// tags have 0 length
var tagReplaceLength:Array = [0,1];
// flag to know when we are inside a tag
var isInsideTag:Boolean = false;
var cnt:int = 0;
// the id of the tag opening found
var tagId:int = -1;
var tagContent:String = “”;
for (var i:int = 0; i < htmlstr.length; i++)
{
// if the counter passes the position specified
// means that we reach the text position
if (cnt>=pos)
break;
// current char
var currentChar:String = htmlstr.charAt(i);
// checking if the current char is in the open tag array
if(!isInsideTag)
{
for (var j:int = 0; j < openTags.length; j++)
{
if (currentChar == openTags[j])
{
// set flag
isInsideTag = true;
// store the tag open id
tagId = j;
}
}
}
if (!isInsideTag)
{
// increment the counter
cnt++;
} else {
// store the tag content
// needed afterwards to find new lines
tagContent += currentChar;
}
if (currentChar == closeTags[tagId]) {
// we ad the replace length
if (tagId > -1) cnt += tagReplaceLength[tagId];
// if we encounter the tag we increment the counter
// because of new line character
if (tagContent == ““) cnt++;
// set flag
isInsideTag = false;
// reset tag content
tagContent = “”;
}
}
// return de position in html text
return i;
}
This fixed my problem. My case is very rare (won’t probably occur in normal HTML), but there are other cases in which my fix might help