Accessing selected node of richfaces tree from Javascript - java

This should be a very simple question. I have a richfaces tree that is rendered using JSF. When the user clicks on a node I want a javascript function to run. Nothing more nothing less. No redirects, no re-submit, no-rerender, no Ajax. Just plain old Javascript.
I have seen the onselected attribute of the tree and it indeed fires a Javascript method. But of course I want to know which node was clicked.
Here is what I have so far
<head>
<script type="text/javascript">
function documentClicked(nodeRef)
{
alert("Node is "+nodeRef);
}
</script>
</head>
<rich:tree switchType="client" value="#{ajaxDocumentTree.rootNode}"
var="document" onselected="documentClicked()" >
<rich:treeNode iconLeaf="../images/tree/doc.gif"
icon="../images/tree/doc.gif">
<h:outputText value="#{document.friendlyName}" />
</rich:treeNode>
But this does not work because nodeRef is undefined. I expected that the first argument of the callback would be the selected node but this is not the case.
So the question is this:
How do I fire a Javascript function with the selected node from a richfaces tree?

The answer is that the javascript code should be on the node level instead of the tree level.
<head>
<script type="text/javascript">
function documentClicked(nodeRef)
{
alert("Node id is "+nodeRef);
}
</script>
</head>
<rich:tree switchType="client" value="#{ajaxDocumentTree.rootNode}"
var="document" >
<rich:treeNode onclick="documentClicked('#{document.id}')">
<h:outputText value="#{document.friendlyName}" />
</rich:treeNode>

I have little experience with JSF, but shouldn't this (in the scope of your event handler) be referring to the selected node, as it usually does in JavaScript?
Change your function to this and try it out:
function documentClicked()
{
alert("Node is " + this);
}
EDIT: the above was obviously not correct. As per my comment below, change your JSF to
<rich:tree switchType="client" value="#{ajaxDocumentTree.rootNode}"
var="document" onselected="documentClicked(this)" >

Related

Jquery in JSF 2.0

im newbie in Jquery , i want to do a placeholder in jsf , something like this : http://niklaskoehler.de/demos/vordefinierter-text/ . I've the next code :
<head>
<script type="text/javascript">
jQuery(document).ready(function() {
var $ = jQuery;
var Element = "#email";
var InputText = "Placeholder demo";
$(Element).val(InputText);
alert("sup bro"); //this alert works
$(Element).bind('focus',function(){
$(this).addClass('focus');
if($(this).val()==InputText){
$(this).val('');
}
}).bind('blur',function(){
if($(this).val()==""){
$(this).val(InputText);
$(this).removeClass('focus');
}
});
});
</script>
</head>
And this is my form :
<h:form>
<div class="form-item">
<h:inputText id="email" title="Email" value="#{UserAction.email}"/>
</div>
</h:form>
And nothing happen with the input , what is wrong in my code?
jQuery doesn't work with JSF component tree in server side. Instead, it works with HTML DOM tree in client side. In case of JSF, you should instead be looking at JSF-generated HTML output while writing jQuery. As you're encountering rather unpredictable HTML element IDs like pbGfb9435b3_2d720d_2d478d_2d8183_2d657b3839216b_j_id1:j_idt5:email, you're likely running a JSF portlet instead of servlet. The pgXxx ID prefix occurs on portlets only.
As a word of advice, don't select non-unique elements by ID. Select by class name instead.
E.g.
<h:inputText ... styleClass="email" />
with
var selector = ".email";
var inputText = "Placeholder demo";
$(selector).val(inputText);
(I took the liberty to fix poor variable names; they should not start with uppercase and the CSS selector is not an element)
See also:
How to refer to a JSF component Id in jquery?
How to select JSF components using jQuery?
Sark,
Execute your web page and viewsource for same.
Whatever ID you will find for your <input type='text' id='something'
add the same id to your Jquery
var Element = "#something";

struts 1.0 logic tag choice - if/else logic

What I have is a dropdown list. When the user selects a certain option, where each option represents a specific String on the Java server side.
Right now, the Java server side able to check which option is selected, and the number to correspond. At the moment, I am able to output the value in Java backend, not on the JSP page.
Is there an if/else tag for Struts 1.0?
I am not sure which logic tag is the best to pass a Java value for frontend processing:
JSP page
if(value = 666)
this textbox is readonly
else
this textbox row is active
My research so far:
Looking at logic:equal, it seems to pass a value on the JSP page using taglibs like below. This doesn't work for me, because I want to pass the value FROM a Java class on the server side.
<logic:equal name="name" property="name" value="<%= theNumber %>" >
<c:choose>
<c:when test="${the number}">
Both are equal.
</c:when>
<c:otherwise>
Both are not equal.
</c:otherwise>
</c:choose>
this is jstl tag
you need to use
<%#taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
The JSTL answer is the best one, however, in my case it was an old Java legacy application without JSTL and I couldn't introduce it.
This was the requirement I had with some legacy Struts 1.3 code. Set a checkbox to match the value of a form bean's value from a database call, as in "Y", "N", "", or null.
I also had to keep in within struts logic tags and not use JSTL, which was my original preference. I know that the struts docs
said the checkbox should equate to a boolean variable in the
actionForm, but I used a string value, which worked.
From the docs link above:
NOTE: The underlying property value associated with this field should be of type boolean, and any value you specify should correspond to one of the Strings that indicate a true value ("true", "yes", or "on"). If you wish to utilize a set of related String values, consider using the multibox tag.
I had thought about converting my string values to booleans in the
form, but it took the strings this way.
Last of all, I used some javascript to set the checked status. All of this is verbose and not the best solution, but faced with the requirement, it does work.
Here is the code:
<logic:equal name="<%=formName%>" property="formInd" value="Y">
<html:checkbox name="<%=formName%>" onchange="setDataChanged()" property="formInd"/>
<script type="text/javascript" LANGUAGE="JavaScript">
document.<%=formName%>.formInd.checked = true;
</script>
</logic:equal>
<logic:equal name="<%=formName%>" property="formInd" value="N">
<html:checkbox name="<%=formName%>" onchange="setDataChanged()" property="formInd"/>
<script type="text/javascript" LANGUAGE="JavaScript">
document.<%=formName%>.formInd.checked = false;
</script>
</logic:equal>
<logic:empty name="<%=formName%>" property="formInd" >
<html:checkbox name="<%=formName%>" onchange="setDataChanged()" property="formInd"/>
<script type="text/javascript" LANGUAGE="JavaScript">
document.<%=formName%>.formInd.checked = false;
</script>
</logic:empty>

JSF to JQuery Component Integration

Since any JSF page gets transformed at the server side into its equivalent HTML and sent to the client for rendering, and JQuery at the client side takes the HTML and re renders it.
In theory it should be possible to take the HTML that is a generated by JSF and wrap it into JQuery, if so I would like to know how it's done. Specifically using RichFaces as the JSF implementation if possible.
<rich:dataTable id="table">
<rich:column>
</rich:column>
</rich:dataTable>
The above snippet of JSF is transformed into it's equivalent HTML which is this
<table id="table">
<tr>
<td></td>
</tr>
</table>
Shouldn't it be possible to do something like this
<script type="text/javascript">
$(document).ready(function () {
$('#table').dataTable();
}
</script>
I've already tried that but it doesn't seem to work.
So please if anyone has any hints, I'd be more than grateful.
Mixing JSF and jquery is doable but there are some gotchas.
JSF is taking over your ids, so if table is in a form with id "form", the actual element id in html would be by default "form:table". I think jquery could have a problem with colon in a selector, so you may mark your table with a class and select by that:
<rich:dataTable styleClass="my-table">
<rich:column>
</rich:column>
</rich:dataTable>
and set selector as:
<script type="text/javascript">
$(document).ready(function () {
$('.my-table').dataTable();
}
</script>
The Id's of the JSF components are generated by combining the Id's of the containers on the hierarchy with a : separator. Not all the containers count, I don't remember exactly the rules.
Normally some JSF libraries have some client side API to get the component ID's I don't know for richfaces.
Anyway, if you'd like to use jQuery based JSF, take a look at primefaces.
Hope this helps.
This issue might be a '$' name spacing conflict arisen by the Jquery and rich faces component which is made of Prototype.js.Try using jQuery.noconflict() method. I had a similar problem of making the jquery work with richfaces jquery.noconflict() did the trick..
<script type="text/javascript">
$.noConflict();
jQuery(document).ready(function($) {
// Code that uses jQuery's $ can follow here.
});
// Code that uses other library's $ can follow here.
</script>
Good Luck!

JSF 2.0 partial rendering on page on document load

I have a page, one section of which I want to load only after the whole page is loaded. For this, I'm using the following code on the page:
<script type="text/javascript">
alert("In the JS");
$(document).ready(
function() {
$.post(jspPath+'/myCommunity/ajax/hotTopicDiscussion.faces',
function(data) {
jsf.ajax.request(this, 'post', {render: 'discussionTopic'});
}
);
}
);
</script>
also
<h:panelGroup id="discussionTopic" reRendered="#{discussionBean.doRender}">
This doRender is a bean property which I set once the AJAX call is done. But this is not loading the data. I can see the ajax method is getting called.
It seems, that your call of jsf.ajax.request is incorrect. According to JsDoc reference arguments of request are following:
source:
The DOM element that triggered this Ajax request, or an id string of the element to use as the triggering element.
event:
The DOM event that triggered this Ajax request. The event argument is optional.
options:
The set of available options that can be sent as request parameters to control client and/or server side request processing.
So first element must be some element inside form or may be form itself. You may try to pass form's id or form element itself to this function.
Do you really need to submit a form ajaxically? That's where the jsf.ajax.request() is for. It seems like that you just want to load some static content inside some <div>. Just do as follows
<script>
$(document).ready(function() {
$.get("#{request.contextPath}/myCommunity/ajax/hotTopicDiscussion.faces", function(data) {
$("#discussionTopic").html(data);
});
});
</script>
<h:panelGroup id="discussionTopic" layout="block" />
Or, simpler, with jQuery.load():
<script>
$(document).ready(function() {
$("#discussionTopic").load("#{request.contextPath}/myCommunity/ajax/hotTopicDiscussion.faces");
});
</script>
<h:panelGroup id="discussionTopic" layout="block" />
In both cases, I assume that the hotTopicDiscussion.xhtml has <ui:composition> as root element and that it contains only the necessary HTML (and thus not <html> and so on).
If you indeed really need to submit a form ajaxically, then simplest would be to let JS "click" the button programmatically. It will delegate all the way up to the proper and needed jsf.ajax.request() call. A jsf.ajax.request() call is useless anyway without a physical form/button component on the page. You can if necessary hide the form by CSS.
<script>
$(document).ready(function() {
$("[id='form:button']")[0].onclick();
});
</script>
<h:form id="form" style="display:none;">
<h:commandButton id="button" action="#{bean.submit}">
<f:ajax render=":discussionTopic" />
</h:commandButton>
</h:form>
<h:panelGroup id="discussionTopic" layout="block" />

How to define an onLoad function in JSF template that will be defined elsewhere

I'm designing the view for my site, which has a standard login and landing page, and I want to have an onLoad function called for my login page, but not for my other pages (yet). I've got a template.xhtml file, which has this insert:
<div id="content">
<ui:insert name="content"/>
</div>
Then in login.xhtml I have:
<ui:define name="content">
...
</ui:define>
Normally I would put this in login.xhtml:
<body onload="document.getElementById('login_form:name').focus();">
But since I'm using JSF's ui composition tags, I can't have the <body/> tag in login.xhtml (at least the way I am attempting to do it).
Is there a way to accomplish this with the structure I've described? The way I would think of doing it is to have onLoad call a function in the template, and then each page with ui:define would populate this function. Is that possible?
Thanks!
I can think of at least two ways:
define the header section with <ui:define name="header">, and put a javascript function (function bodyLoaded(){..}) in it - different on every page, and then reference it via <body onload="bodyLoaded();">
use facelets params. I.e. <body onload="#{onLoadJS}"/> and on each page including the template use <ui:param name="onLoadJS" value="document.getElementById(..)" />

Categories