Asked  7 Months ago    Answers:  5   Viewed   60 times

Problem: Sometimes you will want to access a component from javascript with getElementById, but id's are generated dynamically in JSF, so you need a method of getting an objects id. I answer below on how you can do this.


Original Question: I want to use some code like below. How can I reference the inputText JSF component in my Javascript?

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core">
    <head>
       <title>Input Name Page</title>
        <script type="javascript" >
          function myFunc() {
            // how can I get the contents of the inputText component below          
            alert("Your email address is: " + document.getElementById("emailAddress").value);
          }
       </script>
    </head>
    <h:body>
        <f:view>
            <h:form>
                Please enter your email address:<br/>
                <h:inputText id="emailAddresses" value="#{emailAddresses.emailAddressesStr}"/>
                <h:commandButton onclick="myFunc()" action="results" value="Next"/>
            </h:form>
        </f:view>
    </h:body>
</html>

Update: this post Client Identifiers in JSF2.0 discusses using a technique like:

<script type="javascript" >
  function myFunc() {
    alert("Your email address is: " + document.getElementById("#{myInptTxtId.clientId}").value);
  }
</script>

<h:inputText id="myInptTxtId" value="backingBean.emailAddress"/>
<h:commandButton onclick="myFunc()" action="results" value="Next"/>

Suggesting that the attribute id on the inputText component creates an object that can be accessed with EL using #{myInptTxtId}, in the above example. The article goes on to state that JSF 2.0 adds the zero-argument getClientId() method to the UIComponent class. Thereby allowing the #{myInptTxtId.clientId} construct suggested above to get the actual generated id of the component.

Though in my tests this doesn't work. Can anyone else confirm/deny. The answers suggested below suffer from drawback that the above technique doesn't. So it would be good to know if the above technique actually works.

 Answers

52

Answer: So this is the technique I'm happiest with. Doesn't require doing too much weird stuff to figure out the id of a component. Remember the whole point of this is so you can know the id of a component from anywhere on your page, not just from the actual component itself. This is key. I press a button, launch javascript function, and it should be able to access any other component, not just the one that launched it.

This solution doesn't require any 'right-click' and see what the id is. That type of solution is brittle, as the id is dynamically generated and if I change the page I'll have to go through that nonsense each time.

  1. Bind the component to a backing bean.

  2. Reference the bound component wherever you want.

So here is a sample of how that can be done.

Assumptions: I have an *.xhtml page (could be *.jsp) and I have defined a backing bean. I'm also using JSF 2.0.

*.xhtml page

<script>
  function myFunc() {
    var inputText = document.getElementById("#{backBean.emailAddyInputText.clientId}")                 
    alert("The email address is: " + inputText.value );
  }
</script>

<h:inputText binding="#{backBean.emailAddyInputText}"/>
<h:commandButton onclick="myFunc()" action="results" value="Next"/>

BackBean.java

UIInput emailAddyInputText;

Make sure to create your getter/setter for this property too.

Tuesday, June 1, 2021
 
Dunc
answered 7 Months ago
22

Haven't worked with highcharts , but I did with other charting library...

I'll give you general Instructions on how to combine js based charting directory it with JSF (I'm sure that there are others way's like using servlets and etc...)

1) build a working "hard coded" js only example in your JSF project include the relevant *.js files needed by the library add the "container" div that is required to your page and finally wrtie the js script that build your chart with hard coded values

2) place your hard coded values into your Bean String property and place a ref' to that property in your .xhtml page something like that <h:inputHidden id="chart_input_data" value="#{myBean.valueOfChart}" /> and access it in your js code like that

//I used jQuery selectors....
var data_for_chart = $('input[id$="chart_input_data"]').val(); //you can use a simpler selector like $("#chart_input_data") too

than use the variable data_for_chart as chart series input (or for whatever parameter of your chart constructor)

3) finally I guess you would like to turn some list of Pojos into a proper json format which is most like wold "fit like a glove" for the HigthCharts constractor , this you can achieve with Gson library something like gson.toJson(yourListOfValues) see Gson user guide

Note

This technique should work for all charting library's , such as flot , flotr2 , gRaphael , jqPlot and more...

Saturday, July 3, 2021
 
octern
answered 5 Months ago
38

This is a great tutorial that talks exactly about that: http://www.roseindia.net/java/pass-value-example/pass-value-from-iframe-parent.shtml

you can use it only if the two pages are served from the same domain. There are many solution for cross-domain scripting as well..you can read more here: http://softwareas.com/cross-domain-communication-with-iframes

Saturday, July 31, 2021
 
silvster27
answered 4 Months ago
70

Thanks to the suggestion by @Al-Mothafar, I have finally solved my issue in the following way:

index.xhtml

...
<h:body>
    <script type="text/javascript" src="resources/Javascript/jquery/jquery-1.7.2.js" />
    <script type="text/javascript" src="resources/Javascript/MyJS.js" />
    <script type="text/javascript" >
        var myBeanProperty = '#{myBean.myProperty}';
    </script>        
</h:body>

MyJS.js

$(document).ready(function() {
    alert(myBeanProperty);
});
Friday, August 20, 2021
 
xilec
answered 4 Months ago
94

This isn't an exhaustive guide to rendering because it doesn't include the bits about shader management; instead it focuses on how drawing of WebGL primitives is actually performed, and how to use orthographic projection to precisely position vertices on the screen.

For more information, I highly recommend these sources:

  • Learning WebGL - tutorials
  • The WebGL specification
  • The Typed Arrays specification

WebGL does all of its drawing with Vertex Buffer Objects (VBOs), so you need to compile all your data into 3D vertices and send them down to the video card in as few VBOs as possible (to maximize performance).

A VBO can be created in WebGL like so:

var vbo = gl.createBuffer();

Then you need to send the data down to the buffer, usually in the form of a Float32Array. If you already have your data in the form of a regular JavaScript array, then you can use new Float32Array(jsArray) to initialize the Float32Array from the jsArray's contents. Try to do this rarely though. Typed arrays are very fast, but initialize very slowly. It's best to create them once and reuse them whenever possible.

Once you have a Float32Array, you can pass the data down to the buffer like so:

gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
gl.bufferData(gl.ARRAY_BUFFER, float32Data, gl.DYNAMIC_DRAW);

You'll need to perform a bufferData or bufferSubData call every time the data changes.

By this time the data is on the graphics card, so you only need to actually draw it:

// bind the VBO to be drawn if you haven't already
gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
// send the vertex data to the shader program
gl.vertexAttribPointer(vertexAttributeLocation, 3, gl.FLOAT, false, 0, 0);
// draw the buffer
gl.drawArrays(gl.POINTS, 0, float32Data.length / 3);

Note that although the graphics card can hold quite a few VBOs, you should use as few of them as possible, because the more drawArrays calls you have to perform, the slower things are going to get. Indeed, if you render only a single pixel at a time in a given VBO, it's going to be too slow to run.

The reason the length of the Float32Array is divided by 3 is because each single data element is a 3D (X, Y, Z) coordinate, so each data element consists of 3 float components. Note that the first argument to gl.drawArrays was gl.POINTS. This instructs the graphics card to draw a single point (by default, a single pixel in size) for each item in the array. There are other ways to draw, and if you need to fill a group of pixels, one of the other draw modes (e.g. gl.TRIANGLES) may be more to your liking.

As for lighting up specific pixels, it depends on how the shader is written, but most likely you're making use of a modelview matrix and a projection matrix. The modelview matrix represents the orientation of the camera relative to the points being drawn, and the projection matrix represents the camera dimensions (width and height, field of view, nearest and furthest visible ranges, etc). So if you want to light specific pixels, your best bet is to apply an orthographic projection matrix with a width and height equal to the width and height of the canvas; and a modelview matrix set to the identity (no transformation). In an orthographic projection, objects don't shrink as they get further away from the camera, so they're very helpful for specifying exact positions relative to the screen. Also, if you give them the proper dimensions, you can position vertices very precisely -- at specific pixels, if you wish.

Different matrix libraries work in different ways, but for example, to set up an orthographic matrix in gl-matrix, you can do so like this:

var ortho = mat4.ortho(left, right, bottom, top, near, far);

The exact numbers depend on your preference; if you'd like to place the origin (0, 0) at the bottom-left of the canvas, you'd do so like this:

var ortho = mat4.ortho(0, canvas.width, 0, canvas.height, 0.01, 200);

Note that the Z value of each point still has to lie between near and far in order to be rendered, however, and the near value cannot be set to 0.

Let me know if any of this needs clarifying.

Saturday, October 9, 2021
 
Whakkee
answered 2 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :
 
Share