I am trying to implement jQuery with PrimeFaces and JSF components, but it's not working properly. When I tried to do the same with HTML tags it;s working properly.
Here is the code with HTML tags which works properly with jQuery:
<input type="checkbox" id="check2"></input>
<h:outputText value="Check the box, if your permanent address is as same as current address."></h:outputText>
<h:message for="checkbox" style="color:red" />
with
$("#check2").change(function() {
if ($("#check2").is(":checked")) {
$("#p2").hide();
} else {
$("#p2").show();
}
});
Here is the code with PrimeFaces/JSF which doesn't work properly with jQuery:
<p:selectManyCheckbox >
<f:selectItem itemLabel="1" value="one" id="rad" ></f:selectItem>
</p:selectManyCheckbox>
with
$("#rad").change(function() {
if ($("#rad:checked").val() == "one") {
$("#p2").hide();
} else {
$("#p2").show();
}
});
You should realize that jQuery works with the HTML DOM tree in the client side. jQuery doesn't work directly on JSF components as you've written in the JSF source code, but jQuery works directly with the HTML DOM tree which is generated by those JSF components. You need to open the page in webbrowser and rightclick and then View Source. You'll see that JSF prepends the ID of the generated HTML input elements with the IDs of all parent NamingContainer components (such as <h:form>, <h:dataTable>, etc) with : as default separator character. So for example
<h:form id="foo">
<p:selectManyCheckbox id="bar" />
...
will end up in generated HTML as
<form id="foo" name="foo">
<input type="checkbox" id="foo:bar" name="foo:bar" />
...
You need to select elements by exactly that ID instead. The : is however a special character in CSS identifiers representing a pseudo selector. To select an element with a : in the ID using CSS selectors in jQuery, you need to either escape it by backslash or to use the [id=...] attribute selector or just use the old getElementById():
var $element1 = $("#foo\\:bar");
// or
var $element2 = $("[id='foo:bar']");
// or
var $element3 = $(document.getElementById("foo:bar"));
If you see an autogenerated j_idXXX part in the ID where XXX represents an incremental number, then you must give the particular component a fixed ID, because the incremental number is dynamic and is subject to changes depending on component's physical position in the tree.
As an alternative, you can also just use a class name:
<x:someInputComponent styleClass="someClassName" />
which ends up in HTML as
<input type="..." class="someClassName" />
so that you can get it as
var $elements = $(".someClassName");
This allows for better abstraction and reusability. Surely those kind of elements are not unique. Only the main layout elements like header, menu, content and footer are really unique, but they are in turn usually not in a NamingContainer already.
As again another alternative, you could just pass the HTML DOM element itself into the function:
<x:someComponent onclick="someFunction(this)" />
function someFunction(element) {
var $element = $(element);
// ...
}
See also:
How can I know the id of a JSF component so I can use in Javascript
How to use JSF generated HTML element ID with colon ":" in CSS selectors?
By default, JSF generates unusable IDs, which are incompatible with the CSS part of web standards
Integrate JavaScript in JSF composite component, the clean way
You also can use the jQuery "Attribute Contains Selector" (here is the url http://api.jquery.com/attribute-contains-selector/)
For example If you have a
<p:spinner id="quantity" value="#{toBuyBean.quantityToAdd}" min="0"/>
and you want to do something on its object you can select it with
jQuery('input[id*="quantity"]')
and if you want to print its value you can do this
alert(jQuery('input[id*="quantity"]').val());
In order to know the real html tag of the element you can always look at the real html element (in this case spinner was translated into input) using firebug or ie developer tools or view source...
Daniel.
If you're using RichFaces you can check rich:jQuery comonent. It allows you to specify server side id for jQuery component. For example, you have component with specified server id, then you can apply any jQuery related stuff to in next way:
<rich:jQuery selector="#<server-side-component-id>" query="find('.some-child').removeProp('style')"/>
For more info, please check doumentation.
Hope it helps.
look this will help you when i select experience=Yes my dialoguebox which id is dlg3 is popup.and if value is No it will not open
Related
I have a div with css property text-overflow : ellipsis to add ellipsis and show the text in a single line.
When I perform jquery .text() or .html(), I get the full string, but I need the exact text displaying in the div currently (not the full string).
Can some one guide me how to take the exact displaying string using jquery or JS?
Actual String = "abcdefghijklmnop"
Due to CSS, the div displays "abcd..."
My expected result (using jQuery or JS) "abcd..."
This is not possible without trying to mimic CSS and recreate the strings with the ellipsis using JS.
The reason for this is that CSS only manipulates what is displayed to the user, not the HTML source itself. You can verify this by checking the source code for your document. This means that when you use .text() or .html() you get the values from the DOM, rather than what is displayed via the CSS filter.
There are a couple of hacks that does a pretty good job, but it is still no guarantee that the JS correctly mimics how CSS renders the text.
If you know the number of values you need every time then you can just use JS Like for example if it was always 4 values that gets entered in than it would be like this,
JS Fiddle
form
<form action="" method="post">
<p>
<label for="txt">My txt: </albel>
<input type="text" id="myTxt"><br />
<input type="submit" id="submitButton" value="Send">
</P>
</form>
js
document.getElementById('submitButton').onclick = function() {
myVariable = document.getElementById("myTxt").value;
alert(myVariable.slice(0, 4));
};
No matter what is typed in to the textbox it will be sliced to the first 4 characters.
I have following confirmation box on review.xhtml page:
<p:confirmDialog message="#{msgs['com.yob.dpg.customerReview.invalid.invoiceDate.message']}" width="400" header="#{msgs['portaal.popup.window.confirmation.title']}" closable="false" widgetVar="invoiceDateConfirmation" showEffect="bounce" hideEffect="explode" severity="alert">
<p:commandButton value="#{msgs['portaal.popup.window.cancel']}" onclick="invoiceDateConfirmation.hide()" oncomplete="documentWiz.back(); setFocusToInvoiceNumber()" />
<p:spacer width="5"/>
<p:commandButton value="#{msgs['common.ok.button']}" update="messages,#form,headerForm:todoCountMenu,welcomeMessage" onclick="invoiceDateConfirmation.hide()" />
</p:confirmDialog>
and .js is on documentPreview.xhtml page:
function setFocusToInvoiceNumber(){
document.getElementById("invoiceNumber").focus();
}
input text code on which I want to set focus is on 'documentPreview.xhtml':
<p:inputText style="color:#4d4d4f; width:280px !important; margin-top: -3px;" id="invoiceNumber" value="#{customerReviewLazyDataModel.customerReviewVO.transactionheaderVO.invoiceNumber}" required="true" requiredMessage="#{msgs['com.yob.dpg.customerReview.mandatory.invoiceNumber']}"/>
My problem is that when I click on cancel button of confirmation box, an exception is thrown on browser that 'document.getElementById() is null'
Can any one give me solution for this problem.
Because the component id in JSF is not the same as the HTML DOM object ID, you can see this when you check the component id in the generated HTML file.
Check this blog post (JSF: working with component identifiers (id/clientId)) by McDowell
try adding prependId=false attribute to your form. this will keep the ids of all its children when JSF will generate the html.
Check out the rendered html in your browser. The id of the input element is probably something like "form1:invoiceNumber" instead of simply invoiceNumber. This is because JSF prepends all the parent NamingContainer id's to a component upon rendering to html.
In order to resolve this, you could turn off the prepend id feature like #sergui suggested, but that could have some adverse effect (namely, duplicate id's if composite components are reused multiple times on the same page). Another option is to store the "clientId" (the part that JSF prepends) in javascript.
To do so, add init(String clientId) function to the js file, then call it using an inline script from the JSF facelet
<h:outputScript>init('#{component.clientId}')</h:outputScript>
You'd then have to prepend invoiceNumber with clientId, but only after escaping the delimiter that JSF uses (:).
I get the boolean value into the <h:inputText> but I can't find a way to get it into the rendered-attribute of the <h:panelGroup>. I also don't see a way to use a bean value, because every iteration would need one on it's own.
this is my jsf code:
<ui:repeat var="item" value="#{itemBean.items}" id="iterateItems" varStatus="iteration">
<script type="text/javascript">
showItem("#{item.id}","#{iteration.index}");
</script>
<h:inputText id="rendered"/>
<h:panelGroup layout="block" rendered="???">
Iteration #{iteration.index} rendered
</h:panelGroup>
</ui:repeat>
this is my javascript:
function showItem(item,iteration){
if((clientSideValue==something){
document.getElementById("iterateItems"+":"+iteration+":"+"rendered").value = true;
}
else{
document.getElementById("iterateItems"+":"+iteration+":"+"rendered").value = false;
}
}
JavaScript runs in client side and works on the HTML DOM tree which is retrieved from the server side (and is in your particular case produced by JSF). JavaScript thus expects that the desired HTML element which you'd like to show/hide is always present in the HTML DOM tree.
JSF runs in server side and produces HTML code based on the JSF component tree (the "view"). When the rendered attribute of a JSF component evaluates to false, no HTML code would be produced for the given component and thus nothing would end up in the HTML DOM tree and thus nothing would be available to be selected by JavaScript's document.getElementById().
Your concrete functional requirement for which you thought that this would be the solution is unclear, so it's hard to propose the right solution for your concrete problem. But provided that you're absolutely positive that the show/hide needs to be performed in the client side (by JavaScript) instead of the server side (by JSF), then you should be using CSS' display property for this which you can toggle between block and none.
Here's a basic kickoff example, assuming that you want to initially hide it:
<ui:repeat var="item" value="#{itemBean.items}" id="iterateItems" varStatus="iteration">
<script type="text/javascript">
showItem(#{iteration.index});
</script>
<h:inputText id="rendered" />
<div id="foo#{iteration.index}" style="display:none">
Iteration #{iteration.index} shown
</div>
</ui:repeat>
with
function showItem(index) {
var div = document.getElementById("foo" + index);
if (someCondition) {
div.style.display = "block"; // Show it.
} else {
div.style.display = "none"; // Hide it.
}
}
Don't mix server-side script with client-side script!
Just use the EL as you want:
<ui:repeat var="item" value="#{itemBean.items}" id="iterateItems" varStatus="iteration">
<h:panelGroup layout="block" rendered="#{item.id le 1}">
Iteration #{iteration.index} rendered
</h:panelGroup>
</ui:repeat>
That is not possible: The JSF-Tags - especially the rendered Attribute are used during the RenderResponse Phase of JSF. When the final HTML has been generated, there is no more rendered attribute - the HTML Element containing that attribute is either rendered or not.
So, if you need to do something depending on client's values, you would need to transfer that value to your server.
A workaround would be to set the css-property display:none. But note, that this will JUST not display the element. It is STILL available in the Page Source.
If you are working with Javascript, you should really look at the final Sourcecode. The JSF Tags are resolved and even auto-generated IDs like 23:58:23 are not always the same for a certain element.
I'm writing the ui:composition xhtml file to include in different pages using ui:include. It looks like there's no way I can refer to the tags from javascript in this file using getElementById, as the tag ids might be prepended with the form id from the parent page. Is there a workaround?
Found this answer after I posted the question. It helped!
Acquire full prefix for a component clientId inside naming containers with JSF 2.0
You could do this:
var elem = document.querySelector( '[id$="-test"]' );
where test is the ID without the prefix, and - is the prefix separator.
The above code will select the element which "id" attribute ends with "-test" (e.g. <div id="form1-test">...</div>).
Live demo: http://jsfiddle.net/8kyb2/
Note that querySelector() paired with an attribute-ends-with selector performs slower than getElementById().
If you happen to use Apache's Tomahawk Components, and specify forceId="true", tag ids will remain unchanged. E.g.:
<t:inputText id="name" forceId="true" value="#{myBean.property}" />
will result in an <input type="text" id="name" ... / >.
In JSF, what would be the "right" and "clean" way to integrate JavaScript i.e. into a composite-compenent? I am a fan of Unobtrusive JavaScript, and separating HTML from JS from CSS. What would be a good way to have as little quirks as possible? This is what I like the best so far:
<composite:interface>
// ...
</composite:interface>
<composite:implementation>
// ...
<script> initSomething('#{cc.clientId}'); </script>
</composite:implementation>
What I don't like is, to use language A to generate language B. Basically the same goes for event handlers and stuff. My favorite would be to attach those handlers via <insert favorite DOM JavaScript library here>. Is this possible? How do you do this kind of integration?
I'd say that what you've there is the best you can get, provided that you're absolutely positive that the HTML element's nature is so unique that you absolutely need to select it by an ID, every time again.
If the HTML representation is not that unique (I can imagine that a Facelets template or include file might contain application-wide unique HTML elements like header, menu, footer, etc, but a composite component which can be reused multiple times in a single view? I can't for life imagine that), then you could also consider using an unique classname and hook initialization on it.
E.g. /resources/composites/yourComposite.xhtml
<cc:implementation>
<h:outputScript library="composites" name="yourComposite.js" target="head" />
<div id="#{cc.clientId}" class="your-composite">
...
</div>
</cc:implementation>
with in the /resources/composites/yourComposite.js (assuming that you're using jQuery)
var $yourComposites = $(".your-composite");
// ...
You can if necessary extract the autogenerated HTML element ID for each of them in a jQuery.each():
$yourComposites.each(function(index, yourComposite) {
var id = yourComposite.id;
// ...
});