001: /*
002: ItsNat Java Web Application Framework
003: Copyright (C) 2007 Innowhere Software Services S.L., Spanish Company
004: Author: Jose Maria Arranz Santamaria
005:
006: This program is free software: you can redistribute it and/or modify
007: it under the terms of the GNU Affero General Public License as published by
008: the Free Software Foundation, either version 3 of the License, or
009: (at your option) any later version. See the GNU Affero General Public
010: License for more details. See the copy of the GNU Affero General Public License
011: included in this program. If not, see <http://www.gnu.org/licenses/>.
012: */
013:
014: package org.itsnat.impl.core.js.domrender.node;
015:
016: import java.util.Set;
017: import org.itsnat.impl.core.ItsNatDocumentImpl;
018: import org.itsnat.impl.core.NodeLocation;
019: import org.itsnat.impl.core.domutil.ItsNatDOMUtilInternal;
020: import org.itsnat.impl.core.domutil.NodeConstraints;
021: import org.w3c.dom.Node;
022: import org.w3c.dom.NodeList;
023: import org.w3c.dom.html.HTMLElement;
024:
025: /**
026: *
027: * @author jmarranz
028: */
029: public abstract class JSHTMLElementRenderImpl extends
030: JSElementRenderImpl {
031: /** Creates a new instance of JSElementRender */
032: public JSHTMLElementRenderImpl() {
033: }
034:
035: public abstract NodeConstraints getInnerHTMLNodeConstraints();
036:
037: public abstract Set getInnerHTMLInvalidTags();
038:
039: public boolean isHTMLElementValidWithInnerHTML(HTMLElement elem,
040: boolean isHTML) {
041: if (!isHTML)
042: return false; // XHTML NO tiene innerHTML
043: return isHTMLElementValidWithInnerHTML(elem);
044: }
045:
046: protected boolean isHTMLElementValidWithInnerHTML(HTMLElement elem) {
047: // Merece la pena el esfuerzo pues la ganancia de rendimiento de innerHTML en el cliente es alto
048:
049: // Xerces devuelve el tagNameUpper es mayúsculas siempre (incluso en XHTML pues usa nuestro parche que usa objetos HTML)
050: String tagNameUpper = elem.getTagName();
051:
052: boolean notValid = getInnerHTMLInvalidTags().contains(
053: tagNameUpper);
054: if (notValid)
055: return false;
056:
057: if (ItsNatDOMUtilInternal.hasContainedNodeMatching(elem,
058: getInnerHTMLNodeConstraints()))
059: return false;
060:
061: return true;
062: }
063:
064: public boolean canInsertChildrenWithInnerHTML(HTMLElement parent,
065: ItsNatDocumentImpl itsNatDoc) {
066: // Por ahora si el elemento admite innerHTML podrá usarse innerHTML
067: return isHTMLElementValidWithInnerHTML(parent, itsNatDoc
068: .isHTML());
069: }
070:
071: public boolean canInsertChildWithInnerHTML(HTMLElement parent,
072: Node newChildNode, ItsNatDocumentImpl itsNatDoc) {
073: // newChildNode debe ser el único nodo hijo
074: if (parent.getFirstChild() != newChildNode)
075: return false; // Rarísimo pero por si acaso
076:
077: if (parent.getFirstChild() != parent.getLastChild())
078: return false; // No es el único nodo hijo
079:
080: if (!canInsertChildrenWithInnerHTML(parent, itsNatDoc))
081: return false;
082:
083: return true;
084: }
085:
086: public static String insertWithInnerHTML(HTMLElement parent,
087: Node newNode, ItsNatDocumentImpl itsNatDoc) {
088: // Caso de único nodo, usamos innerHTML que es mucho más eficaz que
089: // con DOM en JavaScript pues JavaScript es muy lento
090: // y via innerHTML se procesa con el parser C/C++ del navegador
091:
092: String nodeHTML = itsNatDoc.serializeNode(newNode);
093: NodeLocation parentLoc = itsNatDoc.getNodeLocation(parent);
094: String strValue = getTransportableStringLiteral(nodeHTML);
095: String code = "itsNatDoc.setInnerHTML("
096: + parentLoc.getParentIdJS() + "," + parentLoc.getIdJS()
097: + "," + parentLoc.getPathJS() + "," + strValue
098: + "); \n";
099: return code;
100: }
101:
102: public static String insertChildrenWithInnerHTML(String parentName,
103: Node parentNode, ItsNatDocumentImpl itsNatDoc) {
104: // Se supone que hay nodos hijo (si no no llamar).
105: NodeList childList = parentNode.getChildNodes();
106: StringBuffer htmlCode = new StringBuffer();
107: for (int i = 0; i < childList.getLength(); i++) {
108: Node child = childList.item(i);
109: String nodeHTML = itsNatDoc.serializeNode(child);
110: htmlCode.append(nodeHTML);
111: }
112:
113: String code = parentName + ".innerHTML = "
114: + getTransportableStringLiteral(htmlCode.toString())
115: + "; \n";
116: return code;
117: }
118:
119: public String fillChildNodes(Node node, String varName,
120: ItsNatDocumentImpl itsNatDoc) {
121: if (canInsertChildrenWithInnerHTML((HTMLElement) node,
122: itsNatDoc))
123: return insertChildrenWithInnerHTML(varName, node, itsNatDoc);
124: else
125: return super .fillChildNodes(node, varName, itsNatDoc);
126: }
127:
128: public String getInsertNewNodeCode(Node newNode,
129: String newNodeName, Node parent,
130: ItsNatDocumentImpl itsNatDoc) {
131: if (canInsertChildWithInnerHTML((HTMLElement) parent, newNode,
132: itsNatDoc))
133: return insertWithInnerHTML((HTMLElement) parent, newNode,
134: itsNatDoc);
135: else
136: return super.getInsertNewNodeCode(newNode, newNodeName,
137: parent, itsNatDoc);
138: }
139: }
|