Use the value entered in a JSF page for Java Applet - jsf

I have created a JSF page which asks the user to enter a value, and this value is being processed via Applet and create a barcode image based on the inputted value. My problem is how can i get the value from the JSF Page and use it in my Applet.. Thanks!

Use JavaScript. E.g.
<h:inputText ... onchange="updateBarcodeApplet(this.value)" />
...
<applet id="barcodeApplet" ...></applet>
with this JS
<script>
function updateBarcodeApplet(value) {
var barcodeApplet = document.getElementById("barcodeApplet");
barcodeApplet.updateValue(value);
}
</script>
and in Applet
public void updateValue(String value) {
// Do your business here.
}
(yes, all Applet's public methods are just available as is in JS)
Needless to say, using an applet for this job is pretty clumsy. Not all clients support or even appreciate applets. I'd also opt for a simple <img> element with a servlet which returns the image as suggested by Denisk. You just have to update the <img src> by JSF or JavaScript.

Why do you do it in a hard way? You don't really want an applet here, create the image on server, serialize it to response stream and display it as plain image.

Related

Display an Image attachment in XPages via a Java Bean

I have a public facing application that is architected with multiple nsfs. I have one nsf that's public facing that manages data through Java controllers in the non-public facing nsfs. For security reasons the non-public nsfs do not allow URL browsing so I can't use the usual "/0/" + UNID + "/$FILE/" + PhotoFilename to display the image on the XPage.
In the controller I can get the attachment (EmbeddedObject) from the document, but I'm not sure how to get it to display in an <xp:image> or <xp:inputRichText> control.
I am using the OpenNTF api, but I can't see anything there that seems to help.
Thanks,
Scott.
One solution: base64 encode the image and use the encoded string in an img tag. Here's a simple code example that uses the inputstream from the EmbeddedObject in a method in a Java controller:
public String getImageAsBase64(InputStream inputStream) {
return Base64.encodeBytes(IOUtils.toByteArray(inputStream));
}
You can then display the base64 encoded image (assuming your Java controller is called 'controller'):
<img src="data:image/jpeg;base64,#{javascript:controller.getImageAsBase64()}" />

How to use Growl with 'position: sticky' in Primefaces?

I am trying to change the p:growl position of primefaces through the .ui-growl class to use position: sticky. However, since the component is rendered at the end in body, the relative behavior of the position does not work as I would like.
Is there any way to use the sticky position for this component?
Or some way to get the component to render where it is declared?
PrimeFaces 5.1;
Mojarra 2.1;
Disclamer: I tried this with the PF 7.0 showcase, but I think the basics also work with the 5.1 version.
You effectively have 4 options. The latter three all need you to inspect the javascript source of the component (which is open, so you can ALWAYS inspect it before asking questions, the java source is irrelevant here) and for the first solution it helps to see how the component works, but inspecting with a browser developer tool is sufficient (that is how I did it).
Basic analysis with or without looking at the source
This is a variant on your "Or some way to get the component to render where it is declared?". Since on the client side, it is all plain html, css and javascript, you can manipulate with al tools available on the client-side.
You can see that the main part of the grow is html technically rendered where it is declared. Check the PrimeFaces showcase and you'll see
<span id="j_idt700:growl" class="ui-growl-pl" data-widget="widget_j_idt700_growl" data-summary="data-summary" data-detail="data-detail" data-severity="all,error" data-redisplay="true"></span>
right inside the form where it also is in the xhtml. The javascript of the component creates the client side dom things, amongst which is the container that you see right before the end of the body (from the showcase)
<div id="j_idt700:growl_container" class="ui-growl ui-widget" style="z-index: 1002;"></div>
This last piece is html is where the individual growls are added to when they need to be rendered and hence the part that makes the component in most normal cases behave correctly but needs to be done differently in your case.
Solution 1, pure client-side component agnostic solution
Effectively this is as simple as moving this piece of html in the dom, see How to move an element into another element?.
In the online showcase I put the following jquery code in the browser developer tool console
$("#j_idt700\\:growl_container").prependTo(".layout-content");
And added the following css
position: sticky;
top: 10px;
float: right; // this is needed in the showcase, might not always be needed
And it worked.
The jquery should be put somewhere in your page where it runs after the component javascript is executed, so best is to do it right before the end of the body.
Keep in mind that the j_idt700 prefix is the dynamic id of the form in the showcase (it does not have a fixed id here), but you can also use different selectors based on the classes or whatever)
Solution 2, changing the source 'locally'
In the javascript source, you can see where the container is technically rendered
render: function() {
//create container
this.jq = $('<div id="' + this.id + '_container" class="ui-growl ui-widget"></div>');
this.jq.appendTo($(document.body));
//render messages
this.show(this.cfg.msgs);
},
Changing the this.jq.appendTo($(document.body)); in some way to have it appended to the current html node ('this'?) will make it work too. Regarding the overriding, you have two options
How do I find and/or override JavaScript in Primefaces component based on widgetVar?
Override a method from a Primefaces specific widget
Solution 3 Changing the source server side
Effectively you do the first part of #2 but patch the source and create a new custom PrimeFaces version
Solution 4 Make this feature avaiable for others too
What can be done here is to create a new attribute on the component and patch the source in some places so it is configurable to have the component behave as it is now or as sticky (they changed the existing 'sticky' attribute to 'keepAlive' in 7.0.x so sticky is avalable again ;-)). Of course this should be submitted as a patch then...

Add target property for dropdownnode in Widget Container

I would like to add a target (e.g. _blank) property for a basicLeafNode on the Widget Container from the extension library.
I do not see the property for this.
Instead I could use the onClick property and return an URL. But then I still would have no target defined.
I could add a postScript method
var target = url;
view.postScript("window.open('"+target+"','_blank')")
but this fires when the container is loaded.
Can I add a target property without using the onClick Property?
In case I use the onClick property what method should I use or how I prevent the postscript is executed when the container is loaded?
The basicLeafNode doesn't currently provide a target property. You have 2 courses of action:
implement your own custom node as Michael suggested (hard)
use a class on the link e.g. "newpageopen" and add an onPageReady script that selects all a elements with the calss newpageopen and add the target property to the resulted HTML.
Something like this:
require(["dojo/ready","dojo/query"], function(ready){
ready(function(){
dojo.query("a.newpageopen").attr("target", "_blank");
});
});
Hope that helps;
To make this list of solutions a bit longer here another on wich does not require dojo or jquery:
Instead of using your code as SSJS like:
var target = url;
view.postScript("window.open('"+target+"','_blank')")
You can use the Client Side Code and add SSJS code in #{javascript:}' wich i think is the shortest solution on this Problem. Here a hardcoded example:
<xe:basicLeafNode>
<xe:this.onClick><![CDATA[window.open('#{javascript: return "http://www.google.com";}','_blank');]]></xe:this.onClick>
</xe:basicLeafNode>
the above example will also work with viewScope variables or SSJS funktions:
<xe:basicLeafNode>
<xe:this.onClick><![CDATA[window.open('#{javascript: return viewScope.url;}','_blank');]]></xe:this.onClick>
</xe:basicLeafNode>
You can add the target attribute using JavaScript. It's kind of inconvenient way but would work.
You can use dojo.query to query the HTML output generated by basicLeafNode on the Widget Container. Once you get the node of <a> then you can add attribute using dojo.attr.
One problem you might face is that the ID generated by XPages contains the character :, which will not work so you would have to escape it.
function escapeColon(controlID) {
return controlID.replace(/:/g, "\\3A");
}
So your code would be something like:
dojo.addOnLoad(function() {
dojo.attr(dojo.query(escapeColon("#{id:ID_of_basicLeafNode}") + " > a")[0], "target", "_blank");
});
The code escapeColon("#{id:ID_of_basicLeafNode}") + " > a" would generate a CSS selector. Here I am assuming that basicLeafNode on the Widget Container would generate something like this <div id="_id1:basicLeafNode"><a href=".... So the CSS selector would search for a tag with that ID and inside it the <a> tag. You would have to modify this based on the output that is generated.
As I said its a bit inconvenient. Also I haven't tested this code.

script not executing in jsf

I am using an ajax request for autocomplete in jsf, I want the autocomplete suggestions to disappear once I click at any other point in website.
I am using onblur, and calling script for to change the display to none, but the script does not appear to be working.
this is the autocomplete code in my xhtml:
<rich:autocomplete id="test" required="true" onblur="hidebox()" requiredMessage="Field is blank" mode="cachedAjax"
minChars="3" value="#{action.do.testmethod}" autocompleteMethod="#{action.autocomplete}">
</rich:autocomplete>
this is the hidebox code:
<script type="text/javascript">
function hidebox() {
alert("Test");
document.getElementById('test').style.display = "none";
}
</script>
The actual id of the element is not test. JSF composes the ID (probably it will be [formId]:test) to avoid ids being repeated (more so when used in tables, lists, etc.).
You can try to do document.getElementById('[formId]:test').... You can use your browser inspector utilities to check the actual Id, if you are not sure of what [formId] is. And you can just do onblur="hidebox(this)" and use directly the object in the JS function.

Custom JSF component: Using "startElement" with "script" results in a comment

I'm rendering a custom JSF component. In the method encodeBegin I want to include some java script.
public void encodeBegin(FacesContext context) throws IOException {
ResponseWriter writer = context.getResponseWriter();
writer.startElement("script", this);
writer.writeAttribute("type", "text/javascript", null);
writer.writeText("var width=400",null);
writer.endElement("script");
}
When rendering the component the content of the script tag is commented out.
<script type="text/javascript"><!--
var width=400;
//--></script>
Can anybody explain why this comment appears and how I get rid of it?
Thanks in advance!
This is specific to the MyFaces implementation, not to JSF specification. The Mojarra implementation doesn't do that.
This approach of putting JavaScript body in a HTML comment is basically a leftover of the HTML prehistory back when browsers existed which doesn't support <script> elements. Those HTML comments basically hides the JavaScript content to prevent those ancient HTML parsers from interpreting and displaying JavaScript code as plain text.
See also Mozilla Developer Network - Writing JavaScript for XHTML:
This was common practice in HTML, to hide the scripts from browsers not capable of JS. In the age of XML comments are what they were intended: comments. Before processing the file, all comments will be stripped from the document, so enclosing your script in them is like throwing your lunch in a Piranha pool. Moreover, there's really no point to commenting out your scripts -- no browser written in the last ten years will display your code on the page.
Note the last sentence, this is very true, no single browser developed in the last decade would do that anymore. MyFaces is apparently a bit overzealously assuming that one would still be using such a prehistoric browser nowadays.
It is ok
The practice is marking the javascript code as comments, so automatic tools don't try to parse it as HTML (for example, tools that check that your page is HTML 4 compliant).
The Javascript engine will ignore the HTML comment and process the code (Javascript comments are /* and //
A variation of this approach is putting the Javascript inside a CDATA tag, for the same reasons.

Resources