Summarize and expand long text output in JSF - jsf

My question is similar to How to hide/show more text within a certain length (like youtube) or Readmore but for JSF. It's a very common metaphor on the web.
I have a page that displays a section with user-entered text, which may be short or it may be long. If it's long, the table height is unmanageable, so in those cases I'd like to show a portion of the text followed by a "(more)" link that will reveal the remaining text. After expansion, there would be a "(less)" link as well. (Note: My particular case has just text with newlines in it.)
Are there any pre-existing JSF components to do this? I've checked PrimeFaces and OmniFaces and ButterFaces and was surprised that I didn't see anything that jumped out at me as having this functionality. I'm sure I could make my own custom component using one of the techniques in the referenced StackOverflow question, but I'd rather not reinvent the wheel.

Maybe this is a good extension for ButterFaces. I will think about it.
But why do you need a JSF component? Just use Readmore.js.

Here's a quick composite component that uses readmore that can be used as a starting point for anyone else wanting something like this. There are a few unrelated features in it that are kind of hacked in (hard-coded style, hard-coded options to the readmore() function, etc.) that you would probably want to improve and customize. Suggestions for improvement welcome.
Parameters
value (String, Required): The text to display. Expected to be plain text with empty lines.
cols (integer, default=40): The number of columns to limit the width of the containing div to. If less than or equal to 0, then don't limit the width.
readmore (boolean, default=false): Whether to use the Readmore feature.
textonly (boolean, default=false): By default, the component assigns a "readonly" class to the containing div. Setting textonly to true does not assign the "readonly" class to the containing div.
Location: Under /resources/{samplelibrary}/readOnlyTextArea.xhtml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html
xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:composite="http://java.sun.com/jsf/composite"
>
<composite:interface>
<composite:attribute name="cols" default="40" type="java.lang.Integer"/>
<composite:attribute name="value" required="true"/>
<composite:attribute name="readmore" default="false" type="java.lang.Boolean"/>
<composite:attribute name="textonly" default="false" type="java.lang.Boolean"/>
</composite:interface>
<composite:implementation>
<h:outputScript library="samplelibrary" name="readmore.min.js" target="head"/>
<div id="#{cc.clientId}_div" class="#{cc.attrs.textonly?'':'readonly'}"
style="overflow: hidden; white-space: pre-wrap; #{cc.attrs.readmore ? '' : 'min-height: 1.3em;'} #{(cc.attrs.cols gt 0) ? 'width: '.concat(cc.attrs.cols / 2.09).concat('em; padding: 2px 2px 2px 2px;') : ''}">
<h:outputText value="#{cc.attrs.value}"
/></div>
<ui:fragment rendered="#{cc.attrs.readmore}">
<script type="text/javascript">
$(window).ready(function() {
var comps = $(document.getElementById('#{cc.clientId}_div'));
comps.readmore({speed:300,collapsedHeight:54});
});
</script>
</ui:fragment>
</composite:implementation>
</html>
Here's some CSS for the readonly CSS class:
.readonly
{
border: 1px solid #999;
background-color: #eee;
color: #333;
}

Related

How to hide h:selectManyListbox default scroll

i hava h:selectManyListbox with size=3 and there's a default disabled scroll appears, i want to hide it, and show it when necessary (if size >3 ).
please advise how to do that, thanks.
something like this
<h:selectManyListbox styleClass="#{(myBean.hideScroll gt 3)?'':'myHideScrollClass'}"...
where in your css
.myHideScrollClass {
}
Or a bit simplified
<h:selectManyListbox style="#{(myBean.hideScroll gt 3)?'':'overflow-y:hidden;'}"...
Also , instead of myBean.hideScroll gt 3 you can use myBean.myList.size() gt 3 but make sure myList is not a null
<h:selectManyListbox /> render 'select' and 'option' html tag. You can't control the look of a select box in such detail, it is displayed depends on the system.
You can use some trick(condition size=3: you can use #Daniel approach):
<style type="text/css">
.test {
display:inline-block;
vertical-align:top;
overflow:hidden;
border:solid grey 1px;
}
.test select {
padding:10px;
margin:-5px -20px -5px -5px;
}
</style>
<div class="test">
<h:selectManyListbox />
</div>

Using charset ISO-8859-1

I'm from Brazil and here we have lots of à é ô ó ç, etc in our words and it is a problem on my JSF project.
I have a master.xhtml as a template for all my pages and here it is:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head>
<meta http-equiv="Content-Type" content="text/html;charset=ISO-8859-1">
<meta http-equiv="pragma" content="no-cache"/>
<link rel="stylesheet" href="#{facesContext.externalContext.requestContextPath}/assets/css/bootstrap.css" type="text/css" media="all" />
<title>#{masterController.projectName}</title>
<style type="text/css">
body {
padding-top: 60px;
padding-bottom: 40px;
}
.sidebar-nav {
padding: 9px 0;
}
</style>
</h:head>
<h:body>
<ui:fragment rendered="#{loginController.isLoggedIn}">
<ui:include src="../includes/top.xhtml"/>
</ui:fragment>
<ui:insert name="body" />
<hr />
<ui:fragment rendered="#{loginController.isLoggedIn}">
<ui:include src="../includes/footer.xhtml" />
</ui:fragment>
</h:body>
<script type="text/javascript" src="#{facesContext.externalContext.requestContextPath}/assets/js/jquery-1.7.2.min.js"></script>
<script type="text/javascript" src="#{facesContext.externalContext.requestContextPath}/assets/js/bootstrap.min.js"></script>
</html>
As you can see my xml encondig is correct as my Content-Type meta tag.
I'm using Eclipse and on my project Properties->Resources I've changed the Text file encoding to ISO-8859-1.
I have a label on my login.xhtml page that goes inside master.xhtml called Usuário (User), if I use the character á, and the word is wrong without it, I get this error:
exception
javax.servlet.ServletException: null source
javax.faces.webapp.FacesServlet.service(FacesServlet.java:321)
root cause
java.lang.IllegalArgumentException: null source
java.util.EventObject.<init>(Unknown Source)
javax.faces.event.SystemEvent.<init>(SystemEvent.java:67)
javax.faces.event.ComponentSystemEvent.<init>(ComponentSystemEvent.java:69)
javax.faces.event.PostRestoreStateEvent.<init>(PostRestoreStateEvent.java:69)
com.sun.faces.lifecycle.RestoreViewPhase.deliverPostRestoreStateEvent(RestoreViewPhase.java:256)
com.sun.faces.lifecycle.RestoreViewPhase.execute(RestoreViewPhase.java:245)
com.sun.faces.lifecycle.Phase.doPhase(Phase.java:97)
com.sun.faces.lifecycle.RestoreViewPhase.doPhase(RestoreViewPhase.java:107)
com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:114)
javax.faces.webapp.FacesServlet.service(FacesServlet.java:308)
Taking the á away it works but as I said, in Portuguese it is necessary and I'm gonna use a lot of other characters with accent.
You should not use the old ISO-8859-1 charset, but the new UTF-8 charset. JSF uses by default UTF-8 already which is much better prepared for world domniation.
Change everything to UTF-8 and change your IDE settings to use UTF-8 everywhere. In Eclipse, the most important setting is Window > Preferences > General > Workspace > Text File Encoding.
Then, enter "encoding" in the type filter text on the left top input field and re-apply the change to UTF-8 for all other settings as well.
See also:
Unicode - How to get the characters right?

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
}

Dijit.Dialog 1.4, setting size is limited to 600x400 no matter what size I set it

I'm trying to set the size of a dijit.Dialog, but it seems limited to 600x400, no matter what size I set it. I've copied the code from dojocampus and the dialog appear, but when i set the size larger, it only shows 600x400. Using firebug and selecting items inside the dialog, I see that they are larger than the dialog, but don't show correctly. I set it up to scroll, but the bottom of the scrollbar is out of view. In firebug, I've check the maxSize from _Widget and it is set to infinity. Here is my code to set the dialog.
<div id="sized" dojoType="dijit.Dialog" title="My scrolling dialog">
<div style="width: 580px; height: 600px; overflow: scroll;">
Any suggestions for sizing the dialog box larger?
I just coded up a quick sample from scratch using dojo 1.4 and was able to set an arbitrarily large DBX size with no problems.
Without seeing your code it might be hard to find where your issue is stemming from but it does not seem to be an inherent limitation of the dojo toolkit. Perhaps you have some CSS rules that are inherited in a way you did not anticipate?
Perhaps you can use my sample below to compare with your use case and figure out what is different about your implementation.
<!DOCTYPE html PUBLIC
"-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<title>test</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script src="http://www.google.com/jsapi" type="text/javascript"></script>
<script type="text/javascript">
djConfig = {
parseOnLoad: true
};
google.load("dojo", "1.4");
google.setOnLoadCallback(function (){
dojo.require("dijit.Dialog");
dojo.require("dijit.form.Button");
});
</script>
<style type="text/css">
#import "http://ajax.googleapis.com/ajax/libs/dojo/1.4/dojo/resources/dojo.css";
#import "http://ajax.googleapis.com/ajax/libs/dojo/1.4/dijit/themes/tundra/tundra.css";
</style>
</head>
<body class="tundra">
<button dojoType="dijit.form.Button" type="button">Show big Dialog
<script type="dojo/method" event="onClick" args="evt">
dijit.byId("bigdbx").show();
</script>
</button>
<div id="bigdbx" dojoType="dijit.Dialog" title="Big Dialog" width="900px">
<p style="width: 1100px; height: 800px;">Paragraph with really wide fixed size...</p>
</div>
</body>
</html>

newbie JSF question - How to achieve this layout?

I'm trying to achieve the layout shown here
Each of the panels should be linked to a backing bean from which I will later add differrent components according to context.
I tried using panelgrid but could not achieve this look.
I would prefer to use just JSF for this but if impossible or too complicated RichFaces is ok too.
Thanks!!
It's not only matter of JSF/HTML, but it's also a matter of CSS. The above layout can basically already be achieved as follows:
<h:panelGroup id="header" layout="block"></h:panelGroup>
<h:panelGroup id="leftcol" layout="block"></h:panelGroup>
<h:panelGroup id="rightcol" layout="block"></h:panelGroup>
(which generates the following HTML)
<div id="header"></div>
<div id="leftcol"></div>
<div id="rightcol"></div>
You can style/position it using CSS like as:
#header {
width: 100%;
height: 100px;
}
#leftcol {
width: 200px;
float: left;
}
#rightcol {
float: left;
}
That's all.
You can use the HTML code with which you have achieved the above layout. I.e.
<table>
<tr>..</tr>
<tr>..</tr>
</table>
However, the table-less layouts are preferred - i.e. using <div> tags. (see here)

Resources