0

Since I started working with JSF pages, I struggled with CSS selectors. I thought that I understood the basic concept but turns out I must be missing something. Of course I read http://api.jquery.com/category/selectors/ but my impression is that these examples are too simple for my use case. So here is what I got in minimalistic form:

<?xml version="1.0" encoding="UTF-8"?>
<ui:composition xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:p="http://primefaces.org/ui">
<ui:define name="center">
    <p:dialog header="Dialog" widgetVar="findParamDialog" resizable="false" id="findParamDlg" modal="true">
        <h:form id="findParamForm">
            <p:scrollPanel id="sp" mode="native">  
                <p:dataTable id="qPdt" var="p" value="..." rowKey="#{p}" selection=""
                 selectionMode="single">
                    <p:column>...</p:column>
                </p:dataTable>
            </p:scrollPanel>

        <script>
        $(document).ready(function() {
            $('#sp').on('click','tr',function() {
                var $item = $(this).closest("tr").find("td:nth-child(1)").text().trim();
                alert('ye');
            });
        });   
        </script>

        </h:form>
    </p:dialog>        
</ui:define>

When I click the row of my datatable I want the alert popup. On another xHTML page this is already working but the scenario is that there is no dialog that contains the scrollpanel.

Now, what I expect is that #sp refers to the one and only element with that id. But that's not working. Moreover, several tries to include the form (findParamForm\\:sp or \\:findParamForm\\:sp or #findParamForm\\:sp or findParamForm sp or findParamForm > sp) didn't work either. So what is my thinking mistake here? Why can't I just refer to sp with the id selector #?

I have the impression is has something to do with these so-called container elements. Please tell me what I am missing here. I am 99,9% sure that the script itself is working, so I suspect the selector. Thanks in advance

dasLort
  • 1,264
  • 1
  • 13
  • 28
  • escape JSF ids in javascript. Here's an answer that could help you [link](http://stackoverflow.com/a/21529321/1227023) – Kuba Jul 30 '14 at 09:42
  • as this may be a general hint (which I dont know how to implement) does this have anything to do with my question? Not sure if I understand you correctly. How can I *base* JS on JSF-generated HTML output? – dasLort Jul 30 '14 at 10:12

2 Answers2

1

typo error

$("#sp").on("click","tr",function() {
     ^^^^-----
Balachandran
  • 9,567
  • 1
  • 16
  • 26
0

Basically it's not too wise to access ids that are generated by JSF like

formId:namingContainerId:componentId

because they can change if you reuse your components. It's much wiser to access them by css class.

What you are doing though and what BalusC mentioned - You base your JavaScript(client side) code on a JSF XHTML(server side). JSF is a HTML generator, it generates HTML that is different in browser(when you analyze source code) than what you see in your text editor. I bet you have never seen a <h:panelGroup> tag in your browser. p:scrollPanel will simply generate a couple of <div> tags with some style.

If you really want to access a JSF component by it's ID like formId:componentId then you would have to escape colons, otherwise jQuery thinks they are some css pseudo selectors. Here's a snippet.

XHTML

<h:form id="formId">
    <h:panelGroup id="componentId" style="display: none;" />
    <h:panelGroup onclick="test('formId:componentId');" />
</h:form>

Output

<form id="formId" ...>
     <span id="formId:componentId" style="display: none;" />
     <span onclick="test('formId:componentId');" />
</form> 

JavaScript

function test(id) {
     id = id.replace(/:/g, "\\:");
     $("#" + id).show();
} 

or

function test(id) {
     element = document.getElementById(id);
     $(element).show();
} 
Kuba
  • 2,069
  • 23
  • 30
  • Thx for your reply. I don't use generated IDs, I only use the ones I gave my components. I know that I have to escape colons with double backslash and I know that JSF generates an HTML page. But my question is "why can't I access something by it's attribute `id` when I use `#givenId`?" And how can I add the script to HTML if I don't put it inside the .xhtml file? I don't have access to an intermediate form, do I? – dasLort Jul 30 '14 at 13:22
  • you can access element by it's id, just escape it in .js not in .xhtml and make sure you use the id with everything that is prepended to it's core. And BTW do not embed JS in XHTML! – Kuba Jul 30 '14 at 13:26
  • Aha! Now we are getting closer. "*prepended to it's core*" what do I need to prepend and why if the id is unique? – dasLort Jul 30 '14 at 13:29
  • read about naming containers in JSF. Basically a `` is a naming container, so it prepends it's id to every component that is inside it. Just analyze my example. – Kuba Jul 30 '14 at 13:31
  • That's exactly what I tried and how I used it all the time, except I didn't use a script to substitute `:` by `\\:` and to prepend `#`. So now this is clear, what reasons can it have that the Id can not be found? – dasLort Jul 30 '14 at 13:41
  • the reason might be that you escape it in xhtml instead of .js file and while passing it to js one escape slash disappears. Select the element either by `document.getElementById` or pass unescaped id to .js and escape it there. Use `console.log(id);` to know where you are standing. – Kuba Jul 30 '14 at 13:44