📄 ajaxrequesttarget.java
字号:
// execute the dom ready javascripts as first javascripts // after component replacement it = domReadyJavascripts.iterator(); while (it.hasNext()) { String js = (String)it.next(); respondInvocation(response, js); } it = appendJavascripts.iterator(); while (it.hasNext()) { String js = (String)it.next(); respondInvocation(response, js); } response.write("</ajax-response>"); } private void fireOnBeforeRespondListeners() { if (listeners != null) { final Map components = Collections.unmodifiableMap(markupIdToComponent); Iterator it = listeners.iterator(); while (it.hasNext()) { ((IListener)it.next()).onBeforeRespond(components, this); } } } private void fireOnAfterRespondListeners(final WebResponse response) { Iterator it; // invoke onafterresponse event on listeners if (listeners != null) { final Map components = Collections.unmodifiableMap(markupIdToComponent); // create response that will be used by listeners to append // javascript final IJavascriptResponse jsresponse = new IJavascriptResponse() { public void addJavascript(String script) { respondInvocation(response, script); } }; it = listeners.iterator(); while (it.hasNext()) { ((IListener)it.next()).onAfterRespond(components, jsresponse); } } } /** * Processes components added to the target. This involves attaching components, rendering * markup into a client side xml envelope, and detaching them * * @param response */ private void respondComponents(WebResponse response) { Iterator it; // TODO: We might need to call prepareRender on all components upfront // process component markup it = markupIdToComponent.entrySet().iterator(); while (it.hasNext()) { final Map.Entry entry = (Entry)it.next(); final Component component = (Component)entry.getValue(); final String markupId = (String)entry.getKey(); respondComponent(response, markupId, component); } } /** * @see java.lang.Object#toString() */ public String toString() { return "[AjaxRequestTarget@" + hashCode() + " markupIdToComponent [" + markupIdToComponent + "], prependJavascript [" + prependJavascripts + "], appendJavascript [" + appendJavascripts + "]"; } /** * Encodes a string so it is safe to use inside CDATA blocks * * @param str * @return encoded string */ protected String encode(String str) { if (str == null) { return null; } return Strings.replaceAll(str, "]", "]^").toString(); } /** * @return name of encoding used to possibly encode the contents of the CDATA blocks */ protected String getEncodingName() { return "wicket1"; } /** * * @param str * @return true if string needs to be encoded, false otherwise */ protected boolean needsEncoding(String str) { /* * TODO Post 1.2: Ajax: we can improve this by keeping a buffer of at least 3 characters and * checking that buffer so that we can narrow down escaping occurring only for ']]>' * sequence, or at least for ]] if ] is the last char in this buffer. * * but this improvement will only work if we write first and encode later instead of working * on fragments sent to write */ return str.indexOf(']') >= 0; } /** * * @param response * @param markupId * id of client-side dom element * @param component * component to render */ private void respondComponent(final Response response, final String markupId, final Component component) { if (component.getRenderBodyOnly() == true) { throw new IllegalStateException( "Ajax render cannot be called on component that has setRenderBodyOnly enabled. Component: " + component.toString()); } component.setOutputMarkupId(true); // substitute our encoding response for the real one so we can capture // component's markup in a manner safe for transport inside CDATA block final Response originalResponse = response; encodingBodyResponse.reset(); RequestCycle.get().setResponse(encodingBodyResponse); // Initialize temporary variables final Page page = component.getPage(); if (page == null) { throw new IllegalStateException( "Ajax request attempted on a component that is not associated with a Page"); } page.startComponentRender(component); component.prepareForRender(); // render any associated headers of the component respondHeaderContribution(response, component); component.renderComponent(); page.endComponentRender(component); // Restore original response RequestCycle.get().setResponse(originalResponse); response.write("<component id=\""); response.write(markupId); response.write("\" "); if (encodingBodyResponse.isContentsEncoded()) { response.write(" encoding=\""); response.write(getEncodingName()); response.write("\" "); } response.write("><![CDATA["); response.write(encodingBodyResponse.getContents()); response.write("]]></component>"); encodingBodyResponse.reset(); } /** * Header response for an ajax request. * * @author Matej Knopp */ private class AjaxHeaderResponse extends HeaderResponse { private static final long serialVersionUID = 1L; private void checkHeaderRendering() { if (headerRendering == false) { throw new WicketRuntimeException( "Only methods that can be called on IHeaderResponse outside renderHead() are renderOnLoadJavascript and renderOnDomReadyJavascript"); } } public void renderCSSReference(ResourceReference reference, String media) { checkHeaderRendering(); super.renderCSSReference(reference, media); } public void renderCSSReference(String url) { checkHeaderRendering(); super.renderCSSReference(url); } public void renderCSSReference(String url, String media) { checkHeaderRendering(); super.renderCSSReference(url, media); } public void renderJavascript(CharSequence javascript, String id) { checkHeaderRendering(); super.renderJavascript(javascript, id); } public void renderCSSReference(ResourceReference reference) { checkHeaderRendering(); super.renderCSSReference(reference); } public void renderJavascriptReference(ResourceReference reference) { checkHeaderRendering(); super.renderJavascriptReference(reference); } public void renderJavascriptReference(ResourceReference reference, String id) { checkHeaderRendering(); super.renderJavascriptReference(reference, id); } public void renderJavascriptReference(String url) { checkHeaderRendering(); super.renderJavascriptReference(url); } public void renderJavascriptReference(String url, String id) { checkHeaderRendering(); super.renderJavascriptReference(url, id); } public void renderString(CharSequence string) { checkHeaderRendering(); super.renderString(string); } /** * Construct. */ public AjaxHeaderResponse() { } public void renderOnDomReadyJavascript(String javascript) { List token = Arrays.asList(new Object[] { "javascript-event", "window", "domready", javascript }); if (wasRendered(token) == false) { domReadyJavascripts.add(javascript); markRendered(token); } } public void renderOnLoadJavascript(String javascript) { List token = Arrays.asList(new Object[] { "javascript-event", "window", "load", javascript }); if (wasRendered(token) == false) { // execute the javascript after all other scripts are executed appendJavascripts.add(javascript); markRendered(token); } } protected Response getRealResponse() { return RequestCycle.get().getResponse(); } }; // whether a header contribution is being rendered private boolean headerRendering = false; private HtmlHeaderContainer header = null; private IHeaderResponse headerResponse; /** * Returns the header response associated with current AjaxRequestTarget. * * Beware that only renderOnDomReadyJavascript and renderOnLoadJavascript can be called outside * the renderHeader(IHeaderResponse response) method. Calls to other render** methods will * result in an exception being thrown. * * @return header response */ public IHeaderResponse getHeaderResponse() { if (headerResponse == null) { headerResponse = new AjaxHeaderResponse(); } return headerResponse; } /** * Header container component for ajax header contributions * * @author Matej Knopp */ private static class AjaxHtmlHeaderContainer extends HtmlHeaderContainer { private static final long serialVersionUID = 1L; /** * Construct. * * @param id * @param target */ public AjaxHtmlHeaderContainer(String id, AjaxRequestTarget target) { super(id); this.target = target; } protected IHeaderResponse newHeaderResponse() { return target.getHeaderResponse(); } private final transient AjaxRequestTarget target; }; /** * * @param response * @param component */ private void respondHeaderContribution(final Response response, final Component component) { headerRendering = true; // create the htmlheadercontainer if needed if (header == null) { header = new AjaxHtmlHeaderContainer(HtmlHeaderSectionHandler.HEADER_ID, this); Component oldHeader = component.getPage().get(HtmlHeaderSectionHandler.HEADER_ID); // add or replace the container to page if (oldHeader != null) { component.getPage().replace(header); } else { component.getPage().add(header); } } // save old response, set new Response oldResponse = RequestCycle.get().setResponse(encodingHeaderResponse); encodingHeaderResponse.reset(); // render the head of component and all it's children component.renderHead(header); if (component instanceof MarkupContainer) { ((MarkupContainer)component).visitChildren(new Component.IVisitor() { public Object component(Component component) { if (component.isVisible()) { component.renderHead(header); return CONTINUE_TRAVERSAL; } else { return CONTINUE_TRAVERSAL_BUT_DONT_GO_DEEPER; } } }); } // revert to old response RequestCycle.get().setResponse(oldResponse); if (encodingHeaderResponse.getContents().length() != 0) { response.write("<header-contribution"); if (encodingHeaderResponse.isContentsEncoded()) { response.write(" encoding=\""); response.write(getEncodingName()); response.write("\" "); } // we need to write response as CDATA and parse it on client, // because // konqueror crashes when there is a <script> element response.write("><![CDATA[<head xmlns:wicket=\"http://wicket.apache.org\">"); response.write(encodingHeaderResponse.getContents()); response.write("</head>]]>"); response.write("</header-contribution>"); } headerRendering = false; } /** * * @param response * @param js */ private void respondInvocation(final Response response, final String js) { boolean encoded = false; String javascript = js; // encode the response if needed if (needsEncoding(js)) { encoded = true; javascript = encode(js); } response.write("<evaluate"); if (encoded) { response.write(" encoding=\""); response.write(getEncodingName()); response.write("\""); } response.write(">"); response.write("<![CDATA["); response.write(javascript); response.write("]]>"); response.write("</evaluate>"); encodingBodyResponse.reset(); } /** * Static method that returns current {@link AjaxRequestTarget} or <code>null</code> of no * {@link AjaxRequestTarget} is available. * * @return {@link AjaxRequestTarget} instance if current request is an Ajax request, * <code>null</code> otherwise. */ public static AjaxRequestTarget get() { final RequestCycle requestCycle = RequestCycle.get(); if (requestCycle != null) { if (requestCycle.getRequestTarget() instanceof AjaxRequestTarget) { return (AjaxRequestTarget)requestCycle.getRequestTarget(); } } return null; } /** * Returns the HTML id of the last focused element. * * @return */ public String getLastFocusedElementId() { String id = ((WebRequestCycle)RequestCycle.get()).getWebRequest() .getHttpServletRequest() .getHeader("Wicket-FocusedElementId"); return Strings.isEmpty(id) ? null : id; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -