/*
* This file is part of the Echo Web Application Framework (hereinafter "Echo").
* Copyright (C) 2002-2009 NextApp, Inc.
*
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*/
package nextapp.echo2.webrender.servermessage;
import nextapp.echo2.webrender.ServerMessage;
import org.w3c.dom.DocumentFragment;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
/**
* A utility class to add <code>EchoDomUpdate</code> message parts to the
* <code>ServerMessage</code>. <code>EchoDomUpdate</code> message parts
* are used to directly update the client DOM with HTML code generated on
* the server.
*/
public class DomUpdate {
private static final String MESSAGE_PART_NAME = "EchoDomUpdate.MessageProcessor";
private static final String XHTML_NAMESPACE = "http://www.w3.org/1999/xhtml";
/**
* Creates a <code>attribute-update</code> operation to update an
* element attribute of the element identified by <code>targetId</code>
* in the client DOM.
*
* @param serverMessage the outgoing <code>ServerMessage</code>
* @param targetId the id of the element whose attribute is to be updated
* @param attributeName the name of the attribute to update
* @param attributeValue the new value of the attribute
*/
public static void renderAttributeUpdate(ServerMessage serverMessage, String targetId, String attributeName,
String attributeValue) {
Element element = serverMessage.appendPartDirective(ServerMessage.GROUP_ID_UPDATE,
MESSAGE_PART_NAME, "attribute-update");
element.setAttribute("target-id", targetId);
element.setAttribute("name", attributeName);
element.setAttribute("value", attributeValue);
}
/**
* Prepares a <code>dom-add</code> operation by immediately appending an
* empty <code>dom-add</code> element to the end of the
* <code>ServerMessage</code>'s 'update' group.
* Content is added to the <code>dom-add</code> element by invoking
* <code>renderElementAddContent()</code>.
*
* @param serverMessage the <code>ServerMessage</code>
* @return the created <code>dom-add</code> <code>Element</code>.
*/
public static Element renderElementAdd(ServerMessage serverMessage) {
Element domAddElement = serverMessage.appendPartDirective(ServerMessage.GROUP_ID_UPDATE,
MESSAGE_PART_NAME, "dom-add");
return domAddElement;
}
/**
* Creates a <code>dom-add</code> operation to append HTML content to the
* end of the element identified by <code>parentId</code>.
*
* @param serverMessage the outgoing <code>ServerMessage</code>
* @param parentId the id of the element the HTML code will be appended to
* @param htmlFragment the HTML fragment to add to the DOM
* @deprecated use of this method can result in DOM modifications
* being performed in improper order
* (instead use <code>renderElementAdd(ServerMessage)</code> followed by
* <code>renderElementAddContent()</code>)
*/
public static void renderElementAdd(ServerMessage serverMessage, String parentId, DocumentFragment htmlFragment) {
renderElementAdd(serverMessage, parentId, null, htmlFragment);
}
/**
* Creates a <code>dom-add</code> operation to insert HTML content in the
* element identified by <code>parentId</code>.
*
* @param serverMessage the outgoing <code>ServerMessage</code>
* @param parentId the id of the element into which the HTML code will be
* inserted
* @param siblingId The id of the element which the content will be inserted
* <strong>before</strong> (this element must be an immediate child
* of the element specified by <code>parentId</code>)
* @param htmlFragment the HTML fragment to add to the DOM
* @deprecated use of this method can result in DOM modifications
* being performed in improper order
* (instead use <code>renderElementAdd(ServerMessage)</code> followed by
* <code>renderElementAddContent()</code>)
*/
public static void renderElementAdd(ServerMessage serverMessage, String parentId, String siblingId,
DocumentFragment htmlFragment) {
setContentNamespace(htmlFragment);
Element domAddElement = serverMessage.appendPartDirective(ServerMessage.GROUP_ID_UPDATE,
MESSAGE_PART_NAME, "dom-add");
Element contentElement = domAddElement.getOwnerDocument().createElement("content");
contentElement.setAttribute("parent-id", parentId);
if (siblingId != null) {
contentElement.setAttribute("sibling-id", siblingId);
}
domAddElement.appendChild(contentElement);
contentElement.appendChild(htmlFragment);
}
/**
* Adds content to be added to an existing <code>dom-add</code> operation.
* The content will be appended to the end of the DOM element identified by
* <code>parentId</code>
*
* @param serverMessage the <code>ServerMessage</code>
* @param domAddElement the <code>dom-add</code> element created by a
* previous invocation of <code>renderAdd(ServerMessage)</code>
* @param parentId the id of the element the HTML code will be appended to
* @param htmlFragment the HTML fragment to add to the DOM
*/
public static void renderElementAddContent(ServerMessage serverMessage, Element domAddElement, String parentId,
DocumentFragment htmlFragment) {
renderElementAddContent(serverMessage, domAddElement, parentId, null, htmlFragment);
}
/**
* Adds content to be added to an existing <code>dom-add</code> operation.
* The content will be inserted into the DOM element identified by
* <code>parentId</code> before the specified <code>siblingId</code>.
*
* @param serverMessage the <code>ServerMessage</code>
* @param domAddElement the <code>dom-add</code> element created by a
* previous invocation of <code>renderAdd(ServerMessage)</code>
* @param parentId the id of the element the HTML code will be appended to
* @param siblingId The id of the element which the content will be inserted
* <strong>before</strong> (this element must be an immediate child
* of the element specified by <code>parentId</code>)
* @param htmlFragment the HTML fragment to add to the DOM
*/
public static void renderElementAddContent(ServerMessage serverMessage, Element domAddElement, String parentId,
String siblingId, DocumentFragment htmlFragment) {
setContentNamespace(htmlFragment);
Element contentElement = domAddElement.getOwnerDocument().createElement("content");
contentElement.setAttribute("parent-id", parentId);
if (siblingId != null) {
contentElement.setAttribute("sibling-id", siblingId);
}
domAddElement.appendChild(contentElement);
contentElement.appendChild(htmlFragment);
}
/**
* Creates a <code>dom-remove</code> operation to remove the HTML element
* identified by <code>targetId</code> from the client DOM.
*
* @param serverMessage the outgoing <code>ServerMessage</code>
* @param targetId the id of the element to remove
*/
public static void renderElementRemove(ServerMessage serverMessage, String targetId) {
Element domRemoveElement = serverMessage.appendPartDirective(ServerMessage.GROUP_ID_REMOVE,
MESSAGE_PART_NAME, "dom-remove");
domRemoveElement.setAttribute("target-id", targetId);
}
/**
* Creates a <code>dom-remove</code> operation to remove all child elements
* of the element identified by <code>targetId</code> from the client DOM.
*
* @param serverMessage the outgoing <code>ServerMessage</code>
* @param targetId the id of the element whose children ware to be removed
*/
public static void renderElementRemoveChildren(ServerMessage serverMessage, String targetId) {
Element domRemoveElement = serverMessage.appendPartDirective(ServerMessage.GROUP_ID_REMOVE,
MESSAGE_PART_NAME, "dom-remove-children");
domRemoveElement.setAttribute("target-id", targetId);
}
/**
* Creates a <code>style-update</code> operation to update a CSS style
* attribute of the element identified by <code>targetId</code> in the
* client DOM.
*
* @param serverMessage the outgoing <code>ServerMessage</code>
* @param targetId the id of the element whose <strong>style</strong>
* attribute is to be updated
* @param attributeName the name of the <strong>style</strong> attribute
* @param attributeValue the new value of the <strong>style</strong>
* attribute
*/
public static void renderStyleUpdate(ServerMessage serverMessage, String targetId, String attributeName,
String attributeValue) {
Element element = serverMessage.appendPartDirective(ServerMessage.GROUP_ID_UPDATE, MESSAGE_PART_NAME, "style-update");
element.setAttribute("target-id", targetId);
element.setAttribute("name", attributeName);
element.setAttribute("value", attributeValue);
}
/**
* Creates a <code>stylesheet-add-rule</code> directive to add a rule
* to a stylesheet
*
* @param serverMessage the relevant <code>ServerMessage</code>
* @param selectorText the selector of the rule to add
* @param style the CSS text for the style
*/
public static void renderStyleSheetAddRule(ServerMessage serverMessage, String selectorText, String style) {
Element element = serverMessage.appendPartDirective(ServerMessage.GROUP_ID_UPDATE, MESSAGE_PART_NAME,
"stylesheet-add-rule");
element.setAttribute("selector", selectorText);
element.setAttribute("style", style);
}
/**
* Creates a <code>stylesheet-remove-rule</code> directive to remove a rule
* from a stylesheet
*
* @param serverMessage the relevant <code>ServerMessage</code>
* @param selectorText the selector of the rule to remove
*/
public static void renderStyleSheetRemoveRule(ServerMessage serverMessage, String selectorText) {
Element element = serverMessage.appendPartDirective(ServerMessage.GROUP_ID_UPDATE, MESSAGE_PART_NAME,
"stylesheet-remove-rule");
element.setAttribute("selector", selectorText);
}
/**
* Configures all child elements of a "content" element to use the XHTML
* namespace.
*
* @param htmlFragment an HTML document fragment
*/
private static void setContentNamespace(DocumentFragment htmlFragment) {
Node childNode = htmlFragment.getFirstChild();
while (childNode != null) {
if (childNode.getNodeType() == Node.ELEMENT_NODE) {
((Element) childNode).setAttribute("xmlns", XHTML_NAMESPACE);
}
childNode = childNode.getNextSibling();
}
}
}