1427 lines
36 KiB
JavaScript
1427 lines
36 KiB
JavaScript
|
"use strict";
|
||
|
var Node = require('./Node');
|
||
|
var Element = require('./Element');
|
||
|
var CSSStyleDeclaration = require('./CSSStyleDeclaration');
|
||
|
var utils = require('./utils');
|
||
|
var URLUtils = require('./URLUtils');
|
||
|
var defineElement = require('./defineElement');
|
||
|
|
||
|
var htmlElements = exports.elements = {};
|
||
|
var htmlNameToImpl = Object.create(null);
|
||
|
|
||
|
exports.createElement = function(doc, localName, prefix) {
|
||
|
var impl = htmlNameToImpl[localName] || HTMLUnknownElement;
|
||
|
return new impl(doc, localName, prefix);
|
||
|
};
|
||
|
|
||
|
function define(spec) {
|
||
|
return defineElement(spec, HTMLElement, htmlElements, htmlNameToImpl);
|
||
|
}
|
||
|
|
||
|
function URL(attr) {
|
||
|
return {
|
||
|
get: function() {
|
||
|
var v = this._getattr(attr);
|
||
|
if (v === null) { return ''; }
|
||
|
var url = this.doc._resolve(v);
|
||
|
return (url === null) ? v : url;
|
||
|
},
|
||
|
set: function(value) {
|
||
|
this._setattr(attr, value);
|
||
|
}
|
||
|
};
|
||
|
}
|
||
|
|
||
|
function CORS(attr) {
|
||
|
return {
|
||
|
get: function() {
|
||
|
var v = this._getattr(attr);
|
||
|
if (v === null) { return null; }
|
||
|
if (v.toLowerCase() === 'use-credentials') { return 'use-credentials'; }
|
||
|
return 'anonymous';
|
||
|
},
|
||
|
set: function(value) {
|
||
|
if (value===null || value===undefined) {
|
||
|
this.removeAttribute(attr);
|
||
|
} else {
|
||
|
this._setattr(attr, value);
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
}
|
||
|
|
||
|
var REFERRER = {
|
||
|
type: ["", "no-referrer", "no-referrer-when-downgrade", "same-origin", "origin", "strict-origin", "origin-when-cross-origin", "strict-origin-when-cross-origin", "unsafe-url"],
|
||
|
missing: '',
|
||
|
};
|
||
|
|
||
|
|
||
|
// XXX: the default value for tabIndex should be 0 if the element is
|
||
|
// focusable and -1 if it is not. But the full definition of focusable
|
||
|
// is actually hard to compute, so for now, I'll follow Firefox and
|
||
|
// just base the default value on the type of the element.
|
||
|
var focusableElements = {
|
||
|
"A":true, "LINK":true, "BUTTON":true, "INPUT":true,
|
||
|
"SELECT":true, "TEXTAREA":true, "COMMAND":true
|
||
|
};
|
||
|
|
||
|
var HTMLFormElement = function(doc, localName, prefix) {
|
||
|
HTMLElement.call(this, doc, localName, prefix);
|
||
|
this._form = null; // Prevent later deoptimization
|
||
|
};
|
||
|
|
||
|
var HTMLElement = exports.HTMLElement = define({
|
||
|
superclass: Element,
|
||
|
ctor: function HTMLElement(doc, localName, prefix) {
|
||
|
Element.call(this, doc, localName, utils.NAMESPACE.HTML, prefix);
|
||
|
},
|
||
|
props: {
|
||
|
innerHTML: {
|
||
|
get: function() {
|
||
|
return this.serialize();
|
||
|
},
|
||
|
set: function(v) {
|
||
|
var parser = this.ownerDocument.implementation.mozHTMLParser(
|
||
|
this.ownerDocument._address,
|
||
|
this);
|
||
|
parser.parse(v===null ? '' : String(v), true);
|
||
|
|
||
|
// Remove any existing children of this node
|
||
|
var target = (this instanceof htmlNameToImpl.template) ?
|
||
|
this.content : this;
|
||
|
while(target.hasChildNodes())
|
||
|
target.removeChild(target.firstChild);
|
||
|
|
||
|
// Now copy newly parsed children to this node
|
||
|
target.appendChild(parser._asDocumentFragment());
|
||
|
}
|
||
|
},
|
||
|
style: { get: function() {
|
||
|
if (!this._style)
|
||
|
this._style = new CSSStyleDeclaration(this);
|
||
|
return this._style;
|
||
|
}, set: function(v) {
|
||
|
if (v===null||v===undefined) { v = ''; }
|
||
|
this._setattr('style', String(v));
|
||
|
}},
|
||
|
|
||
|
// These can't really be implemented server-side in a reasonable way.
|
||
|
blur: { value: function() {}},
|
||
|
focus: { value: function() {}},
|
||
|
forceSpellCheck: { value: function() {}},
|
||
|
|
||
|
click: { value: function() {
|
||
|
if (this._click_in_progress) return;
|
||
|
this._click_in_progress = true;
|
||
|
try {
|
||
|
if (this._pre_click_activation_steps)
|
||
|
this._pre_click_activation_steps();
|
||
|
|
||
|
var event = this.ownerDocument.createEvent("MouseEvent");
|
||
|
event.initMouseEvent("click", true, true,
|
||
|
this.ownerDocument.defaultView, 1,
|
||
|
0, 0, 0, 0,
|
||
|
// These 4 should be initialized with
|
||
|
// the actually current keyboard state
|
||
|
// somehow...
|
||
|
false, false, false, false,
|
||
|
0, null
|
||
|
);
|
||
|
|
||
|
// Dispatch this as an untrusted event since it is synthetic
|
||
|
var success = this.dispatchEvent(event);
|
||
|
|
||
|
if (success) {
|
||
|
if (this._post_click_activation_steps)
|
||
|
this._post_click_activation_steps(event);
|
||
|
}
|
||
|
else {
|
||
|
if (this._cancelled_activation_steps)
|
||
|
this._cancelled_activation_steps();
|
||
|
}
|
||
|
}
|
||
|
finally {
|
||
|
this._click_in_progress = false;
|
||
|
}
|
||
|
}},
|
||
|
submit: { value: utils.nyi },
|
||
|
},
|
||
|
attributes: {
|
||
|
title: String,
|
||
|
lang: String,
|
||
|
dir: {type: ["ltr", "rtl", "auto"], missing: ''},
|
||
|
accessKey: String,
|
||
|
hidden: Boolean,
|
||
|
tabIndex: {type: "long", default: function() {
|
||
|
if (this.tagName in focusableElements ||
|
||
|
this.contentEditable)
|
||
|
return 0;
|
||
|
else
|
||
|
return -1;
|
||
|
}}
|
||
|
},
|
||
|
events: [
|
||
|
"abort", "canplay", "canplaythrough", "change", "click", "contextmenu",
|
||
|
"cuechange", "dblclick", "drag", "dragend", "dragenter", "dragleave",
|
||
|
"dragover", "dragstart", "drop", "durationchange", "emptied", "ended",
|
||
|
"input", "invalid", "keydown", "keypress", "keyup", "loadeddata",
|
||
|
"loadedmetadata", "loadstart", "mousedown", "mousemove", "mouseout",
|
||
|
"mouseover", "mouseup", "mousewheel", "pause", "play", "playing",
|
||
|
"progress", "ratechange", "readystatechange", "reset", "seeked",
|
||
|
"seeking", "select", "show", "stalled", "submit", "suspend",
|
||
|
"timeupdate", "volumechange", "waiting",
|
||
|
|
||
|
// These last 5 event types will be overriden by HTMLBodyElement
|
||
|
"blur", "error", "focus", "load", "scroll"
|
||
|
]
|
||
|
});
|
||
|
|
||
|
|
||
|
// XXX: reflect contextmenu as contextMenu, with element type
|
||
|
|
||
|
|
||
|
// style: the spec doesn't call this a reflected attribute.
|
||
|
// may want to handle it manually.
|
||
|
|
||
|
// contentEditable: enumerated, not clear if it is actually
|
||
|
// reflected or requires custom getter/setter. Not listed as
|
||
|
// "limited to known values". Raises syntax_err on bad setting,
|
||
|
// so I think this is custom.
|
||
|
|
||
|
// contextmenu: content is element id, idl type is an element
|
||
|
// draggable: boolean, but not a reflected attribute
|
||
|
// dropzone: reflected SettableTokenList, experimental, so don't
|
||
|
// implement it right away.
|
||
|
|
||
|
// data-* attributes: need special handling in setAttribute?
|
||
|
// Or maybe that isn't necessary. Can I just scan the attribute list
|
||
|
// when building the dataset? Liveness and caching issues?
|
||
|
|
||
|
// microdata attributes: many are simple reflected attributes, but
|
||
|
// I'm not going to implement this now.
|
||
|
|
||
|
|
||
|
var HTMLUnknownElement = define({
|
||
|
ctor: function HTMLUnknownElement(doc, localName, prefix) {
|
||
|
HTMLElement.call(this, doc, localName, prefix);
|
||
|
}
|
||
|
});
|
||
|
|
||
|
|
||
|
var formAssociatedProps = {
|
||
|
// See http://www.w3.org/TR/html5/association-of-controls-and-forms.html#form-owner
|
||
|
form: { get: function() {
|
||
|
return this._form;
|
||
|
}}
|
||
|
};
|
||
|
|
||
|
define({
|
||
|
tag: 'a',
|
||
|
ctor: function HTMLAnchorElement(doc, localName, prefix) {
|
||
|
HTMLElement.call(this, doc, localName, prefix);
|
||
|
},
|
||
|
props: {
|
||
|
_post_click_activation_steps: { value: function(e) {
|
||
|
if (this.href) {
|
||
|
// Follow the link
|
||
|
// XXX: this is just a quick hack
|
||
|
// XXX: the HTML spec probably requires more than this
|
||
|
this.ownerDocument.defaultView.location = this.href;
|
||
|
}
|
||
|
}},
|
||
|
},
|
||
|
attributes: {
|
||
|
href: URL,
|
||
|
ping: String,
|
||
|
download: String,
|
||
|
target: String,
|
||
|
rel: String,
|
||
|
media: String,
|
||
|
hreflang: String,
|
||
|
type: String,
|
||
|
referrerPolicy: REFERRER,
|
||
|
// Obsolete
|
||
|
coords: String,
|
||
|
charset: String,
|
||
|
name: String,
|
||
|
rev: String,
|
||
|
shape: String,
|
||
|
}
|
||
|
});
|
||
|
// Latest WhatWG spec says these methods come via HTMLHyperlinkElementUtils
|
||
|
URLUtils._inherit(htmlNameToImpl.a.prototype);
|
||
|
|
||
|
define({
|
||
|
tag: 'area',
|
||
|
ctor: function HTMLAreaElement(doc, localName, prefix) {
|
||
|
HTMLElement.call(this, doc, localName, prefix);
|
||
|
},
|
||
|
attributes: {
|
||
|
alt: String,
|
||
|
target: String,
|
||
|
download: String,
|
||
|
rel: String,
|
||
|
media: String,
|
||
|
href: URL,
|
||
|
hreflang: String,
|
||
|
type: String,
|
||
|
shape: String,
|
||
|
coords: String,
|
||
|
ping: String,
|
||
|
// XXX: also reflect relList
|
||
|
referrerPolicy: REFERRER,
|
||
|
// Obsolete
|
||
|
noHref: Boolean,
|
||
|
}
|
||
|
});
|
||
|
// Latest WhatWG spec says these methods come via HTMLHyperlinkElementUtils
|
||
|
URLUtils._inherit(htmlNameToImpl.area.prototype);
|
||
|
|
||
|
define({
|
||
|
tag: 'br',
|
||
|
ctor: function HTMLBRElement(doc, localName, prefix) {
|
||
|
HTMLElement.call(this, doc, localName, prefix);
|
||
|
},
|
||
|
attributes: {
|
||
|
// Obsolete
|
||
|
clear: String
|
||
|
},
|
||
|
});
|
||
|
|
||
|
define({
|
||
|
tag: 'base',
|
||
|
ctor: function HTMLBaseElement(doc, localName, prefix) {
|
||
|
HTMLElement.call(this, doc, localName, prefix);
|
||
|
},
|
||
|
attributes: {
|
||
|
"target": String
|
||
|
}
|
||
|
});
|
||
|
|
||
|
|
||
|
define({
|
||
|
tag: 'body',
|
||
|
ctor: function HTMLBodyElement(doc, localName, prefix) {
|
||
|
HTMLElement.call(this, doc, localName, prefix);
|
||
|
},
|
||
|
// Certain event handler attributes on a <body> tag actually set
|
||
|
// handlers for the window rather than just that element. Define
|
||
|
// getters and setters for those here. Note that some of these override
|
||
|
// properties on HTMLElement.prototype.
|
||
|
// XXX: If I add support for <frameset>, these have to go there, too
|
||
|
// XXX
|
||
|
// When the Window object is implemented, these attribute will have
|
||
|
// to work with the same-named attributes on the Window.
|
||
|
events: [
|
||
|
"afterprint", "beforeprint", "beforeunload", "blur", "error",
|
||
|
"focus","hashchange", "load", "message", "offline", "online",
|
||
|
"pagehide", "pageshow","popstate","resize","scroll","storage","unload",
|
||
|
],
|
||
|
attributes: {
|
||
|
// Obsolete
|
||
|
text: { type: String, treatNullAsEmptyString: true },
|
||
|
link: { type: String, treatNullAsEmptyString: true },
|
||
|
vLink: { type: String, treatNullAsEmptyString: true },
|
||
|
aLink: { type: String, treatNullAsEmptyString: true },
|
||
|
bgColor: { type: String, treatNullAsEmptyString: true },
|
||
|
background: String,
|
||
|
}
|
||
|
});
|
||
|
|
||
|
define({
|
||
|
tag: 'button',
|
||
|
ctor: function HTMLButtonElement(doc, localName, prefix) {
|
||
|
HTMLFormElement.call(this, doc, localName, prefix);
|
||
|
},
|
||
|
props: formAssociatedProps,
|
||
|
attributes: {
|
||
|
name: String,
|
||
|
value: String,
|
||
|
disabled: Boolean,
|
||
|
autofocus: Boolean,
|
||
|
type: { type:["submit", "reset", "button", "menu"], missing: 'submit' },
|
||
|
formTarget: String,
|
||
|
formNoValidate: Boolean,
|
||
|
formMethod: { type: ["get", "post", "dialog"], invalid: 'get', missing: '' },
|
||
|
formEnctype: { type: ["application/x-www-form-urlencoded", "multipart/form-data", "text/plain"], invalid: "application/x-www-form-urlencoded", missing: '' },
|
||
|
}
|
||
|
});
|
||
|
|
||
|
define({
|
||
|
tag: 'dl',
|
||
|
ctor: function HTMLDListElement(doc, localName, prefix) {
|
||
|
HTMLElement.call(this, doc, localName, prefix);
|
||
|
},
|
||
|
attributes: {
|
||
|
// Obsolete
|
||
|
compact: Boolean,
|
||
|
}
|
||
|
});
|
||
|
|
||
|
define({
|
||
|
tag: 'data',
|
||
|
ctor: function HTMLDataElement(doc, localName, prefix) {
|
||
|
HTMLElement.call(this, doc, localName, prefix);
|
||
|
},
|
||
|
attributes: {
|
||
|
value: String,
|
||
|
}
|
||
|
});
|
||
|
|
||
|
define({
|
||
|
tag: 'datalist',
|
||
|
ctor: function HTMLDataListElement(doc, localName, prefix) {
|
||
|
HTMLElement.call(this, doc, localName, prefix);
|
||
|
}
|
||
|
});
|
||
|
|
||
|
define({
|
||
|
tag: 'details',
|
||
|
ctor: function HTMLDetailsElement(doc, localName, prefix) {
|
||
|
HTMLElement.call(this, doc, localName, prefix);
|
||
|
},
|
||
|
attributes: {
|
||
|
"open": Boolean
|
||
|
}
|
||
|
});
|
||
|
|
||
|
define({
|
||
|
tag: 'div',
|
||
|
ctor: function HTMLDivElement(doc, localName, prefix) {
|
||
|
HTMLElement.call(this, doc, localName, prefix);
|
||
|
},
|
||
|
attributes: {
|
||
|
// Obsolete
|
||
|
align: String
|
||
|
}
|
||
|
});
|
||
|
|
||
|
define({
|
||
|
tag: 'embed',
|
||
|
ctor: function HTMLEmbedElement(doc, localName, prefix) {
|
||
|
HTMLElement.call(this, doc, localName, prefix);
|
||
|
},
|
||
|
attributes: {
|
||
|
src: URL,
|
||
|
type: String,
|
||
|
width: String,
|
||
|
height: String,
|
||
|
// Obsolete
|
||
|
align: String,
|
||
|
name: String,
|
||
|
}
|
||
|
});
|
||
|
|
||
|
define({
|
||
|
tag: 'fieldset',
|
||
|
ctor: function HTMLFieldSetElement(doc, localName, prefix) {
|
||
|
HTMLFormElement.call(this, doc, localName, prefix);
|
||
|
},
|
||
|
props: formAssociatedProps,
|
||
|
attributes: {
|
||
|
disabled: Boolean,
|
||
|
name: String
|
||
|
}
|
||
|
});
|
||
|
|
||
|
define({
|
||
|
tag: 'form',
|
||
|
ctor: function HTMLFormElement(doc, localName, prefix) {
|
||
|
HTMLElement.call(this, doc, localName, prefix);
|
||
|
},
|
||
|
attributes: {
|
||
|
action: String,
|
||
|
autocomplete: {type:['on', 'off'], missing: 'on'},
|
||
|
name: String,
|
||
|
acceptCharset: {name: "accept-charset"},
|
||
|
target: String,
|
||
|
noValidate: Boolean,
|
||
|
method: { type: ["get", "post", "dialog"], invalid: 'get', missing: 'get' },
|
||
|
// Both enctype and encoding reflect the enctype content attribute
|
||
|
enctype: { type: ["application/x-www-form-urlencoded", "multipart/form-data", "text/plain"], invalid: "application/x-www-form-urlencoded", missing: "application/x-www-form-urlencoded" },
|
||
|
encoding: {name: 'enctype', type: ["application/x-www-form-urlencoded", "multipart/form-data", "text/plain"], invalid: "application/x-www-form-urlencoded", missing: "application/x-www-form-urlencoded" },
|
||
|
}
|
||
|
});
|
||
|
|
||
|
define({
|
||
|
tag: 'hr',
|
||
|
ctor: function HTMLHRElement(doc, localName, prefix) {
|
||
|
HTMLElement.call(this, doc, localName, prefix);
|
||
|
},
|
||
|
attributes: {
|
||
|
// Obsolete
|
||
|
align: String,
|
||
|
color: String,
|
||
|
noShade: Boolean,
|
||
|
size: String,
|
||
|
width: String,
|
||
|
},
|
||
|
});
|
||
|
|
||
|
define({
|
||
|
tag: 'head',
|
||
|
ctor: function HTMLHeadElement(doc, localName, prefix) {
|
||
|
HTMLElement.call(this, doc, localName, prefix);
|
||
|
}
|
||
|
});
|
||
|
|
||
|
define({
|
||
|
tags: ['h1','h2','h3','h4','h5','h6'],
|
||
|
ctor: function HTMLHeadingElement(doc, localName, prefix) {
|
||
|
HTMLElement.call(this, doc, localName, prefix);
|
||
|
},
|
||
|
attributes: {
|
||
|
// Obsolete
|
||
|
align: String,
|
||
|
},
|
||
|
});
|
||
|
|
||
|
define({
|
||
|
tag: 'html',
|
||
|
ctor: function HTMLHtmlElement(doc, localName, prefix) {
|
||
|
HTMLElement.call(this, doc, localName, prefix);
|
||
|
},
|
||
|
attributes: {
|
||
|
// Obsolete
|
||
|
version: String
|
||
|
}
|
||
|
});
|
||
|
|
||
|
define({
|
||
|
tag: 'iframe',
|
||
|
ctor: function HTMLIFrameElement(doc, localName, prefix) {
|
||
|
HTMLElement.call(this, doc, localName, prefix);
|
||
|
var Window = require('./Window'); // Avoid circular dependencies.
|
||
|
this._contentWindow = new Window();
|
||
|
},
|
||
|
props: {
|
||
|
contentWindow: { get: function() {
|
||
|
return this._contentWindow;
|
||
|
} },
|
||
|
contentDocument: { get: function() {
|
||
|
return this.contentWindow.document;
|
||
|
} },
|
||
|
},
|
||
|
attributes: {
|
||
|
src: URL,
|
||
|
srcdoc: String,
|
||
|
name: String,
|
||
|
width: String,
|
||
|
height: String,
|
||
|
// XXX: sandbox is a reflected settable token list
|
||
|
seamless: Boolean,
|
||
|
allowFullscreen: Boolean,
|
||
|
allowUserMedia: Boolean,
|
||
|
allowPaymentRequest: Boolean,
|
||
|
referrerPolicy: REFERRER,
|
||
|
// Obsolete
|
||
|
align: String,
|
||
|
scrolling: String,
|
||
|
frameBorder: String,
|
||
|
longDesc: URL,
|
||
|
marginHeight: { type: String, treatNullAsEmptyString: true },
|
||
|
marginWidth: { type: String, treatNullAsEmptyString: true },
|
||
|
}
|
||
|
});
|
||
|
|
||
|
define({
|
||
|
tag: 'img',
|
||
|
ctor: function HTMLImageElement(doc, localName, prefix) {
|
||
|
HTMLElement.call(this, doc, localName, prefix);
|
||
|
},
|
||
|
attributes: {
|
||
|
alt: String,
|
||
|
src: URL,
|
||
|
srcset: String,
|
||
|
crossOrigin: CORS,
|
||
|
useMap: String,
|
||
|
isMap: Boolean,
|
||
|
height: { type: "unsigned long", default: 0 },
|
||
|
width: { type: "unsigned long", default: 0 },
|
||
|
referrerPolicy: REFERRER,
|
||
|
// Obsolete:
|
||
|
name: String,
|
||
|
lowsrc: URL,
|
||
|
align: String,
|
||
|
hspace: { type: "unsigned long", default: 0 },
|
||
|
vspace: { type: "unsigned long", default: 0 },
|
||
|
longDesc: URL,
|
||
|
border: { type: String, treatNullAsEmptyString: true },
|
||
|
}
|
||
|
});
|
||
|
|
||
|
define({
|
||
|
tag: 'input',
|
||
|
ctor: function HTMLInputElement(doc, localName, prefix) {
|
||
|
HTMLFormElement.call(this, doc, localName, prefix);
|
||
|
},
|
||
|
props: {
|
||
|
form: formAssociatedProps.form,
|
||
|
_post_click_activation_steps: { value: function(e) {
|
||
|
if (this.type === 'checkbox') {
|
||
|
this.checked = !this.checked;
|
||
|
}
|
||
|
else if (this.type === 'radio') {
|
||
|
var group = this.form.getElementsByName(this.name);
|
||
|
for (var i=group.length-1; i >= 0; i--) {
|
||
|
var el = group[i];
|
||
|
el.checked = (el === this);
|
||
|
}
|
||
|
}
|
||
|
}},
|
||
|
},
|
||
|
attributes: {
|
||
|
name: String,
|
||
|
disabled: Boolean,
|
||
|
autofocus: Boolean,
|
||
|
accept: String,
|
||
|
alt: String,
|
||
|
max: String,
|
||
|
min: String,
|
||
|
pattern: String,
|
||
|
placeholder: String,
|
||
|
step: String,
|
||
|
dirName: String,
|
||
|
defaultValue: {name: 'value'},
|
||
|
multiple: Boolean,
|
||
|
required: Boolean,
|
||
|
readOnly: Boolean,
|
||
|
checked: Boolean,
|
||
|
value: String,
|
||
|
src: URL,
|
||
|
defaultChecked: {name: 'checked', type: Boolean},
|
||
|
size: {type: 'unsigned long', default: 20, min: 1, setmin: 1},
|
||
|
width: {type: 'unsigned long', min: 0, setmin: 0, default: 0},
|
||
|
height: {type: 'unsigned long', min: 0, setmin: 0, default: 0},
|
||
|
minLength: {type: 'unsigned long', min: 0, setmin: 0, default: -1},
|
||
|
maxLength: {type: 'unsigned long', min: 0, setmin: 0, default: -1},
|
||
|
autocomplete: String, // It's complicated
|
||
|
type: { type:
|
||
|
["text", "hidden", "search", "tel", "url", "email", "password",
|
||
|
"datetime", "date", "month", "week", "time", "datetime-local",
|
||
|
"number", "range", "color", "checkbox", "radio", "file", "submit",
|
||
|
"image", "reset", "button"],
|
||
|
missing: 'text' },
|
||
|
formTarget: String,
|
||
|
formNoValidate: Boolean,
|
||
|
formMethod: { type: ["get", "post"], invalid: 'get', missing: '' },
|
||
|
formEnctype: { type: ["application/x-www-form-urlencoded", "multipart/form-data", "text/plain"], invalid: "application/x-www-form-urlencoded", missing: '' },
|
||
|
inputMode: { type: [ "verbatim", "latin", "latin-name", "latin-prose", "full-width-latin", "kana", "kana-name", "katakana", "numeric", "tel", "email", "url" ], missing: '' },
|
||
|
// Obsolete
|
||
|
align: String,
|
||
|
useMap: String,
|
||
|
}
|
||
|
});
|
||
|
|
||
|
define({
|
||
|
tag: 'keygen',
|
||
|
ctor: function HTMLKeygenElement(doc, localName, prefix) {
|
||
|
HTMLFormElement.call(this, doc, localName, prefix);
|
||
|
},
|
||
|
props: formAssociatedProps,
|
||
|
attributes: {
|
||
|
name: String,
|
||
|
disabled: Boolean,
|
||
|
autofocus: Boolean,
|
||
|
challenge: String,
|
||
|
keytype: { type:["rsa"], missing: '' },
|
||
|
}
|
||
|
});
|
||
|
|
||
|
define({
|
||
|
tag: 'li',
|
||
|
ctor: function HTMLLIElement(doc, localName, prefix) {
|
||
|
HTMLElement.call(this, doc, localName, prefix);
|
||
|
},
|
||
|
attributes: {
|
||
|
value: {type: "long", default: 0},
|
||
|
// Obsolete
|
||
|
type: String,
|
||
|
}
|
||
|
});
|
||
|
|
||
|
define({
|
||
|
tag: 'label',
|
||
|
ctor: function HTMLLabelElement(doc, localName, prefix) {
|
||
|
HTMLFormElement.call(this, doc, localName, prefix);
|
||
|
},
|
||
|
props: formAssociatedProps,
|
||
|
attributes: {
|
||
|
htmlFor: {name: 'for', type: String}
|
||
|
}
|
||
|
});
|
||
|
|
||
|
define({
|
||
|
tag: 'legend',
|
||
|
ctor: function HTMLLegendElement(doc, localName, prefix) {
|
||
|
HTMLElement.call(this, doc, localName, prefix);
|
||
|
},
|
||
|
attributes: {
|
||
|
// Obsolete
|
||
|
align: String
|
||
|
},
|
||
|
});
|
||
|
|
||
|
define({
|
||
|
tag: 'link',
|
||
|
ctor: function HTMLLinkElement(doc, localName, prefix) {
|
||
|
HTMLElement.call(this, doc, localName, prefix);
|
||
|
},
|
||
|
attributes: {
|
||
|
// XXX Reflect DOMSettableTokenList sizes also DOMTokenList relList
|
||
|
href: URL,
|
||
|
rel: String,
|
||
|
media: String,
|
||
|
hreflang: String,
|
||
|
type: String,
|
||
|
crossOrigin: CORS,
|
||
|
nonce: String,
|
||
|
integrity: String,
|
||
|
referrerPolicy: REFERRER,
|
||
|
// Obsolete
|
||
|
charset: String,
|
||
|
rev: String,
|
||
|
target: String,
|
||
|
}
|
||
|
});
|
||
|
|
||
|
define({
|
||
|
tag: 'map',
|
||
|
ctor: function HTMLMapElement(doc, localName, prefix) {
|
||
|
HTMLElement.call(this, doc, localName, prefix);
|
||
|
},
|
||
|
attributes: {
|
||
|
name: String
|
||
|
}
|
||
|
});
|
||
|
|
||
|
define({
|
||
|
tag: 'menu',
|
||
|
ctor: function HTMLMenuElement(doc, localName, prefix) {
|
||
|
HTMLElement.call(this, doc, localName, prefix);
|
||
|
},
|
||
|
attributes: {
|
||
|
// XXX: not quite right, default should be popup if parent element is
|
||
|
// popup.
|
||
|
type: { type: [ 'context', 'popup', 'toolbar' ], missing: 'toolbar' },
|
||
|
label: String,
|
||
|
// Obsolete
|
||
|
compact: Boolean,
|
||
|
}
|
||
|
});
|
||
|
|
||
|
define({
|
||
|
tag: 'meta',
|
||
|
ctor: function HTMLMetaElement(doc, localName, prefix) {
|
||
|
HTMLElement.call(this, doc, localName, prefix);
|
||
|
},
|
||
|
attributes: {
|
||
|
name: String,
|
||
|
content: String,
|
||
|
httpEquiv: {name: 'http-equiv', type: String},
|
||
|
// Obsolete
|
||
|
scheme: String,
|
||
|
}
|
||
|
});
|
||
|
|
||
|
define({
|
||
|
tag: 'meter',
|
||
|
ctor: function HTMLMeterElement(doc, localName, prefix) {
|
||
|
HTMLFormElement.call(this, doc, localName, prefix);
|
||
|
},
|
||
|
props: formAssociatedProps
|
||
|
});
|
||
|
|
||
|
define({
|
||
|
tags: ['ins', 'del'],
|
||
|
ctor: function HTMLModElement(doc, localName, prefix) {
|
||
|
HTMLElement.call(this, doc, localName, prefix);
|
||
|
},
|
||
|
attributes: {
|
||
|
cite: URL,
|
||
|
dateTime: String
|
||
|
}
|
||
|
});
|
||
|
|
||
|
define({
|
||
|
tag: 'ol',
|
||
|
ctor: function HTMLOListElement(doc, localName, prefix) {
|
||
|
HTMLElement.call(this, doc, localName, prefix);
|
||
|
},
|
||
|
props: {
|
||
|
// Utility function (see the start attribute default value). Returns
|
||
|
// the number of <li> children of this element
|
||
|
_numitems: { get: function() {
|
||
|
var items = 0;
|
||
|
this.childNodes.forEach(function(n) {
|
||
|
if (n.nodeType === Node.ELEMENT_NODE && n.tagName === "LI")
|
||
|
items++;
|
||
|
});
|
||
|
return items;
|
||
|
}}
|
||
|
},
|
||
|
attributes: {
|
||
|
type: String,
|
||
|
reversed: Boolean,
|
||
|
start: {
|
||
|
type: "long",
|
||
|
default: function() {
|
||
|
// The default value of the start attribute is 1 unless the list is
|
||
|
// reversed. Then it is the # of li children
|
||
|
if (this.reversed)
|
||
|
return this._numitems;
|
||
|
else
|
||
|
return 1;
|
||
|
}
|
||
|
},
|
||
|
// Obsolete
|
||
|
compact: Boolean,
|
||
|
}
|
||
|
});
|
||
|
|
||
|
define({
|
||
|
tag: 'object',
|
||
|
ctor: function HTMLObjectElement(doc, localName, prefix) {
|
||
|
HTMLFormElement.call(this, doc, localName, prefix);
|
||
|
},
|
||
|
props: formAssociatedProps,
|
||
|
attributes: {
|
||
|
data: URL,
|
||
|
type: String,
|
||
|
name: String,
|
||
|
useMap: String,
|
||
|
typeMustMatch: Boolean,
|
||
|
width: String,
|
||
|
height: String,
|
||
|
// Obsolete
|
||
|
align: String,
|
||
|
archive: String,
|
||
|
code: String,
|
||
|
declare: Boolean,
|
||
|
hspace: { type: "unsigned long", default: 0 },
|
||
|
standby: String,
|
||
|
vspace: { type: "unsigned long", default: 0 },
|
||
|
codeBase: URL,
|
||
|
codeType: String,
|
||
|
border: { type: String, treatNullAsEmptyString: true },
|
||
|
}
|
||
|
});
|
||
|
|
||
|
define({
|
||
|
tag: 'optgroup',
|
||
|
ctor: function HTMLOptGroupElement(doc, localName, prefix) {
|
||
|
HTMLElement.call(this, doc, localName, prefix);
|
||
|
},
|
||
|
attributes: {
|
||
|
disabled: Boolean,
|
||
|
label: String
|
||
|
}
|
||
|
});
|
||
|
|
||
|
define({
|
||
|
tag: 'option',
|
||
|
ctor: function HTMLOptionElement(doc, localName, prefix) {
|
||
|
HTMLElement.call(this, doc, localName, prefix);
|
||
|
},
|
||
|
props: {
|
||
|
form: { get: function() {
|
||
|
var p = this.parentNode;
|
||
|
while (p && p.nodeType === Node.ELEMENT_NODE) {
|
||
|
if (p.localName === 'select') return p.form;
|
||
|
p = p.parentNode;
|
||
|
}
|
||
|
}},
|
||
|
value: {
|
||
|
get: function() { return this._getattr('value') || this.text; },
|
||
|
set: function(v) { this._setattr('value', v); },
|
||
|
},
|
||
|
text: {
|
||
|
get: function() {
|
||
|
// Strip and collapse whitespace
|
||
|
return this.textContent.replace(/[ \t\n\f\r]+/g, ' ').trim();
|
||
|
},
|
||
|
set: function(v) { this.textContent = v; },
|
||
|
},
|
||
|
// missing: index
|
||
|
},
|
||
|
attributes: {
|
||
|
disabled: Boolean,
|
||
|
defaultSelected: {name: 'selected', type: Boolean},
|
||
|
label: String,
|
||
|
}
|
||
|
});
|
||
|
|
||
|
define({
|
||
|
tag: 'output',
|
||
|
ctor: function HTMLOutputElement(doc, localName, prefix) {
|
||
|
HTMLFormElement.call(this, doc, localName, prefix);
|
||
|
},
|
||
|
props: formAssociatedProps,
|
||
|
attributes: {
|
||
|
// XXX Reflect for/htmlFor as a settable token list
|
||
|
name: String
|
||
|
}
|
||
|
});
|
||
|
|
||
|
define({
|
||
|
tag: 'p',
|
||
|
ctor: function HTMLParagraphElement(doc, localName, prefix) {
|
||
|
HTMLElement.call(this, doc, localName, prefix);
|
||
|
},
|
||
|
attributes: {
|
||
|
// Obsolete
|
||
|
align: String
|
||
|
}
|
||
|
});
|
||
|
|
||
|
define({
|
||
|
tag: 'param',
|
||
|
ctor: function HTMLParamElement(doc, localName, prefix) {
|
||
|
HTMLElement.call(this, doc, localName, prefix);
|
||
|
},
|
||
|
attributes: {
|
||
|
name: String,
|
||
|
value: String,
|
||
|
// Obsolete
|
||
|
type: String,
|
||
|
valueType: String,
|
||
|
}
|
||
|
});
|
||
|
|
||
|
define({
|
||
|
tags: ['pre',/*legacy elements:*/'listing','xmp'],
|
||
|
ctor: function HTMLPreElement(doc, localName, prefix) {
|
||
|
HTMLElement.call(this, doc, localName, prefix);
|
||
|
},
|
||
|
attributes: {
|
||
|
// Obsolete
|
||
|
width: { type: "long", default: 0 },
|
||
|
}
|
||
|
});
|
||
|
|
||
|
define({
|
||
|
tag: 'progress',
|
||
|
ctor: function HTMLProgressElement(doc, localName, prefix) {
|
||
|
HTMLFormElement.call(this, doc, localName, prefix);
|
||
|
},
|
||
|
props: formAssociatedProps,
|
||
|
attributes: {
|
||
|
max: {type: Number, float: true, default: 1.0, min: 0}
|
||
|
}
|
||
|
});
|
||
|
|
||
|
define({
|
||
|
tags: ['q', 'blockquote'],
|
||
|
ctor: function HTMLQuoteElement(doc, localName, prefix) {
|
||
|
HTMLElement.call(this, doc, localName, prefix);
|
||
|
},
|
||
|
attributes: {
|
||
|
cite: URL
|
||
|
}
|
||
|
});
|
||
|
|
||
|
define({
|
||
|
tag: 'script',
|
||
|
ctor: function HTMLScriptElement(doc, localName, prefix) {
|
||
|
HTMLElement.call(this, doc, localName, prefix);
|
||
|
},
|
||
|
props: {
|
||
|
text: {
|
||
|
get: function() {
|
||
|
var s = "";
|
||
|
for(var i = 0, n = this.childNodes.length; i < n; i++) {
|
||
|
var child = this.childNodes[i];
|
||
|
if (child.nodeType === Node.TEXT_NODE)
|
||
|
s += child._data;
|
||
|
}
|
||
|
return s;
|
||
|
},
|
||
|
set: function(value) {
|
||
|
this.removeChildren();
|
||
|
if (value !== null && value !== "") {
|
||
|
this.appendChild(this.ownerDocument.createTextNode(value));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
attributes: {
|
||
|
src: URL,
|
||
|
type: String,
|
||
|
charset: String,
|
||
|
defer: Boolean,
|
||
|
async: Boolean,
|
||
|
crossOrigin: CORS,
|
||
|
nonce: String,
|
||
|
integrity: String,
|
||
|
}
|
||
|
});
|
||
|
|
||
|
define({
|
||
|
tag: 'select',
|
||
|
ctor: function HTMLSelectElement(doc, localName, prefix) {
|
||
|
HTMLFormElement.call(this, doc, localName, prefix);
|
||
|
},
|
||
|
props: {
|
||
|
form: formAssociatedProps.form,
|
||
|
options: { get: function() {
|
||
|
return this.getElementsByTagName('option');
|
||
|
}}
|
||
|
},
|
||
|
attributes: {
|
||
|
autocomplete: String, // It's complicated
|
||
|
name: String,
|
||
|
disabled: Boolean,
|
||
|
autofocus: Boolean,
|
||
|
multiple: Boolean,
|
||
|
required: Boolean,
|
||
|
size: {type: "unsigned long", default: 0}
|
||
|
}
|
||
|
});
|
||
|
|
||
|
define({
|
||
|
tag: 'source',
|
||
|
ctor: function HTMLSourceElement(doc, localName, prefix) {
|
||
|
HTMLElement.call(this, doc, localName, prefix);
|
||
|
},
|
||
|
attributes: {
|
||
|
src: URL,
|
||
|
type: String,
|
||
|
media: String
|
||
|
}
|
||
|
});
|
||
|
|
||
|
define({
|
||
|
tag: 'span',
|
||
|
ctor: function HTMLSpanElement(doc, localName, prefix) {
|
||
|
HTMLElement.call(this, doc, localName, prefix);
|
||
|
}
|
||
|
});
|
||
|
|
||
|
define({
|
||
|
tag: 'style',
|
||
|
ctor: function HTMLStyleElement(doc, localName, prefix) {
|
||
|
HTMLElement.call(this, doc, localName, prefix);
|
||
|
},
|
||
|
attributes: {
|
||
|
media: String,
|
||
|
type: String,
|
||
|
scoped: Boolean
|
||
|
}
|
||
|
});
|
||
|
|
||
|
define({
|
||
|
tag: 'caption',
|
||
|
ctor: function HTMLTableCaptionElement(doc, localName, prefix) {
|
||
|
HTMLElement.call(this, doc, localName, prefix);
|
||
|
},
|
||
|
attributes: {
|
||
|
// Obsolete
|
||
|
align: String,
|
||
|
}
|
||
|
});
|
||
|
|
||
|
|
||
|
define({
|
||
|
ctor: function HTMLTableCellElement(doc, localName, prefix) {
|
||
|
HTMLElement.call(this, doc, localName, prefix);
|
||
|
},
|
||
|
attributes: {
|
||
|
colSpan: {type: "unsigned long", default: 1},
|
||
|
rowSpan: {type: "unsigned long", default: 1},
|
||
|
//XXX Also reflect settable token list headers
|
||
|
scope: { type: ['row','col','rowgroup','colgroup'], missing: '' },
|
||
|
abbr: String,
|
||
|
// Obsolete
|
||
|
align: String,
|
||
|
axis: String,
|
||
|
height: String,
|
||
|
width: String,
|
||
|
ch: { name: 'char', type: String },
|
||
|
chOff: { name: 'charoff', type: String },
|
||
|
noWrap: Boolean,
|
||
|
vAlign: String,
|
||
|
bgColor: { type: String, treatNullAsEmptyString: true },
|
||
|
}
|
||
|
});
|
||
|
|
||
|
define({
|
||
|
tags: ['col', 'colgroup'],
|
||
|
ctor: function HTMLTableColElement(doc, localName, prefix) {
|
||
|
HTMLElement.call(this, doc, localName, prefix);
|
||
|
},
|
||
|
attributes: {
|
||
|
span: {type: 'limited unsigned long with fallback', default: 1, min: 1},
|
||
|
// Obsolete
|
||
|
align: String,
|
||
|
ch: { name: 'char', type: String },
|
||
|
chOff: { name: 'charoff', type: String },
|
||
|
vAlign: String,
|
||
|
width: String,
|
||
|
}
|
||
|
});
|
||
|
|
||
|
define({
|
||
|
tag: 'table',
|
||
|
ctor: function HTMLTableElement(doc, localName, prefix) {
|
||
|
HTMLElement.call(this, doc, localName, prefix);
|
||
|
},
|
||
|
props: {
|
||
|
rows: { get: function() {
|
||
|
return this.getElementsByTagName('tr');
|
||
|
}}
|
||
|
},
|
||
|
attributes: {
|
||
|
// Obsolete
|
||
|
align: String,
|
||
|
border: String,
|
||
|
frame: String,
|
||
|
rules: String,
|
||
|
summary: String,
|
||
|
width: String,
|
||
|
bgColor: { type: String, treatNullAsEmptyString: true },
|
||
|
cellPadding: { type: String, treatNullAsEmptyString: true },
|
||
|
cellSpacing: { type: String, treatNullAsEmptyString: true },
|
||
|
}
|
||
|
});
|
||
|
|
||
|
define({
|
||
|
tag: 'template',
|
||
|
ctor: function HTMLTemplateElement(doc, localName, prefix) {
|
||
|
HTMLElement.call(this, doc, localName, prefix);
|
||
|
this._contentFragment = doc._templateDoc.createDocumentFragment();
|
||
|
},
|
||
|
props: {
|
||
|
content: { get: function() { return this._contentFragment; } },
|
||
|
serialize: { value: function() { return this.content.serialize(); } }
|
||
|
}
|
||
|
});
|
||
|
|
||
|
define({
|
||
|
tag: 'tr',
|
||
|
ctor: function HTMLTableRowElement(doc, localName, prefix) {
|
||
|
HTMLElement.call(this, doc, localName, prefix);
|
||
|
},
|
||
|
props: {
|
||
|
cells: { get: function() {
|
||
|
return this.querySelectorAll('td,th');
|
||
|
}}
|
||
|
},
|
||
|
attributes: {
|
||
|
// Obsolete
|
||
|
align: String,
|
||
|
ch: { name: 'char', type: String },
|
||
|
chOff: { name: 'charoff', type: String },
|
||
|
vAlign: String,
|
||
|
bgColor: { type: String, treatNullAsEmptyString: true },
|
||
|
},
|
||
|
});
|
||
|
|
||
|
define({
|
||
|
tags: ['thead', 'tfoot', 'tbody'],
|
||
|
ctor: function HTMLTableSectionElement(doc, localName, prefix) {
|
||
|
HTMLElement.call(this, doc, localName, prefix);
|
||
|
},
|
||
|
props: {
|
||
|
rows: { get: function() {
|
||
|
return this.getElementsByTagName('tr');
|
||
|
}}
|
||
|
},
|
||
|
attributes: {
|
||
|
// Obsolete
|
||
|
align: String,
|
||
|
ch: { name: 'char', type: String },
|
||
|
chOff: { name: 'charoff', type: String },
|
||
|
vAlign: String,
|
||
|
}
|
||
|
});
|
||
|
|
||
|
define({
|
||
|
tag: 'textarea',
|
||
|
ctor: function HTMLTextAreaElement(doc, localName, prefix) {
|
||
|
HTMLFormElement.call(this, doc, localName, prefix);
|
||
|
},
|
||
|
props: {
|
||
|
form: formAssociatedProps.form,
|
||
|
type: { get: function() { return 'textarea'; } },
|
||
|
defaultValue: {
|
||
|
get: function() { return this.textContent; },
|
||
|
set: function(v) { this.textContent = v; },
|
||
|
},
|
||
|
value: {
|
||
|
get: function() { return this.defaultValue; /* never dirty */ },
|
||
|
set: function(v) {
|
||
|
// This isn't completely correct: according to the spec, this
|
||
|
// should "dirty" the API value, and result in
|
||
|
// `this.value !== this.defaultValue`. But for most of what
|
||
|
// folks want to do, this implementation should be fine:
|
||
|
this.defaultValue = v;
|
||
|
},
|
||
|
},
|
||
|
textLength: { get: function() { return this.value.length; } },
|
||
|
},
|
||
|
attributes: {
|
||
|
autocomplete: String, // It's complicated
|
||
|
name: String,
|
||
|
disabled: Boolean,
|
||
|
autofocus: Boolean,
|
||
|
placeholder: String,
|
||
|
wrap: String,
|
||
|
dirName: String,
|
||
|
required: Boolean,
|
||
|
readOnly: Boolean,
|
||
|
rows: {type: 'limited unsigned long with fallback', default: 2 },
|
||
|
cols: {type: 'limited unsigned long with fallback', default: 20 },
|
||
|
maxLength: {type: 'unsigned long', min: 0, setmin: 0, default: -1},
|
||
|
minLength: {type: 'unsigned long', min: 0, setmin: 0, default: -1},
|
||
|
inputMode: { type: [ "verbatim", "latin", "latin-name", "latin-prose", "full-width-latin", "kana", "kana-name", "katakana", "numeric", "tel", "email", "url" ], missing: '' },
|
||
|
}
|
||
|
});
|
||
|
|
||
|
define({
|
||
|
tag: 'time',
|
||
|
ctor: function HTMLTimeElement(doc, localName, prefix) {
|
||
|
HTMLElement.call(this, doc, localName, prefix);
|
||
|
},
|
||
|
attributes: {
|
||
|
dateTime: String,
|
||
|
pubDate: Boolean
|
||
|
}
|
||
|
});
|
||
|
|
||
|
define({
|
||
|
tag: 'title',
|
||
|
ctor: function HTMLTitleElement(doc, localName, prefix) {
|
||
|
HTMLElement.call(this, doc, localName, prefix);
|
||
|
},
|
||
|
props: {
|
||
|
text: { get: function() {
|
||
|
return this.textContent;
|
||
|
}}
|
||
|
}
|
||
|
});
|
||
|
|
||
|
define({
|
||
|
tag: 'ul',
|
||
|
ctor: function HTMLUListElement(doc, localName, prefix) {
|
||
|
HTMLElement.call(this, doc, localName, prefix);
|
||
|
},
|
||
|
attributes: {
|
||
|
type: String,
|
||
|
// Obsolete
|
||
|
compact: Boolean,
|
||
|
}
|
||
|
});
|
||
|
|
||
|
define({
|
||
|
ctor: function HTMLMediaElement(doc, localName, prefix) {
|
||
|
HTMLElement.call(this, doc, localName, prefix);
|
||
|
},
|
||
|
attributes: {
|
||
|
src: URL,
|
||
|
crossOrigin: CORS,
|
||
|
preload: { type:["metadata", "none", "auto", {value: "", alias: "auto"}], missing: 'auto' },
|
||
|
loop: Boolean,
|
||
|
autoplay: Boolean,
|
||
|
mediaGroup: String,
|
||
|
controls: Boolean,
|
||
|
defaultMuted: {name: "muted", type: Boolean}
|
||
|
}
|
||
|
});
|
||
|
|
||
|
define({
|
||
|
tag: 'audio',
|
||
|
superclass: htmlElements.HTMLMediaElement,
|
||
|
ctor: function HTMLAudioElement(doc, localName, prefix) {
|
||
|
htmlElements.HTMLMediaElement.call(this, doc, localName, prefix);
|
||
|
}
|
||
|
});
|
||
|
|
||
|
define({
|
||
|
tag: 'video',
|
||
|
superclass: htmlElements.HTMLMediaElement,
|
||
|
ctor: function HTMLVideoElement(doc, localName, prefix) {
|
||
|
htmlElements.HTMLMediaElement.call(this, doc, localName, prefix);
|
||
|
},
|
||
|
attributes: {
|
||
|
poster: URL,
|
||
|
width: {type: "unsigned long", min: 0, default: 0 },
|
||
|
height: {type: "unsigned long", min: 0, default: 0 }
|
||
|
}
|
||
|
});
|
||
|
|
||
|
define({
|
||
|
tag: 'td',
|
||
|
superclass: htmlElements.HTMLTableCellElement,
|
||
|
ctor: function HTMLTableDataCellElement(doc, localName, prefix) {
|
||
|
htmlElements.HTMLTableCellElement.call(this, doc, localName, prefix);
|
||
|
}
|
||
|
});
|
||
|
|
||
|
define({
|
||
|
tag: 'th',
|
||
|
superclass: htmlElements.HTMLTableCellElement,
|
||
|
ctor: function HTMLTableHeaderCellElement(doc, localName, prefix) {
|
||
|
htmlElements.HTMLTableCellElement.call(this, doc, localName, prefix);
|
||
|
},
|
||
|
});
|
||
|
|
||
|
define({
|
||
|
tag: 'frameset',
|
||
|
ctor: function HTMLFrameSetElement(doc, localName, prefix) {
|
||
|
HTMLElement.call(this, doc, localName, prefix);
|
||
|
}
|
||
|
});
|
||
|
|
||
|
define({
|
||
|
tag: 'frame',
|
||
|
ctor: function HTMLFrameElement(doc, localName, prefix) {
|
||
|
HTMLElement.call(this, doc, localName, prefix);
|
||
|
}
|
||
|
});
|
||
|
|
||
|
define({
|
||
|
tag: 'canvas',
|
||
|
ctor: function HTMLCanvasElement(doc, localName, prefix) {
|
||
|
HTMLElement.call(this, doc, localName, prefix);
|
||
|
},
|
||
|
props: {
|
||
|
getContext: { value: utils.nyi },
|
||
|
probablySupportsContext: { value: utils.nyi },
|
||
|
setContext: { value: utils.nyi },
|
||
|
transferControlToProxy: { value: utils.nyi },
|
||
|
toDataURL: { value: utils.nyi },
|
||
|
toBlob: { value: utils.nyi }
|
||
|
},
|
||
|
attributes: {
|
||
|
width: { type: "unsigned long", default: 300},
|
||
|
height: { type: "unsigned long", default: 150}
|
||
|
}
|
||
|
});
|
||
|
|
||
|
define({
|
||
|
tag: 'dialog',
|
||
|
ctor: function HTMLDialogElement(doc, localName, prefix) {
|
||
|
HTMLElement.call(this, doc, localName, prefix);
|
||
|
},
|
||
|
props: {
|
||
|
show: { value: utils.nyi },
|
||
|
showModal: { value: utils.nyi },
|
||
|
close: { value: utils.nyi }
|
||
|
},
|
||
|
attributes: {
|
||
|
open: Boolean,
|
||
|
returnValue: String
|
||
|
}
|
||
|
});
|
||
|
|
||
|
define({
|
||
|
tag: 'menuitem',
|
||
|
ctor: function HTMLMenuItemElement(doc, localName, prefix) {
|
||
|
HTMLElement.call(this, doc, localName, prefix);
|
||
|
},
|
||
|
props: {
|
||
|
// The menuitem's label
|
||
|
_label: {
|
||
|
get: function() {
|
||
|
var val = this._getattr('label');
|
||
|
if (val !== null && val !== '') { return val; }
|
||
|
val = this.textContent;
|
||
|
// Strip and collapse whitespace
|
||
|
return val.replace(/[ \t\n\f\r]+/g, ' ').trim();
|
||
|
}
|
||
|
},
|
||
|
// The menuitem label IDL attribute
|
||
|
label: {
|
||
|
get: function() {
|
||
|
var val = this._getattr('label');
|
||
|
if (val !== null) { return val; }
|
||
|
return this._label;
|
||
|
},
|
||
|
set: function(v) {
|
||
|
this._setattr('label', v);
|
||
|
},
|
||
|
}
|
||
|
},
|
||
|
attributes: {
|
||
|
type: { type: ["command","checkbox","radio"], missing: 'command' },
|
||
|
icon: URL,
|
||
|
disabled: Boolean,
|
||
|
checked: Boolean,
|
||
|
radiogroup: String,
|
||
|
default: Boolean
|
||
|
}
|
||
|
});
|
||
|
|
||
|
define({
|
||
|
tag: 'source',
|
||
|
ctor: function HTMLSourceElement(doc, localName, prefix) {
|
||
|
HTMLElement.call(this, doc, localName, prefix);
|
||
|
},
|
||
|
attributes: {
|
||
|
srcset: String,
|
||
|
sizes: String,
|
||
|
media: String,
|
||
|
src: URL,
|
||
|
type: String
|
||
|
}
|
||
|
});
|
||
|
|
||
|
define({
|
||
|
tag: 'track',
|
||
|
ctor: function HTMLTrackElement(doc, localName, prefix) {
|
||
|
HTMLElement.call(this, doc, localName, prefix);
|
||
|
},
|
||
|
attributes: {
|
||
|
src: URL,
|
||
|
srclang: String,
|
||
|
label: String,
|
||
|
default: Boolean,
|
||
|
kind: { type: ["subtitles", "captions", "descriptions", "chapters", "metadata"], missing: 'subtitles', invalid: 'metadata' },
|
||
|
},
|
||
|
props: {
|
||
|
NONE: { get: function() { return 0; } },
|
||
|
LOADING: { get: function() { return 1; } },
|
||
|
LOADED: { get: function() { return 2; } },
|
||
|
ERROR: { get: function() { return 3; } },
|
||
|
readyState: { get: utils.nyi },
|
||
|
track: { get: utils.nyi }
|
||
|
}
|
||
|
});
|
||
|
|
||
|
define({
|
||
|
// obsolete
|
||
|
tag: 'font',
|
||
|
ctor: function HTMLFontElement(doc, localName, prefix) {
|
||
|
HTMLElement.call(this, doc, localName, prefix);
|
||
|
},
|
||
|
attributes: {
|
||
|
color: { type: String, treatNullAsEmptyString: true },
|
||
|
face: { type: String },
|
||
|
size: { type: String },
|
||
|
},
|
||
|
});
|
||
|
|
||
|
define({
|
||
|
// obsolete
|
||
|
tag: 'dir',
|
||
|
ctor: function HTMLDirectoryElement(doc, localName, prefix) {
|
||
|
HTMLElement.call(this, doc, localName, prefix);
|
||
|
},
|
||
|
attributes: {
|
||
|
compact: Boolean,
|
||
|
},
|
||
|
});
|
||
|
|
||
|
define({
|
||
|
tags: [
|
||
|
"abbr", "address", "article", "aside", "b", "bdi", "bdo",
|
||
|
"cite", "code", "dd", "dfn", "dt", "em", "figcaption", "figure",
|
||
|
"footer", "header", "hgroup", "i", "kbd", "main", "mark", "nav", "noscript",
|
||
|
"rb", "rp", "rt", "rtc", "ruby", "s", "samp", "section", "small", "strong",
|
||
|
"sub", "summary", "sup", "u", "var", "wbr",
|
||
|
// Legacy elements
|
||
|
"acronym", "basefont", "big", "center", "nobr", "noembed", "noframes",
|
||
|
"plaintext", "strike", "tt"
|
||
|
]
|
||
|
});
|