js: DOM API. Part 1 (#12296)
parent
0ff23eeb74
commit
cfecb62299
|
@ -0,0 +1,7 @@
|
|||
Drawing with mouse events using DOM API. Adopted from MDN examples.
|
||||
|
||||
# Compiling
|
||||
```
|
||||
v -b js_browser examples/js_dom_draw/draw.v
|
||||
```
|
||||
Then you can open `index.html` with your favourite browser.
|
|
@ -0,0 +1,72 @@
|
|||
import jsdom
|
||||
import jsdom.ctx
|
||||
|
||||
fn get_2dcontext(canvas jsdom.IElement) ?ctx.CanvasRenderingContext2D {
|
||||
if canvas is jsdom.HTMLCanvasElement {
|
||||
c := canvas.get_context('2d')
|
||||
match c {
|
||||
ctx.CanvasRenderingContext2D {
|
||||
return c
|
||||
}
|
||||
else {
|
||||
return error('cannot fetch 2d context')
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return error('canvas is not an HTMLCanvasElement')
|
||||
}
|
||||
}
|
||||
|
||||
fn draw_line(context ctx.CanvasRenderingContext2D, x1 int, y1 int, x2 int, y2 int) {
|
||||
context.begin_path()
|
||||
context.set_stroke_style('black')
|
||||
context.set_line_width(1)
|
||||
context.move_to(x1, y1)
|
||||
context.line_to(x2, y2)
|
||||
context.stroke()
|
||||
context.close_path()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
document := jsdom.document
|
||||
|
||||
elem := document.get_element_by_id('myButton') ?
|
||||
elemc := document.get_element_by_id('myCanvas') or { panic('no canvas') }
|
||||
canv := jsdom.get_html_canvas_element(elemc) or { panic('expected canvas') }
|
||||
|
||||
context := get_2dcontext(canv) or { panic('wow') }
|
||||
mut drawing := false
|
||||
mut x := int(0)
|
||||
mut y := int(0)
|
||||
canv.add_event_listener('mousedown', fn [mut drawing, mut x, mut y] (_ jsdom.IEventTarget, event jsdom.IEvent) {
|
||||
drawing = true
|
||||
if event is jsdom.MouseEvent {
|
||||
x = event.offset_x()
|
||||
y = event.offset_y()
|
||||
}
|
||||
})
|
||||
|
||||
canv.add_event_listener('mousemove', fn [context, drawing, mut x, mut y] (_ jsdom.IEventTarget, event jsdom.IEvent) {
|
||||
if drawing {
|
||||
if event is jsdom.MouseEvent {
|
||||
draw_line(context, x, y, event.offset_x(), event.offset_y())
|
||||
x = event.offset_x()
|
||||
y = event.offset_y()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
jsdom.window.add_event_listener('mouseup', fn [context, mut drawing, mut x, mut y] (_ jsdom.IEventTarget, event jsdom.IEvent) {
|
||||
if drawing {
|
||||
if event is jsdom.MouseEvent {
|
||||
draw_line(context, x, y, event.offset_x(), event.offset_y())
|
||||
}
|
||||
x = 0
|
||||
y = 0
|
||||
drawing = false
|
||||
}
|
||||
})
|
||||
elem.add_event_listener('click', fn [context, canv] (_ jsdom.IEventTarget, _ jsdom.IEvent) {
|
||||
context.clear_rect(0, 0, canv.width(), canv.height())
|
||||
})
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
<body class="main">
|
||||
<title>Drawing with mouse events</title>
|
||||
<input type="button" id="myButton" value="Clear canvas">
|
||||
<canvas style="border: 1px solid black;" width="720" height="480" id="myCanvas"></canvas>
|
||||
<script type="text/javascript" src="draw.js"></script>
|
||||
|
||||
</body>
|
|
@ -917,3 +917,10 @@ pub fn (_rune string) utf32_code() int {
|
|||
|
||||
return res
|
||||
}
|
||||
|
||||
pub fn tos(jsstr JS.String) string {
|
||||
res := ''
|
||||
#res.str = jsstr
|
||||
|
||||
return res
|
||||
}
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
// Wrapper around 2d context and WebGL APIs
|
||||
|
||||
module ctx
|
||||
|
||||
pub struct ContextAttributes {
|
||||
pub:
|
||||
alpha bool
|
||||
desynchronized bool
|
||||
}
|
||||
|
||||
pub enum PowerPreference {
|
||||
default_
|
||||
high_performance
|
||||
low_performance
|
||||
}
|
||||
|
||||
pub struct WebGLAttributes {
|
||||
pub:
|
||||
alpha bool
|
||||
desynchronized bool
|
||||
antialias bool
|
||||
depth bool
|
||||
fail_if_major_perf_caveat bool
|
||||
power_preference PowerPreference
|
||||
premultiplied_alpha bool
|
||||
preserve_drawing_buffer bool
|
||||
stencil bool
|
||||
}
|
||||
|
||||
pub struct NoneContext {}
|
||||
|
||||
pub type ContextResult = CanvasRenderingContext2D | NoneContext | WebGLRenderingContext
|
|
@ -0,0 +1,67 @@
|
|||
module ctx
|
||||
|
||||
struct JS.CanvasRenderingContext2D {
|
||||
mut:
|
||||
lineWidth JS.Number
|
||||
lineCap JS.String
|
||||
lineJoin JS.String
|
||||
miterLimit JS.Number
|
||||
lineDashOffset JS.Number
|
||||
font JS.String
|
||||
textAlign JS.String
|
||||
textBaseline JS.String
|
||||
direction JS.String
|
||||
fillStyle voidptr
|
||||
strokeStyle voidptr
|
||||
shadowBlur JS.Number
|
||||
shadowColor JS.String
|
||||
shadowOffsetX JS.Number
|
||||
shadowOffsetY JS.Number
|
||||
globalAlpha JS.Number
|
||||
globalCompositeOperation JS.String
|
||||
}
|
||||
|
||||
pub struct CanvasRenderingContext2D {
|
||||
ctx JS.CanvasRenderingContext2D [noinit]
|
||||
}
|
||||
|
||||
pub type StrokeStyle = string
|
||||
|
||||
pub fn (ctx CanvasRenderingContext2D) begin_path() {
|
||||
#ctx.ctx.beginPath();
|
||||
}
|
||||
|
||||
pub fn (ctx CanvasRenderingContext2D) set_stroke_style(style StrokeStyle) {
|
||||
#ctx.ctx.strokeStyle = style.str;
|
||||
}
|
||||
|
||||
pub fn (ctx CanvasRenderingContext2D) line_width() int {
|
||||
res := 0
|
||||
#res.val = ctx.ctx.lineWidth
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
pub fn (ctx CanvasRenderingContext2D) set_line_width(width int) {
|
||||
#ctx.ctx.lineWidth = width.val
|
||||
}
|
||||
|
||||
pub fn (ctx CanvasRenderingContext2D) move_to(x int, y int) {
|
||||
#ctx.ctx.moveTo(x.val,y.val);
|
||||
}
|
||||
|
||||
pub fn (ctx CanvasRenderingContext2D) line_to(x int, y int) {
|
||||
#ctx.ctx.lineTo(x.val,y.val);
|
||||
}
|
||||
|
||||
pub fn (ctx CanvasRenderingContext2D) stroke() {
|
||||
#ctx.ctx.stroke();
|
||||
}
|
||||
|
||||
pub fn (ctx CanvasRenderingContext2D) close_path() {
|
||||
#ctx.ctx.closePath();
|
||||
}
|
||||
|
||||
pub fn (ctx CanvasRenderingContext2D) clear_rect(x int, y int, width int, height int) {
|
||||
#ctx.ctx.clearRect(x.val,y.val,width.val,height.val);
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
module ctx
|
||||
|
||||
pub struct WebGLRenderingContext {}
|
|
@ -0,0 +1,230 @@
|
|||
module jsdom
|
||||
|
||||
pub struct JS.Document {
|
||||
}
|
||||
|
||||
pub struct Document {
|
||||
Node
|
||||
}
|
||||
|
||||
pub struct Location {
|
||||
mut:
|
||||
loc JS.Location [noinit]
|
||||
}
|
||||
|
||||
pub fn (l Location) str() string {
|
||||
mut res := 'Location{\n'
|
||||
res += ' origin: $l.origin()\n'
|
||||
res += ' href: $l.href()\n'
|
||||
res += ' protocol: $l.protocol()\n'
|
||||
res += ' host: $l.host()\n'
|
||||
res += ' hostname: $l.hostname()\n'
|
||||
res += ' port: $l.port()\n'
|
||||
res += ' pathname: $l.pathname()\n'
|
||||
res += ' search: $l.search()\n'
|
||||
res += ' hash: $l.hash()\n'
|
||||
return res
|
||||
}
|
||||
|
||||
pub fn (mut l Location) assign(url string) {
|
||||
#l.val.loc.assign(url.str)
|
||||
}
|
||||
|
||||
pub fn (l Location) reload() {
|
||||
#l.loc.reload()
|
||||
}
|
||||
|
||||
pub fn (mut l Location) replace(url string) {
|
||||
#l.val.loc.replace(url.str)
|
||||
}
|
||||
|
||||
pub fn (l Location) origin() string {
|
||||
return tos(l.loc.origin)
|
||||
}
|
||||
|
||||
pub fn (l Location) href() string {
|
||||
return tos(l.loc.href)
|
||||
}
|
||||
|
||||
pub fn (mut l Location) set_href(href string) {
|
||||
l.loc.href = href.str
|
||||
}
|
||||
|
||||
pub fn (l Location) protocol() string {
|
||||
return tos(l.loc.protocol)
|
||||
}
|
||||
|
||||
pub fn (mut l Location) set_protocol(protocol string) {
|
||||
l.loc.protocol = protocol.str
|
||||
}
|
||||
|
||||
pub fn (l Location) host() string {
|
||||
return tos(l.loc.host)
|
||||
}
|
||||
|
||||
pub fn (mut l Location) set_host(host string) {
|
||||
l.loc.host = host.str
|
||||
}
|
||||
|
||||
pub fn (l Location) hostname() string {
|
||||
return tos(l.loc.hostname)
|
||||
}
|
||||
|
||||
pub fn (mut l Location) set_hostname(hostname string) {
|
||||
l.loc.hostname = hostname.str
|
||||
}
|
||||
|
||||
pub fn (l Location) port() string {
|
||||
return tos(l.loc.port)
|
||||
}
|
||||
|
||||
pub fn (mut l Location) set_port(port string) {
|
||||
l.loc.port = port.str
|
||||
}
|
||||
|
||||
pub fn (l Location) pathname() string {
|
||||
return tos(l.loc.pathname)
|
||||
}
|
||||
|
||||
pub fn (mut l Location) set_pathname(pathname string) {
|
||||
l.loc.pathname = pathname.str
|
||||
}
|
||||
|
||||
pub fn (l Location) hash() string {
|
||||
return tos(l.loc.hash)
|
||||
}
|
||||
|
||||
pub fn (mut l Location) set_hash(hash string) {
|
||||
l.loc.hash = hash.str
|
||||
}
|
||||
|
||||
pub fn (l Location) search() string {
|
||||
return tos(l.loc.search)
|
||||
}
|
||||
|
||||
pub fn (mut l Location) set_search(search string) {
|
||||
l.loc.search = search.str
|
||||
}
|
||||
|
||||
pub struct JS.Location {
|
||||
pub:
|
||||
origin JS.String
|
||||
mut:
|
||||
href JS.String
|
||||
protocol JS.String
|
||||
host JS.String
|
||||
hostname JS.String
|
||||
port JS.String
|
||||
pathname JS.String
|
||||
search JS.String
|
||||
hash JS.String
|
||||
}
|
||||
|
||||
pub fn (doc Document) active_element() Element {
|
||||
mut elem := Element{}
|
||||
#elem.node = doc.node.activeElement;
|
||||
|
||||
return elem
|
||||
}
|
||||
|
||||
pub fn (doc Document) get(name string) ?Element {
|
||||
mut elem := Element{}
|
||||
#elem.node = doc.node[name.str];
|
||||
#console.log(elem.node)
|
||||
#if (elem.node === null || elem.node === undefined) return new $ref(new Option({state: new byte(2),err: none__}));
|
||||
|
||||
return elem
|
||||
}
|
||||
|
||||
// location returns URI of the document
|
||||
pub fn (doc Document) location() Location {
|
||||
mut loc := Location{}
|
||||
#loc.loc = doc.node.location;
|
||||
|
||||
return loc
|
||||
}
|
||||
|
||||
// get_title returns current title of document
|
||||
pub fn (doc Document) get_title() string {
|
||||
res := ''
|
||||
#res.str = doc.node.title;
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
// set_title updates document title
|
||||
pub fn (doc Document) set_title(title string) {
|
||||
#doc.node.title = title.str;
|
||||
}
|
||||
|
||||
// url returns document location as a string
|
||||
pub fn (doc Document) url() string {
|
||||
res := ''
|
||||
#res.str = doc.node.URL;
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
// node casts `Document` back to `Node`.
|
||||
pub fn (doc Document) node() Node {
|
||||
node := Node{}
|
||||
#node.node = doc.node
|
||||
|
||||
return node
|
||||
}
|
||||
|
||||
pub fn (doc Document) get_element_by_id(id string) ?IElement {
|
||||
mut elem := IElement(Element{})
|
||||
found := false
|
||||
#let tmp = doc.node.getElementById(id.str);
|
||||
#elem = jsdom__dispatch_event_target(tmp);
|
||||
#found.val = !(elem.node == null)
|
||||
if !found {
|
||||
return none
|
||||
}
|
||||
return elem
|
||||
}
|
||||
|
||||
pub type DocumentPrepend = Node | string
|
||||
|
||||
pub fn (doc Document) prepend(nodes_or_strings ...DocumentPrepend) ? {
|
||||
caught := false
|
||||
err := ''
|
||||
#try {
|
||||
|
||||
for elem in nodes_or_strings {
|
||||
match elem {
|
||||
string {
|
||||
#doc.node.prepend(elem.str)
|
||||
}
|
||||
Node {
|
||||
#doc.node.prepend(elem.node)
|
||||
}
|
||||
}
|
||||
}
|
||||
#} catch (e) { caught.val = true; err.str = e.toString(); }
|
||||
if caught {
|
||||
return error(err)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (doc Document) create_element(tag_name string) Element {
|
||||
elem := Element{}
|
||||
#elem.node = doc.node.createElement(tag_name.str)
|
||||
|
||||
return elem
|
||||
}
|
||||
|
||||
pub fn get_document() Document {
|
||||
doc := Document{}
|
||||
#doc.node = document;
|
||||
|
||||
return doc
|
||||
}
|
||||
|
||||
pub fn (elem Document) add_event_listener(event string, cb EventCallback) {
|
||||
#elem.node.addEventListener(event.str, function (event) { let e = jsdom__dispatch_event_target(this);
|
||||
#let ev = jsdom__dispatch_event(event); ev.event = event;
|
||||
#return cb(e,ev)
|
||||
#});
|
||||
}
|
|
@ -0,0 +1,186 @@
|
|||
// DOM API for JS backend
|
||||
module jsdom
|
||||
|
||||
[heap]
|
||||
pub struct JS.Node {
|
||||
baseURI JS.String [noinit]
|
||||
childNodes JS.NodeList [noinit]
|
||||
firstChild voidptr [noinit]
|
||||
isConnected JS.bool [noinit]
|
||||
lastChild voidptr [noinit]
|
||||
nextSibling voidptr [noinit]
|
||||
nodeName JS.String [noinit]
|
||||
nodeType NodeType [noinit]
|
||||
nodeValue voidptr [noinit]
|
||||
ownerDocument JS.Document [noinit]
|
||||
parentNode voidptr [noinit]
|
||||
parentElement JS.Element [noinit]
|
||||
previousSibling voidptr [noinit]
|
||||
textContext voidptr
|
||||
}
|
||||
|
||||
pub struct JS.NodeList {
|
||||
pub mut:
|
||||
length JS.Number
|
||||
}
|
||||
|
||||
pub enum NodeType {
|
||||
element = 1
|
||||
attribute = 2
|
||||
text = 3
|
||||
cdata_section = 4
|
||||
entity_reference = 5
|
||||
entity = 6
|
||||
processing_instruction = 7
|
||||
comment = 8
|
||||
document = 9
|
||||
document_type = 10
|
||||
document_fragment = 11
|
||||
notation = 12
|
||||
}
|
||||
|
||||
pub struct Node {
|
||||
node JS.Node [noinit]
|
||||
}
|
||||
|
||||
pub fn (n Node) typ() NodeType {
|
||||
return n.node.nodeType
|
||||
}
|
||||
|
||||
/// IEventTarget interface is implemented by objects that can receive events and may have listeners for them.
|
||||
// In other words, any target of events implements the three methods associated with this interface.
|
||||
// TODO: remove_event_listener and dispatch_event
|
||||
pub interface IEventTarget {
|
||||
add_event_listener(event string, cb EventCallback)
|
||||
}
|
||||
|
||||
/// The DOM Node interface is an abstract base class upon which many other DOM API objects are based, thus
|
||||
// letting those object types to be used similarly and often interchangeably. As an abstract class,
|
||||
// there is no such thing as a plain Node object. All objects that implement Node functionality are based on one of its subclasses.
|
||||
// Most notable are Document, Element, and DocumentFragment.
|
||||
pub interface INode {
|
||||
IEventTarget
|
||||
typ() NodeType
|
||||
}
|
||||
|
||||
pub fn (elem Node) add_event_listener(event string, cb EventCallback) {
|
||||
#elem.node.addEventListener(event.str, function (event) { let e = jsdom__dispatch_event_target(this);
|
||||
#let ev = jsdom__dispatch_event(event); ev.event = event;
|
||||
#return cb(e,ev)
|
||||
#});
|
||||
}
|
||||
|
||||
pub fn (n INode) is_(ty NodeType) bool {
|
||||
res := false
|
||||
#res.val = n.node.nodeType == ty
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
pub fn (n INode) document() ?Document {
|
||||
res := Document{}
|
||||
if n.is_(.document) {
|
||||
#res.node = n.node
|
||||
|
||||
return res
|
||||
} else {
|
||||
return none
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (n INode) element() ?Element {
|
||||
res := Element{}
|
||||
if n.is_(.element) {
|
||||
#res.node = n.node
|
||||
|
||||
return res
|
||||
} else {
|
||||
return none
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (n INode) append_child(child INode) {
|
||||
#n.node.appendChild(child.node)
|
||||
}
|
||||
|
||||
pub fn (n INode) clone_node(deep ...int) INode {
|
||||
cloned := Node{}
|
||||
if deep.len == 0 {
|
||||
#cloned.node = n.node.cloneNode()
|
||||
} else {
|
||||
#cloned.node = n.node.cloneNode(deep.arr.get(new int(0)).val)
|
||||
}
|
||||
return cloned
|
||||
}
|
||||
|
||||
pub fn (n INode) contains(other INode) bool {
|
||||
res := false
|
||||
#res.val = n.node.contains(other.node)
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
pub fn (n INode) get_root_node() INode {
|
||||
root := Node{}
|
||||
#root.node = n.node.getRootNode()
|
||||
|
||||
return root
|
||||
}
|
||||
|
||||
pub fn (n INode) has_child_nodes() bool {
|
||||
res := false
|
||||
#res.val = n.node.hasChildNodes()
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
pub fn (n INode) insert_before(new_node INode, reference_node INode) Node {
|
||||
inserted := Node{}
|
||||
#inserted.node = n.node.insertBefore(new_node.node,reference_node.node)
|
||||
|
||||
return inserted
|
||||
}
|
||||
|
||||
/*
|
||||
pub fn (x Node) == (y Node) bool {
|
||||
res := false
|
||||
#res.val = x.node.isEqualNode(y.node)
|
||||
|
||||
return res
|
||||
}*/
|
||||
|
||||
pub fn (n INode) remove_child(child INode) {
|
||||
#n.node.removeChild(child.node)
|
||||
}
|
||||
|
||||
pub fn (n INode) replace_child(new_child INode, old_child INode) INode {
|
||||
#old_child.node = n.node.replace_child(new_child.node,old_child.node)
|
||||
|
||||
return old_child
|
||||
}
|
||||
|
||||
pub struct JS.EventTarget {}
|
||||
|
||||
fn dispatch_event_target(target JS.EventTarget) IEventTarget {
|
||||
mut ret := IEventTarget(Element{})
|
||||
#if (target instanceof HTMLCanvasElement) { ret = new jsdom__HTMLCanvasElement({}); ret.node = target; }
|
||||
#else if (target instanceof HTMLElement) { ret = new jsdom__HTMLElement({}); ret.node = target; }
|
||||
#else if (target instanceof Window) { ret = new jsdom__Window({}); ret.node = target;}
|
||||
#else if (target instanceof SVGElement) { ret = new jsdom__SVGElement({}); ret.node = target; }
|
||||
#else if (target instanceof Element) { ret = new jsdom__Element({}); ret.node = target; }
|
||||
#else if (target instanceof Document) { ret = new jsdom__Document({}); ret.node = target; }
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
pub type EventCallback = fn (_ IEventTarget, _ IEvent)
|
||||
|
||||
pub const (
|
||||
document = Document{}
|
||||
window = Window{}
|
||||
)
|
||||
|
||||
fn init() {
|
||||
#jsdom__document.node = document;
|
||||
#jsdom__window.node = window;
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
// DOM API wrapper for JS backend
|
||||
module jsdom
|
||||
|
||||
pub fn get_html_canvas_element(elem IElement) ?HTMLCanvasElement {
|
||||
if elem is HTMLCanvasElement {
|
||||
return *elem
|
||||
} else {
|
||||
return none
|
||||
}
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
module jsdom
|
||||
|
||||
pub struct JS.DOMString {
|
||||
}
|
||||
|
||||
pub struct JS.DOMTokenList {
|
||||
length JS.Number
|
||||
value JS.DOMString
|
||||
}
|
||||
|
||||
pub struct DOMTokenList {
|
||||
list JS.DOMTokenList [noinit]
|
||||
}
|
||||
|
||||
pub fn (x DOMTokenList) len() int {
|
||||
res := 0
|
||||
#res.val = x.list.length;
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
pub fn (x DOMTokenList) item(idx int) ?string {
|
||||
res := ''
|
||||
#let tmp = x.list.item(idx.list.val)
|
||||
#if (tmp === undefined) return new Option({state: new byte(2),err: none__});
|
||||
#res.val = tmp
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
pub fn (x DOMTokenList) contains(token string) bool {
|
||||
res := false
|
||||
#res.val = x.list.contains(token.str);
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
pub fn (x DOMTokenList) add(tokens ...string) {
|
||||
for token in tokens {
|
||||
#x.list.add(token.str);
|
||||
|
||||
_ := token
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (x DOMTokenList) remove(tokens ...string) {
|
||||
for token in tokens {
|
||||
#x.list.remove(token.str);
|
||||
|
||||
_ := token
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (x DOMTokenList) replace(old_token string, new_token string) bool {
|
||||
is_replaced := false
|
||||
#is_replaced.val = x.list.replace(old_token.str,new_token.str);
|
||||
|
||||
return is_replaced
|
||||
}
|
||||
|
||||
// supports returns true if the given `token` is in the associated attibute's supported tokens.
|
||||
pub fn (x DOMTokenList) supports(token string) bool {
|
||||
supports := false
|
||||
#supports.val = x.list.supports(token.str)
|
||||
|
||||
return supports
|
||||
}
|
||||
|
||||
// toggle removes a given token from the list and returns `false`. If token does not exist
|
||||
// it is added and function returns `true`.
|
||||
pub fn (x DOMTokenList) toggle(token string, force bool) bool {
|
||||
res := false
|
||||
#res.val = x.list.toggle(token.str, force.val);
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
// entries returns array of all tokens in this token list
|
||||
pub fn (x DOMTokenList) values() []string {
|
||||
mut res := []string{}
|
||||
#for (let [_,value] of x.list.entries()) array_push(res, new string(value));
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
pub fn (x DOMTokenList) str() string {
|
||||
mut fmt := 'DOMTokenList['
|
||||
values := x.values()
|
||||
for i, val in values {
|
||||
fmt += '"' + val + '"'
|
||||
if i != values.len - 1 {
|
||||
fmt += ','
|
||||
}
|
||||
}
|
||||
fmt += ']'
|
||||
return fmt
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
module jsdom
|
||||
|
||||
pub struct JS.Element {
|
||||
classList JS.DOMTokenList
|
||||
childElementCount JS.Number
|
||||
className JS.String
|
||||
clientHeight JS.Number
|
||||
clientWidth JS.Number
|
||||
clientTop JS.Number
|
||||
clientLeft JS.Number
|
||||
id JS.String
|
||||
innerHTML JS.String
|
||||
namespaceURI JS.String
|
||||
outerHTML JS.String
|
||||
scrollHeight JS.Number
|
||||
scrollLeft JS.Number
|
||||
scrollTop JS.Number
|
||||
scrollWidth JS.Number
|
||||
}
|
||||
|
||||
pub struct Element {
|
||||
Node
|
||||
}
|
||||
|
||||
pub fn (e Element) str() string {
|
||||
res := ''
|
||||
#res.str = e.node + ''
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
pub fn (elem Element) typ() NodeType {
|
||||
return .element
|
||||
}
|
||||
|
||||
pub fn (e Element) class_name() string {
|
||||
res := ''
|
||||
#res.str = e.node.className
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
pub fn (e Element) class_list() DOMTokenList {
|
||||
list := DOMTokenList{}
|
||||
#list.list = e.node.classList
|
||||
|
||||
return list
|
||||
}
|
||||
|
||||
// node casts `Element` back to `Node`.
|
||||
pub fn (elem Element) node() Node {
|
||||
node := Node{}
|
||||
#node.node = elem.node
|
||||
|
||||
return node
|
||||
}
|
||||
|
||||
pub fn (elem Element) add_event_listener(event string, cb EventCallback) {
|
||||
#elem.node.addEventListener(event.str, function (event) { let e = jsdom__dispatch_event_target(this);
|
||||
#let ev = jsdom__dispatch_event(event); ev.event = event;
|
||||
#return cb(e,ev)
|
||||
#});
|
||||
}
|
||||
|
||||
pub interface IElement {
|
||||
INode
|
||||
}
|
||||
|
||||
pub struct HTMLElement {
|
||||
Element
|
||||
}
|
||||
|
||||
pub fn (elem HTMLElement) typ() NodeType {
|
||||
return .element
|
||||
}
|
||||
|
||||
pub fn (elem HTMLElement) access_key() string {
|
||||
res := ''
|
||||
#res.str = elem.node.accessKey;
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
pub fn (mut elem HTMLElement) set_access_key(key string) {
|
||||
#elem.val.node.accessKey = key.str;
|
||||
}
|
||||
|
||||
pub fn (elem HTMLElement) add_event_listener(event string, cb EventCallback) {
|
||||
#elem.node.addEventListener(event.str, function (event) { let e = jsdom__dispatch_event_target(this);
|
||||
#let ev = jsdom__dispatch_event(event); ev.event = event;
|
||||
#return cb(e,ev)
|
||||
#});
|
||||
}
|
|
@ -0,0 +1,164 @@
|
|||
module jsdom
|
||||
|
||||
pub interface IEvent {
|
||||
composed_path() []IEventTarget
|
||||
}
|
||||
|
||||
pub struct JS.Event {}
|
||||
|
||||
pub struct JS.MouseEvent {}
|
||||
|
||||
pub struct Event {
|
||||
event JS.Event [noinit]
|
||||
}
|
||||
|
||||
pub fn (ev Event) composed_path() []IEventTarget {
|
||||
mut composed := []IEventTarget{}
|
||||
#ev.event.composedPath().forEach((item) => {
|
||||
#array_push(composed, jsdom__dispatch_event())
|
||||
#})
|
||||
|
||||
return composed
|
||||
}
|
||||
|
||||
pub struct UIEvent {
|
||||
Event
|
||||
}
|
||||
|
||||
// detail returns `int` with detail about the event, depending on the event type.
|
||||
pub fn (ev UIEvent) detail() int {
|
||||
ret := 0
|
||||
#ret.val = ev.event.detail
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
pub struct MouseEvent {
|
||||
UIEvent
|
||||
}
|
||||
|
||||
// button returns the button number that was pressed (if applicable) when the mouse event was fired.
|
||||
pub fn (ev MouseEvent) button() int {
|
||||
ret := 0
|
||||
#ret.val = ev.event.button;
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
// alt_key returns `true` if the `alt` key was down when the mouse event was fired.
|
||||
pub fn (ev MouseEvent) alt_key() bool {
|
||||
ret := false
|
||||
#ret.val = ev.event.altKey;
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
// buttons returns the buttons being depressed (if any) when the mouse event was fired.
|
||||
pub fn (ev MouseEvent) buttons() int {
|
||||
ret := 0
|
||||
#ret.val = ev.event.buttons;
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
// client_x returns the X coordinate of the mouse pointer in local coordinates.
|
||||
pub fn (ev MouseEvent) client_x() int {
|
||||
ret := 0
|
||||
#ret.val = ev.event.clientX;
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
// client_y returns the Y coordinate of the mouse pointer in local coordinates.
|
||||
pub fn (ev MouseEvent) client_y() int {
|
||||
ret := 0
|
||||
#ret.val = ev.event.clientY;
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
// ctrl_key returns `true` if the `ctrl` key was down when the mouse event was fired.
|
||||
pub fn (ev MouseEvent) ctrl_key() bool {
|
||||
ret := false
|
||||
#ret.val = ev.event.ctrlKey;
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
// meta_key returns `true` if the `meta` key was down when the mouse event was fired.
|
||||
pub fn (ev MouseEvent) meta_key() bool {
|
||||
ret := false
|
||||
#ret.val = ev.event.metaKey;
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
// movenet_x reaturns the X coordinate of the mouse pointer relative to the position of the last `mousemove` event.
|
||||
pub fn (ev MouseEvent) movement_x() int {
|
||||
ret := 0
|
||||
#ret.val = ev.event.movementX;
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
// movenet_y reaturns the Y coordinate of the mouse pointer relative to the position of the last `mousemove` event.
|
||||
pub fn (ev MouseEvent) movement_y() int {
|
||||
ret := 0
|
||||
#ret.val = ev.event.movementY;
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
// offset_x returns the X coordinate of the mouse pointer relative to the position of the padding edge of the target node.
|
||||
pub fn (ev MouseEvent) offset_x() int {
|
||||
ret := 0
|
||||
#ret.val = ev.event.offsetX;
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
// offset_y reaturns the Y coordinate of the mouse pointer relative to the position of the padding edge of the target node.
|
||||
pub fn (ev MouseEvent) offset_y() int {
|
||||
ret := 0
|
||||
#ret.val = ev.event.offsetY;
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
pub fn (ev MouseEvent) composed_path() []IEventTarget {
|
||||
mut composed := []IEventTarget{}
|
||||
#ev.event.composedPath().forEach((item) => {
|
||||
#array_push(composed, jsdom__dispatch_event())
|
||||
#})
|
||||
|
||||
return composed
|
||||
}
|
||||
|
||||
pub struct AbortSignal {
|
||||
Event
|
||||
}
|
||||
|
||||
pub fn (ev AbortSignal) composed_path() []IEventTarget {
|
||||
mut composed := []IEventTarget{}
|
||||
#ev.event.composedPath().forEach((item) => {
|
||||
#array_push(composed, jsdom__dispatch_event(item))
|
||||
#})
|
||||
|
||||
return composed
|
||||
}
|
||||
|
||||
pub fn (sig AbortSignal) aborted() bool {
|
||||
res := false
|
||||
#res.val = sig.event.aborted;
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
fn dispatch_event(event JS.Event) IEvent {
|
||||
mut ret := IEvent(Event{})
|
||||
#if (event instanceof AbortSignal) { ret = new jsdom__AbortSignal({}); }
|
||||
#else if (event instanceof MouseEvent) { ret = new jsdom__MouseEvent({}); }
|
||||
#ret.event = event
|
||||
|
||||
return ret
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
module jsdom
|
||||
|
||||
import jsdom.ctx
|
||||
|
||||
pub struct HTMLCanvasElement {
|
||||
HTMLElement
|
||||
}
|
||||
|
||||
pub fn (cv HTMLCanvasElement) height() int {
|
||||
ret := 0
|
||||
#ret.val = cv.node.height;
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
pub fn (cv HTMLCanvasElement) width() int {
|
||||
ret := 0
|
||||
#ret.val = cv.node.width;
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
pub fn (cv HTMLCanvasElement) typ() NodeType {
|
||||
return .element
|
||||
}
|
||||
|
||||
pub fn (elem HTMLCanvasElement) add_event_listener(event string, cb EventCallback) {
|
||||
#elem.node.addEventListener(event.str, function (event) { let e = jsdom__dispatch_event_target(this);
|
||||
#let ev = jsdom__dispatch_event(event); ev.event = event;
|
||||
#return cb(e,ev)
|
||||
#});
|
||||
}
|
||||
|
||||
pub fn (elem HTMLCanvasElement) get_context(ctx_ string) ctx.ContextResult {
|
||||
mut res := ctx.NoneContext{}
|
||||
#let ctx = elem.node.getContext(ctx_.str);
|
||||
#if (ctx instanceof CanvasRenderingContext2D) { res = new jsdom__ctx__CanvasRenderingContext2D(ctx); res.ctx = ctx; }
|
||||
|
||||
return res
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
module jsdom
|
||||
|
||||
pub struct JS.Window {
|
||||
}
|
||||
|
||||
pub struct Window {
|
||||
node JS.Window [noinit]
|
||||
}
|
||||
|
||||
pub fn (elem Window) add_event_listener(event string, cb EventCallback) {
|
||||
#elem.node.addEventListener(event.str, function (event) { let e = jsdom__dispatch_event_target(this);
|
||||
#let ev = jsdom__dispatch_event(event); ev.event = event;
|
||||
#return cb(e,ev)
|
||||
#});
|
||||
}
|
|
@ -164,7 +164,7 @@ fn (mut g JsGen) method_call(node ast.CallExpr) {
|
|||
g.expr(it.left)
|
||||
mut ltyp := it.left_type
|
||||
for ltyp.is_ptr() {
|
||||
g.write('.val')
|
||||
g.write('.valueOf()')
|
||||
ltyp = ltyp.deref()
|
||||
}
|
||||
g.write('.')
|
||||
|
|
|
@ -2718,7 +2718,7 @@ fn (mut g JsGen) gen_index_expr(expr ast.IndexExpr) {
|
|||
fn (mut g JsGen) gen_deref_ptr(ty ast.Type) {
|
||||
mut t := ty
|
||||
for t.is_ptr() {
|
||||
g.write('.val')
|
||||
g.write('.valueOf()')
|
||||
t = t.deref()
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue