Close ModalWindow on keypress
Asked Answered
H

3

6

I would like to be able to close a ModalWindow when the user presses a key, in my case ESC.

I have a Javascript listener for the keypress which calls the click event of the cancel button's ID:

jQuery("#"+modalWindowInfo.closeButtonId).click();

Is this the correct way to do it?

I am wondering because it works in Chrome but not in FF, but it could be due my specific implementation.

Honeybunch answered 18/2, 2011 at 14:25 Comment(0)
F
7

The 'right' way to do it is to call the server, then close it with the response. You can do this with an ajax behavior:

ModalTestPage.java

public class ModalTestPage extends WebPage {
    public ModalTestPage(PageParameters parameters) {
        super(parameters);

        final ModalWindow modal = new ModalWindow("modal");
        modal.setContent(new Fragment(modal.getContentId(), "window", this));
        add(modal);

        add(new AjaxLink<Void>("link") {
            @Override
            public void onClick(AjaxRequestTarget target) {
                modal.show(target);
            }
        });

        add(new CloseOnESCBehavior(modal));
    }

    private static class CloseOnESCBehavior extends AbstractDefaultAjaxBehavior {
        private final ModalWindow modal;
        public CloseOnESCBehavior(ModalWindow modal) {
            this.modal = modal;
        }    
        @Override
        protected void respond(AjaxRequestTarget target) {
            modal.close(target);
        }    
        @Override
        public void renderHead(Component component, IHeaderResponse response) {
            response.renderJavaScriptReference("https://ajax.googleapis.com/ajax/libs/jquery/1.5.0/jquery.min.js");
            response.renderJavaScript("" +
                "$(document).ready(function() {\n" +
                "  $(document).bind('keyup', function(evt) {\n" +
                "    if (evt.keyCode == 27) {\n" +
                getCallbackScript() + "\n" +
                "        evt.preventDefault();\n" +
                "    }\n" +
                "  });\n" +
                "});", "closeModal");
        }
    }
}

ModalTestPage.html

<html xmlns:wicket="http://wicket.apache.org">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>

  <a wicket:id="link">SHOW</a>
  <div wicket:id="modal"></div>

<wicket:fragment wicket:id="window">
  Press ESC to dismiss
</wicket:fragment>
</body>
</html>
Figural answered 20/2, 2011 at 22:36 Comment(5)
This seems a much neater way - thanks! I have implemented a version of your solution (I say a "version" because my implementation must work with multiple ModalWindows, so in JS I keep a list of open windows so that successive presses of ESC close the next modal window) and it works in Chrome but in FF I still get "aborted" in Firebug next to the http request. I put a breakpoint on modal.close() which gets triggered but Firebug already reports the request is aborted.Honeybunch
The plot thickens; by putting an alert() either side of the JS returned from getCallbackScript() makes it work in FF.Honeybunch
I figured it out, in FF the ESC key kills the current request, which is why the requests were immediately aborted. The keydown event can be swallowed by calling e.preventDefault(); I'll update the answer and mark it correct - thanks!Honeybunch
To make this work with Wicket 1.4, three small changes are needed: 1) the renderHead method to override is defined as public void renderHead(IHeaderResponse response) 2) renderJavaScriptReference -> renderJavascriptReference 3) renderJavaScript -> renderJavascriptIdleman
+1, works as advertised. Though I guess it'd be possible to put most of the JavaScript code cleanly in a .js file, to avoid generating it by concatenating Java strings (which is ugly)...Idleman
C
2

The example above is good, very good, however there is one issue which may be crucial for some programming users (was for me).

For the actual close to happen there are 2 ajax requests happening - first one is issued with the CloseOnESCBehavior which calls window.close. MW.close() would render javascript which would first do call to server to ask its windowClosedCallback, and would only then close (hide contents of) the modal window.

I'd suggest instead doing something like this - in the code of ModalWindow ctor:

    add(new AbstractBehavior() {
        @Override
        public void renderHead(IHeaderResponse response) {
            response.renderOnDomReadyJavascript(
                    " if($(document).data('wicketWindowCloseBound')) {return;} "
                            + " $(document).data('wicketWindowCloseBound', true); "
                            + " $(document).bind('keyup', function(evt) {\n"
                            + "    if (evt.keyCode == 27) {\n"
                            + getCloseJavacript()
                            + "\n"
                            + "        evt.preventDefault();\n"
                            + "        evt.stopPropagation();\n"
                            + "    }\n"
                            + "  });\n");

        }
    });
Committeewoman answered 3/1, 2012 at 9:41 Comment(0)
E
1

Also, you can use Wicket Jquery UI

HTML

<div wicket:id="dialog">[dialog]</div>

Java

MessageDialog dialog = new MessageDialog("dialog", "Warning", "Is it ok?",
                        DialogButtons.OK_CANCEL, DialogIcon.WARN)
    {
        protected void onClose(AjaxRequestTarget target, DialogButton button)
        {
            if(button != null && button.equals(LBL_OK))
            {
                //do something here

                //note1: #equals() compare either DialogButton or String (button text)
                //note2: predefined button text are:
                //LBL_OK, LBL_CANCEL, LBL_YES, LBL_NO, LBL_CLOSE, LBL_SUBMIT
            }
        }   
    }

    this.add(dialog); //TODO: open it, using dialog.open(target);

And the ESC key works fine. You should see this aproach at Wicket JQuery UI demo page

Effloresce answered 3/1, 2013 at 23:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.