How to create a button in JSF page with custom label - jsf

I have this simple JSF button:
//Question Dialog
function deletedialog(button, a){
$("<div />", {
text: a
}).dialog({
width: 600,
buttons: {
"Ok": function() {
$("#form\\:deleterow").click();
// $('input[id$="deleterow"]').click();
$(this).dialog("close");
button.value = "Processing...";
button.disabled = true;
},
"Cancel": function(event) {
$(this).dialog("close");
event.preventDefault();
button.value = "Delete";
button.disabled = false;
}
}
});
}
<!-- hidden button -->
<h:commandButton id="deleterow" value="HiddenDelete" action="#{AccountsController.deleteSelectedIDs}" style="display:none">
<f:ajax render="#form"></f:ajax>
</h:commandButton>
<!-- the delete button -->
<h:button onclick="deletedialog(this, 'Do you want to delete the selected rows?'); return false;" >
<h:graphicImage name="small-hover.png" library="images" title="Delete" />
</h:button>
I want to create png image which will be the visual body of the button. The only thing that I will change will be the title of the button which I will set every time using the value attribute of the button. Is this possible? Now when I load the JSF page I see only empty button without label.
P.S 1 I get this result:

Use a command link that will wrap your image:
<script type="text/javascript">
function deletedialog(button, a) {
$("<div />", {
text: a
}).dialog({
width: 600,
buttons: {
"Ok": function() {
//$("#form\\:deleterow").click();
//using the hidden button click
document.getElementById('myForm:deleterow').click();
// $('input[id$="deleterow"]').click();
$(this).dialog("close");
button.value = "Processing...";
button.disabled = true;
},
"Cancel": function(event) {
$(this).dialog("close");
event.preventDefault();
button.value = "Delete";
button.disabled = false;
}
}
});
}
</script>
<h:form id="myForm">
<h:commandLink onclick="deletedialog(this, 'Do you want to delete the selected rows?')) return false;">
<h:graphicImage name="small-hover.png" library="images"
title="#{someBean.imageTitle}" />
</h:commandLink>
<h:commandButton id="deleterow" value="HiddenDelete" action="#{AccountsController.deleteSelectedIDs}" style="display:none">
<f:ajax render="#form" />
</h:commandButton>
</h:form>
Also, there is a good example of <h:graphicImage/> in mkyong site.
Based on your comments, it looks like you want to have a button with an icon. Also, the real action is performed by your hidden <h:commandButton>. so I recommend you to read this answer:
HTML / CSS How to add image icon to input type=“button”?
Your code would be like this:
<h:commandButton id="deleterow" value="HiddenDelete" action="#{AccountsController.deleteSelectedIDs}" style="display:none">
<f:ajax render="#form" />
</h:commandButton>
<button type="submit" onclick="deletedialog(this, 'Do you want to delete the selected rows?')) return false;"><img src="resources/images/small-hover.png" /> Delete</button>
Yes, you can mix basic HTML with JSF code, but read the link warning about this implementation on IE 6 browser clients.

I'd start from basics. Since you don't even see an image, when you right click on the browser window, and select 'view source' does it provide any meaningful information on whether the image is even being inserted onto the page? If you don't have the image path correct, it won't render the image on the page. That is the first thing to check and try to correct. (i.e. is the computer plugged in).

Related

p:graphicImage and Fancybox Integration

I'm using JSF 2.2 with PrimeFaces 5.3 under the GlassFish 4.1
Inside the application I use the approach to show the images from the database.
So that means I don't have an URL.
There're tons of example from this point of view, but I will paste here in order to be more useful.
Here the facelets
<p:graphicImage value="#{applicationScopedBean.imagesFromDb}" class="img">
<f:param name="imageId" value="#{actualAd.favouriteImageId}" />
<f:param name="cvlTimeStamp" value="#{now}" />
</p:graphicImage>
And here the Backing Bean
public StreamedContent getImagesFromDb() {
FacesContext context = FacesContext.getCurrentInstance();
if (context.getCurrentPhaseId() == PhaseId.RENDER_RESPONSE) {
// So, we're rendering the HTML. Return a stub StreamedContent so that it will generate right URL.
return new DefaultStreamedContent();
} else {
// So, browser is requesting the image. Return a real StreamedContent with the image bytes.
String imageId = context.getExternalContext().getRequestParameterMap().get("imageId");
return new DefaultStreamedContent(new ByteArrayInputStream(imageManager.getById(Long.valueOf(imageId)).getContent()));
}
}
Here an example of a the generated HTML code
<img src="/myWebApp/faces/javax.faces.resource/dynamiccontent.properties?ln=primefaces&v=5.3&pfdrid=GgwXKejrBbRvnC%2Fxp98FzlaymhDf7Gb%2BEVoD%2BlqKVRmYUBBZeMmjKw%3D%3D&pfdrt=sc&imageId=23&myTimeStamp=Sun+May+15+19%3A19%3A08+CEST+2016&pfdrid_c=true">
By design, in order to use the gallery that comes from fancybox we need a code similar to the following
<a class="fancybox" rel="group" href="resources/bootstrap/css/images/single/1.jpg">
<img id="img_01" alt="" class="raised" src="resources/bootstrap/css/images/single/1.jpg" style="width: 100%" />
But using graphicImages with streams, I don't have the link needed in the href value.
There's a chance to retrieve the generated image url?
Basically I need to retrieve the generated string used to fill the src attribute of the img tag.
Is it possible to solve the problem?
Thank you!
The solution is to mark every p:graphicImage and his h:outputLink with a custom id.
<c:forEach items="#{myController.images}" var="img" begin="0" class="hidden-xs" varStatus="loop">
<h:outputLink id="aInsideLightbox#{loop.index+1}" class="fancybox imgCVLGalleryDetail hidden-xs" rel="group">
<p:graphicImage id="imgInsideLightbox#{loop.index+1}" value="#{applicationScopedBean.imagesFromDb}" class="img">
<f:param name="imageId" value="#{img.imageWrapper.id}" />
</p:graphicImage>
</h:outputLink>
</c:forEach>
and then in the front-end side when the page is ready
<h:outputScript library="js" name="external.js"/>
<script>
$(document).ready(function () {
setUrlInTheFancyboxLinkAndImage();
setTypeImageInFancybox();
});
</script>
and in an external .js file the following functions.
function setUrlInTheFancyboxLinkAndImage() {
for (i = 0; i < 20; i++) {
$imgToImprove = document.getElementById("imgInsideLightbox" + i);
if ($imgToImprove !== null) {
$aToImprove = document.getElementById("aInsideLightbox" + i);
if ($aToImprove !== null) {
$aToImprove.setAttribute("href", $imgToImprove.getAttribute("src"));
}
}
}
}
function setTypeImageInFancybox() {
$(".fancybox").fancybox({
type: 'image',
openEffect: 'none',
closeEffect: 'none'
}); }

Problems with multiple actions in a JSF page

I have a JSF 2.2 + Primefaces 5 web application which contains an .xhtml with multiple possible outcomes:
<h:body>
<script type="text/javascript">
function download(file) {
document.forms[0].elements["filename"].value = file;
document.forms[0].submit();
}
function back() {
document.forms[0].method = "get";
document.forms[0].action = "home.xhtml";
document.forms[0].submit();
}
</script>
<form id="download" action="DownloadServlet" method="post">
. . . .
<h:commandButton id="back" value="Back" onclick="back();" />
<h:commandButton id="download" value="Download" type="Submit"
onclick="download('#{value}');" />
</form>
By clicking on the "Download" button, the Servlet "DownloadServlet" kicks in and downloads a file selected in the form.
However by clicking on the Back button, I'm not redirected to the page "home.xhtml". The Javascript function "back" simply is not invoked but the Servlet kicks again. It seems a conflict between the two actions. How can I solve it and add a button to return to another page ?
Thanks
Don't do it the hard way. Use a <h:button> to generate a GET button.
<h:button id="back" value="Back" outcome="home.xhtml" />
The second <h:commandButton> could better be just a plain vanilla <input type="submit">, by the way.

How to disable Choose button in PrimeFaces FileUpload until the upload is complete

Is it possible to block/disable the "Choose" button in FileUpload?
I use the p:fileUpload in advanced mode and set multiple="true". If I click on the Upload button to start the upload of all file, I want to prevent the adding of more files until all files are uploaded.
Version of PrimeFaces is 5.1.
Definition of p:fileUpload:
<p:fileUpload id="fileUpload" update=":form:uploadTable :msg :msgs" fileUploadListener="#{fileUploadBean.handleFileUpload}" mode="advanced" dragDropSupport="false"
multiple="true" sizeLimit="3221225472" fileLimit="100" style="margin:15px 0px;width:900px;" />
Workaround with p:blockUI
I found a workaround with using of blockUI element. So on start the blockUI is show and after all uploads are completed the blockUI is hide. For that javascript code is needed.
<p:fileUpload id="fileUpload" update=":form:uploadTable :msg :msgs" fileUploadListener="#{fileUploadBean.handleFileUpload}" mode="advanced" dragDropSupport="false"
multiple="true" sizeLimit="3221225472" fileLimit="100" style="margin:15px 0px;width:900px;"
onstart="setUploadFilesCount()" oncomplete="handleUploadComplete()" />
<p:blockUI block="fileUpload" widgetVar="wVarBFileUpload" />
Javascript Code:
<script type="text/javascript">
var fileCounter;
var numberOfFiles;
function setUploadFilesCount() {
PF('wVarBFileUpload').show();
fileCounter = 0;
numberOfFiles = $('.ui-fileupload-preview').size();
}
function handleUploadComplete() {
fileCounter++;
if(fileCounter == numberOfFiles) {
PF('wVarBFileUpload').hide();
}
}
</script>
You can use onstart and oncomplete to achieve this:
<p:fileUpload onstart="disableChoosing()"
oncomplete="enableChoosing()"
widgetVar="uploadWV"/>
<script>
function disableChoosing() {
PF('uploadWV').disableButton(PF('uploadWV').chooseButton);
PF('uploadWV').chooseButton.find('input[type="file"]').attr('disabled', 'disabled');
}
function enableChoosing() {
if(!PF('uploadWV').files.length) {
PF('uploadWV').enableButton(PF('uploadWV').chooseButton);
PF('uploadWV').chooseButton.find('input[type="file"]').removeAttr('disabled');
}
}
</script>

Radio buttons using twitter bootstrap - unable to get value

I've browsed SO, and found some answers that have guided me closer to getting working radio buttons, but I'm stuck now.
I have the buttons, but am unable to get the value of the selected one.
I'm using JSF, hence the #{searchFlightsBean.setDir()}
Here's what I currently have:
<h:panelGrid>
<div class="btn-group" data-toggle-name="is_private" data-toggle="buttons-radio" >
<button type="button" value="0" class="btn" data-toggle="button">Public</button>
<button type="button" value="1" class="btn" data-toggle="button">Private</button>
</div>
<h:inputHidden id="hiddenDir" value="0" valueChangeListener="#{searchFlightsBean.setDir()}" onchange="submit()"/>
</h:panelGrid>
<script>
$(function() {
$('div.btn-group[data-toggle-name]').each(function() {
var group = $(this);
var form = group.parents('form').eq(0);
var name = group.attr('data-toggle-name');
var hidden = $('input[name="' + name + '"]', form);
$('button', group).each(function() {
var button = $(this);
button.on('click', function() {
hidden.val($(this).val());
});
if (button.val() == hidden.val()) {
button.addClass('active');
#{searchFlightsBean.setDir(button.value)}
}
});
});
});
</script>
In my bean, when setDir() is called, I am logging the value that it receives, like so:
public void setDir(ValueChangeEvent e) {
this.dir = e.getNewValue().toString();
log.info("NEW DIRECTION: " + this.getDir());
}
It doesn't log - setDir() is never called. For some reason the valueChangeListener attribute on the h:inputHidden tag doesn't work. Am I missing something?
Your concrete problem is caused because you used valueChangeListener the wrong way.
<h:inputHidden ... valueChangeListener="#{searchFlightsBean.setDir()}">
This does not match the method signature. You should omit the parentheses ().
<h:inputHidden ... valueChangeListener="#{searchFlightsBean.setDir}">
Otherwise JSF expects an argumentless setDir() method. Then, you're nowhere in JavaScript triggering the change event on the input element. The onchange="submit()" is therefore never invoked. You should be doing hidden.trigger("change") in JS to achieve that.
But, after all, this is somewhat clumsy. You're sending a full synchronous request and your JS code is rather overcomplicated (and stops working once you ajax-update the form). Provided that you're indeeed using JSF 2.x, I suggest to bring in <f:ajax> — which unfortunately doesn't work in <h:inputHidden>, hence the <h:inputText style="display:none"> — and to make use of $.on() in jQuery to keep the functions working even when you ajax-update the DOM.
<h:form>
<div class="btn-group" data-toggle-name="is_private" data-toggle="buttons-radio" >
<button type="button" value="0" class="btn" data-toggle="button">Public</button>
<button type="button" value="1" class="btn" data-toggle="button">Private</button>
</div>
<h:inputText id="is_private" value="#{bean.dir}" style="display: none;">
<f:ajax listener="#{bean.changeDir}" />
</h:inputText>
<!-- Note: <h:inputText id> must be exactly the same as <div data-toggle-name> -->
</h:form>
<h:outputScript>
$(document).on("click", "[data-toggle=buttons-radio] button", function() {
var $button = $(this);
var id = $button.closest(".btn-group").attr("data-toggle-name");
var $input = $button.closest("form").find("input[id$=':" + id + "']");
if ($input.val() != $button.val()) {
$input.val($button.val()).trigger("change");
}
});
</h:outputScript>
(noted should be that the whole script should really be placed in its own .js file which you include by <h:outputScript name="some.js" target="body">; note that you don't need $(document).ready() nor $(function() {}) mess; also note that the very JS function is reusable on all other <div data-toggle="buttons-radio"> groups without changes)
With this bean:
private Integer dir;
public void changeDir() {
System.out.println("New direction: " + dir);
}
// ...
(noted should be that when you're doing further nothing relevant in changeDir() method, then you could just omit the whole method and <f:ajax> altogether and revert <h:inputText style="display:none"> back to <h:inputHidden> and remove .trigger("change") and rely on the regular form submit. It'll work as good)
You cannot just call any backing bean functions via Expression Language calls (#{...}) in JavaScript.
What you could do, is using a4j:jsFunction to offer your bean method to the java script code. That might look like this:
<a4j:jsFunction name="setDir" action="#{searchFlightsBean.setDir()}" ajaxSingle="true">
<a4j:param name="dir" assignTo="#{searchFlightsBean.dir}" />
</a4j:jsFunction>
See http://docs.jboss.org/richfaces/latest_3_3_X/en/devguide/html/a4j_jsFunction.html
and http://showcase.richfaces.org/richfaces/component-sample.jsf?demo=jsFunction&skin=blueSky

Show a piece of text only when mouseover a certain region

I need to show a outputText component only when the mouse is over a panel region. How can I achieve that ?
I tried using show() & hide() js functions with onmouseover event on panel but failed to achieve results.
If i understood correctly
<script>
$(document).ready(function(){
$("#something").mouseover(function (){
$("#myText").show();
})
$("#something").mouseout(function (){
$("#myText").hide();
}
)}
);
And your Panel
<p:panel id="something" >
<h:outputText id="myText" styleClass="hidden" value="hi i am hidden when is mouse is somewhere"/>
</p:panel>

Resources