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 (:).
Related
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
I am creating a GoDaddy web page using a pre-formatted template that does not indicate visual focus on the SEND button of a Contact Us form. To make my form compliant with WCAG accessibility guidelines, active elements must show visual focus; however, it is a template and I do not have access to the code to modify the styles directly.
Although I can't access the template code directly, it does permit me to add a section to a page that allows html javascript and css. I would like to understand if there is code or a script I can include in that section to modify the button style?
Below is the button tag code copied from page source using Inspect:
<button tccltracking="click" data-ux="Button" type="submit" data-aid="CONTACT_SUBMIT_BUTTON_REND" data-tccl="ux2.contact.submit_form.click,click" class="x-el x-el-button c2-1 c2-2x c2-2y c2-2u c2-2v c2-2z c2-30 c2-3 c2-31 c2-32 c2-r c2-33 c2-1v c2-b c2-26 c2-d c2-e c2-2b c2-34 c2-2i c2-35 c2-36 c2-4 c2-5 x-d-ux x-d-aid x-d-traffic2 x-d-tccl">Send</button>
I am not a programmer and would appreciate as much detail as possible. I can view page source to obtain tag and class names to cite as necessary.
Include or find an element in your rendered page with an id attribute. Then, run the following javascript:
let id = '<the id that you want>'
let element = document.findElementById(id)
console.log(element)
if null is printed, then your answer is no. Anything else, then your answer is yes.
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 use TEmbeddedWebBrowser to fill a html form using FillForm method. But my html form contains a fully javascript based editor and i don't know how to fill that.
Something like this :
your comment :
<script type='text/javascript' src='public/scripts/src/editor.js?1'></script>
And the submit btton :
<input type="submit" name="btnSubmit" id="btnSubmit" value="Send" class="btn" onclick="rtevalue("data[body]",437934);" />
The editor itself is a DIV (could be other HTML element) or IFRAME set to contentEditable / designMode = on.
If the element is a DIVyou could use it's InnerHTML property.
For the best results with an IFRAME use the below code:
procedure TForm1.Button1Click(Sender: TObject);
var
editorDoc: OleVariant;
range: OleVariant;
id: OleVariant;
begin
id := 'editor'; // frame ID
editorDoc := (WebBrowser1.Document as IHTMLDocument2).parentWindow.frames.item(id).Document;
range := editorDoc.body.createTextRange();
// range.collapse(false); // if you need to append
range.select();
range.pasteHTML('<b>Boo!</b>');
end;
Notes:
No error checking to simplify the code.
You might also try range.execCommand('inserthtml', false, MyText) (Not tested with TEmbeddedWebBrowser, but had bogus results when I tried it with plain HTML/Javascript on IE).
I have no experience concerning this TEmbeddedWebBrowser tool, but according to your post I'm thinking of a way to retrieve the form's fields. Once you know what fields it contains, I suppose you can fill them as it doesn't seem to be the purpose of your post.
Assuming there is a form declared and it is reachable: you can grab the form and
parse its .elements collection: easily if it's declared in your page
(give it an id attribute, then use a document.getElementById()),
it may still be doable if the form is declared by/inside
editor.js, using document.forms then.
Otherwise: you can get a dump
script from the Net - like this one -
and see what is printed when you call (after including editor.js
naturally) dump(data) or dump(data[body]). As data[] is
used as an argument to the rtevalue() called by your submit button's
onclick, it should contain the form's key/value pairs. The bad thing about this method is that data[] must
be filled by Javascript, so if your form has radio buttons or
checkboxes you may only see the selected ones, which is why I would give a shot at the first option before trying this trick.
About the comments, you should not directly use innerHTML to insert an HTML subtree to the document as most of the times it doesn't work (especially when forms are involved), have an appendChild() redo the work to ensure a correct document, like this:
var dummyContainer=document.createElement("span");
var dummyContainer.innerHTML="..."; //insert stuff here, because it's easy to use ;)
myContainer.innerHTML=""; //clearing your "real" container doesn't add anything to the HTML tree, it'll work - you can also use removeChild() in a loop (but it's not as easy to use!)
myContainer.appendChild(dummyContainer); //appendChild will translate properly the text inserted by innerHTML in dummyContainer into a clean HTML subtree
As it's recommended, Javascript must be kept in a physically separate file (to be unobtrusive). So how do I access a particular element in particular page? should I detect those elements by id? that would mean 2 elements can't have the same id even if they are not located in the same page.
Well, for instance, using the Html helpers methods generates element's name + id from the model's properties. If I use the same model in several pages, many elements will have the same id. How can I target them in different pages. By the way, CSS work the same way.
EDIT
Let's say I've this
<% = Html.TextBoxFor(x => x.FirstName)%>
It will generates
<input type = "Text" name = "FirstName" id = "FirstName"/>
Let's say I've this textbox in 2 differen pages. If want, for instance, to disable the textbox located in page A, how do I do it knowing they are two of them in 2 different pages. How do I discriminate them from my external javascript file?
Thanks for helping
I suggest that for each page the uses the same model, you create a wrapper div
<div class="pageA">
// the model stuff here
<% = Html.TextBoxFor(x => x.FirstName)%>
</div>
<div class="pageB">
// the model stuff here
<% = Html.TextBoxFor(x => x.FirstName)%>
</div>
and then use Jquery selectors to get the correct element $(".pageA input[name='FirstName']") (not sure if this syntax is correct).
You cannot have multiple elements on the page with the same id. That isn't valid HTML.
So when you use the same HTML helper multiple times, you need to pass different names:
<%: Html.TextBox("Foo", Model.Foo) %>
<%: Html.TextBox("Bar", Model.Bar) %>
Correct me if i'm wrong, but are you saying, you have some elements with the same id, on multiple pages, that you want to attach different behaviour to? If so then this could help you out. if not, then what Craig said.
You can use more specific selectors, or give your selectors context
have a look at the documentations here: http://api.jquery.com/jQuery/
under this header:
jQuery( selector, [ context ] )
it explains a bit about selects and context. you should be able to use this and some creative page building to target the right element with your jQuery.
So you have two files, each with a text field with the id "FirstName". When you're script runs on Page A you want to disable the field, but not when your script runs on Page B.
Is the structure of the two pages identical? I suspect not if you're handling these fields differently. Use the context to your advantage. Like if the one on Page A is in a div with id "thisDiv" and the other is in a div with id "thatDiv" you could document.getElementById('thisDiv'). If you get an element then disable the field, if not do nothing.
If you want a more specific answer you're going to have to give us more context.
Well JavaScript may be kept in a separate file or not, but it is definitely included as part of the HTML send to the browser for a particular page. I Hope I've understood your question, but, generally if you have you JavaScript code in a file, lets say utils.js then in your html generated should include (probably within the <head> tag):
<script type="text/javascript" src="/path/to/utils.js"></script>
The script get included in the page, and when the browser encounters this, it loads and then runs the script, for that page. Therefore, it is not important what the ids for elements on different pages are.
Does that make sense, or have I completely misunderstood your question?
Update:
Ok, so based on your comments, I think I understand. You have
//Page 1
//When loaded, this input should flash blue via javascript for example
<input id="firstName" .../>
And
//Page 2
//When loaded, this input has some other fancy effect/behaviour
<input id="firstName" .../>
Well in this case, as far as I see, there are only 2 types of answers. Have two seperate external js files, one per page and this way you can change to your hearts content ...OR... have some sort of hidden field in your page that tells your script what page it is looking at (this seems hacky)
<input type="hidden" value="page1"/> //etc..