page not in open in new window - jsf

I am using PrimeFaces 5.1 with PrettyFaces for rewrite URL in my project. I face one problem in PrettyFaces. E.g in same (same window PrettyFaces) view open the page fine. But using menuitem click open page new window time page not show shown so PrettyFaces not working.
I try below code:
prettyface.xml
<url-mapping id="studenFaceId">
<pattern value="/BSCMain" />
<view-id value="/pages/bsc/bscMain.xhtml"/>
</url-mapping>
javascript
function NewWindow(mypage,myname)
{
params = 'width='+screen.width;
params += ', height='+screen.height;
params += ', top=0, left=0';
params +=', scrollbars=yes';
newwin=window.open(mypage,myname, params);
if (window.focus)
{
newwin.focus()
}
return false;
}
xhtml
<p:menuitem id="dashBoard" ajax="false" value="student"
onclick="return NewWindow('./../bsc/bscMain.xhtml','BSCMain');"
update="main"/>
My doubt I use same window prettyface work fine but in same to open new window time prettyface not working it will shown only a empty page.

You should use the pretty URL instead of some relative view id in your JavaScript. Something like:
<p:menuitem id="dashBoard" ajax="false" value="student"
onclick="return NewWindow('#{request.contextPath}/BSCMain','BSCMain');"
update="main"/>

Related

non-ajax call not working in moved DOM

due to some other reasons moved some part of DOM into other place by using JQuery, in this moved DOM i have one non-ajax button its not working now.
below is the moving code
var duplicateOverCount = 1;
var duplicateOverPandata;
var duplicateOverRecdata;
function duplicateScrOvrPanFix() {
while (duplicateOverCount < 2) {
duplicateOverPandata = $('.duplicatSrcOverLaySty')[0];
duplicateOverRecdata = $('.duplicateSrcRecordsSty')[0];
$('.duplicatSrcOverLaySty').remove();
$('.duplicateSrcRecordsSty').remove();
duplicateOverCount++;
}
$(duplicateOverPandata).appendTo('.frozencolDatatabe');
$(duplicateOverRecdata).prependTo('.frozencolDatatabe');
}
Below is non-ajax call button, it need download file. i'm using primefaces 6
<p:commandButton
value="exportExcel"
ajax="false" action="#{xyzMBean.abc}" onclick="bypassLocking();">
<p:fileDownload
value="#{reportMBean.streamedContent}" />
</p:commandButton>

How to refresh page after f:actionlistener event

Working with JSF, I have a <ux:confirm> tag, which has a confirm button. When clicked it triggers a actionListenerEvent. The page and the objects in the faces context are updated, however I have a bootstrap accordion which is not updated. A solution would be refreshing the page, which is my question.
<ux:confirm
ok="#{message.get('Label.Sim')}"
ajax="true"
render="form-consulta"
cancel="#{message.get('Label.Nao')}"
title="#{message.get('Label.Excluir')}"
message="#{message.get('Msg.DesejaExcluirRegistro')}"
>
<f:actionListener
for="onOkClick"
binding="#{bean.excluir()}"
/>
</ux:confirm>
Ok, solved by just adding a JavaScript function on the ajax event and also calling somewhat a template method using javascript.
<f:ajax
render="#{cc.attrs.render}"
disabled="#{not cc.attrs.ajax}"
onevent="onEventConfirm"
/>
function onEventConfirm(data) {
App.ajax.onEvent(App.view.block, null, null, App.view.unblock);
var status = data.status;
switch (status) {
case "complete":
if(shouldRefreshAfterConfirmation)
this.location.reload();
break;
}
}

Pretty not reWrite URL in new window

I am using Primefaces 5.1 with JSF and PrettyFaces.In commandlink to press open page in new window at the page open new window fine but the rewrite URL is not working.
Javascript
var newwin=null;
function NewWindow(mypage,myname)
{
params = 'width='+screen.width;
params += ', height='+screen.height;
params += ', top=0, left=0';
//params +=', scrollbars=yes,menubar=yes,toolbar=yes';
params +=', scrollbars=yes';
newwin=window.open(mypage,myname, params);
if (window.focus)
{
newwin.focus()
}
return false;
}
</script>
Xhmtl
<p:commandLink value="Link" ajax="false" onclick="return
NewWindow('#{request.contextPath}/pages/student/userMain.xhtml','user');"/>
prettyConfig.xml
<url-mapping id="user">
<pattern value="/user" />
<view-id value="/faces/pages/student/userMain.xhtml"/>
</url-mapping>
My doubt is in same window URL reWrite is works fine but in new window not working it show given full path then how reWrite URL in new window.In above code to need any other changes to reWrite how to show in new Window.

How to count the number of times a h:outputLink was clicked?

I have a PrimeFaces page with following code:
<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>
When the user clicks on the h:outputLink, I want 2 things to happen:
A new page with URL item.url is opened in the browser.
Method likeditems.itemLinkClicked(item) is invoked (in that method I update the number of times a particular link was clicked).
First thing is already working (target="_new").
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?
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?
The simplest (naive) JSF-ish way would be triggering a <p:remoteCommand> on click.
<h:outputLink value="#{item.url}" target="_blank" onclick="count_#{item.id}()">
...
</h:outputLink>
<p:remoteCommand name="count_#{item.id}" action="#{likeditems.itemLinkClicked(item)}" />
But this generates lot of duplicate JS code which is not very effective. You could put it outside the data list and fiddle with function arguments. But this still won't work when the enduser rightclicks and chooses a context menu item (open in new tab, new window, new incognito window, save as, copy address, etc). This also won't work when the enduser middleclicks (default browser behavior of middleclick is "open in a new window").
At ZEEF we're using a script which changes the <a href> on click, middleclick or rightclick to an URL which invokes a servlet which updates the count and then does a window.open() on the given URL.
Given a
<h:outputLink value="#{item.url}" styleClass="tracked" target="_blank">
the relevant script should basically look like this:
// 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));
}
}
and the click servlet should look like this (request parameter validation omitted for brevity):
#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);
}
}
Note that this way the target="_blank" isn't necessary. It would only be used by users who have JavaScript disabled. But then many more other things on the website wouldn't work anyway, including the above JS tracking. It this is also really your concern, then you'd better just put that click servlet URL directly in <h:outputLink value>.

How to do double-click prevention in JSF

We have a few search pages that run against a lot of data and take a while to complete. When a user clicks on the search button, we'd like to not allow them to submit the search result a second time.
Is there a best practice for doing "double-click" detection/prevention in JSF?
The PrimeFaces component seems like it can do what we want as it will disable the UI for a period of time between when the search button is clicked and when the search completes, but is there a more generic strategy we can use (perhaps something that isnt reliant on PrimeFaces)? Ideally, any click of the button will either be disabled or disregarded until the search completes. We dont necessarily need to disable the entire UI (as blockUI allows you to do).
If you're using solely ajax requests, you could use jsf.ajax.addOnEvent handler of the JSF JavaScript API for this. The below example will apply on all buttons of type="submit".
function handleDisableButton(data) {
if (data.source.type != "submit") {
return;
}
switch (data.status) {
case "begin":
data.source.disabled = true;
break;
case "complete":
data.source.disabled = false;
break;
}
}
jsf.ajax.addOnEvent(handleDisableButton);
Alternatively, if you need this on specific buttons only, use the onevent attribute of <f:ajax>.
<h:commandButton ...>
<f:ajax ... onevent="handleDisableButton" />
</h:commandButton>
If you also need to apply this on synchronous requests, then you need to take into account that when you disable a button during onclick, then the button's name=value pair won't be sent as request parameter and hence JSF won't be able to identify the action and invoke it. You should thus only disable it after the POST request has been sent by the browser. There is no DOM event handler for this, you'd need to use the setTimeout() hack which disables the button ~50ms after click.
<h:commandButton ... onclick="setTimeout('document.getElementById(\'' + this.id + '\').disabled=true;', 50);" />
This is only rather brittle. It might be too short on slow clients. You'd need to increase the timeout or head to another solution.
That said, keep in mind that this only prevents double submits when submitting by a web page. This does not prevent double submits by programmatic HTTP clients like URLConnection, Apache HttpClient, Jsoup, etc. If you want to enforce uniqueness in the data model, then you should not be preventing double submits, but preventing double inserts. This can in SQL easily be achieved by putting an UNIQUE constraint on the column(s) of interest.
See also:
Pure Java/JSF implementation for double submit prevention
How to handle multiple submits before response is rendered?
You can use 'onclick' and 'oncomplete' listeners. When user click on button - disable it. When action completed - enable.
<p:commandButton id="saveBtn"
onclick="$('#saveBtn').attr('disabled',true);"
oncomplete="$('#saveBtn').attr('disabled',false);"
actionListener="#{myBean.save}" />
i came upon this question, having the same problem. The solution did not work for me - after a brief look at primefaces.js i guess they do not use jsf.ajax there anymore.
so i had to work something out myself and here is my solution, for people who also can not use the one in the answer by BalusC:
// we override the default send function of
// primeFaces here, so we can disable a button after a click
// and enable it again after
var primeFacesOriginalSendFunction = PrimeFaces.ajax.AjaxUtils.send;
PrimeFaces.ajax.AjaxUtils.send = function(cfg){
var callSource = '';
// if not string, the caller is a process - in this case we do not interfere
if(typeof(cfg.source) == 'string') {
callSource = jQuery('#' + cfg.source);
callSource.attr('disabled', 'disabled');
}
// in each case call original send
primeFacesOriginalSendFunction(cfg);
// if we disabled the button - enable it again
if(callSource != '') {
callSource.attr('disabled', 'enabled');
}
};
None of alternatives above has worked for me (I've really tried each one of them). My form was always sent twice when user double-clicked the login button. I'm working with JSF (Mojarra 2.1.6) on Glassfish 3.1.2.
Consider that it was a non-AJAX login page.
So here's the way I solved it:
define a global JavaScript var to control submition in the page header or anywhere outside your form:
var submitting = false;
set it to true when submit h:form onsubmit event is fired:
<h:form onsubmit="submitting = true">
Check the var's value on h:commandLink's click event:
<h:commandLink ... onclick="if(submitting){return false}">
This is just another simple alternative and it was tested in Chrome [Version 47.0.2526.106 (64-bit)], Mozilla Firefox (37.0.2) and Internet Explorer 11. I hope it helps someone.
For me works this way:
<h:commandLink ... onclick="jQuery(this).addClass('ui-state-disabled')">
PrimeFaces 12 and up
From PrimeFaces 12, p:commandButtons are disabled by default when they trigger an Ajax request. The button is enabled again when the Ajax request is finished.
To disable this default behavior, use disableOnAjax="false".
See a demo at: https://www.primefaces.org/showcase/ui/button/commandButton.xhtml
PrimeFaces 11 and lower
The approach by BalusC is great, but if you are using PrimeFaces you'll run into styling issues. Because some classes are not toggled, the button will not look disabled.
If you are looking for a solution which takes care of styling as well, you can replace the CommandButtonRenderer with one that disables the button on click using the button's widget to disable and enable it.
PrimeFaces Extensions 8 or up contains such a renderer. You can add this to your faces-config.xml like:
<render-kit>
<renderer>
<component-family>org.primefaces.component</component-family>
<renderer-type>org.primefaces.component.CommandButtonRenderer</renderer-type>
<renderer-class>org.primefaces.extensions.renderer.CommandButtonSingleClickRenderer</renderer-class>
</renderer>
</render-kit>
You can see it in action in the showcase.
If you cannot or don't want to use PFE, you can add the render class to your project by getting it from:
https://github.com/primefaces-extensions/primefaces-extensions/blob/master/core/src/main/java/org/primefaces/extensions/renderer/CommandButtonSingleClickRenderer.java
Note: this still requires you to add the renderer to your faces-config.xml.
See also
How to use resolveWidgetVar before PrimeFaces 8?
very useful solution jsf-primefaces, used with facelets template spreads to other pages consumers
<f:view>
<Script language="javascript">
function checkKeyCode(evt)
{
var evt = (evt) ? evt : ((event) ? event : null);
var node = (evt.target) ? evt.target : ((evt.srcElement) ? evt.srcElement : null);
if(event.keyCode==116)
{
evt.keyCode=0;
return false
}
}
document.onkeydown=checkKeyCode;
function handleDisableButton(data) {
if (data.source.type != "submit") {
return;
}
switch (data.status) {
case "begin":
data.source.disabled = true;
break;
case "complete":
data.source.disabled = false;
break;
}
}
jsf.ajax.addOnEvent(handleDisableButton);
</Script>
</f:view>
<h:head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link href="./resources/css/default.css" rel="stylesheet" type="text/css" />
<link href="./resources/css/cssLayout.css" rel="stylesheet" type="text/css" />
<title>infoColegios - Bienvenido al Sistema de Administracion</title>
</h:head>
<h:body onload="#{login.validaDatos(e)}">
<p:layout fullPage="true">
<p:layoutUnit position="north" size="120" resizable="false" closable="false" collapsible="false">
<p:graphicImage value="./resources/images/descarga.jpg" title="imagen"/>
<h:outputText value="InfoColegios - Bienvenido al Sistema de Administracion" style="font-size: large; color: #045491; font-weight: bold"></h:outputText>
</p:layoutUnit>
<p:layoutUnit position="west" size="175" header="Nuestra InstituciĆ³n" collapsible="true" effect="drop" effectSpeed="">
<p:menu>
<p:submenu>
<p:menuitem value="Quienes Somos" url="http://www.primefaces.org/showcase-labs/ui/home.jsf" />
</p:submenu>
</p:menu>
</p:layoutUnit>
<p:layoutUnit position="center">
<ui:insert name="content">Content</ui:insert>
</p:layoutUnit>
</p:layout>
</h:body>
Did a simple work with hide and show, works well with element having input type submit Jquery
$(":submit").click(function (event) {
// add exception to class skipDisable
if (!$(this).hasClass("skipDisable")) {
$(this).hide();
$(this).after("<input type='submit' value='"+$(this).val()+"' disabled='disabled'/>");
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js"></script>
<form>
<input type="submit" value="hello">
</form>
I addressed this issue by simply hiding the button after clicking it:
<p:commandButton... onclick="jQuery(this).css('visibility','hidden')" />

Resources