diff options
author | bptato <nincsnevem662@gmail.com> | 2023-06-29 18:55:28 +0200 |
---|---|---|
committer | bptato <nincsnevem662@gmail.com> | 2023-06-29 18:55:44 +0200 |
commit | 1499a0757a8877355a2c5983cbe63c16837a83f8 (patch) | |
tree | dcdd918eca1c2959269d6eafe132a5cb1241a988 /src/html | |
parent | cd6b8bf5cf93ada0ee60202c249ae80693e5ca89 (diff) | |
download | chawan-1499a0757a8877355a2c5983cbe63c16837a83f8.tar.gz |
Add window.location
Note: setters do not work yet.
Diffstat (limited to 'src/html')
-rw-r--r-- | src/html/dom.nim | 134 | ||||
-rw-r--r-- | src/html/env.nim | 12 |
2 files changed, 140 insertions, 6 deletions
diff --git a/src/html/dom.nim b/src/html/dom.nim index 7fa012bc..bfb5581f 100644 --- a/src/html/dom.nim +++ b/src/html/dom.nim @@ -90,16 +90,21 @@ type discard #TODO type + Location = ref object + window: Window + Window* = ref object attrs*: WindowAttributes console* {.jsget.}: console navigator* {.jsget.}: Navigator settings*: EnvironmentSettings loader*: Option[FileLoader] + location* {.jsget.}: Location jsrt*: JSRuntime jsctx*: JSContext document* {.jsget.}: Document timeouts*: TimeoutState[int] + navigate*: proc(url: URL) # Navigator stuff Navigator* = ref object @@ -172,8 +177,7 @@ type Document* = ref object of Node charset*: Charset window*: Window - url*: URL #TODO expose as URL (capitalized) - location* {.jsget.}: URL #TODO should be location + url* {.jsget: "URL".}: URL mode*: QuirksMode currentScript: HTMLScriptElement isxml*: bool @@ -1081,6 +1085,131 @@ func item(collection: HTMLCollection, i: int): Element {.jsfunc.} = func getter(collection: HTMLCollection, i: int): Option[Element] {.jsgetprop.} = return option(collection.item(i)) +proc newLocation*(window: Window): Location = + let location = Location(window: window) + let ctx = window.jsctx + if ctx != nil: + let val = toJS(ctx, location) + let valueOf = ctx.getOpaque().Object_prototype_valueOf + defineProperty(ctx, val, "valueOf", valueOf) + defineProperty(ctx, val, "toPrimitive", JS_UNDEFINED) + #TODO [[DefaultProperties]] + JS_FreeValue(ctx, val) + return location + +func location(document: Document): Location {.jsfget.} = + return document.window.location + +func document(location: Location): Document = + return location.window.document + +func url(location: Location): URL = + let document = location.document + if document != nil: + return document.url + return newURL("about:blank").get + +proc setLocation*(document: Document, s: string): Err[DOMException] + {.jsfset: "location".} = + let url = parseURL(s) + if url.isNone: + return err(newDOMException("Invalid URL", "SyntaxError")) + document.window.navigate(url.get) + return ok() + +# Note: we do not implement security checks (as documents are in separate +# windows anyway). +func href(location: Location): string {.jsfget.} = + return location.url.serialize() + +proc href(location: Location, s: string): Err[DOMException] {.jsfset.} = + if location.document == nil: + return ok() + return location.document.setLocation(s) + +func origin(location: Location): string {.jsfget.} = + return location.url.origin + +func protocol(location: Location): string {.jsfget.} = + return location.url.protocol + +proc protocol(location: Location, s: string): Err[DOMException] {.jsfset.} = + let document = location.document + if document == nil: + return + let copyURL = newURL(location.url) + copyURL.setProtocol(s) + if copyURL.scheme != "http" and copyURL.scheme != "https": + return err(newDOMException("Invalid URL", "SyntaxError")) + document.window.navigate(copyURL) + return ok() + +func host(location: Location): string {.jsfget.} = + return location.url.host + +proc setHost(location: Location, s: string) {.jsfset: "host".} = + let document = location.document + if document == nil: + return + let copyURL = newURL(location.url) + copyURL.setHost(s) + document.window.navigate(copyURL) + +proc hostname(location: Location): string {.jsfget.} = + return location.url.hostname + +proc setHostname(location: Location, s: string) {.jsfset: "hostname".} = + let document = location.document + if document == nil: + return + let copyURL = newURL(location.url) + copyURL.setHostname(s) + document.window.navigate(copyURL) + +proc port(location: Location): string {.jsfget.} = + return location.url.port + +proc setPort(location: Location, s: string) {.jsfset: "port".} = + let document = location.document + if document == nil: + return + let copyURL = newURL(location.url) + copyURL.setPort(s) + document.window.navigate(copyURL) + +proc pathname(location: Location): string {.jsfget.} = + return location.url.pathname + +proc setPathname(location: Location, s: string) {.jsfset: "pathname".} = + let document = location.document + if document == nil: + return + let copyURL = newURL(location.url) + copyURL.setPathname(s) + document.window.navigate(copyURL) + +proc search(location: Location): string {.jsfget.} = + return location.url.search + +proc setSearch(location: Location, s: string) {.jsfset: "search".} = + let document = location.document + if document == nil: + return + let copyURL = newURL(location.url) + copyURL.setSearch(s) + document.window.navigate(copyURL) + +proc hash(location: Location): string {.jsfget.} = + return location.url.hash + +proc setHash(location: Location, s: string) {.jsfset: "hash".} = + let document = location.document + if document == nil: + return + let copyURL = newURL(location.url) + copyURL.setHash(s) + document.window.navigate(copyURL) + func newAttr(parent: Element, localName, value: string, prefix = "", namespaceURI = ""): Attr = return Attr( nodeType: ATTRIBUTE_NODE, @@ -2838,6 +2967,7 @@ proc addDOMModule*(ctx: JSContext) = let nodeCID = ctx.registerType(Node, parent = eventTargetCID) ctx.registerType(NodeList) ctx.registerType(HTMLCollection) + ctx.registerType(Location) ctx.registerType(Document, parent = nodeCID) ctx.registerType(DOMImplementation) ctx.registerType(DOMTokenList) diff --git a/src/html/env.nim b/src/html/env.nim index b3c14fc5..09cf1c5c 100644 --- a/src/html/env.nim +++ b/src/html/env.nim @@ -86,8 +86,9 @@ proc screenTop(window: Window): int64 {.jsfget.} = 0 #TODO outerWidth, outerHeight proc devicePixelRatio(window: Window): float64 {.jsfget.} = 1 -func location(window: Window): URL {.jsfget.} = - window.document.location +proc setLocation(window: Window, s: string): Err[DOMException] + {.jsfset: "location".} = + window.document.setLocation(s) proc addScripting*(window: Window, selector: Selector[int]) = let rt = newJSRuntime() @@ -129,7 +130,8 @@ proc runJSJobs*(window: Window) = window.jsrt.runJSJobs(window.console.err) proc newWindow*(scripting: bool, selector: Selector[int], - attrs: WindowAttributes, loader = none(FileLoader)): Window = + attrs: WindowAttributes, navigate: proc(url: URL) = nil, + loader = none(FileLoader)): Window = let window = Window( attrs: attrs, console: console(err: newFileStream(stderr)), @@ -137,8 +139,10 @@ proc newWindow*(scripting: bool, selector: Selector[int], loader: loader, settings: EnvironmentSettings( scripting: scripting - ) + ), + navigate: navigate ) + window.location = window.newLocation() if scripting: window.addScripting(selector) return window |