如何计算h:outputLink被点击的次数?
How to count the number of times a h:outputLink was clicked?
我有一个包含以下代码的 PrimeFaces 页面:
<pm:content id="content">
<p:dataList value="#{likeditems.likedItems}" var="item" pt:data-inset="true" paginator="true" rows="5">
<f:facet name="header">
Products you liked in the past
</f:facet>
<h:outputLink value="#{item.url}" target="_new">
<p:graphicImage name="http://example.com/my-product-mobile/f/op/img/underConstructionImage.jpg" />
<h2>#{item.title}</h2>
<p>Approx. #{item.price} (for most up-to-date price, click on this row and view the vendor's page)</p>
</h:outputLink>
<f:facet name="footer">
Products you liked in the past
</f:facet>
</p:dataList>
</pm:content>
当用户点击 h:outputLink
时,我希望发生两件事:
- 在浏览器中打开了 URL
item.url
的新页面。
- 方法
likeditems.itemLinkClicked(item)
被调用(在该方法中我更新了特定 link 被点击的次数)。
第一件事已经开始工作 (target="_new"
)。
如何在第一个停止工作的情况下实现第二个(更新 link 被点击次数的方法调用)?
First thing is already working (target="_new"
).
The target should actually be _blank
.
How can I implement the second one (method call for updating the number of times the link was clicked) without the first ceasing to work?
最简单(幼稚)的 JSF 式方法是在点击时触发 <p:remoteCommand>
。
<h:outputLink value="#{item.url}" target="_blank" onclick="count_#{item.id}()">
...
</h:outputLink>
<p:remoteCommand name="count_#{item.id}" action="#{likeditems.itemLinkClicked(item)}" />
但是这样会产生很多重复的JS代码,效果不是很好。您可以将它放在数据列表之外,并使用函数参数 fiddle 。但是,当最终用户右键单击并选择上下文菜单项(在新选项卡中打开、新 window、新隐身 window、另存为、复制地址等)时,这仍然不起作用。这在最终用户 middleclicks 时也不起作用(middleclick 的默认浏览器行为是 "open in a new window")。
在 ZEEF,我们使用的脚本将点击、中键点击或右键点击时的 <a href>
更改为 URL,后者会调用更新计数的 servlet,然后执行window.open()
在给定的 URL 上。
给定一个
<h:outputLink value="#{item.url}" styleClass="tracked" target="_blank">
相关脚本基本上应该是这样的:
// Normal click.
$(document).on("click", "a.tracked", function(event) {
var $link = $(this);
updateTrackedLink($link);
var trackingURL = $link.attr("href");
$link.attr("href", $link.data("href"));
$link.removeData("href");
window.open(trackingURL);
event.preventDefault();
});
// Middle click.
$(document).on("mouseup", "a.tracked", function(event) {
if (event.which == 2) {
updateTrackedLink($(this));
}
});
// Right click.
$(document).on("contextmenu", "a.tracked", function(event) {
updateTrackedLink($(this));
});
// Update link href to one of click count servlet, if necessary.
function updateTrackedLink($link) {
if ($link.data("href") == null) {
var url = $link.attr("href");
$link.data("href", url);
$link.attr("href", "/click?url=" + encodeURIComponent(url));
}
}
点击 servlet 应如下所示(为简洁起见省略了请求参数验证):
@WebServlet("/click")
public class ClickServlet extends HttpServlet {
@EJB
private ClickService clickService;
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String url = request.getParameter("url");
clickService.incrementClickCount(url);
response.sendRedirect(url);
}
}
请注意,这样就不需要 target="_blank"
。它只会被禁用 JavaScript 的用户使用。但是网站上还有很多其他东西无论如何都不起作用,包括上面的 JS 跟踪。这也是您真正关心的,那么您最好直接将点击 servlet URL 放在 <h:outputLink value>
.
中
我有一个包含以下代码的 PrimeFaces 页面:
<pm:content id="content">
<p:dataList value="#{likeditems.likedItems}" var="item" pt:data-inset="true" paginator="true" rows="5">
<f:facet name="header">
Products you liked in the past
</f:facet>
<h:outputLink value="#{item.url}" target="_new">
<p:graphicImage name="http://example.com/my-product-mobile/f/op/img/underConstructionImage.jpg" />
<h2>#{item.title}</h2>
<p>Approx. #{item.price} (for most up-to-date price, click on this row and view the vendor's page)</p>
</h:outputLink>
<f:facet name="footer">
Products you liked in the past
</f:facet>
</p:dataList>
</pm:content>
当用户点击 h:outputLink
时,我希望发生两件事:
- 在浏览器中打开了 URL
item.url
的新页面。 - 方法
likeditems.itemLinkClicked(item)
被调用(在该方法中我更新了特定 link 被点击的次数)。
第一件事已经开始工作 (target="_new"
)。
如何在第一个停止工作的情况下实现第二个(更新 link 被点击次数的方法调用)?
First thing is already working (
target="_new"
).
The target should actually be _blank
.
How can I implement the second one (method call for updating the number of times the link was clicked) without the first ceasing to work?
最简单(幼稚)的 JSF 式方法是在点击时触发 <p:remoteCommand>
。
<h:outputLink value="#{item.url}" target="_blank" onclick="count_#{item.id}()">
...
</h:outputLink>
<p:remoteCommand name="count_#{item.id}" action="#{likeditems.itemLinkClicked(item)}" />
但是这样会产生很多重复的JS代码,效果不是很好。您可以将它放在数据列表之外,并使用函数参数 fiddle 。但是,当最终用户右键单击并选择上下文菜单项(在新选项卡中打开、新 window、新隐身 window、另存为、复制地址等)时,这仍然不起作用。这在最终用户 middleclicks 时也不起作用(middleclick 的默认浏览器行为是 "open in a new window")。
在 ZEEF,我们使用的脚本将点击、中键点击或右键点击时的 <a href>
更改为 URL,后者会调用更新计数的 servlet,然后执行window.open()
在给定的 URL 上。
给定一个
<h:outputLink value="#{item.url}" styleClass="tracked" target="_blank">
相关脚本基本上应该是这样的:
// Normal click.
$(document).on("click", "a.tracked", function(event) {
var $link = $(this);
updateTrackedLink($link);
var trackingURL = $link.attr("href");
$link.attr("href", $link.data("href"));
$link.removeData("href");
window.open(trackingURL);
event.preventDefault();
});
// Middle click.
$(document).on("mouseup", "a.tracked", function(event) {
if (event.which == 2) {
updateTrackedLink($(this));
}
});
// Right click.
$(document).on("contextmenu", "a.tracked", function(event) {
updateTrackedLink($(this));
});
// Update link href to one of click count servlet, if necessary.
function updateTrackedLink($link) {
if ($link.data("href") == null) {
var url = $link.attr("href");
$link.data("href", url);
$link.attr("href", "/click?url=" + encodeURIComponent(url));
}
}
点击 servlet 应如下所示(为简洁起见省略了请求参数验证):
@WebServlet("/click")
public class ClickServlet extends HttpServlet {
@EJB
private ClickService clickService;
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String url = request.getParameter("url");
clickService.incrementClickCount(url);
response.sendRedirect(url);
}
}
请注意,这样就不需要 target="_blank"
。它只会被禁用 JavaScript 的用户使用。但是网站上还有很多其他东西无论如何都不起作用,包括上面的 JS 跟踪。这也是您真正关心的,那么您最好直接将点击 servlet URL 放在 <h:outputLink value>
.