JSF 2: How show different ajax status in same input?

The Ajax4jsf's onbegin and oncomplete attributes are just extra abstractions of the existing onevent attribute of the JSF2 standard <f:ajax> tag. You only need to bring in some extra JavaScript code in to achieve the same functionality.

Here's a kickoff example:

<h:form>
    <h:panelGrid columns="3">
        <h:outputLabel for="input1" value="Input 1" />
        <h:inputText id="input1" value="#{bean.input1}" required="true">
            <f:ajax event="blur" render="input1_message" onevent="showProgress" />
        </h:inputText>
        <h:message id="input1_message" for="input1" />

        <h:outputLabel for="input2" value="Input 2" />
        <h:inputText id="input2" value="#{bean.input2}" required="true">
            <f:ajax event="blur" render="input2_message" onevent="showProgress" />
        </h:inputText>
        <h:message id="input2_message" for="input2" />

        <h:panelGroup />
        <h:commandButton value="Submit" action="#{bean.submit}">
            <f:ajax execute="@form" render="@form" />
        </h:commandButton>
        <h:messages globalOnly="true" layout="table" />
    </h:panelGrid>
</h:form>

Here's a basic kickoff example the showProgress function. The data argument is a JS object whose properties are already described in tables 14-4 and 14-3 of the JSF specification.

function showProgress(data) {
    var inputElement = data.source; // The HTML DOM input element.
    var ajaxStatus = data.status; // Can be "begin", "success" and "complete"

    var messageForInputElement = document.getElementById(inputElement.id + "_message");

    switch (ajaxStatus) {
        case "begin": // This is called right before ajax request is been sent.
            messageForInputElement.innerHTML = "validating...";
            break;

        case "complete": // This is called right after ajax response is received.
            messageForInputElement.innerHTML = "";
            break;

        case "success": // This is called when ajax response is successfully processed.
            if (messageForInputElement.innerHTML.length == 0) { // So, no message has been set.
                messageForInputElement.innerHTML = "valid!";
            }
            break;
    }
}

You could substitute the innerHTML of this kickoff example with for example images or adding/removing CSS style class on the message element which uses CSS background images, etc. This is not exactly trivial to keep crossbrowser compatible. I'd suggest to throw in some jQuery in there.

Basically, the Ajax4jsf's onbegin and oncomplete attributes removes the need that you've to write a whole JS function with a switch to achieve the desired functionality. You could just refer directly some JavaScript functions which do the same as the lines inside the case statements of the switch. It's just an extra abstraction. You may want to consider using it so that amount of boilerplate code is minimized.