Popup helpful message before selecting from h:selectOneMenu in JSF - jsf

I am using JSF and I have an h:selectOneMenu which is populated using f:selectItems from a backing bean. I would like to display a helpful message for each option in the h:selectOneMenu. This message will come from a bean too and it will be different for each option. I want to do that while the user navigates between the options and before selecting the options that he wants. The idea is to help the user decide what to select. In other words I want something very similar to “title” attribute of component but more fancy and powerful than this. Specifically I want something like a small popup window which allows unlimited number of characters. Is this possible? Do you have any idea as to how to proceed? Is there any JSF library that can help me do this?
I found this link ToolTip for each SelectOneMenu Items in jsf but it is not helpful for me because first of all it uses the “title” attribute and secondly the message does not come from a backing bean.
Thanks in advance!

As BalusC mentioned, you can just use Primefaces, and here is a sample code using the PowerTip jQuery plugin:
<p:selectOneMenu id="users" converter="userConverter" var="u">
<f:selectItems value="#{userManagedBean.users}" var="user" itemLabel="#{user.firstName}" itemValue="#{user}"/>
<p:column >
<span customData="#{u.emailOrAnyOtheInfoYouWantToDisplayInTooltip}" class="aClassForTooltips">
<h:outputText value="#{u.firstName} - #{u.lastName}" />
</span>
</p:column>
And on the jQuery part:
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
<h:outputScript name="js/jquery.powertip.min.js" />
<script type="text/javascript">
$.noConflict();
jQuery(document).ready(function () {
jQuery('.aClassForTooltips').each(function(){
var elementToH = jQuery(this),
data = elementToH.attr('customdata').replace(/%20/g,' ');
elementToH.data('powertip', function() {
return '<div style="background-color:black;width:200px;height:25px">'+data+'.</div>';
});
///////
elementToH.powerTip({
placement: 'ne' // north-east tooltip position
});
//////
});
});
Notice the use of a custom attribute in the span element. This attribute is ignored by JSF renderers if used with any JSF component, that's why you need a span.
Finally do not forget to include at least this CSS:
#powerTip {
position: absolute;
display: none;
z-index: 2147483647;
color:red;
}
I hope this helps

Related

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

Using CKEditor instead of PrimeFaces Editor

I am trying to use CKEditor in my JSF application. How to get the content of CKEditor into backing bean..?
index.xhtml
<form action="" method="post">
<p>
My Editor:<br />
<textarea cols="90" rows="20" id="editor1" name="editor1" value="#{EditorBean.value}"></textarea>
<script type="text/javascript">
CKEDITOR.replace( 'editor1',
{
uiColor: '#85B5D9'
});
</script>
<input type="button" value="Clear" name="clear" onclick="clear1()"/>
</p>
</form>
BackingBean
#ManagedBean
public class EditorBean {
private String value;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
System.out.println("Content: "+value);
}
}
When I tried to print the value, It is not printing. Help me on this issue. PrimeFaces Editor is not supporting "Insert Table" function. So, I want to use CKE.
As el wont be able to evaluate non-JSF component.
Add this to your page :
<h:inputHidden value="#{EditorBean.value}" id="editorValue"/>
and onblur of editor textarea assign the value to the hidden element using
document.getElementById(editorValue).value = this.value;
Since this question bumped up somehow....
There is another option:
You can use the PrimeFaces Extensions , here is the link PrimeFaces Extensions CKEditor
Here an example from the showcase
<p:growl id="growl" showDetail="true" />
<pe:ckEditor id="editor" value="#{editorController.content}" interfaceColor="#33fc14">
<p:ajax event="save" listener="#{editorController.saveListener}" update="growl"/>
</pe:ckEditor>
<p:commandButton actionListener="#{editorController.changeColor}" update="editor"
value="Change color with AJAX" style="margin-top:10px;"/>
try this:
<textarea class="ckeditor" cols="80" id="editor1" rows="10"/>
<h:inputHidden value="#{tskCtrl.selected.dsc}" id="editorValue"/>
<p:commandButton onclick="document.getElementById('editorValue').value = CKEDITOR.instances.editor1.getData();" action="#{tskCtrl.create()}" value="Post" />
The answer from niksvp was helpful and set me in the right direction, but
the problem I found was that the blur handler never fires. I had to copy
the value from the textarea to the inputHidden on the onclick handler of
the commandButton:
<textarea id="textareaValue" .../>
<a4j:commandButton execute="editorValue" onclick="document.getElementById('editorValue').value = document.getElementById('textareaValue').value;"
...
or
<a4j:commandButton execute="editorValue" onclick="jQuery('#editorValue').val(jQuery('#textareaValue').val())"
I tried using onbegin & onbeforedomupdate but they didn't work.
Another option is to use the JSF versions of form and textarea. (It is likely possible to do this with passthrough elements as well, but I didn't try that.)
<h:form id="form">
<p>
My Editor:<br />
<h:inputTextarea cols="90" rows="20" id="editor1" value="#{EditorBean.value}" />
<script type="text/javascript">
ClassicEditor.create(document.querySelector('form\\:editor1'))
.then( editor => {
console.log( editor );
} )
.catch( error => {
console.error( error );
} );
</script>
</p>
</form>
This assumes that you do not have prependId=false.
The weird \\: is an escaping issue. It won't work without that. You'd get the "is an invalid selector" error in the console.
You can ID form and editor1 with other names, but you'll need to change the selector as well. You don't want to leave it to the defaults, as those are fragile, often changing as you update the page. Now it will only change if you change the structure of where editor1 is relative to form. E.g. if you add a fieldset around editor1, that would make the ID something like form\\:fieldset\\:editor1, where fieldset is the ID of the fieldset as specified in JSF. JSF will create the long version for you.
This also requires the CKEditor script to be added to the head, e.g.:
<script src="https://cdn.ckeditor.com/ckeditor5/11.2.0/classic/ckeditor.js"></script>
This particular example is for the ClassicEditor version. If you want a different version, you'd need to change the script and the part that says ClassicEditor.
Differences between the script as called in the question and this version may be that this is the current version (as I write this) while the question is older.
Alternately, you might prefer to use h:outputScript. But then you might need to host the script in your resources folder rather than using the version from the CDN.
See also:
Is the ID generated by JSF guaranteed to be the same across different versions and implementations?
Select element with double dot in id, error: “#octo:cat” is not a valid selector
Acquire full prefix for a component clientId inside naming containers with JSF 2.0
How to find out client ID of component for ajax update/render? Cannot find component with expression “foo” referenced from “bar”
How to include JavaScript files by h:outputScript?

How to make an image button in JSF

I want to have a component that looks like a button, but instead of text it should contain an image.
Because the standard button does not offer this functionality, I tried to use a <h:commandLink>:
<h:commandLink action="#{some_action}">
<p:panel styleClass="some_style">
<h:graphicImage value="#{some_image}">
</p:panel>
</h:commandLink>
This doesn't work. The <h:commandLink> is translated into an <a> tag, and the <p:panel> into a <div>. <a>-tags may not contain <div>-tags, so the <div>-tag is automatically placed outside the <a>-tag.
The result is that only the image is clickable, not the surrounding panel which is styled to look like a button. Is there a way to make the surrounding panel part of the link, or to put an image inside a button?
My project uses JSF and the Primefaces library:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:composite="http://java.sun.com/jsf/composite"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.prime.com.tr/ui">
There are a couple ways you can add an image to a commandButton:
Using the image attribute
<h:commandButton action="#{some_action}" image="button.gif" />
Absolute or relative URL of the image
to be displayed for this button. If
specified, this "input" element will
be of type "image". Otherwise, it will
be of the type specified by the "type"
property with a label specified by the
"value" property.
Use CSS
<h:commandButton action="#{some_action}" styleClass="button" />
.button {
background: white url('button.gif') no-repeat top;
}
You could just move the div outside e.g.
<div class="myButton">
<h:commandLink action="#{some_action}" styleClass="clickAll">
<h:graphicImage value="#{some_image}">
</h:commandLink>
</div>
And style the div that way. Just make the anchor (a tag) display as a block and it should fill the whole div so it's all clickable. For example in your CSS go:
.clickAll{
display:block;
}
If you can use an icon from PrimeFaces/JSF, then there is a simple and sound solution is
<p:column>
<p:commandButton icon="ui-icon-wrench"
style="border-width:0;background:none;"/>
</p:column>
It may help to avoid JavaScript code in JSF.
If the image does not fit then add properties to a сss class:
.button {
background: white url('button.gif') no-repeat top;
width: 32px; // button width
height: 32px; // button height
background-size: contain;
border: none; // hide border of button
}

Jsf custom selectItems

Look the following code
<h:selectManyCheckbox layout="pageDirection" styleClass="pressReviewTable">
<f:selectItems value="#{theme.articles}" var="prArt" itemLabel="#{prArt.prLabel}" itemValue="#{prArt.id}" itemLabelEscaped="false"/>
</h:selectManyCheckbox>
I try to put some html on on the itemLabel like a <b> but i have the following error:
The value of attribute "itemLabel"
associated with an element type
"f:selectItems" must not contain the
'<' character.
I find a trick to put directly in #{prArt.prLabel} the html but i'm not satisfied with that. I use mojarra and primefaces.
I want to do something like :
<f:selectItems value="#{theme.articles}" var="prArt" itemLabel="<b>#{prArt.value1}</b> : <font>#{prArt.value2}</font>" itemValue="#{prArt.id}" itemLabelEscaped="false"/>
What's the other way? If there...
Thanks
Since each item label get printed as <label> in HTML, you can just use CSS
<h:selectManyCheckbox styleClass="foo">
with
.foo label { font-weight: bold; }

Is there any rich text editor component for JSF RI?

I am using JSF RI 1.1. How to add rich text editor component? Is there any rich text editor component available?
I am displaying set of images horizontally using the below code. Selected image is stored in database. while showing the images in edit mode, how to highlight the previously selected image?
<t:dataList
var="item"
value="#{occasionBean.messageInfo}"
layout="simple">
<h:commandLink action="#{occasionBean.selectedImage}" >
<h:graphicImage
width="100" height="100"
url="#{item.imageSnapUrl}"
onclick="return setMsgId(this.id,{item.img_id},'{item.imageUrl}');"
id="test">
</h:graphicImage>
</h:commandLink>
</t:dataList>
Richfaces has editor component.
1) Mojarra Scales has a htmlEditor component.
(source: kenai.com)
2) Add a styleClass conditionally.
styleClass="#{item.previouslySelected ? 'selected' : ''}"
with this getter
public boolean isPreviouslySelected() {
return previouslySelected;
}
and this CSS
img.selected {
border: 2px solid red; /* Use whatever highlight style here. */
}

Resources