org.htmlunit.html.HtmlScript Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of xlt Show documentation
Show all versions of xlt Show documentation
XLT (Xceptance LoadTest) is an extensive load and performance test tool developed and maintained by Xceptance.
/*
* Copyright (c) 2002-2024 Gargoyle Software Inc.
*
* 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
* https://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 org.htmlunit.html;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Map;
import org.htmlunit.SgmlPage;
import org.htmlunit.javascript.AbstractJavaScriptEngine;
import org.htmlunit.javascript.PostponedAction;
import org.htmlunit.javascript.host.dom.Document;
/**
* Wrapper for the HTML element "script".
* When a script tag references an external script (with attribute src) it gets executed when the node
* is added to the DOM tree. When the script code is nested, it gets executed when the text node
* containing the script is added to the HtmlScript.
* The ScriptFilter feature of NekoHtml can't be used because it doesn't allow immediate access to the DOM
* (i.e. document.write("<span id='mySpan'/>"); document.getElementById("mySpan").tagName;
* can't work with a filter).
*
* @author Mike Bowler
* @author Christian Sell
* @author Marc Guillemot
* @author David K. Taylor
* @author Ahmed Ashour
* @author Daniel Gredler
* @author Dmitri Zoubkov
* @author Sudhan Moghe
* @author Ronald Brill
* @author Daniel Wagner-Hall
* @author Frank Danek
* @see DOM Level 1
* @see DOM Level 2
*/
public class HtmlScript extends HtmlElement implements ScriptElement {
/** The HTML tag represented by this element. */
public static final String TAG_NAME = "script";
private boolean executed_;
private boolean createdByDomParser_;
/**
* Creates an instance of HtmlScript
*
* @param qualifiedName the qualified name of the element type to instantiate
* @param page the HtmlPage that contains this element
* @param attributes the initial attributes
*/
HtmlScript(final String qualifiedName, final SgmlPage page,
final Map attributes) {
super(qualifiedName, page, attributes);
}
/**
* {@inheritDoc}
*/
@Override
public final String getCharsetAttribute() {
return getAttributeDirect("charset");
}
/**
* Returns the value of the attribute {@code type}. Refer to the
* HTML 4.01
* documentation for details on the use of this attribute.
*
* @return the value of the attribute {@code type}
* or an empty string if that attribute isn't defined.
*/
public final String getTypeAttribute() {
return getAttributeDirect(TYPE_ATTRIBUTE);
}
/**
* Returns the value of the attribute {@code language}. Refer to the
* HTML 4.01
* documentation for details on the use of this attribute.
*
* @return the value of the attribute {@code language}
* or an empty string if that attribute isn't defined.
*/
public final String getLanguageAttribute() {
return getAttributeDirect("language");
}
/**
* {@inheritDoc}
*/
@Override
public final String getSrcAttribute() {
return getSrcAttributeNormalized();
}
/**
* Returns the value of the attribute {@code event}.
* @return the value of the attribute {@code event}
*/
public final String getEventAttribute() {
return getAttributeDirect("event");
}
/**
* Returns the value of the attribute {@code for}.
* @return the value of the attribute {@code for}
*/
public final String getHtmlForAttribute() {
return getAttributeDirect("for");
}
/**
* Returns the value of the attribute {@code defer}. Refer to the
* HTML 4.01
* documentation for details on the use of this attribute.
*
* @return the value of the attribute {@code defer}
* or an empty string if that attribute isn't defined.
*/
public final String getDeferAttribute() {
return getAttributeDirect("defer");
}
/**
* {@inheritDoc}
*/
@Override
public boolean isDeferred() {
return getDeferAttribute() != ATTRIBUTE_NOT_DEFINED;
}
/**
* {@inheritDoc}
*/
@Override
public boolean mayBeDisplayed() {
return false;
}
/**
* If setting the src
attribute, this method executes the new JavaScript if necessary
* (behavior varies by browser version). {@inheritDoc}
*/
@Override
protected void setAttributeNS(final String namespaceURI, final String qualifiedName, final String attributeValue,
final boolean notifyAttributeChangeListeners, final boolean notifyMutationObservers) {
final String qualifiedNameLC = org.htmlunit.util.StringUtils.toRootLowerCase(qualifiedName);
// special additional processing for the 'src'
if (namespaceURI != null || !SRC_ATTRIBUTE.equals(qualifiedNameLC)) {
super.setAttributeNS(namespaceURI, qualifiedNameLC, attributeValue, notifyAttributeChangeListeners,
notifyMutationObservers);
return;
}
// namespaceURI is always null here - we can call getAttribute directly
final String oldValue = getAttribute(qualifiedNameLC);
super.setAttributeNS(null, qualifiedNameLC, attributeValue, notifyAttributeChangeListeners,
notifyMutationObservers);
if (isAttachedToPage() && oldValue.isEmpty() && getFirstChild() == null) {
final PostponedAction action = new PostponedAction(getPage(), "HtmlScript.setAttributeNS") {
@Override
public void execute() {
ScriptElementSupport.executeScriptIfNeeded(HtmlScript.this, false, false);
}
};
final AbstractJavaScriptEngine> engine = getPage().getWebClient().getJavaScriptEngine();
engine.addPostponedAction(action);
}
}
/**
* Executes the onreadystatechange
handler when simulating IE, as well as executing
* the script itself, if necessary.
* {@inheritDoc}
*/
@Override
public void onAllChildrenAddedToPage(final boolean postponed) {
ScriptElementSupport.onAllChildrenAddedToPage(this, postponed);
}
/**
* Gets the script held within the script tag.
*/
private String getScriptCode() {
final Iterable textNodes = getChildren();
final StringBuilder scriptCode = new StringBuilder();
for (final DomNode node : textNodes) {
if (node instanceof DomText) {
final DomText domText = (DomText) node;
scriptCode.append(domText.getData());
}
}
return scriptCode.toString();
}
/**
* Indicates if a node without children should be written in expanded form as XML
* (i.e. with closing tag rather than with "/>")
* @return {@code true} to make generated XML readable as HTML
*/
@Override
protected boolean isEmptyXmlTagExpanded() {
return true;
}
/**
* {@inheritDoc}
*/
@Override
protected void printChildrenAsXml(final String indent, final PrintWriter printWriter) {
final DomCharacterData textNode = (DomCharacterData) getFirstChild();
if (textNode == null) {
return;
}
final String data = textNode.getData();
if (data.contains("//");
printWriter.print("\r\n");
}
}
/**
* INTERNAL API - SUBJECT TO CHANGE AT ANY TIME - USE AT YOUR OWN RISK.
*
* Resets the executed flag.
* @see HtmlScript#processImportNode(Document)
*/
public void resetExecuted() {
executed_ = false;
}
@Override
public void processImportNode(final Document doc) {
super.processImportNode(doc);
executed_ = true;
}
/**
* Returns a string representation of this object.
* @return a string representation of this object
*/
@Override
public String toString() {
final StringWriter writer = new StringWriter();
final PrintWriter printWriter = new PrintWriter(writer);
printWriter.print(getClass().getSimpleName());
printWriter.print("[<");
printOpeningTagContentAsXml(printWriter);
printWriter.print(">");
printWriter.print(getScriptCode());
printWriter.print("]");
printWriter.flush();
return writer.toString();
}
/**
* {@inheritDoc}
*/
@Override
public DisplayStyle getDefaultStyleDisplay() {
return DisplayStyle.NONE;
}
/**
* {@inheritDoc}
*/
@Override
public void markAsCreatedByDomParser() {
createdByDomParser_ = true;
}
/**
* {@inheritDoc}
*/
@Override
public boolean wasCreatedByDomParser() {
return createdByDomParser_;
}
/**
* {@inheritDoc}
*/
@Override
public boolean isExecuted() {
return executed_;
}
/**
* {@inheritDoc}
*/
@Override
public void setExecuted(final boolean executed) {
executed_ = executed;
}
}