001 // Copyright 2009, 2010, 2011 The Apache Software Foundation 002 // 003 // Licensed under the Apache License, Version 2.0 (the "License"); 004 // you may not use this file except in compliance with the License. 005 // You may obtain a copy of the License at 006 // 007 // http://www.apache.org/licenses/LICENSE-2.0 008 // 009 // Unless required by applicable law or agreed to in writing, software 010 // distributed under the License is distributed on an "AS IS" BASIS, 011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 012 // See the License for the specific language governing permissions and 013 // limitations under the License. 014 015 package org.apache.tapestry5.internal.services.ajax; 016 017 import org.apache.tapestry5.MarkupWriter; 018 import org.apache.tapestry5.dom.Element; 019 import org.apache.tapestry5.internal.services.PageRenderQueue; 020 import org.apache.tapestry5.json.JSONObject; 021 import org.apache.tapestry5.runtime.RenderCommand; 022 import org.apache.tapestry5.runtime.RenderQueue; 023 import org.apache.tapestry5.services.PartialMarkupRenderer; 024 import org.apache.tapestry5.services.PartialMarkupRendererFilter; 025 026 /** 027 * Responsible for capturing the content for a single zone and storing it into the JSON reply object. As a {@link PartialMarkupRendererFilter} , this 028 * has access to the {@link JSONObject} for the reply, and can {@linkplain PageRenderQueue#addPartialRenderer(org.apache.tapestry5.runtime.RenderCommand) add renderers that generate and package the markup content}. 029 * 030 * @see org.apache.tapestry5.ajax.MultiZoneUpdate 031 * @see org.apache.tapestry5.services.ajax.AjaxResponseRenderer#addRender(String, Object) 032 * @since 5.1.0.1 033 */ 034 public class SingleZonePartialRendererFilter implements PartialMarkupRendererFilter 035 { 036 private final String zoneId; 037 038 private final RenderCommand zoneRenderCommand; 039 040 private final PageRenderQueue queue; 041 042 private final AjaxFormUpdateController ajaxFormUpdateController; 043 044 public SingleZonePartialRendererFilter(String zoneId, RenderCommand zoneRenderCommand, PageRenderQueue queue, 045 AjaxFormUpdateController ajaxFormUpdateController) 046 { 047 this.zoneId = zoneId; 048 this.zoneRenderCommand = zoneRenderCommand; 049 this.queue = queue; 050 this.ajaxFormUpdateController = ajaxFormUpdateController; 051 } 052 053 public void renderMarkup(MarkupWriter writer, final JSONObject reply, PartialMarkupRenderer renderer) 054 { 055 RenderCommand forZone = new RenderCommand() 056 { 057 public void render(MarkupWriter writer, RenderQueue queue) 058 { 059 // Create an element to contain the content for the zone. We give it a mnemonic 060 // element name and attribute just to help with debugging (the element itself is discarded). 061 062 final Element zoneContainer = writer.element("zone-update", "zoneId", zoneId); 063 064 ajaxFormUpdateController.setupBeforePartialZoneRender(writer); 065 066 queue.push(new RenderCommand() 067 { 068 public void render(MarkupWriter writer, RenderQueue queue) 069 { 070 writer.end(); // the zoneContainer element 071 072 // Need to do this Ajax Form-related cleanup here, before we extract the zone content. 073 074 ajaxFormUpdateController.cleanupAfterPartialZoneRender(); 075 076 String zoneUpdateContent = zoneContainer.getChildMarkup(); 077 078 zoneContainer.remove(); 079 080 if (!reply.has("zones")) 081 { 082 reply.put("zones", new JSONObject()); 083 } 084 085 reply.getJSONObject("zones").put(zoneId, zoneUpdateContent); 086 } 087 }); 088 089 // Make sure the zone's actual rendering command is processed first, then the inline 090 // RenderCommand just above. 091 092 queue.push(zoneRenderCommand); 093 } 094 }; 095 096 queue.addPartialRenderer(forZone); 097 098 renderer.renderMarkup(writer, reply); 099 } 100 }