ICEfaces
  1. ICEfaces
  2. ICE-5581

inputText fields cannot get focus by tabbing after a model popup is opened and closed

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 1.8.2, 1.8.2-EE-GA
    • Fix Version/s: 1.8.3, 1.8.2-EE-GA_P02
    • Component/s: ICE-Components
    • Labels:
      None
    • Environment:
      1.8.2-EE-GA-p01 build 6
      Tomcat 5.5.28
      Tomcat 6.0.26
    • Workaround Exists:
      Yes
    • Workaround Description:
      Hide
       - Use just the visible attribute to show/hide the popup
       - Use a non-modal popup
       - Move the popup to inside of the same form.
      Show
       - Use just the visible attribute to show/hide the popup  - Use a non-modal popup  - Move the popup to inside of the same form.

      Description

      After open and close the popup, the inputText fields are no longer able to get focus by tabbing. Failed in FF3.6, Chrome 4 and IE8

      Test app is available at repo\qa\trunk\Regression\ICE-4475

        Activity

        Hide
        Adnan Durrani added a comment -

        I did run this demo with 1.8.2 release bundle, and can see the same behaviour as trunk, which shows that its not a regression in this release.

        Show
        Adnan Durrani added a comment - I did run this demo with 1.8.2 release bundle, and can see the same behaviour as trunk, which shows that its not a regression in this release.
        Hide
        Adnan Durrani added a comment - - edited

        It won't be as easier as written. The client keeps the handles of running modal popups, we can clearup these popup on client side that would be straightforward then doing server side stuff. I think in first place it should have client responsibility to start and off the popup and sent the notification to server.

        Thanks,
        Adnan
        Mark Collette wrote:
        > We could have a dedicated PhaseListener, that always runs, do this feature. We'd register it in the faces-config.xml in the component jar, and it would walk the component tree, looking for panelPopup components. But that's still problematic, since the PhaseListener won't know how rendered properties will evaluate in UIData containers, which might change row to row. Maybe if we use the idea of escrow. When a panelPopup does decode, it knows if it's still showing, after having been made visible before, so it could put in escrow some javascript to close itself, if it becomes unrendered later. If it does render, then it will cancel that javascript in escrow, and if it does not render, then that javascript becomes active. We could add something to JavascriptContext, where each components can pass in their clientId with their script snippet, and then be able to cancel a snippet using that clientId later.
        >
        > - Mark
        >
        >
        > Adnan Durrani wrote:
        >
        >>
        >> | LifecycleFactory factory = (LifecycleFactory)FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY);
        >> Lifecycle lifecycle = factory.getLifecycle(LifecycleFactory.DEFAULT_LIFECYCLE);
        >> lifecycle.addPhaseListener(new OneOffPhaseListener());
        >>
        >>
        >> |Adnan Durrani wrote:
        >>
        >>> Yes, that is right. Other option is to use PhaseListener, I looked it already, I found to add a phaseListener dynamically I will have to get the reference of LifeCycle. May be there is a way I am not aware of it.
        >>>
        >>> Thanks,
        >>> Adnan
        >>>
        >>> Mark Collette wrote:
        >>>
        >>>> Even then, what if a parent of the panelPopup becomes unrendered, and not just the panelPopup itself? Then how will it know to cancel the modal dialog? In JSF 2 it could use the pre-render system event. With JSF 1.1/1.2, we'd need to use a PhaseListener.
        >>>>
        >>>> - Mark
        >>>>
        >>>>
        >>>> Adnan Durrani wrote:
        >>>>
        >>>>> I looked the demo closely, and found out that clientOnly attribute only effects drag operation so that was not the real issue.
        >>>>>
        >>>>> The real issue is a code in panelPopup which take care of stopping panel popup.
        >>>>>
        >>>>> public boolean isRendered() {
        >>>>> boolean rendered = super.isRendered();
        >>>>> if (!rendered)

        { >>>>> stopModal(); >>>>> }

        >>>>> return rendered;
        >>>>> }
        >>>>>
        >>>>> private void stopModal() {
        >>>>> String caller = new Exception().getStackTrace()[2].getMethodName();
        >>>>> if(caller.startsWith("render"))

        { JavascriptContext.addJavascriptCall(getFacesContext(), "Ice.modal.stop('" + getClientId(getFacesContext()) + "');"); >>>>> }

        }
        >>>>>
        >>>>> The fact is that the panelPopup's "rendered" attribute can be toggled by any component, so if it "rendered" attribute get set to false by some component, its Renderer never even get a chance to stop the modal. To deal with this issue, in the isRendered() method we check if its invoked by the renderResponsePhase and its "rendered" value is set to false, then we should send a request to stop the modal. So according to the current design of the component this is the only way to send a stop request. The only problem is in a hack which checks whether or not we are in renderResponsePhase. You can see above its incompetent, the stack calls an be changed on the basis of markup complexity.
        >>>>>
        >>>>> So to fix this issue, we just need a cleaner API to identify which phase I am in. The JSF 2.0 provides public API for that:
        >>>>>
        >>>>> PhaseId currentPhaseId = FacesContext.getCurrentInstance().getCurrentPhaseId();
        >>>>>
        >>>>> I am just wondering wouldn't it be good if we can provide some similar API at framework level?

        Show
        Adnan Durrani added a comment - - edited It won't be as easier as written. The client keeps the handles of running modal popups, we can clearup these popup on client side that would be straightforward then doing server side stuff. I think in first place it should have client responsibility to start and off the popup and sent the notification to server. Thanks, Adnan Mark Collette wrote: > We could have a dedicated PhaseListener, that always runs, do this feature. We'd register it in the faces-config.xml in the component jar, and it would walk the component tree, looking for panelPopup components. But that's still problematic, since the PhaseListener won't know how rendered properties will evaluate in UIData containers, which might change row to row. Maybe if we use the idea of escrow. When a panelPopup does decode, it knows if it's still showing, after having been made visible before, so it could put in escrow some javascript to close itself, if it becomes unrendered later. If it does render, then it will cancel that javascript in escrow, and if it does not render, then that javascript becomes active. We could add something to JavascriptContext, where each components can pass in their clientId with their script snippet, and then be able to cancel a snippet using that clientId later. > > - Mark > > > Adnan Durrani wrote: > >> >> | LifecycleFactory factory = (LifecycleFactory)FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY); >> Lifecycle lifecycle = factory.getLifecycle(LifecycleFactory.DEFAULT_LIFECYCLE); >> lifecycle.addPhaseListener(new OneOffPhaseListener()); >> >> >> |Adnan Durrani wrote: >> >>> Yes, that is right. Other option is to use PhaseListener, I looked it already, I found to add a phaseListener dynamically I will have to get the reference of LifeCycle. May be there is a way I am not aware of it. >>> >>> Thanks, >>> Adnan >>> >>> Mark Collette wrote: >>> >>>> Even then, what if a parent of the panelPopup becomes unrendered, and not just the panelPopup itself? Then how will it know to cancel the modal dialog? In JSF 2 it could use the pre-render system event. With JSF 1.1/1.2, we'd need to use a PhaseListener. >>>> >>>> - Mark >>>> >>>> >>>> Adnan Durrani wrote: >>>> >>>>> I looked the demo closely, and found out that clientOnly attribute only effects drag operation so that was not the real issue. >>>>> >>>>> The real issue is a code in panelPopup which take care of stopping panel popup. >>>>> >>>>> public boolean isRendered() { >>>>> boolean rendered = super.isRendered(); >>>>> if (!rendered) { >>>>> stopModal(); >>>>> } >>>>> return rendered; >>>>> } >>>>> >>>>> private void stopModal() { >>>>> String caller = new Exception().getStackTrace() [2] .getMethodName(); >>>>> if(caller.startsWith("render")) { JavascriptContext.addJavascriptCall(getFacesContext(), "Ice.modal.stop('" + getClientId(getFacesContext()) + "');"); >>>>> } } >>>>> >>>>> The fact is that the panelPopup's "rendered" attribute can be toggled by any component, so if it "rendered" attribute get set to false by some component, its Renderer never even get a chance to stop the modal. To deal with this issue, in the isRendered() method we check if its invoked by the renderResponsePhase and its "rendered" value is set to false, then we should send a request to stop the modal. So according to the current design of the component this is the only way to send a stop request. The only problem is in a hack which checks whether or not we are in renderResponsePhase. You can see above its incompetent, the stack calls an be changed on the basis of markup complexity. >>>>> >>>>> So to fix this issue, we just need a cleaner API to identify which phase I am in. The JSF 2.0 provides public API for that: >>>>> >>>>> PhaseId currentPhaseId = FacesContext.getCurrentInstance().getCurrentPhaseId(); >>>>> >>>>> I am just wondering wouldn't it be good if we can provide some similar API at framework level?
        Hide
        yip.ng added a comment -

        Fixed based on Adnan's last suggestion. See video at http://screencast.com/t/NjVkNTZkOWI.

        (The other approaches either don't work for all cases or are overly complicated to implement and test properly in limited time.)

        Show
        yip.ng added a comment - Fixed based on Adnan's last suggestion. See video at http://screencast.com/t/NjVkNTZkOWI . (The other approaches either don't work for all cases or are overly complicated to implement and test properly in limited time.)
        Hide
        yip.ng added a comment -

        Revision: 22058


        Modified : /icefaces/trunk/icefaces/component/src/com/icesoft/faces/component/ext/renderkit/GroupRenderer.java
        Modified : /icefaces/trunk/icefaces/component/src/com/icesoft/faces/component/panelpopup/PanelPopup.java
        Modified : /icefaces/trunk/icefaces/component/src/com/icesoft/faces/component/panelpopup/PanelPopupRenderer.java

        Show
        yip.ng added a comment - Revision: 22058 Modified : /icefaces/trunk/icefaces/component/src/com/icesoft/faces/component/ext/renderkit/GroupRenderer.java Modified : /icefaces/trunk/icefaces/component/src/com/icesoft/faces/component/panelpopup/PanelPopup.java Modified : /icefaces/trunk/icefaces/component/src/com/icesoft/faces/component/panelpopup/PanelPopupRenderer.java

          People

          • Assignee:
            yip.ng
            Reporter:
            Joanne Bai
          • Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: