/** * Check if process this trigger only. * * @param triggerWithContext the trigger with its context * @param operation current ajax operation * @return true if process this trigger only */ private boolean isProcessTriggerOnly( final ComponentWithContext triggerWithContext, final AjaxOperation operation) { // Target container implies only process the trigger if (operation.getTargetContainerId() != null) { return true; } WComponent trigger = triggerWithContext.getComponent(); // Check if trigger is a polling AJAX control if (trigger instanceof WAjaxControl) { // Get user context UIContext uic = triggerWithContext.getContext(); UIContextHolder.pushContext(uic); try { WAjaxControl ajax = (WAjaxControl) trigger; // Is a polling region so only process trigger if (ajax.getDelay() > 0) { return true; } } finally { UIContextHolder.popContext(); } } // Check if the operation only has one target and it is the same as the trigger List<String> targets = operation.getTargets(); if (targets == null || targets.isEmpty() || targets.size() > 1) { return false; } return operation.getTriggerId().equals(targets.get(0)); }
/** * Convenience method that adds a parameter emulating a button press. * * @param uic the current user's UIContext * @param button the button to add a parameter for. */ public void addParameterForButton(final UIContext uic, final WButton button) { UIContextHolder.pushContext(uic); try { parameters.put(button.getId(), "x"); } finally { UIContextHolder.popContext(); } }
/** {@inheritDoc} */ @Override public void serviceRequest(final Request request) { String triggerId = request.getParameter(WServlet.AJAX_TRIGGER_PARAM_NAME); AjaxOperation ajaxOperation = AjaxHelper.getCurrentOperation(); if (ajaxOperation == null) { throw new IllegalStateException("No AJAX operation available for trigger " + triggerId + "."); } ComponentWithContext triggerWithContext = AjaxHelper.getCurrentTriggerAndContext(); if (triggerWithContext == null) { throw new IllegalStateException( "No component/context available for AJAX trigger " + triggerId + "."); } UIContext uic = UIContextHolder.getCurrent(); // Reset the focus for this new request. uic.setFocussed(null, null); // We've hit the action phase, so we do want focus on this app. uic.setFocusRequired(true); // Process trigger only if (isProcessTriggerOnly(triggerWithContext, ajaxOperation)) { // Get user context UIContext tuic = triggerWithContext.getContext(); UIContextHolder.pushContext(tuic); try { WComponent trigger = triggerWithContext.getComponent(); trigger.serviceRequest(request); // Manually invoke laters as the InvokeLaters in the service request is not run due to the // trigger // having a "parent" tuic.doInvokeLaters(); } finally { UIContextHolder.popContext(); } } // GET only supports the above scenarios else if ("GET".equals(request.getMethod())) { throw new IllegalStateException( "GET is not supported for the AJAX trigger " + triggerId + "."); } else { // service the request super.serviceRequest(request); } }
/** {@inheritDoc} */ @Override public void writeHeader(final PrintWriter writer) { UIContext uic = UIContextHolder.getCurrent(); addHeadlines(writer, uic.getHeaders().getHeadLines()); addJsHeadlines(writer, uic.getHeaders().getHeadLines(Headers.JAVASCRIPT_HEADLINE)); addCssHeadlines(writer, uic.getHeaders().getHeadLines(Headers.CSS_HEADLINE)); }
/** * Retrieves the application title for the given context. This mess is required due to WWindow * essentially existing as a separate UI root. If WWindow is eventually removed, then we can just * retrieve the title from the root WApplication. * * @param uic the context to check. * @return the current application title. */ private String getApplicationTitle(final UIContext uic) { WComponent root = uic.getUI(); String title = root instanceof WApplication ? ((WApplication) root).getTitle() : null; Map<String, String> params = uic.getEnvironment().getHiddenParameters(); String target = params.get(WWindow.WWINDOW_REQUEST_PARAM_KEY); if (target != null) { ComponentWithContext targetComp = WebUtilities.getComponentById(target, true); if (targetComp != null && targetComp.getComponent() instanceof WWindow) { try { UIContextHolder.pushContext(targetComp.getContext()); title = ((WWindow) targetComp.getComponent()).getTitle(); } finally { UIContextHolder.popContext(); } } } return title == null ? "" : title; }
/** * Paint the ajax container response. * * @param renderContext the render context * @param operation the ajax operation */ private void paintContainerResponse( final RenderContext renderContext, final AjaxOperation operation) { WebXmlRenderContext webRenderContext = (WebXmlRenderContext) renderContext; XmlStringBuilder xml = webRenderContext.getWriter(); // Get trigger's context ComponentWithContext trigger = AjaxHelper.getCurrentTriggerAndContext(); if (trigger == null) { throw new SystemException("No context available for trigger " + operation.getTriggerId()); } xml.appendTagOpen("ui:ajaxTarget"); xml.appendAttribute("id", operation.getTargetContainerId()); xml.appendAttribute("action", "replaceContent"); xml.appendClose(); // Paint targets - Assume targets are in the same context as the trigger UIContextHolder.pushContext(trigger.getContext()); try { for (String targetId : operation.getTargets()) { ComponentWithContext target = null; if (targetId.equals(operation.getTriggerId())) { target = trigger; } else { target = WebUtilities.getComponentById(targetId, true); if (target == null) { log.warn("Could not find ajax target to render " + target); continue; } } target.getComponent().paint(renderContext); } } finally { UIContextHolder.popContext(); } xml.appendEndTag("ui:ajaxTarget"); }
/** {@inheritDoc} */ @Override public void openDoc(final PrintWriter writer) { UIContext uic = UIContextHolder.getCurrent(); String title = getApplicationTitle(uic); writer.write(XMLUtil.getXMLDeclarationWithThemeXslt(uic)); // Provide temporary backward compatibility with while // applications convert to be XML compliant. writer.write(XMLUtil.DOC_TYPE); writer.write( "\n<ui:root title=\"" + WebUtilities.encode(title) + "\" " + XMLUtil.STANDARD_NAMESPACES + ">"); }