All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cat.inspiracio.html.HTMLElementImp Maven / Gradle / Ivy

Go to download

HTML-parser provides a parser for HTML 5 that produces HTML 5 document object model. It aims to be a Java-implementation of http://www.w3.org/TR/html5/. It is for use in the server. It does not implement features that are relevant in the client, like event handling. It is for use from javascript, via Java's scripting library.

The newest version!
/*
Copyright 2015 Alexander Bunkenburg 

Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cat.inspiracio.html;

import static java.lang.Double.parseDouble;
import static java.lang.Long.parseLong;
import static java.util.Locale.ENGLISH;

import java.io.StringWriter;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;

import org.apache.xerces.dom.ElementImpl;
import org.w3c.dom.Attr;
import org.w3c.dom.DOMException;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;

import cat.inspiracio.dom.DOMStringMap;
import cat.inspiracio.dom.HTMLCollection;
import cat.inspiracio.dom.HTMLCollectionImp;

/** Implementation class for html elements.
 * 
 * You can make a new html element by extending this class.
 * */
public class HTMLElementImp extends ElementImpl implements HTMLElement{
	private static final long serialVersionUID = -7630166106874010622L;
	
	// construction ---------------------------------------------------------------

	/** Make a new HTML element.
	 * @param owner The document
	 * @param tag The tag name. Not case-sensitive. Will be converted to lower-case.
	 * */
	protected HTMLElementImp(HTMLDocumentImp owner, String tag){
		super(owner, tag.toLowerCase());//can remove conversion?
	}
	
	@Override public HTMLElementImp cloneNode(boolean deep){
		return (HTMLElementImp)super.cloneNode(deep);
	}
	
    // DOM tree manipulation -------------------------------------------
	
	/** Tests whether this element is a descendant of another. 
	 * 
	 * Equals: false. (This is probably a special case for the caller.)
	 * 
	 * @param ancestor If null, return false.
	 * */
	private boolean descendsFrom(HTMLElement ancestor){
		if(ancestor==null)return false;
		if(ancestor==this)return false;
		Node parent=getParentNode();
		while(parent!=null){
			if(parent==ancestor)return true;
			parent=parent.getParentNode();
		}
		return false;
	}

	/** First adopts the new child, then inserts it.
	 * 
	 * I do this so that we can insert elements that were created with a 
	 * different owner document or no owner document, such as from
	 * "new Image()" in javascript.
	 * 
	 * @param newChild the new child
	 * @param refChild If null, inserts at end.
	 * 
	 * @see org.apache.xerces.dom.NodeImpl#appendChild(org.w3c.dom.Node)
	 */
	@Override public Node insertBefore(Node newChild, Node refChild) throws DOMException{
		Node n=adoptNode(newChild);
		if(n==null){
			//result of adoptNode is null if this and newChild have different implementation
			DOMImplementation mine=this.getOwnerDocument().getImplementation();
			DOMImplementation yours=newChild.getOwnerDocument().getImplementation();
			throw new IllegalArgumentException("Must have same DOM implementation. Mine: " + mine + ". Yours: " + yours);
		}
		return super.insertBefore(n, refChild);
	}
	
	/** First adopts the new child, then appends it.
	 * 
	 * I do this so that we can insert elements that were created with a 
	 * different owner document or no owner document, such as from
	 * "new Image()" in javascript.
	 * 
	 * @param newChild the new child
	 * @see org.apache.xerces.dom.NodeImpl#appendChild(org.w3c.dom.Node)
	 */
	@Override public Node appendChild(Node newChild) throws DOMException {
		//We don't need adoptChild(newChild) because super.appendChild() calls insertBefore(n,r)?
		//adoptNode(newChild);
		return super.appendChild(newChild);
	}
	
	/** Adopts a node into the owner document. */
	private Node adoptNode(Node newChild){
		HTMLDocument document=getOwnerDocument();
		HTMLDOMImplementation implementation=(HTMLDOMImplementation)document.getImplementation();
		
		//Transfer the DOM implementation to new child
		HTMLDocumentImp d=(HTMLDocumentImp)newChild.getOwnerDocument();
		d.setImplementation(implementation);
		
		return document.adoptNode(newChild);
	}
	
    /** 
     * Explicit implementation of getChildNodes() to avoid problems with
     * overriding the getLength() method hidden in the super class.
     * 
     * The problem is that the superclass ParentNode overrides 
     * getChildNodes(){return this;}. That is good for performance,
     * but also means that no subclass can use the method names of 
     * the two NodeList methods (item(Node) and getLength()) for any
     * different meaning. At least HTMLSelectElement and HTMLFormElement
     * want to do that. Confusion that comes from optimisation.
     * In order to avoid this confusion, here I override getChildNodes()
     * so that it returns a fresh object. 
     */
    @Override public NodeList getChildNodes(){return getChildNodesUnoptimized();}
    
	@Override public HTMLCollection getChildElements(){
		HTMLCollectionImp elements=new HTMLCollectionImp();
		NodeList children=getChildNodes();
		int length=children.getLength();
		for(int i=0; iSpec
	 * */
	protected void remove(){
		Node parent=getParentNode();
		if(parent!=null)parent.removeChild(this);
	}

	/** Convenience for subclass implementations 
	 * @param id of the element to get 
	 * @return the element or null */
	protected HTMLElement getElementById(String id){
		return getOwnerDocument().getElementById(id);
	}
	
    @Override public String getStyle(){return getAttribute("style");}
    @Override public void setStyle(String style){setAttribute("style", style);}
    
    /**
     * Convenience method returns the form in which this form element is contained.
     * This method is exposed for form elements through the DOM API, but other
     * elements have no access to it through the API.
     * @return the form or null 
     */
    protected HTMLFormElement getForm(){
        Node parent=getParentNode(); 
        while(parent!=null){
            if(parent instanceof HTMLFormElement)
                return (HTMLFormElement)parent;
            parent=parent.getParentNode();
        }
        return null;
    }
    
    /** Convenience: concatenates the text of all Text children of this element,
     * ignoring comment and data. Used in script element and others. 
     * @return the text */
    protected String getText(){
        StringBuilder text=new StringBuilder();
        Node child=getFirstChild();
        while(child!=null){
            if(child instanceof Text){
                Text t=(Text)child;
                String data=t.getData();
                text.append(data);
            }
            child=child.getNextSibling();
        }
        return text.toString();
    }

    /** Add an element as first child. */
    @Override public void prepend(HTMLElement element){
        Node first=getFirstChild();
        insertBefore(element, first);
    }

	// interface HTMLElement ------------------------------------------------------

	@Override public String getId(){return getAttribute("id");}
	@Override public void setId(String id){setAttribute("id", id);}

	@Override public String getName(){return getAttribute("name");}
	@Override public void setName(String n){setAttribute("name", n);}

	@Override public String getTitle(){return getAttribute("title");}
	@Override public void setTitle(String title){setAttribute("title", title);}

	@Override public String getLang(){return getAttribute("lang");}
	@Override public void setLang(String lang){setAttribute("lang", lang);}

	@Override public HTMLDocument getOwnerDocument(){return (HTMLDocument)super.getOwnerDocument();}
	
	/** Is this element inside a document?
	 * The only document that it can be in is its owner document.
	 * @return Is this element inside a document? */
    protected boolean isInDocument(){
        HTMLDocument document=getOwnerDocument();
        if(document==null)
            return false;
        HTMLHtmlElement html=document.getDocumentElement();
        if(html==null)
            return false;
        boolean descends=descendsFrom(html);
        return descends;
    }

    @Override public String getDir(){return getAttribute("dir");}
	@Override public void setDir(String dir){setAttribute("dir", dir);}

	@Override public String getClassName(){return getAttribute("class");}
	@Override public void setClassName(String className){setAttribute("class", className);}

	/** Not implemented. */
	@Override public boolean getTranslate(){throw new UnsupportedOperationException();}
	@Override public void setTranslate(boolean t){setAttribute("translate", yesNo(t));}

	/** Spec */
	@Override public DOMStringMap getDataset(){return new DatasetImp(this);}

	// User interaction ---------------------------------------
	
	@Override public boolean getHidden(){return getAttributeBoolean("hidden");}
	@Override public void setHidden(boolean h){setAttribute("hidden", h);}

	@Override public int getTabIndex(){return getAttributeInt("tabindex");}
	@Override public void setTabIndex(int t){setAttribute("tabindex", t);}

	@Override public String getAccessKey(){return getAttribute("accesskey");}
	@Override public void setAccessKey(String key){setAttribute("accesskey", key);}

	/** On the server, we don't assign access keys. A browser can do that. Returns "". */
	@Override public String getAccessKeyLabel(){return "";}

	/** Not implemented. */
	@Override public String getContentEditable(){throw new UnsupportedOperationException();}

	/** Not implemented. */
	@Override public void setContentEditable(String s){throw new UnsupportedOperationException();}
	
	/** Not implemented. */
	@Override public boolean isContentEditable(){throw new UnsupportedOperationException();}

	/** Not implemented. */
	@Override public boolean getSpellcheck(){throw new UnsupportedOperationException();}
	
	/** Not implemented. */
	@Override public void setSpellcheck(boolean b){throw new UnsupportedOperationException();}

	/** Does nothing. */
	@Override public void blur(){}
	
	/** Does nothing. */
	@Override public void focus(){}
	
	/** Does nothing. */
	@Override public void click(){}

	// interface Element -----------------------------------------------------------------

    /** @param namespace the namespace
     * @param key case-sensitive */
    @Override public Attr getAttributeNodeNS( String namespace, String key ) {
        if(namespace!=null && 0 getElementsByTagName(String tag){
    	tag=tag.toLowerCase(ENGLISH);
        NodeList nodes=super.getElementsByTagName(tag);
        HTMLCollectionImpcollection=new HTMLCollectionImp<>();
        for(int i=0; i
    	tag=tag.toLowerCase(ENGLISH);
        if(namespace!=null && 0 r=new DocumentWriter(writer);
			r.element(this);
			return writer.toString();
		}
		catch(Exception e){
		   return "<" + getTagName() + ">";
		}
	}
	
	/** Factory method for convenience 
	 * @param tag make an element with this tag
	 * @return new element */
	protected HTMLElement createElement(String tag){
		HTMLDocument document=getOwnerDocument();
		return document.createElement(tag);
	}
	
	/** Factory method for convenience:
	 * Creates an element of this interface.
	 * Saves having to cast the result to the interface.
	 * @param  type of the new element
	 * @param c Interface like HTMLTableCaptionElement
	 * @return the new element
	 * @throws UnsupportedOperationException Not implemented for this interface,
	 * 	maybe because the interface applies to several tag names
	 * 	and therefore the call is ambiguous.
	 *  */
	protected  T createElement(Classc){
		HTMLDocument document=getOwnerDocument();
		return document.createElement(c);
	}
	
	/** Convenience: returns the first child element with this tag, or null. 
	 * @param tag looking for elements with this tag
	 * @return the first one or null */
	protected HTMLElement getElementByTagName(String tag){
		NodeList nodes=getElementsByTagName(tag);
		if(nodes.getLength()==0)
			return null;
		return (HTMLElement)nodes.item(0);
	}

	// interface ScriptMap ----------------------
	
	@Override public boolean has(String key){return hasAttribute(key);}
	@Override public String get(String key){return getAttribute(key);}
	@Override public void set(String key, String value){setAttribute(key, value);}
	@Override public void set(String key, int value){setAttribute(key, value);}
    @Override public void deleter(String key){removeAttribute(key);}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy