0

Please have a look at the following form. In particular, take note of the ajax and graphicImage elements. The ajax element is embedded in a selectOneMenu. When the menu selection is changed the image is correspondingly updated. The update will sometimes cause a "blink" (old image disappears, form resizes (shrinks), new image appears, form is back to original size). I am guessing that the not blink (blink) results from the speed (or lack thereof) with which the new image is fetched from the url (a server elsewhere on the web). Short of caching all the images locally, is there a way to address this? Cause old image to remain in place until the new image is ready? At least prevent the form from resizing?

<h:form rendered="#{orderController.addingNew}" styleClass="demo">
    <fieldset>
        <legend>New Order</legend>

        <h:panelGrid columns="2">
            <h:outputText value="Patient"></h:outputText>
            <h:selectOneMenu validatorMessage="required" value="#{orderController.patientId}"  onchange="submit()">
                <f:selectItems value="#{orderController.patients}" />
            </h:selectOneMenu>

            <h:outputText value="Product"></h:outputText>
            <h:selectOneMenu value="#{orderController.productId}">
                <f:selectItems value="#{orderController.products}" var="product" itemValue="#{product.id}" itemLabel="#{product.name}" />
                <f:ajax render="productImage" listener="#{orderController.productSelectionChanged}"/>
            </h:selectOneMenu>

            <h:graphicImage url="#{orderController.productImageUrl}" id="productImage"/>
        </h:panelGrid>

        <h:panelGroup>
            <h:commandButton value="Save" action="#{orderController.save}" accesskey="s" styleClass="demo"/>
            <h:commandButton value="Cancel" action="#{orderController.cancel}" accesskey="c" immediate="true" styleClass="demo"/>
        </h:panelGroup>
    </fieldset>
    <h:outputText value="&#160;" />
</h:form>
Verticon
  • 2,419
  • 16
  • 34

1 Answers1

0

You could bind an onevent attribute to your ajax tag:

<f:ajax render="productImage" listener="#{orderController.productSelectionChanged}" 
    onevent="ajaxEventListener"/>

Then, you get notified whenever some phase of the ajax process happens. You might be interested in implementing something like this with jQuery:

function ajaxEventListener(data) {
    var status = data.status; // Can be "begin", "complete" or "success".
    var source = data.source; // The parent HTML DOM element.
    //Give your form an id in order to access the image in JS
    var $image = $(document.getElementById("yourFormId:productImage"));  //Grab your image

    switch (status) {
        case "begin": // Before the ajax request is sent.
            // Fade out your image
            $image.fadeOut( "slow" );
            break;

        case "success": // After update of HTML DOM based on ajax response.
            // You've got the url properly updated, start fading in the image again
            $image.fadeIn( "slow" );
            break;
    }
}

In order to improve loading times, you should read some papers about how to cache resources in the web browser. That's not JSF specific, though, it's something you could do with a web filter.

See also:

Aritz
  • 30,971
  • 16
  • 136
  • 217
  • 1
    Effectively it is not that different than what you can/should do in plain html. I'd personally also look into copying the current image and its url to a new one (in plain javascript), display that and in the 'begin' and in the success (that is when the new image starts actually loading if I remember correctly) register a 'load' event handler that fires when the new image is fully loaded and then hide the copied image (or via a transition). Then you don't even have a moment of not showing anything. https://stackoverflow.com/questions/1977871/check-if-an-image-is-loaded-no-errors-in-javascript – Kukeltje May 09 '18 at 08:33