GWT: Putting raw HTML inside a Label - java

Is there a way to put raw HTML inside of a Label widget with GWT? The constructor and setText() methods automatically escape the text for HTML (so < appears as <, etc).
What I need is something like:
String matched = "two";
List<String> values = Arrays.asList("one", "two", "three");
StringBuilder sb = new StringBuilder();
for (String v : values){
if (v.equals(matched)){
sb.append("<b>" + v + "<b>");
} else {
sb.append(v);
}
sb.append(", ");
}
Label label = new Label();
label.setRawText(sb.toString());
//div contains the following HTML: "one, <b>two</b>, three, "
I want to output a comma-separated list of Strings, but I want one of those Strings to be bolded. Thanks.

Use the HTML class (Or more likely: The InlineHTML class instead of the Label class. InlineHTML works like label, except that you can give it html.
And just a security warning: if part of the input to your InlineHTML object is input by the user, remember to strip html out of that part, so users can't insert their own scripts into your code.

Sorry, I'm going to answer my own question because I found what I was looking for.
The SafeHtmlBuilder class is perfect for this. You tell it what strings you want to escape and what strings you do not want to escape. It works like StringBuilder because you call append methods:
String matched = "two";
List<String> values = Arrays.asList("one", "two", "three <escape-me>");
SafeHtmlBuilder builder = new SafeHtmlBuilder();
for (String v : values){
if (v.equals(matched)){
builder.appendHtmlConstant("<b>");
builder.appendEscaped(v);
builder.appendHtmlConstant("</b>");
} else {
builder.appendEscaped(v);
}
builder.appendEscaped(", ");
}
HTML widget = new HTML();
widget.setHTML(builder.toSafeHtml());
//div contains the following HTML: "one, <b>two</b>, three <escape-me>, "
Note that the appendHtmlConstant method expects a complete tag. So if you want to add attributes to the tag whose values change during runtime, it won't work. For example, this won't work (it throws an IllegalArgumentException):
String url = //...
SafeHtmlBuilder builder = new SafeHtmlBuilder();
builder.appendHtmlConstant("<a href=\""); //throws IllegalArgumentException
builder.appendEscaped(url);
builder.appendHtmlConstant("\">link</a>");

Either create a label and set it to bold:
Label label = new Label("text");
label.getElement().getStyle().setFontWeight(FontWeight.BOLD);
Or you can create a SpanElement and set its innerHtml.

Here's example to put a space in a widget, e.g. Label:
public void setTextNbsp( final Widget w ) {
w.getElement().setInnerHTML( " " );
}
Other HTML entities could be used as well. Take care with this not to open security holes. SafeHtml, etc. might need consideration if doing something more dynamic.

I think you should use SpanElement where you don't want the html to be escaped and label where you want then to be escaped and put them on a vertical panel so that they would appear as a single line of text.

Related

How to format Java Strings in the Java class not using the xml

I have a String array list set up to populate text to multiple intro screens. As the text is populated in the actualy Java class and not in the xml resource file I want to know how can I make certain words in the text bold from within the java class?
public String [] slide_descriptions = {
"I want this text in bold \n",
"and maybe this too!"
};
You can use Html tags. For example:
textView.setText(Html.fromHtml("< b >This is Bold< /b >"));
For String, do it like this:
public String [] slide_descriptions = {
"<b>I want this text in bold</b> \n",
"<b>and maybe this too!</b>"
};
So at the end when you put the string in the textview:
textView.setText(Html.fromHtml(slide_description));
See answer below: link
However in comment says that This will slow down performance.
You can use spannable string as it is easy and less costly
SpannableString spannableString = new SpannableString(yourstringhere);
spannableString.setSpan(new StyleSpan(Typeface.BOLD),indexStart,indexEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

How to verify the tooltip message in table using selenium webdriver?

I have to verify the tool tip message displayed in a table using selenium web driver.I have taken the actions class and used build.perform() but it returns an empty string. The problem is , html code is in such a way that the tool tip tags are incorporated with the span tag. Please let me know how to resolve this issue.
HTML code :
<span class="abcd" data-qtip="<table><tr><td>xxx as of 05/04/2017 </td><td>$1.00</td></tr><tr><td>yyy</td><td>$1.00</td></tr><tr><tdzzz</td><td>$0.00</td></tr><tr><td>xyz</td><td>0.00%</tr></td></table>"/>
xxx,yyy,zzz and xyz are the texts I need to verify.
Method I used:
public void mouseOver(String loc) {
Actions ToolTip1 = new Actions(driver);
WebElement pr = findElement(loc);
System.out.println(pr);
pause(2000);
ToolTip1.moveToElement(pr).perform();
pause(2000);
String toolTipMsg = pr.getText();
pause(1000);
System.out.println(toolTipMsg);
}
where loc = xpath of the element.
Any help on this is appreciated.
After doing mousehover to the webelement, use the getAttribute method to get the value of "data-qtip". Below line can help you.
String toolTip = driver.findElement(By.xpath("//span[#class='abcd']")).getAttribute("data-qtip").toString();
Store the expected message in another string and compare that with toolTip.
Since in this case, the string toolTip is in Html and we need to parse it to required format and compare it to the expected string. The below code parses the toolTip and gives the String which needs to be validated.
System.out.println(toolTip);
String[] word1 = toolTip.split("<td>");
String a = word1[1].split(" ")[0];
System.out.println(a);
String b = word1[3].split("</")[0];
System.out.println(b);
String c = word1[6].split("</")[0];
System.out.println(c);
String d = word1[4].split("<td")[1].split("<")[0];
System.out.println(d);
We can even parse it a better way but this works. Later validate a, b, c, d with the expected messages. Thanks
try this:
Actions ToolTip1 = new Actions(driver);
WebElement pr = findElement(loc);
System.out.println(pr);
ToolTip1.moveToElement(pr).perform();
pause(2000);
String toolTipMsg = driver.findElement(by.cssSelector("span.abcd")).getAttribute("data-qtip");
System.out.println(toolTipMsg);
I was looking for a better solution and i came up with this.
Step 1: Store the result in a string,
String Tooltip = driver.findElement(By.xpath("//span[#class='abcd']")).getAttribute("data-qtip").toString();
Step 2: Use some regex pattern to get the data only from "td" tags and add it to a ArrayList.
ArrayList<String> lists = new ArrayList<>();
Pattern p = Pattern.compile("(<td>(.*?)<\\/td>)");
Matcher m = p.matcher(toolTip);
while(m.find())
{
String tag2 = m.group(1);
String tag = tag2.substring(4,(tag2.length()-5)); //removes the <td> and </td> tags in the matched string
lists.add(tag);
System.out.println(tag);
}
Now the lists will have all the table data's. Iterate through the list elements and compare it to the expected String. Thanks.

how to replace a word with in contains() Method form a JtextPane

Well, I'm trying to replace a word by using contains() Method:
String z = tfB.getText().toString();
String show = textPane.getText().toString();
if(show.contains(z)){
// how I specify the word that were found and change it without
effecting anything with in that line
}
well what I main by that:
What I'm trying to do is get the value from the user.
then search if it found replace it with something. For example:
String x = "one two three four five";
It should set the textPane to "one two 3 four five"
or
"one two 3-three-3 four five"
could any one please tell me how to do it.
Thank you
What I'm trying to do is get the value from the user. then search if it found replace it with something.
Don't use the contains() method because you will need to search the text twice:
once to see if the text is found in the string
again to replace the text with a new string.
Instead, use the String.indexof(...) method. It will return the index of the text IF it is found in the String.
Then you should replace the text directly in the Document of the text pane, not in the String itself. So the code would be something like:
int length = textPane.getDocument().getLength();
String text = textPane.getDocument().getText(0, length);
String search = "abc...";
int offset = text.indexOf(search);
if (offset != -1)
{
textPane.setSelectionStart(offset);
textPane.setSelectionEnd(offset + search.length();
textPane.replaceSelection("123...");
}
Also, not that you get the text from the Document, not the text pane. This is to make sure the offsets are correct when you replace the text in the Document. Check out Text and New Lines for more information on why this is important.

JTextPane losing styling just after the text is displayed

I have a thread which functions as follows: characters are continuously entered, which are being stored in a StringBuilder. The contents of this string builder need to be styled according to some codes. As the character is appended in the string builder, I have a loop that splits this into an array of strings, and does some processing. Here is small (but complete in itself processing):
SimpleAttributeSet set = new SimpleAttributeSet();
if(string.contains(code1)){
str = string;
int index = string.indexOf(code1);
string = string.replaceAll(code1, "");
StyleConstants.setForeground(set, Color.GREEN);
// data is a another variable of string builder
data.append(string);
i = sb.indexOf(string);
String st = string.substring(index);
doc.setCharacterAttributes(data.indexOf(st), st.length(), set, true);
}
//similarly there are checks and styling for other codes
//terminalArea is of JTextPane type
terminalArea.setText(dataToShow.toString());
The text is colored correctly according to the codes, But as the data is displayed, the colors appear for an instant, and then lost. After that that, when a key is pressed, the colors appear again, but as the key is released, they lost.
I tried terminalArea.repaint(), but nothing happens.
Update:
With respect to StanislavL's answer, Here is what I am having now:
doc = new DefaultStyledDocument();
if(string.contains(code)){
str = string;
int index = string.indexOf(code);
string = string.replaceAll(code, "");
StyleConstants.setForeground(set, Color.GREEN);
dataToShow.append(string);
i = sb.indexOf(string);
String st = string.substring(index);
doc.setCharacterAttributes(dataToShow.indexOf(st), st.length(), set, true);
doc.insertString(doc.getLength() , string, null);
}
//after all conditions
terminalArea.setDocument(doc);
Though the color persists, but only that text is shown colored, which was colored last. The previous ones are shown in white.Please note, the whole string is not colored, only a part of it is colored.
Solved:
StanislavL's answer solved the problem. I overlooked this thing that I was setting the character attributes first, then inserting the array. Interchanging the position solved the issue.
I assume you use StyledEditorKit.
terminalArea.setText(dataToShow.toString());
The code just erases all you have and readd the text to the document. In fact in the document remove(0, docLength) is called and then insertString(theToStringResult) replaces all the styled.
I would recomment to create a new Document instance, insert all the texts with styled using insertString() where you can pass your attributes (or call insertString() just once and the call multiple times setCharacterAttributes()). After the Document instance is ready just call terminalArea.setDocument(theDocumentInstance); rather than setText();

How to design String decollator in a string contains many params

I need pass a string parameter that contains many params. When receive the parameter, I use String.split() to split it to get all the params.
But one promblem accured. How to design my string decollator so that any ASCII CODE on keyboard can be passed correctly.
Hope for any advice.
Maybe you could have a look at variadic arguments instead of splitting a string. For example:
public void method(String... strings) {
// strings is actually an array
String firstParam = strings[0];
String secondParam = strings[1];
// ...
}
Calling:
method("string1");
method("string1", "string2", "string3");
// as many string args as you want
If I understood correctly - you need to encode set of parameters to one string. You can use some sequence of characters for this purpose, E.g.
final String delimiter = "###"
String value = "param1###param2###param3";
String[] parameters = value.split(delimiter);
Choose a character which is easy to enter and unlikely to appear in the input. Let's assume that character is #.
Normal input would like like Item 1#Item 2#Item 3. Actually, you can .trim() every item and let the user enter Item 1 # Item 2 # Item 3 if s/he prefers.
However, like you describe, say the user would like to enter Item #1, Item #2, etc.. There are a few ways to let him/her do this, but the easier is to let them escape the delimiter. For example, instead of Item #1 # Item #2 # Item #3, which would result in 6 different items being found normally, let the user enter, for example Item ##1 # Item ##2 # Item ##3. Then in your parsing, make sure to handle the case when two or more #'s have been entered in a row. split likely won't be good enough, you'll have to go through the string yourself.
Here's a sketch of a method which would split the input string for you:
private static List<String> parseArguments(String input) {
ArrayList<String> arguments = new ArrayList<String>();
String[] prelArguments = input.split("#");
for (int i = 0; i < prelArguments.length; i++) {
String argument = prelArguments[i];
if (argument.equals("")) {
// We will enter here if there were two or more #'s in a row
StringBuilder combinedArgument = new StringBuilder(arguments.remove(arguments.size() - 1));
int inARow = 0;
while (prelArguments[i+inARow].equals("")) {
inARow++;
combinedArgument.append('#');
}
i += inARow;
combinedArgument.append(prelArguments[i]);
arguments.add(combinedArgument.toString());
} else {
arguments.add(argument);
}
}
return arguments;
}
Error handling, edge-case handling and some performance improvement is missing from the above, but I think the idea comes through.
I would eliminate the problem, which is the misuse of String as an argument container. If you need to pass more parameters, pass more parameters. If this gets out of hand, consider passing a map, or a custom object that can contain all the parameters.

Categories