miracle occurs here|

Archive for November, 2010

JavaScript – Referencing CSS Properties Containing Hyphens or Dashes

Tuesday, November 23rd, 2010

If, in JavaScript, you need to reference/manipulate CSS properties at runtime that contain a hyphen or dash in their names, omit the hyphen and, instead, camelcase the surrounding letters. You need to do this because hyphens in JavaScript variable names are illegal. For example, this won’t work:

div.style.background-color = "red";
div.style.z-index = 3;

Whereas this will:

div.style.backgroundColor = "red";
div.style.zIndex = 3;

Hope this helps.

JSF – You Can’t Submit a Disabled Form Element

Friday, November 12th, 2010

I previously discussed the JSF truism that you can’t re-render something you never rendered in the first place. Here’s another one:
You can’t submit a disabled form element.

Here’s the situation. We’ve got a form with a text input element that, by default, we want to be disabled unless the user changes something else, client-side, on the page. The obvious, intuitive way to do this is with the disabled attribute:

<h:inputText id="newId" value="#{thePage.newId}" disabled="true" />

Then, once the user initiates whatever action to enable the text input element, we use some JavaScript to twiddle the disabled attribute, thereby making it editable. However, if the user then fills out that text input element and submits the form, the backing bean won’t receive the user-supplied value. Why? I can only surmise that, according to the JSF viewState, the text input element in question is still disabled. Therefore, JSF sees no point in processing text input element.

One efficient (but hacky and verbose) way around this is to always keep the text input element enabled from JSF’s standpoint and, instead, do it all using JavaScript. The first step is to remove the disabled attribute from the text input element:

<h:inputText id="newId" value="#{thePage.newId}" />

Instead, we use jQuery to disable the text input element at page-load time:

jQuery(document).ready(function(){
    var newIdInput = jQuery("#theForm\\:newId");
    newIdInput.attr({ disabled:true });
});

Some CSS styling completes the job, making the text input element actually “look” disabled in all browsers:

input#theForm\3A newId
{
    background-color: #D6D6D6;
}
span#theForm\3A newIdInputLabel
{
    color: #9C9C9C;
}

Finally, we add a JavaScript event handler function to twiddle the attribute value:

var handleSomeChange = function()
{
    var labelColor = "#9C9C9C";
    var inputColor = "#D6D6D6";
    var disabledSwitch = true;
    if ([test to see if newId should be enabled returns true])
    {
        labelColor = "#000000";
        inputColor = "#FFFFFF";
        disabledSwitch = false;
    }

    var newIdInputLabel =
        jQuery("#theForm\\:newIdInputLabel");
    newIdInputLabel.css("color", labelColor);
    var newIdInput = jQuery("#theForm\\:newId");
    newIdInput.attr({ disabled:disabledSwitch });
    newIdInput.css("backgroundColor", inputColor);
}

The more pure JSF way to get this done (using RichFaces) is to have the event handler function call the server, which would determine the proper disabled/enabled state and then reRender the text input element or containing form. In this way, the server-side viewState and client-side state remain in sync. But, in some instances, this introduces too much latency and negatively impacts usability. The option is available, though.

If you are, for example, disabling/enabling a text input element in a compact form in response to a checkbox being checked in that same form, I’d go with the client-side approach. However, if you are disabling/enabling lots of form elements in response to a button being clicked, going the server-side route might be more appropriate (from both a technical complexity and usability perspective).

I hope this helps.

Finding/Selecting RichFaces Components using jQuery

Thursday, November 4th, 2010

If you try to use jQuery to interact with JSF Richfaces components, you might run into difficulty selecting those components using their ID. The match is never made for some reason. That “reason” might very well be that RichFaces tends to put colons in the ID’s of their generated DOM elements. For example:

editForm:requiredOptions:1:listAllOptions:0:colorBox

There’s nothing wrong with this. It’s very well structured and successfully handles nested components and collections. But, if you try to get jQuery to select the component matching this ID, you’ll fail because of the colons. The solution is to properly escape the colons in the ID before passing it to the selector:

var componentId = component.id;
componentId = componentId.replace(/:/g, "\\\:");
var $component = jQuery("#" + componentId);

Hope this helps.