001: /*
002: * This file is part of the Echo Web Application Framework (hereinafter "Echo").
003: * Copyright (C) 2002-2005 NextApp, Inc.
004: *
005: * Version: MPL 1.1/GPL 2.0/LGPL 2.1
006: *
007: * The contents of this file are subject to the Mozilla Public License Version
008: * 1.1 (the "License"); you may not use this file except in compliance with
009: * the License. You may obtain a copy of the License at
010: * http://www.mozilla.org/MPL/
011: *
012: * Software distributed under the License is distributed on an "AS IS" basis,
013: * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
014: * for the specific language governing rights and limitations under the
015: * License.
016: *
017: * Alternatively, the contents of this file may be used under the terms of
018: * either the GNU General Public License Version 2 or later (the "GPL"), or
019: * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
020: * in which case the provisions of the GPL or the LGPL are applicable instead
021: * of those above. If you wish to allow use of your version of this file only
022: * under the terms of either the GPL or the LGPL, and not to allow others to
023: * use your version of this file under the terms of the MPL, indicate your
024: * decision by deleting the provisions above and replace them with the notice
025: * and other provisions required by the GPL or the LGPL. If you do not delete
026: * the provisions above, a recipient may use your version of this file under
027: * the terms of any one of the MPL, the GPL or the LGPL.
028: */
029:
030: package nextapp.echo2.webrender.servermessage;
031:
032: import nextapp.echo2.webrender.ServerMessage;
033:
034: import org.w3c.dom.DocumentFragment;
035: import org.w3c.dom.Element;
036: import org.w3c.dom.Node;
037:
038: /**
039: * A utility class to add <code>EchoDomUpdate</code> message parts to the
040: * <code>ServerMessage</code>. <code>EchoDomUpdate</code> message parts
041: * are used to directly update the client DOM with HTML code generated on
042: * the server.
043: */
044: public class DomUpdate {
045:
046: private static final String MESSAGE_PART_NAME = "EchoDomUpdate.MessageProcessor";
047: private static final String XHTML_NAMESPACE = "http://www.w3.org/1999/xhtml";
048:
049: /**
050: * Creates a <code>attribute-update</code> operation to update an
051: * element attribute of the element identified by <code>targetId</code>
052: * in the client DOM.
053: *
054: * @param serverMessage the outgoing <code>ServerMessage</code>
055: * @param targetId the id of the element whose attribute is to be updated
056: * @param attributeName the name of the attribute to update
057: * @param attributeValue the new value of the attribute
058: */
059: public static void renderAttributeUpdate(
060: ServerMessage serverMessage, String targetId,
061: String attributeName, String attributeValue) {
062: //BUGBUG. support nulls for deletion.
063: Element element = serverMessage.appendPartDirective(
064: ServerMessage.GROUP_ID_UPDATE, MESSAGE_PART_NAME,
065: "attribute-update");
066: element.setAttribute("target-id", targetId);
067: element.setAttribute("name", attributeName);
068: element.setAttribute("value", attributeValue);
069: }
070:
071: /**
072: * Prepares a <code>dom-add</code> operation by immediately appending an
073: * empty <code>dom-add</code> element to the end of the
074: * <code>ServerMessage</code>'s 'update' group.
075: * Content is added to the <code>dom-add</code> element by invoking
076: * <code>renderElementAddContent()</code>.
077: *
078: * @param serverMessage the <code>ServerMessage</code>
079: * @return the created <code>dom-add</code> <code>Element</code>.
080: */
081: public static Element renderElementAdd(ServerMessage serverMessage) {
082: Element domAddElement = serverMessage.appendPartDirective(
083: ServerMessage.GROUP_ID_UPDATE, MESSAGE_PART_NAME,
084: "dom-add");
085: return domAddElement;
086: }
087:
088: /**
089: * Creates a <code>dom-add</code> operation to append HTML content to the
090: * end of the element identified by <code>parentId</code>.
091: *
092: * @param serverMessage the outgoing <code>ServerMessage</code>
093: * @param parentId the id of the element the HTML code will be appended to
094: * @param htmlFragment the HTML fragment to add to the DOM
095: * @deprecated use of this method can result in DOM modifications
096: * being performed in improper order
097: * (instead use <code>renderElementAdd(ServerMessage)</code> followed by
098: * <code>renderElementAddContent()</code>)
099: */
100: public static void renderElementAdd(ServerMessage serverMessage,
101: String parentId, DocumentFragment htmlFragment) {
102: renderElementAdd(serverMessage, parentId, null, htmlFragment);
103: }
104:
105: /**
106: * Creates a <code>dom-add</code> operation to insert HTML content in the
107: * element identified by <code>parentId</code>.
108: *
109: * @param serverMessage the outgoing <code>ServerMessage</code>
110: * @param parentId the id of the element into which the HTML code will be
111: * inserted
112: * @param siblingId The id of the element which the content will be inserted
113: * <strong>before</strong> (this element must be an immediate child
114: * of the element specified by <code>parentId</code>)
115: * @param htmlFragment the HTML fragment to add to the DOM
116: * @deprecated use of this method can result in DOM modifications
117: * being performed in improper order
118: * (instead use <code>renderElementAdd(ServerMessage)</code> followed by
119: * <code>renderElementAddContent()</code>)
120: */
121: public static void renderElementAdd(ServerMessage serverMessage,
122: String parentId, String siblingId,
123: DocumentFragment htmlFragment) {
124: setContentNamespace(htmlFragment);
125: Element domAddElement = serverMessage.appendPartDirective(
126: ServerMessage.GROUP_ID_UPDATE, MESSAGE_PART_NAME,
127: "dom-add");
128: Element contentElement = domAddElement.getOwnerDocument()
129: .createElement("content");
130: contentElement.setAttribute("parent-id", parentId);
131: if (siblingId != null) {
132: contentElement.setAttribute("sibling-id", siblingId);
133: }
134: domAddElement.appendChild(contentElement);
135: contentElement.appendChild(htmlFragment);
136: }
137:
138: /**
139: * Adds content to be added to an existing <code>dom-add</code> operation.
140: * The content will be appended to the end of the DOM element identified by
141: * <code>parentId</code>
142: *
143: * @param serverMessage the <code>ServerMessage</code>
144: * @param domAddElement the <code>dom-add</code> element created by a
145: * previous invocation of <code>renderAdd(ServerMessage)</code>
146: * @param parentId the id of the element the HTML code will be appended to
147: * @param htmlFragment the HTML fragment to add to the DOM
148: */
149: public static void renderElementAddContent(
150: ServerMessage serverMessage, Element domAddElement,
151: String parentId, DocumentFragment htmlFragment) {
152: renderElementAddContent(serverMessage, domAddElement, parentId,
153: null, htmlFragment);
154: }
155:
156: /**
157: * Adds content to be added to an existing <code>dom-add</code> operation.
158: * The content will be inserted into the DOM element identified by
159: * <code>parentId</code> before the specified <code>siblingId</code>.
160: *
161: * @param serverMessage the <code>ServerMessage</code>
162: * @param domAddElement the <code>dom-add</code> element created by a
163: * previous invocation of <code>renderAdd(ServerMessage)</code>
164: * @param parentId the id of the element the HTML code will be appended to
165: * @param siblingId The id of the element which the content will be inserted
166: * <strong>before</strong> (this element must be an immediate child
167: * of the element specified by <code>parentId</code>)
168: * @param htmlFragment the HTML fragment to add to the DOM
169: */
170: public static void renderElementAddContent(
171: ServerMessage serverMessage, Element domAddElement,
172: String parentId, String siblingId,
173: DocumentFragment htmlFragment) {
174: setContentNamespace(htmlFragment);
175: Element contentElement = domAddElement.getOwnerDocument()
176: .createElement("content");
177: contentElement.setAttribute("parent-id", parentId);
178: if (siblingId != null) {
179: contentElement.setAttribute("sibling-id", siblingId);
180: }
181: domAddElement.appendChild(contentElement);
182: contentElement.appendChild(htmlFragment);
183: }
184:
185: /**
186: * Creates a <code>dom-remove</code> operation to remove the HTML element
187: * identified by <code>targetId</code> from the client DOM.
188: *
189: * @param serverMessage the outgoing <code>ServerMessage</code>
190: * @param targetId the id of the element to remove
191: */
192: public static void renderElementRemove(ServerMessage serverMessage,
193: String targetId) {
194: Element domRemoveElement = serverMessage.appendPartDirective(
195: ServerMessage.GROUP_ID_REMOVE, MESSAGE_PART_NAME,
196: "dom-remove");
197: domRemoveElement.setAttribute("target-id", targetId);
198: }
199:
200: /**
201: * Creates a <code>dom-remove</code> operation to remove all child elements
202: * of the element identified by <code>targetId</code> from the client DOM.
203: *
204: * @param serverMessage the outgoing <code>ServerMessage</code>
205: * @param targetId the id of the element whose children ware to be removed
206: */
207: public static void renderElementRemoveChildren(
208: ServerMessage serverMessage, String targetId) {
209: Element domRemoveElement = serverMessage.appendPartDirective(
210: ServerMessage.GROUP_ID_REMOVE, MESSAGE_PART_NAME,
211: "dom-remove-children");
212: domRemoveElement.setAttribute("target-id", targetId);
213: }
214:
215: /**
216: * Creates a <code>style-update</code> operation to update a CSS style
217: * attribute of the element identified by <code>targetId</code> in the
218: * client DOM.
219: *
220: * @param serverMessage the outgoing <code>ServerMessage</code>
221: * @param targetId the id of the element whose <strong>style</strong>
222: * attribute is to be updated
223: * @param attributeName the name of the <strong>style</strong> attribute
224: * @param attributeValue the new value of the <strong>style</strong>
225: * attribute
226: */
227: public static void renderStyleUpdate(ServerMessage serverMessage,
228: String targetId, String attributeName, String attributeValue) {
229: //BUGBUG. support nulls for deletion.
230: Element element = serverMessage.appendPartDirective(
231: ServerMessage.GROUP_ID_UPDATE, MESSAGE_PART_NAME,
232: "style-update");
233: element.setAttribute("target-id", targetId);
234: element.setAttribute("name", attributeName);
235: element.setAttribute("value", attributeValue);
236: }
237:
238: /**
239: * Creates a <code>stylesheet-add-rule</code> directive to add a rule
240: * to a stylesheet
241: *
242: * @param serverMessage the relevant <code>ServerMessage</code>
243: * @param selectorText the selector of the rule to add
244: * @param style the CSS text for the style
245: */
246: public static void renderStyleSheetAddRule(
247: ServerMessage serverMessage, String selectorText,
248: String style) {
249: Element element = serverMessage.appendPartDirective(
250: ServerMessage.GROUP_ID_UPDATE, MESSAGE_PART_NAME,
251: "stylesheet-add-rule");
252: element.setAttribute("selector", selectorText);
253: element.setAttribute("style", style);
254: }
255:
256: /**
257: * Creates a <code>stylesheet-remove-rule</code> directive to remove a rule
258: * from a stylesheet
259: *
260: * @param serverMessage the relevant <code>ServerMessage</code>
261: * @param selectorText the selector of the rule to remove
262: */
263: public static void renderStyleSheetRemoveRule(
264: ServerMessage serverMessage, String selectorText) {
265: Element element = serverMessage.appendPartDirective(
266: ServerMessage.GROUP_ID_UPDATE, MESSAGE_PART_NAME,
267: "stylesheet-remove-rule");
268: element.setAttribute("selector", selectorText);
269: }
270:
271: /**
272: * Configures all child elements of a "content" element to use the XHTML
273: * namespace.
274: *
275: * @param htmlFragment an HTML document fragment
276: */
277: private static void setContentNamespace(
278: DocumentFragment htmlFragment) {
279: Node childNode = htmlFragment.getFirstChild();
280: while (childNode != null) {
281: if (childNode.getNodeType() == Node.ELEMENT_NODE) {
282: ((Element) childNode).setAttribute("xmlns",
283: XHTML_NAMESPACE);
284: }
285: childNode = childNode.getNextSibling();
286: }
287: }
288: }
|