Java Wicket标签中的嵌套链接
我想知道这样的事情在wicket是否可行:Java Wicket标签中的嵌套链接,java,wicket,Java,Wicket,我想知道这样的事情在wicket是否可行: <span wicket:id="label"><a wicket:id="link"></a></span> 链接可以呈现在标签的所需位置(无需拆分) 例如,考虑下面的标签:“链接[玫瑰] [链接]是红色的” 如果“The”和“are red”是动态的,我们必须使用多个标签: <span wicket:id="firstPartLabel"/><a wicket:id="link
<span wicket:id="label"><a wicket:id="link"></a></span>
链接可以呈现在标签的所需位置(无需拆分)
例如,考虑下面的标签:“链接[玫瑰] [链接]是红色的”
如果“The”和“are red”是动态的,我们必须使用多个标签:
<span wicket:id="firstPartLabel"/><a wicket:id="link"/><span wicket:id="lastPartLabel">
这是相当丑陋的,我们不能插入链接,所以,考虑到标签
${link}是红色的
并用正确的链接替换占位符
感谢Wicket消息支持您所寻找的内容:
如果您想做的是类似于Twitter的标签/用户名链接(处理纯文本并添加到特殊片段的链接),您可以扩展标签来实现这一点。只需搜索文本中的特殊单词(这里我使用了regex模式,但您可以使用任何其他方法),并将它们替换为链接的HTML 在本例中,
isInternalRef
创建指向Ajax行为的链接。它还可以用于创建指向资源、页面和其他类型组件的链接(有些处理直接链接,有些不处理)
这个类是一个非常简单的例子,它并不打算支持Twitter的所有语法
public class TweetLabel extends Label {
private static final Pattern USERNAME_HASHTAG_PATTERN = Pattern.compile("\\B([@#*])([a-zA-Z0-9_]+)", Pattern.CASE_INSENSITIVE);
private transient CharSequence body;
public TweetLabel(String id) {
super(id);
}
public TweetLabel(String id, String label) {
super(id, label);
}
public TweetLabel(String id, Serializable label) {
super(id, label);
}
public TweetLabel(String id, IModel<?> model) {
super(id, model);
}
protected void onLinkClicked(AjaxRequestTarget target, String word) {
target.appendJavaScript("alert('You clicked on \"" + JavaScriptUtils.escapeQuotes(word) + "\", and the server knows...');");
}
@Override
protected void onConfigure() {
super.onConfigure();
// process text here, because we can add behaviors here, but not at onComponentTagBody()
body = processText(getDefaultModelObjectAsString());
}
@Override
public void onComponentTagBody(MarkupStream markupStream, ComponentTag openTag) {
replaceComponentTagBody(markupStream, openTag, body);
}
/**
* based on Matcher.replaceAll()
*/
private CharSequence processText(String text) {
Matcher m = USERNAME_HASHTAG_PATTERN.matcher(text);
boolean result = m.find();
if (result) {
StringBuffer sb = new StringBuffer();
do {
final String replacement = getLinkedTextAndAddBehavior(text, m.start(), m.end());
m.appendReplacement(sb, replacement);
result = m.find();
} while (result);
m.appendTail(sb);
return sb;
}
return text;
}
private String getLinkedTextAndAddBehavior(String fullText, int start, int end) {
final String matchedString = fullText.substring(start, end);
final int length = matchedString.length();
final String prefix = matchedString.substring(0, 1);
final String identifier = matchedString.substring(1, length);
final boolean isUsername = prefix.equals("@");
final boolean isHashtag = prefix.equals("#") && (start == 0 || fullText.charAt(start - 1) != '&');
final boolean isInternalRef = prefix.equals("*");
final String replacement;
if (isUsername) {
final String url = "https://twitter.com/" + identifier;
replacement = "<a href='" + url + "'>" + matchedString + "</a>";
} else if (isHashtag) {
final String url = "https://twitter.com/search?src=hash&q=" + UrlEncoder.QUERY_INSTANCE.encode(matchedString, "UTF-8");
replacement = "<a href='" + url + "'>" + matchedString + "</a>";
} else if (isInternalRef) {
final LinkedWordBehavior behavior = getOrAddBehavior(new LinkedWordBehavior(identifier));
final String rawFunction = behavior.getCallbackScript().toString();
replacement = String.format("<a href='#' onclick='%s;return false;'>%s</a>", rawFunction, matchedString);
} else {
replacement = matchedString;
}
return replacement;
}
/**
* Verify if the behavior was already added, add if not.
*/
private LinkedWordBehavior getOrAddBehavior(LinkedWordBehavior behavior) {
final List<LinkedWordBehavior> behaviors = getBehaviors(LinkedWordBehavior.class);
final int index = behaviors.indexOf(behavior);
if (index > -1) {
return behaviors.get(index);
} else {
add(behavior);
return behavior;
}
}
private final class LinkedWordBehavior extends AbstractDefaultAjaxBehavior {
private final String word;
public LinkedWordBehavior(String word) {
this.word = word;
}
@Override
protected void respond(AjaxRequestTarget target) {
final String word = TweetLabel.this.getRequest().getRequestParameters().getParameterValue("word").toString();
if (!Strings.isEmpty(word)) {
TweetLabel.this.onLinkClicked(target, word);
}
}
protected void updateAjaxAttributes(AjaxRequestAttributes attributes) {
super.updateAjaxAttributes(attributes);
attributes.getExtraParameters().put("word", word);
}
@Override
public int hashCode() {
return word.hashCode();
}
@Override
public boolean equals(Object obj) {
return word.equals(((LinkedWordBehavior) obj).word);
}
}
}
公共类TweetLabel扩展标签{
私有静态最终模式USERNAME\u HASHTAG\u Pattern=Pattern.compile(\\B([@#*])([a-zA-Z0-9++),模式。不区分大小写);
私有瞬态序列体;
公共TweetLabel(字符串id){
超级(id);
}
公共TweetLabel(字符串id、字符串标签){
超级(id、标签);
}
公共TweetLabel(字符串id,可序列化标签){
超级(id、标签);
}
公共TweetLabel(字符串id,IModel模型){
超级(id,型号);
}
受保护的void onLinkClicked(AjaxRequestTarget目标,字符串字){
appendJavaScript(“警报('您单击\”“+JavaScriptUtils.escapeQuotes(word)+”“\”,服务器知道…);”;
}
@凌驾
配置()上受保护的空{
super.onConfigure();
//在此处处理文本,因为我们可以在此处添加行为,但不能在onComponentTagBody()处添加行为
body=processText(getDefaultModelObjectAsString());
}
@凌驾
ComponentTagBody(MarkupStream MarkupStream,ComponentTag openTag)上的公共空白{
replaceComponentTagBody(标记上游、openTag、body);
}
/**
*基于Matcher.replaceAll()
*/
私有字符序列processText(字符串文本){
Matcher m=用户名\标签\模式。Matcher(文本);
布尔结果=m.find();
如果(结果){
StringBuffer sb=新的StringBuffer();
做{
最终字符串替换=GetLinkedTextAndBehavior(text,m.start(),m.end());
m、 替换(sb,替换);
结果=m.find();
}而(结果);
m、 (某人);
归还某人;
}
返回文本;
}
私有字符串GetLinkedTextAndBehavior(字符串全文、整数开始、整数结束){
final String matchedString=fullText.substring(开始、结束);
final int length=matchedString.length();
最终字符串前缀=matchedString.substring(0,1);
最终字符串标识符=matchedString.substring(1,长度);
最终布尔值isUsername=前缀.equals(“@”);
最终布尔值isHashtag=prefix.equals(“#”)&&(start==0 | | fullText.charAt(start-1)!='&');
最终布尔值isInternalRef=前缀。等于(“*”);
最终管柱更换;
if(isUsername){
最终字符串url=”https://twitter.com/“+标识符;
替换=”;
}else if(isHashtag){
最终字符串url=”https://twitter.com/search?src=hash&q=“+UrlEncoder.QUERY_INSTANCE.encode(匹配字符串,“UTF-8”);
替换=”;
}else if(isInternalRef){
最终LinkedWordBehavior=GetOradBehavior(新LinkedWordBehavior(标识符));
最后一个字符串rawFunction=behavior.getCallbackScript().toString();
replacement=String.format(“”,rawFunction,matchedString);
}否则{
替换=匹配字符串;
}
退换货;
}
/**
*验证是否已添加行为,如果未添加,请添加。
*/
私有LinkedWordBehavior getOrAddBehavior(LinkedWordBehavior){
最终列表行为=getBehaviors(LinkedWordBehavior.class);
最终int索引=behaviors.indexOf(behavior);
如果(索引>-1){
返回行为。获取(索引);
}否则{
添加(行为);
回归行为;
}
}
私有最终类LinkedWordBehavior扩展了AbstractDefaultAjaxBehavior{
私有最后字符串字;
公共LinkedWordBehavior(字符串字){
这个单词=单词;
}
@凌驾
受保护的无效响应(AjaxRequestTarget目标){
最后一个字符串word=TweetLabel.this.getRequest().getRequestParameters().getParameterValue(“word”).toString();
if(!Strings.isEmpty(word)){
TweetLabel.this.onLinkClicked(target,word);
}
}
受保护的void updateAjaxAttributes(AjaxRequestAttributes){
super.updateAjaxAttributes(attributes);
attributes.getExtraParameters().put(“word”,word);
}
@凌驾
公共int hashCode(){
返回word.hashCode();
}
@凌驾
公共布尔等于(对象obj){
返回word.equals(((LinkedWordBehavior)obj.word);
}
}
}
更新了将示例更改为使用行为处理ajax请求。还有其他方法可以做到这一点。例如,您可以有一个单一的行为来处理所有链接,或者使用一个资源,但这种方式在我看来更干净
LinkLabel myLabel = new LinkLabel("description",
"First ${link} second", "my link", new ILinkListener() {
private static final long serialVersionUID = 1L;
@Override
public void onLinkClicked() {
// Your desired onClick action
}
});
public class LinkLabel extends Panel {
private static final long serialVersionUID = 1L;
public LinkLabel(String id, String model, String linkName,
ILinkListener linkListener) {
super(id);
setRenderBodyOnly(true);
String[] split = model.split("\\$\\{link\\}");
if (split.length == 2) {
Label first = new Label("first", split[0]);
Label second = new Label("second", split[1]);
add(first);
add(second);
add(generateLink(linkListener, linkName));
} else if (split.length == 1) {
Label first = new Label("first", split[0]);
Label second = new Label("second");
second.setVisible(false);
add(first);
add(second);
add(generateLink(linkListener, linkName));
} else {
throw new UnsupportedOperationException(
"LinkLabel needs the ${link} placeholder!");
}
}
private Link<?> generateLink(final ILinkListener linkListener,
String linkName) {
Label linkLabel = new Label("linkLabel", linkName);
Link<String> link = new Link<String>("link") {
private static final long serialVersionUID = 1L;
@Override
public void onClick() {
linkListener.onLinkClicked();
}
};
link.add(linkLabel);
return link;
}
}
<wicket:panel>
<span wicket:id="first"></span>
<a wicket:id="link"><span wicket:id="linkLabel"></span></a>
<span wicket:id="second"></span>
</wicket:panel>
<span wicket:id="mylabel"><u>Lorem ipsum dolor</u></span>
this.createLink("mylabel", "The", "ROSES", "are red", "https://testurl.com");
}
private Void createLink(String label, String textBefore, String textLink, String textAfter, String url)
{
String htmlLink = "<a href='" + url + "'>" + textLink + "</a>";
String labelText = textBefore + htmlLink + textAfter;
this.add(new Label(label, labelText).setEscapeModelStrings(false));
}