org.cobraparser.html.domimpl.HTMLAbstractUIElement Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of Cobra Show documentation
Show all versions of Cobra Show documentation
Cobra is the rendering engine designed for LoboBrowser
package org.cobraparser.html.domimpl;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import org.cobraparser.html.js.Executor;
import org.cobraparser.html.js.Window;
import org.cobraparser.js.JavaScript;
import org.cobraparser.ua.UserAgentContext;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.EcmaError;
import org.mozilla.javascript.Function;
import org.mozilla.javascript.Scriptable;
import org.w3c.dom.Document;
/**
* Implements common functionality of most elements.
*/
public class HTMLAbstractUIElement extends HTMLElementImpl {
private Function onfocus, onblur, onclick, ondblclick, onmousedown, onmouseup, onmouseover, onmousemove, onmouseout, onkeypress,
onkeydown, onkeyup, oncontextmenu;
public HTMLAbstractUIElement(final String name) {
super(name);
}
public Function getOnblur() {
return this.getEventFunction(onblur, "onblur");
}
public void setOnblur(final Function onblur) {
this.onblur = onblur;
}
public Function getOnclick() {
return this.getEventFunction(onclick, "onclick");
}
public void setOnclick(final Function onclick) {
this.onclick = onclick;
}
public Function getOndblclick() {
return this.getEventFunction(ondblclick, "ondblclick");
}
public void setOndblclick(final Function ondblclick) {
this.ondblclick = ondblclick;
}
public Function getOnfocus() {
return this.getEventFunction(onfocus, "onfocus");
}
public void setOnfocus(final Function onfocus) {
this.onfocus = onfocus;
}
public Function getOnkeydown() {
return this.getEventFunction(onkeydown, "onkeydown");
}
public void setOnkeydown(final Function onkeydown) {
this.onkeydown = onkeydown;
}
public Function getOnkeypress() {
return this.getEventFunction(onkeypress, "onkeypress");
}
public void setOnkeypress(final Function onkeypress) {
this.onkeypress = onkeypress;
}
public Function getOnkeyup() {
return this.getEventFunction(onkeyup, "onkeyup");
}
public void setOnkeyup(final Function onkeyup) {
this.onkeyup = onkeyup;
}
public Function getOnmousedown() {
return this.getEventFunction(onmousedown, "onmousedown");
}
public void setOnmousedown(final Function onmousedown) {
this.onmousedown = onmousedown;
}
public Function getOnmousemove() {
return this.getEventFunction(onmousemove, "onmousemove");
}
public void setOnmousemove(final Function onmousemove) {
this.onmousemove = onmousemove;
}
public Function getOnmouseout() {
return this.getEventFunction(onmouseout, "onmouseout");
}
public void setOnmouseout(final Function onmouseout) {
this.onmouseout = onmouseout;
}
public Function getOnmouseover() {
return this.getEventFunction(onmouseover, "onmouseover");
}
public void setOnmouseover(final Function onmouseover) {
this.onmouseover = onmouseover;
}
public Function getOnmouseup() {
return this.getEventFunction(onmouseup, "onmouseup");
}
public void setOnmouseup(final Function onmouseup) {
this.onmouseup = onmouseup;
}
public Function getOncontextmenu() {
return this.getEventFunction(oncontextmenu, "oncontextmenu");
}
public void setOncontextmenu(final Function oncontextmenu) {
this.oncontextmenu = oncontextmenu;
}
public void focus() {
final UINode node = this.getUINode();
if (node != null) {
node.focus();
}
}
public void blur() {
final UINode node = this.getUINode();
if (node != null) {
node.blur();
}
}
private Map functionByAttribute = null;
protected Function getEventFunction(final Function varValue, final String attributeName) {
if (varValue != null) {
return varValue;
}
final String normalAttributeName = normalizeAttributeName(attributeName);
synchronized (this) {
Map fba = this.functionByAttribute;
Function f = fba == null ? null : fba.get(normalAttributeName);
if (f != null) {
return f;
}
final UserAgentContext uac = this.getUserAgentContext();
if (uac == null) {
throw new IllegalStateException("No user agent context.");
}
if (uac.isScriptingEnabled()) {
final String attributeValue = this.getAttribute(attributeName);
if ((attributeValue != null) && (attributeValue.length() != 0)) {
final String functionCode = "function " + normalAttributeName + "_" + System.identityHashCode(this) + "() { " + attributeValue
+ " }";
final Document doc = this.document;
if (doc == null) {
throw new IllegalStateException("Element does not belong to a document.");
}
final Window window = ((HTMLDocumentImpl) doc).getWindow();
final Context ctx = Executor.createContext(this.getDocumentURL(), uac, window.getContextFactory());
try {
final Scriptable scope = window.getWindowScope();
if (scope == null) {
throw new IllegalStateException("Scriptable (scope) instance was null");
}
final Scriptable thisScope = (Scriptable) JavaScript.getInstance().getJavascriptObject(this, scope);
try {
// TODO: Get right line number for script. //TODO: Optimize this
// in case it's called multiple times? Is that done?
f = ctx.compileFunction(thisScope, functionCode, this.getTagName() + "[" + this.getId() + "]." + attributeName, 1, null);
} catch (final EcmaError ecmaError) {
logger.log(Level.WARNING, "Javascript error at " + ecmaError.sourceName() + ":" + ecmaError.lineNumber() + ": "
+ ecmaError.getMessage(), ecmaError);
f = null;
} catch (final Exception err) {
logger.log(Level.WARNING, "Unable to evaluate Javascript code", err);
f = null;
}
} finally {
Context.exit();
}
}
if (fba == null) {
fba = new HashMap<>(1);
this.functionByAttribute = fba;
}
fba.put(normalAttributeName, f);
}
return f;
}
}
@Override
protected void handleAttributeChanged(String name, String oldValue, String newValue) {
super.handleAttributeChanged(name, oldValue, newValue);
if (name.startsWith("on")) {
synchronized (this) {
final Map fba = this.functionByAttribute;
if (fba != null) {
fba.remove(name);
}
}
}
}
}