2015-01-07 2 views
1

У меня есть страница PrimeFaces с помощью следующего кода:Как подсчитать количество раз h: outputLink был нажат?

<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, я хочу 2 вещи происходят:

  1. Новая страница с URL item.url открыт в браузере ,
  2. Вызывается метод likeditems.itemLinkClicked(item) (в этом методе я обновляю количество раз, когда была нажата конкретная ссылка).

Первое, что уже работает (target="_new").

Как я могу реализовать второй (вызов метода для обновления количества раз, когда ссылка была нажата) без первого прекращения работы?

ответ

2

Первое, что уже работает (target="_new").

The target should actually be _blank.


Как я могу реализовать второй (вызов метода для обновления несколько раз ссылка была нажата) без первого переставая работать?

Самый простой (наивный) 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-кода, который не очень эффективен. Вы можете вывести его за пределы списка данных и поиграть с аргументами функции. Но это все равно не сработает, когда enduser правильно щелкнет и выберет пункт контекстного меню (откройте в новой вкладке, в новом окне, новом окне инкогнито, сохраните как, адрес копирования и т. Д.). Это также не будет работать, когда enduser endclicks (поведение браузера по умолчанию для middleclick «открыто в новом окне»).

В ZEEF мы используем скрипт, который меняет <a href> на клик, middleclick или RightClick к URL, который вызывает сервлет, который обновляет счетчик, а затем делает 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)); 
    } 
} 

и нажмите сервлет должен выглядеть следующим образом (проверка запроса параметров для краткости опускаем):

@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.Это также является вашей заботой, тогда вам лучше просто поместить этот URL-адрес сервлета прямо в <h:outputLink value>.