I'm having an issue with applying textformat to various parts of a string:
feedBackText = "This is <b>bold</b>, and this is some more text, and <b>this is bold too</b>. But this is not bold. This is <b>bold</b>!";
feedbackTextField.htmlText = feedBackText;
var startBoldPos:int = 0;
var closeBoldPos:int = 0;
var i:uint = 0;
while(true) {
startBoldPos = feedBackText.indexOf("<b>", startBoldPos);
closeBoldPos = feedBackText.indexOf("</b>", startBoldPos);
if(startBoldPos > 0) {
i++;
// Here is the main trouble:
feedbackTextField.setTextFormat(_boldFormat, startBoldPos-((7)*i), closeBoldPos-((10)*i));
trace("i is: " + i);
trace("Feedbacktext: " + feedBackText);
trace("Start bold: " + startBoldPos);
trace("End bold: " + closeBoldPos + "\n");
} else {
// This works as expected
feedbackTextField.setTextFormat(_boldFormat, startBoldPos, closeBoldPos-3);
// trace("Feedbacktext: " + feedBackText);
// trace("Start bold: " + startBoldPos);
// trace("End bold: " + closeBoldPos + "\n");
}
if(startBoldPos == -1) break;
startBoldPos = closeBoldPos;
}
I'm trying to play around with the index of where the setTextFormat should be assigned, but it doesn't seem to align with startBoldPos and endBoldPos. Even if the traces are showing the correct numbers of where to place setTextFormat it in the string.
Any ideas would be apppreciated!
Regards,
Hans Magnus
I tested your code and it works as expected. I don't fully understand what you trying to do, so here some general remarks:
You can set some formatting without setTextFormat only with htmlText. After assigning text with html tags textField text will be already partly formatted.
setTextFormat works with text property, so start and end index calculated depend on text without html tags. In your case it will be: This is bold, and this is some more text, and this is bold too. But this is not bold. This is bold!
And tracing your code step by step:
1) Setting text with to htmlText property in TextField. After this TextField contained:
This is bold, and this is some more text, and this is bold too. But this is not bold. This is bold!
2) Loop starts. First iteration:
startBoldPos-((7)*i) = 1
closeBoldPos-((10)*i) = 5
TextField: This is bold, and this is some more text, and this is bold too. But this is not bold. This is bold!
3) Second iteration:
startBoldPos-((7)*i) = 39
closeBoldPos-((10)*i) = 52
TextField: This is bold, and this is some more text, and this is bold too. But this is not bold. This is bold!
4) Third iteration:
startBoldPos-((7)*i) = 87
closeBoldPos-((10)*i) = 85
Nothing changed bacause endPosition < startPosition.
5) Fourth iteration:
startBoldPos = -1
closeBoldPos-3 = 12
TextField: This is bold, and this is some more text, and this is bold too. But this is not bold. This is bold!
And final result on screenshot:
UPDATE (formatting without setTextFormat method):
...
[Embed(source="GOTHIC.TTF", fontName="Gothic", embedAsCFF="false", advancedAntiAliasing="true")]
private var gothicFont:Class;
[Embed(source="GOTHICB.TTF", fontName="Gothic", embedAsCFF="false", advancedAntiAliasing="true", fontWeight="bold")]
private var gothicFontBold:Class;
...
var feedBackText:String = "This is <b>bold</b>, and this is some more text, and <b>this is bold too</b>. But this is not bold. This is <b>bold</b>!";
var feedbackTextField:TextField = new TextField();
feedbackTextField.defaultTextFormat = new TextFormat("Gothic", 14);
feedbackTextField.embedFonts = true;
feedbackTextField.width = 500;
feedbackTextField.htmlText = feedBackText;
And result (with embed font as you see):
Related
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.
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.
I have :
$scope.text = "<b>TESTNAME</b>"; (This can be any string. This is to specify that there can be html tags written as text in the string.)
The bold tags are part of text and need to be displayed as text only and not HTML.
Now suppose someone enters a search string(for eg.. anyone can enter any string) :
$scope.searchTerm = "NAME";
Then i want that $scope.text gets modified such that i see <b>TESTNAME</b> but with the substring of "NAME" highlighted.
My highlight function does :
$scope.text = $scope.text.replace(new RegExp("(" + $scope.searchTerm + ")","gi"), "<span class='highlighted'>\$1</span>");
and in the HTML I had to write :
<span ng-bing-html="text"></span>
However, the issue now arises is that, the <b> and </b> also get rendered in the HTML form and bold the string in between.
How can this be handled?
EDIT
In order to avoid the b tags from rendering as HTML, I modified the angular brackets to their HTML counterparts using this :
$scope.text = $scope.text.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
after using the first replace function mentioned above. Now when the $scope.text is rendered using ng-bing-html, the b tags are only rendered as text.
However, now the span tags added are also rendered as text as angular brackets have been replaced globally.
EDIT
Another way to deal with the problem was that i replaced the angular tags before adding the span tags to highlight the text. So my highlight function was :
$scope.text = $scope.text.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
$scope.searchTerm = $scope.searchTerm.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
$scope.text = $scope.text.replace(new RegExp("(" + $scope.searchTerm + ")","gi"), "<span class='highlighted'>\$1</span>");
However, the issue with this is that if the user searches for the string lt or gt,then due to the replacements done for < and >, the highlight spans are added to these too and the net result is not as expected.
Please check working example: DEMO
Controller:
var app = angular.module('plunker', ["ngSanitize"]);
app.controller('MainCtrl', function($scope) {
$scope.searchTerm = "NAME";
$scope.content = "TESTNAME";
$scope.matchClass = 'bold';
var re = new RegExp($scope.searchTerm, 'g');
$scope.content = $scope.content.replace(re, '<span class="' + $scope.matchClass + '">' + $scope.searchTerm + '</span>');
});
HTML
<body ng-controller="MainCtrl">
<p ng-bind-html="content"></p>
</body>
CSS
.bold {
font-weight: bold;
}
Edit: new solution:
$scope.text = $scope.text.replace(new RegExp("(" + $scope.searchTerm + ")","gi"), "long-random-string-one$1long-random-string-two");
// Any encoding goes here
$scope.text = $scope.text.replace("long-random-string-one", "<span class='highlighted'>").replace("long-random-string-two", "</span>")
The idea is to insert two strings that won't be changed by the encoding, and are unique enough that they are extremely unlikely to be present in the text you are searching. Replace them with GUIDs if you want.
I want to build an InDesign script which when you import html tags such as bold and italics, those words are converted to bold or italics.
e.g.
I really like <strong>walking to the park</strong> and eating icecream would be:
I really like walking to the park and eating icecream.
However, In my textframe I can only get a whole paragraph to pick up a style and not individual words or phrases.
In the example below, I would want to apply a bold style to the secondPhrase variable (I have no problem stripping out the tags etc - just want to know how I can apply a style to JUST the secondPhrase
with (myElement) {
// Apply basic text style
applyParagraphStyle(myDoc.paragraphStyles.item("DefaultText"));
var firstPhrase = "I really like";
var secondPhrase = " walking to the park";
var thirdPhrase = " and eating icecream";
contents = firstLine + secondLine + thirdPhrase;
}
Something like the code below should do the trick. The insertionPoint acts just like the cursor in InDesign. If you keep grabbing the last insertionPoint you can change it's style while you are adding text.
var doc = app.documents.add();
var frame = doc.pages[0].textFrames.add({
geometricBounds: [6, 6, 40, 40]
});
var bold = doc.characterStyles.add({ name: "Bold", fontStyle: "Bold" });
var none = doc.characterStyles.itemByName("[None]");
frame.insertionPoints.lastItem().applyCharacterStyle(none);
frame.insertionPoints.lastItem().contents = "I really like";
frame.insertionPoints.lastItem().applyCharacterStyle(bold);
frame.insertionPoints.lastItem().contents = " walking to the park";
frame.insertionPoints.lastItem().applyCharacterStyle(none);
frame.insertionPoints.lastItem().contents = " and eating icecream";
Here's a DRY-er take on Josh's solution -- insertion points are the way to go. If you need to manipulate, mirror, or are working with dynamic JSON content / want to separate out your text, you'll need to run it through a loop, and simply assign your chunks of text as objects. This makes it much easier to swap out text and make use of some things like Array.prototype.reverse(), which I needed to use in my case.
Here's my take on it:
// Basic Setup
var doc = app.documents.add();
var myPage = doc.pages.item(0); // Arbitrary page
// Character-Styles
var bold = doc.characterStyles.add({ name: "Bold", fontStyle: "Bold" });
var none = doc.characterStyles.itemByName("[None]");
// My String as an Array of Objects (Basic JSON format)
var myStringsAndStyles = [
{
contents: "I really like",
characterStyle: none
},
{
contents: " walking to the park ",
characterStyle: bold
},
{
contents: "and eating ice cream.",
characterStyle: none
}
];
// Do stuff
with ( myPage) {
var myTextFrame = textFrames.add({
geometricBounds: [6, 6, 40, 40] // Arbitrary coords
});
with ( myTextFrame.insertionPoints ) {
for ( var i = 0, arrlength = myStringsAndStyles.length; i < arrlength; i++ ) {
lastItem().properties = {
contents: myStringsAndStyles[i].contents,
appliedCharacterStyle: myStringsAndStyles[i].characterStyle
}
}
}
}
Ta da!
Let's say you want to use a single label whose text changes in real-time, based on the value of a variable, which is pretty easy to do in AS3. But let's say you want part of the text to be in regular font-weight, and you want the other part to be in bold. I'm assuming a TextArea with an htmlText value is necessary, to maintain the bold / not bold parts within the single label, but I don't see how to make the data in there change, based upon a variable, like you can with an ordinary text attribute.
How can this be done?
var firstPart:String = "someText";
var boldPart:String = "this is bold";
text.htmlText = firstPart + "<b>" + boldPart + "</b>";
You can also use setTextFormat to make only a part of a text in a textfield bold:
var tf:TextFormat = new TextFormat();
tf.bold = true;
textField.setTextFormat(tf,10,20); // makes chars from 10 to 20 bold