diff --git a/framework/widget/src/main/java/org/apache/ofbiz/widget/WidgetWorker.java b/framework/widget/src/main/java/org/apache/ofbiz/widget/WidgetWorker.java index af342107d22..858c3a6b763 100644 --- a/framework/widget/src/main/java/org/apache/ofbiz/widget/WidgetWorker.java +++ b/framework/widget/src/main/java/org/apache/ofbiz/widget/WidgetWorker.java @@ -140,7 +140,6 @@ public static Element makeHiddenFormLinkAnchorElement(String linkStyle, String d final String href = "javascript:document." + makeLinkHiddenFormName(context, modelFormField) + ".submit()"; anchorElement.attr("href", href); - if (isNotEmpty(modelFormField.getEvent()) && isNotEmpty(modelFormField.getAction(context))) { anchorElement.attr(modelFormField.getEvent(), modelFormField.getAction(context)); } @@ -149,6 +148,22 @@ public static Element makeHiddenFormLinkAnchorElement(String linkStyle, String d anchorElement.attr("onclick", "return confirm('" + confirmation + "')"); } + int size = 0; + String title = request.getAttribute("title").toString(); + if (UtilValidate.isNotEmpty(request.getAttribute("descriptionSize"))) { + size = Integer.parseInt(request.getAttribute("descriptionSize").toString()); + } + + // if description is truncated, always use description as title + if (UtilValidate.isNotEmpty(description) && size > 0 && description.length() > size) { + title = description; + description = description.substring(0, size) + "…"; + } + + if (isNotEmpty(title)) { + anchorElement.attr("title", title); + } + anchorElement.text(description); if (isNotEmpty(request.getAttribute("image"))) { diff --git a/framework/widget/src/main/java/org/apache/ofbiz/widget/model/CommonWidgetModels.java b/framework/widget/src/main/java/org/apache/ofbiz/widget/model/CommonWidgetModels.java index b05c6314b05..0f1779d7060 100644 --- a/framework/widget/src/main/java/org/apache/ofbiz/widget/model/CommonWidgetModels.java +++ b/framework/widget/src/main/java/org/apache/ofbiz/widget/model/CommonWidgetModels.java @@ -330,6 +330,7 @@ public static final class Link { private final boolean encode; private final boolean fullPath; private final FlexibleStringExpander idExdr; + private final String title; private final Image image; private final String linkType; // anchor or hidden form private final FlexibleStringExpander nameExdr; @@ -352,6 +353,7 @@ public static final class Link { public Link(Element linkElement) { this.textExdr = FlexibleStringExpander.getInstance(linkElement.getAttribute("text")); this.idExdr = FlexibleStringExpander.getInstance(linkElement.getAttribute("id")); + this.title = linkElement.getAttribute("title"); this.styleExdr = FlexibleStringExpander.getInstance(linkElement.getAttribute("style")); this.nameExdr = FlexibleStringExpander.getInstance(linkElement.getAttribute("name")); this.targetExdr = FlexibleStringExpander.getInstance(linkElement.getAttribute("target")); @@ -426,6 +428,7 @@ public Link(GenericValue portalPage, List parameterList, String targe this.encode = false; this.fullPath = false; this.idExdr = FlexibleStringExpander.getInstance(""); + this.title = ""; this.image = null; this.linkType = ""; this.nameExdr = FlexibleStringExpander.getInstance(""); @@ -452,6 +455,7 @@ public Link() { this.encode = false; this.fullPath = false; this.idExdr = FlexibleStringExpander.getInstance(""); + this.title = ""; this.image = null; this.linkType = ""; this.nameExdr = FlexibleStringExpander.getInstance(""); @@ -510,6 +514,10 @@ public FlexibleStringExpander getIdExdr() { return idExdr; } + public String getTitle() { + return this.title; + } + public Image getImage() { return this.image; } diff --git a/framework/widget/src/main/java/org/apache/ofbiz/widget/model/ModelFormField.java b/framework/widget/src/main/java/org/apache/ofbiz/widget/model/ModelFormField.java index c1d16e3f26e..093f6c0a439 100644 --- a/framework/widget/src/main/java/org/apache/ofbiz/widget/model/ModelFormField.java +++ b/framework/widget/src/main/java/org/apache/ofbiz/widget/model/ModelFormField.java @@ -3018,6 +3018,14 @@ public FlexibleStringExpander getIdExdr() { return link.getIdExdr(); } + /** + * Gets title. + * @return the title + */ + public String getTitle() { + return link.getTitle(); + } + /** * Gets image. * @return the image diff --git a/framework/widget/src/main/java/org/apache/ofbiz/widget/renderer/macro/MacroFormRenderer.java b/framework/widget/src/main/java/org/apache/ofbiz/widget/renderer/macro/MacroFormRenderer.java index 38fb5ebfdda..5e5f4f42762 100644 --- a/framework/widget/src/main/java/org/apache/ofbiz/widget/renderer/macro/MacroFormRenderer.java +++ b/framework/widget/src/main/java/org/apache/ofbiz/widget/renderer/macro/MacroFormRenderer.java @@ -215,6 +215,7 @@ public void renderHyperlinkField(Appendable writer, Map context, this.request.setAttribute("imageTitle", encodedImageTitle); this.request.setAttribute("descriptionSize", hyperlinkField.getSize()); this.request.setAttribute("id", modelFormField.getCurrentContainerId(context)); + this.request.setAttribute("title", hyperlinkField.getTitle()); this.request.setAttribute("width", hyperlinkField.getWidth()); this.request.setAttribute("height", hyperlinkField.getHeight()); makeHyperlinkByType(writer, hyperlinkField.getLinkType(), modelFormField.getWidgetStyle(), hyperlinkField.getUrlMode(), @@ -2971,12 +2972,13 @@ public void makeHyperlinkString(Appendable writer, String linkStyle, String targ String event = ""; String action = ""; String imgSrc = ""; + String imgTitle = ""; String alt = ""; String id = ""; String uniqueItemName = ""; String width = ""; String height = ""; - String imgTitle = ""; + String title = ""; String hiddenFormName = WidgetWorker.makeLinkHiddenFormName(context, modelFormField); if (UtilValidate.isNotEmpty(modelFormField.getEvent()) && UtilValidate.isNotEmpty(modelFormField.getAction(context))) { event = modelFormField.getEvent(); @@ -2985,22 +2987,22 @@ public void makeHyperlinkString(Appendable writer, String linkStyle, String targ if (UtilValidate.isNotEmpty(request.getAttribute("image"))) { imgSrc = request.getAttribute("image").toString(); } - if (UtilValidate.isNotEmpty(request.getAttribute("alternate"))) { - alt = request.getAttribute("alternate").toString(); - } if (UtilValidate.isNotEmpty(request.getAttribute("imageTitle"))) { imgTitle = request.getAttribute("imageTitle").toString(); } - Integer size = Integer.valueOf("0"); + if (UtilValidate.isNotEmpty(request.getAttribute("alternate"))) { + alt = request.getAttribute("alternate").toString(); + } + int size = 0; if (UtilValidate.isNotEmpty(request.getAttribute("descriptionSize"))) { - size = Integer.valueOf(request.getAttribute("descriptionSize").toString()); + size = Integer.parseInt(request.getAttribute("descriptionSize").toString()); } + // if description is truncated, always use description as title if (UtilValidate.isNotEmpty(description) && size > 0 && description.length() > size) { - imgTitle = description; - description = description.substring(0, size - 8) + "..." + description.substring(description.length() - 5); - } - if (UtilValidate.isEmpty(imgTitle)) { - imgTitle = modelFormField.getTitle(context); + title = description; + description = description.substring(0, size) + "…"; + } else if (UtilValidate.isNotEmpty(request.getAttribute("title"))) { + title = request.getAttribute("title").toString(); } if (UtilValidate.isNotEmpty(request.getAttribute("id"))) { id = request.getAttribute("id").toString(); @@ -3037,8 +3039,10 @@ public void makeHyperlinkString(Appendable writer, String linkStyle, String targ sr.append(action); sr.append("\" imgSrc=\""); sr.append(imgSrc); - sr.append("\" title=\""); + sr.append("\" imgTitle=\""); sr.append(imgTitle); + sr.append("\" title=\""); + sr.append(title); sr.append("\" alternate=\""); sr.append(alt); sr.append("\" targetParameters=\""); diff --git a/framework/widget/src/main/java/org/apache/ofbiz/widget/renderer/macro/RenderableFtlFormElementsBuilder.java b/framework/widget/src/main/java/org/apache/ofbiz/widget/renderer/macro/RenderableFtlFormElementsBuilder.java index 5bde105eeaf..4a39a1b675a 100644 --- a/framework/widget/src/main/java/org/apache/ofbiz/widget/renderer/macro/RenderableFtlFormElementsBuilder.java +++ b/framework/widget/src/main/java/org/apache/ofbiz/widget/renderer/macro/RenderableFtlFormElementsBuilder.java @@ -414,12 +414,13 @@ public RenderableFtl hyperlinkMacroCall(String linkStyle, String targetType, Str String event = ""; String action = ""; String imgSrc = ""; + String imgTitle = ""; String alt = ""; String id = ""; String uniqueItemName = ""; String width = ""; String height = ""; - String imgTitle = ""; + String title = ""; String hiddenFormName = WidgetWorker.makeLinkHiddenFormName(context, modelFormField); if (UtilValidate.isNotEmpty(modelFormField.getEvent()) && UtilValidate.isNotEmpty(modelFormField.getAction(context))) { @@ -429,23 +430,21 @@ public RenderableFtl hyperlinkMacroCall(String linkStyle, String targetType, Str if (UtilValidate.isNotEmpty(request.getAttribute("image"))) { imgSrc = request.getAttribute("image").toString(); } - if (UtilValidate.isNotEmpty(request.getAttribute("alternate"))) { - alt = request.getAttribute("alternate").toString(); - } if (UtilValidate.isNotEmpty(request.getAttribute("imageTitle"))) { imgTitle = request.getAttribute("imageTitle").toString(); } + if (UtilValidate.isNotEmpty(request.getAttribute("alternate"))) { + alt = request.getAttribute("alternate").toString(); + } Integer size = Integer.valueOf("0"); if (UtilValidate.isNotEmpty(request.getAttribute("descriptionSize"))) { size = Integer.valueOf(request.getAttribute("descriptionSize").toString()); } if (UtilValidate.isNotEmpty(description) && size > 0 && description.length() > size) { - imgTitle = description; - description = description.substring(0, size - 8) + "..." - + description.substring(description.length() - 5); - } - if (UtilValidate.isEmpty(imgTitle)) { - imgTitle = modelFormField.getTitle(context); + title = description; + description = description.substring(0, size) + "…"; + } else if (UtilValidate.isNotEmpty(request.getAttribute("title"))) { + title = request.getAttribute("title").toString(); } if (UtilValidate.isNotEmpty(request.getAttribute("id"))) { id = request.getAttribute("id").toString(); @@ -463,7 +462,8 @@ public RenderableFtl hyperlinkMacroCall(String linkStyle, String targetType, Str .stringParameter("event", event) .stringParameter("action", action) .stringParameter("imgSrc", imgSrc) - .stringParameter("title", imgTitle) + .stringParameter("imgTitle", imgTitle) + .stringParameter("title", title) .stringParameter("alternate", alt) .mapParameter("targetParameters", parameterMap) .stringParameter("linkUrl", linkUrl.toString()) diff --git a/framework/widget/src/test/java/org/apache/ofbiz/widget/renderer/macro/MacroFormRendererTest.java b/framework/widget/src/test/java/org/apache/ofbiz/widget/renderer/macro/MacroFormRendererTest.java index a30fb15b01f..03daf5ddf99 100644 --- a/framework/widget/src/test/java/org/apache/ofbiz/widget/renderer/macro/MacroFormRendererTest.java +++ b/framework/widget/src/test/java/org/apache/ofbiz/widget/renderer/macro/MacroFormRendererTest.java @@ -887,6 +887,57 @@ public void renderSortFieldUsesQueryString(@Mocked ModelForm modelForm) throws I "linkUrl", new FreemarkerRawString(linkFromQbeString))); } + @Test + public void hyperlinkFieldMacroRenderedTitleNotTruncated(@Mocked ModelFormField.HyperlinkField hyperlinkField) throws IOException { + final String description = "DESCRIPTION"; + final String title = "TITLE"; + + new Expectations() { + { + hyperlinkField.getDescription(withNotNull()); result = description; + hyperlinkField.getTarget(withNotNull()); result = "#"; + request.getAttribute("title"); result = title; + } + }; + + macroFormRenderer.renderHyperlinkField(appendable, new HashMap<>(), hyperlinkField); + assertAndGetMacroString("makeHyperlinkString", ImmutableMap.of("description", description, "title", title)); + } + + @Test + public void hyperlinkFieldMacroRenderedTruncatedNoTitle(@Mocked ModelFormField.HyperlinkField hyperlinkField) throws IOException { + final String description = "DESCRIPTION"; + + new Expectations() { + { + hyperlinkField.getDescription(withNotNull()); result = description; + hyperlinkField.getTarget(withNotNull()); result = "#"; + request.getAttribute("descriptionSize"); result = 5; + } + }; + + macroFormRenderer.renderHyperlinkField(appendable, new HashMap<>(), hyperlinkField); + assertAndGetMacroString("makeHyperlinkString", ImmutableMap.of("description", "DESCR…", "title", description)); + } + + @Test + public void hyperlinkFieldMacroRenderedTruncatedWithTitle(@Mocked ModelFormField.HyperlinkField hyperlinkField) throws IOException { + final String description = "DESCRIPTION"; + final String title = "TITLE"; + + new Expectations() { + { + hyperlinkField.getDescription(withNotNull()); result = description; + hyperlinkField.getTarget(withNotNull()); result = "#"; + hyperlinkField.getTitle(); result = title; + request.getAttribute("descriptionSize"); result = 5; + } + }; + + macroFormRenderer.renderHyperlinkField(appendable, new HashMap<>(), hyperlinkField); + assertAndGetMacroString("makeHyperlinkString", ImmutableMap.of("description", "DESCR…", "title", description)); + } + private String assertAndGetMacroString(final String expectedName) { return assertAndGetMacroString(expectedName, ImmutableMap.of()); } diff --git a/themes/common-theme/template/macro/HtmlFormMacroLibrary.ftl b/themes/common-theme/template/macro/HtmlFormMacroLibrary.ftl index 6b13c4d42a4..21b08ca3832 100644 --- a/themes/common-theme/template/macro/HtmlFormMacroLibrary.ftl +++ b/themes/common-theme/template/macro/HtmlFormMacroLibrary.ftl @@ -735,7 +735,7 @@ Parameter: delegatorName, String, optional - name of the delegator in context. <#if confirmation?has_content> onclick="return confirm('${confirmation?js_string}')"> <#if imgSrc?has_content>${description} -<#macro makeHyperlinkString hiddenFormName imgSrc title alternate linkUrl description linkStyle="" event="" action="" targetParameters="" targetWindow="" confirmation="" uniqueItemName="" height="" width="" id=""> +<#macro makeHyperlinkString hiddenFormName imgSrc imgTitle title alternate linkUrl description linkStyle="" event="" action="" targetParameters="" targetWindow="" confirmation="" uniqueItemName="" height="" width="" id=""> <#if uniqueItemName?has_content> <#local params = "{"presentation": "layer""> <#if targetParameters?has_content && !targetParameters?is_hash> @@ -760,7 +760,7 @@ Parameter: delegatorName, String, optional - name of the delegator in context. <#if action?has_content && event?has_content> ${event}="${action}" <#if confirmation?has_content> data-confirm-message="${confirmation}" <#if id?has_content> id="${id}" - <#if imgSrc?length == 0 && title?has_content> title="${title}"> - <#if imgSrc?has_content>${alternate}${description?html} + <#if title?has_content> title="${title}"> + <#if imgSrc?has_content>${alternate}title="${imgTitle}"/>${description?html}