script not executing in jsf - 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.

Related

Some weird behavior of Chrome (FF too) when debugging javascript part of JSF composite component

I'm making JSF composite component, something simple with the following code:
<cc:implementation componentType="timePickerComponent">
<div id="#{cc.clientId}" style="#{cc.attrs.style}">
<h:outputScript name="js/timepicker/timepicker_helper.js"/>
<p:autoComplete id="timepicker"
scrollHeight="200"
onfocus="openAutocompletePanel(this);"
widgetVar="#{cc.attrs.widgetVar}"
completeMethod="#{cc.completeMethod}"
value="#{cc.timeLocal}"
size="5"/>
</div>
</cc:implementation>
And timepicker_helper.js which contains only single function:
function openAutocompletePanel(field){
console.log("ups");
console.log(field);
}
When I try to debug openAutocompletePanel function in Chrome developer tools, i.e. defining breakpoints at the beginning or at the middle of the function it doesn't work. But function itself is invoked, it prints to console.
When I added row debugger; in the middle of the openAutocompletePanel, it has stopped at this point but instead of file timepicker_helper.js Chrome has opened file VM3339.
There is snapshot of my screen:
This isn't first time I debug JSF's javascript in Chrome but first time I've met this issue. What could cause such behavior?
Thank you.
UPDATE:
Ok, it was my fault.
BalusC said many time that when you include javascript in composite component you should specify target="head" otherwise it will be loaded multiple time.
When I changed loading sentence to <h:outputScript name="js/timepicker/timepicker_helper.js" target="head"/> the problem has gone.
I cannot consider this as answer because I not sure 100% if I right.
Sorry, cant put it into comment, so put it as an answer...
The such behavior could be if timepicker_helper.js is loaded and executed by JavaScript eval(); function.
In this case developer console will show the common file where your origin file has been included, like you see: VM3339.
And debugger; is the only way to break inside in this case.

JSF format an h:inputText while typing

I'm constructing a page with pure JSF.
On that page I've some field for dates... but I don't need a date picker. So I used an <h:inputText>
This is working when I type a valid date like 01/01/1970. But I need to type the "/".
I want to put some mask on this input. How can I do that?
You'll want to use jQuery or a JSF component library like Primefaces.
With Primefaces inputMask, you can do this
<p:inputMask id="date" value="#{maskView.date}" mask="99/99/9999"/>
Alternatively, if using jQuery, the jQuery Mask plugin provides similar functionality. It is used by simply locating the input element, then applying the mask() javascript function
$(document).ready(function(){
$('.date').mask('00/00/0000');
});
If Primefaces and jQuery are not options, plain Javascript can always be used. A bit of warning thought, using plain JS for this will require a lot of work.
Solved with plain JS...
Added <f:ajax event="keypress" onevent="formatDate(this)"/> on inputText
and the function
function formatarData(obj) {
if (obj.value.length == 2 || obj.value.length == 5) {
obj.value += "/";
}
return;
}

How to destroy growl div component that hides other stuff

On my jsf page at some point I send a message to the growl component.
<p:growl id="growlLong" for="growlLong" showDetail="true" life="10000" sticky="false"/>
Once the 10sec is over, or dismissed by clicking the X, the issue that occurs is the element below the growl is not selectable. By inspecting the components on the page, looks like the actual div stayed there and blocks the content below it.
<?xml version="1.0" encoding="UTF-8"?>
<div class="ui-growl-item">
<div class="ui-growl-icon-close ui-icon ui-icon-closethick" style="display: none;" />
<span class="ui-growl-image ui-growl-image-info" />
<div class="ui-growl-message">
<span class="ui-growl-title">Success!</span>
<p>Configuration successfully saved.</p>
</div>
<div style="clear: both;" />
</div>
So, the question is - how do I make this to go away and keep the content below still usable?
Here is the screenshot of the issue, as seen with "inspect element", blue boxes are existing links, red box is the dismissed growl. Inside the blue box, we can't click the part that is covered by the red box.
This topic might be older but I just recently stumbled upon it:
The reason that the showcase is working but my version was not was that I gave the .ui-growl CSS class a height AND a width. In the showcase, the size of the container is only defined by its content and thus 0 if there are no items to display.
I moved my height definition to .ui-growl-item (which is more appropriate anyhow) and now it's working like a charm.
While the it would be desirable to be able to tell growl to not leave behind the <div id="growlLong_container"> structure in the DOM, the simple solution is to just select it and remove it using your favorite method to manipulate the DOM.
The ID appears to be the ID you passed to growl: id="growlLong" + "_container". With a DOM ID it is a simple matter of selecting it and removing it.
Yes, it would be nice to be able to get growl to not leave it in there. However, there is a point of diminishing returns vs. the amount of effort you spend trying to find a solution. It appears to be well past the point where you should just use a hack and remove it. Make a note about it, move on. Leave a comment in the code that this is why you are making the DOM manipulation. A possibility rather than removing teh <div> is to adjust the z-index such that it is below that of the UI elements. Another possibility is to add display:none; to the style. Obviously, code it such that if the <div> is not there nothing goes wrong. Verify that the next use of growl still performs correctly.
Ask on the Growl discussion group. Submit it as a bug with growl. If a way surfaces to make growl not leave something like this in the DOM revisit the code and apply it.
As to removing it, if you have JavaScript available it is as simple as:
document.getElementById("growlLong_container").remove();
To be more specific we really need more information about your code and the environment in which you are running.
A "solution" that should remove the <div>:
Hopefully you will receive an answer which allows the elements to be hidden/removed by growl. However, there does not appear to be one at present.
The following script should wait around checking every 250ms to see if the <div id="growlLong_container"> has been entered into the DOM. Once the <div> has been entered into the DOM, the script will wait 10s. If the <div> exists after the 10s it will be removed. The script is a hack. But it should work.
You will need to place it such that it makes it onto the page, either enclosed in tags (as are here), or in a file without the first line:<script class="code" type="text/javascript"> and the last line: </script> removed. If you use a separate file you will need to have it included in a similar manner as you do jquery.js, foundation.js, foundation.topbar.js and foundation.tooltip.js.
<script class="code" type="text/javascript">
(function () {
"use strict";
const maxGrowlTime = 10000; //In milliseconds
const checkFrequency = 250; //In milliseconds
var intervalTimer=0;
var foundGrowl=false;
function dismissGrowl() {
var growlId;
growlId = document.getElementById("growlLong_container");
if(growlId) {
growlId.parentNode.removeChild(growlId);
}
foundGrowl=false;
setGrowlCheckInterval();
}
function checkForGrowl() {
var growlId;
if(foundGrowl) {
return;
}
growlId = document.getElementById("growlLong_container");
if(growlId) {
foundGrowl=true;
clearInterval(intervalTimer);
setTimeout(dismissGrowl, maxGrowlTime );
}
}
function setGrowlCheckInterval() {
intervalTimer = setInterval(checkForGrowl, checkFrequency );
}
setGrowlCheckInterval();
})();
</script>
My hope is that you find an answer that does not require a hack such as this. However, this should solve your problem, at least to an extent. With the script, the prevention of using those controls will last for at least the entire 10s up to 10.25s even if the user dismisses the growl early. With the two screenshots mentioned in the comments it would probably be possible to change the script such that it detects if the user dismisses the grow and then remove the <div> immediately. This would make it more responsive to user input.
This solution assumes that the <div id="growlLong_container"> does not exist in the DOM prior to your issuing the <p:growl id="growlLong" and that it is not needed afterwards. This is very likely because the ID of the dive appears to be composed of the ID you pass the growl.
Mainly, this issue looks like a bug or incompatibility issue between components.

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.

Use the value entered in a JSF page for Java Applet

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.

Resources