diff --git a/karax/kajax.nim b/karax/kajax.nim index c226c50..2fd14fa 100644 --- a/karax/kajax.nim +++ b/karax/kajax.nim @@ -8,7 +8,9 @@ import karax proc ajax(meth, url: cstring; headers: openarray[(cstring, cstring)]; data: cstring; cont: proc (httpStatus: int; response: cstring); - kxi: KaraxInstance = kxi) = + kxi: KaraxInstance = kxi, + useBinary: bool = false, + blob: Blob = nil) = proc contWrapper(httpStatus: int; response: cstring) = cont(httpStatus, response) redraw(kxi) @@ -22,6 +24,7 @@ proc ajax(meth, url: cstring; headers: openarray[(cstring, cstring)]; proc setRequestHeader(r: HttpRequest; a, b: cstring) {.importcpp: "#.setRequestHeader(@)".} proc statechange(r: HttpRequest; cb: proc()) {.importcpp: "#.onreadystatechange = #".} proc send(r: HttpRequest; data: cstring) {.importcpp: "#.send(#)".} + proc send(r: HttpRequest, data: Blob) {.importcpp: "#.send(#)".} proc open(r: HttpRequest; meth, url: cstring; async: bool) {.importcpp: "#.open(@)".} proc newRequest(): HttpRequest {.importcpp: "new XMLHttpRequest(@)".} @@ -36,7 +39,10 @@ proc ajax(meth, url: cstring; headers: openarray[(cstring, cstring)]; contWrapper(this.status, this.responseText) else: contWrapper(this.status, this.statusText) - ajax.send(data) + if useBinary: + ajax.send(blob) + else: + ajax.send(data) proc ajaxPost*(url: cstring; headers: openarray[(cstring, cstring)]; data: cstring; @@ -44,6 +50,12 @@ proc ajaxPost*(url: cstring; headers: openarray[(cstring, cstring)]; kxi: KaraxInstance = kxi) = ajax("POST", url, headers, data, cont, kxi) +proc ajaxPost*(url: cstring; headers: openarray[(cstring, cstring)]; + data: Blob; + cont: proc (httpStatus: int, response: cstring); + kxi: KaraxInstance = kxi) = + ajax("POST", url, headers, "", cont, kxi, true, data) + proc ajaxGet*(url: cstring; headers: openarray[(cstring, cstring)]; cont: proc (httpStatus: int, response: cstring); kxi: KaraxInstance = kxi) = diff --git a/karax/karax.nim b/karax/karax.nim index 0ff666b..0359e59 100644 --- a/karax/karax.nim +++ b/karax/karax.nim @@ -2,7 +2,7 @@ import kdom, vdom, jstrutils, compact, jdict, vstyles -export kdom.Event +export kdom.Event, kdom.Blob proc kout*[T](x: T) {.importc: "console.log", varargs, deprecated.} ## the preferred way of debugging karax applications. Now deprecated, @@ -85,7 +85,7 @@ proc wrapEvent(d: Node; n: VNode; k: EventKind; let action = action let n = n result = proc (ev: Event) = - if ((KeyboardEvent)ev).keyCode == 13: keyeventBody() + if cast[KeyboardEvent](ev).keyCode == 13: keyeventBody() proc laterWrapper(): NativeEventHandler = let action = action diff --git a/karax/kdom.nim b/karax/kdom.nim index 17f2630..c276bfb 100644 --- a/karax/kdom.nim +++ b/karax/kdom.nim @@ -164,10 +164,8 @@ type name*: cstring readOnly*: bool options*: seq[OptionElement] + selectedOptions*: seq[OptionElement] clientWidth*, clientHeight*: int - - # https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement - HtmlElement* = ref object of Element contentEditable*: string isContentEditable*: bool dir*: string @@ -176,6 +174,87 @@ type offsetLeft*: int offsetTop*: int + # https://developer.mozilla.org/en-US/docs/Web/API/ValidityState + ValidityState* = ref ValidityStateObj + ValidityStateObj {.importc.} = object + badInput*: bool + customError*: bool + patternMismatch*: bool + rangeOverflow*: bool + rangeUnderflow*: bool + stepMismatch*: bool + tooLong*: bool + tooShort*: bool + typeMismatch*: bool + valid*: bool + valueMissing*: bool + + # https://developer.mozilla.org/en-US/docs/Web/API/Blob + Blob* = ref BlobObj + BlobObj {.importc.} = object of RootObj + size*: int + `type`*: cstring + + # https://developer.mozilla.org/en-US/docs/Web/API/File + File* = ref FileObj + FileObj {.importc.} = object of Blob + lastModified*: int + name*: cstring + + # https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement + InputElement* = ref InputElementObj + InputElementObj {.importc.} = object of Element + # Properties related to the parent form + formAction*: cstring + formEncType*: cstring + formMethod*: cstring + formNoValidate*: bool + formTarget*: cstring + + # Properties that apply to any type of input element that is not hidden + `type`*: cstring + autofocus*: bool + required*: bool + value*: cstring + validity*: ValidityState + validationMessage*: cstring + willValidate*: bool + + # Properties that apply only to elements of type "checkbox" or "radio" + indeterminate*: bool + + # Properties that apply only to elements of type "image" + alt*: cstring + height*: cstring + src*: cstring + width*: cstring + + # Properties that apply only to elements of type "file" + accept*: cstring + files*: seq[Blob] + + # Properties that apply only to text/number-containing or elements + autocomplete*: cstring + maxLength*: int + size*: int + pattern*: cstring + placeholder*: cstring + min*: cstring + max*: cstring + selectionStart*: int + selectionEnd*: int + selectionDirection*: cstring + + # Properties not yet categorized + dirName*: cstring + accessKey*: cstring + list*: Element + multiple*: bool + labels*: seq[Element] + step*: cstring + valueAsDate*: cstring + valueAsNumber*: float + LinkElement* = ref LinkObj LinkObj {.importc.} = object of ElementObj target*: cstring @@ -205,13 +284,19 @@ type text*: cstring value*: cstring + # https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement FormElement* = ref FormObj FormObj {.importc.} = object of ElementObj + acceptCharset*: cstring action*: cstring - encoding*: cstring - `method`*: cstring - target*: cstring + autocomplete*: cstring elements*: seq[Element] + encoding*: cstring + enctype*: cstring + length*: int + `method`*: cstring + noValidate*: bool + target*: cstring ImageElement* = ref ImageObj ImageObj {.importc.} = object of ElementObj @@ -339,12 +424,14 @@ type isTrusted*: bool # https://developer.mozilla.org/en-US/docs/Web/API/UIEvent - UIEvent* {.importc.} = ref object of Event + UIEvent* = ref UIEventObj + UIEventObj {.importc.} = object of Event detail*: int64 view*: Window # https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent - KeyboardEvent* {.importc.} = ref object of UIEvent + KeyboardEvent* = ref KeyboardEventObj + KeyboardEventObj {.importc.} = object of UIEvent altKey*, ctrlKey*, metaKey*, shiftKey*: bool code*: cstring isComposing*: bool @@ -708,7 +795,8 @@ type FifthButton = 16 # https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent - MouseEvent* {.importc.} = ref object of UIEvent + MouseEvent* = ref MouseEventObj + MouseEventObj {.importc.} = object of UIEvent altKey*, ctrlKey*, metaKey*, shiftKey*: bool button*: int buttons*: int @@ -720,18 +808,20 @@ type #region*: cstring screenX*, screenY*: int x*, y*: int - + DataTransferItemKind* {.pure.} = enum File = "file", String = "string" # https://developer.mozilla.org/en-US/docs/Web/API/DataTransferItem - DataTransferItem* {.importc.} = ref object of RootObj + DataTransferItem* = ref DataTransferItemObj + DataTransferItemObj {.importc.} = object of RootObj kind*: cstring `type`*: cstring # https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer - DataTransfer* {.importc.} = ref object of RootObj + DataTransfer* = ref DataTransferObj + DataTransferObj {.importc.} = object of RootObj dropEffect*: cstring effectAllowed*: cstring files*: seq[Element] @@ -766,16 +856,14 @@ type Drop = "drop" # https://developer.mozilla.org/en-US/docs/Web/API/DragEvent - DragEvent* {.importc.} = ref object of MouseEvent + DragEvent* {.importc.} = object of MouseEvent dataTransfer*: DataTransfer - + TouchList* {.importc.} = ref object of RootObj - length*: int + length*: int - TouchEvent* {.importc.} = ref object of UIEvent - changedTouches*, targetTouches*, touches*: TouchList - - Touch* {.importc.} = ref object of RootObj + Touch* = ref TouchObj + TouchObj {.importc.} = object of RootObj identifier*: int screenX*, screenY*, clientX*, clientY*, pageX*, pageY*: int target*: Element @@ -783,6 +871,10 @@ type rotationAngle*: int force*: float + TouchEvent* = ref TouchEventObj + TouchEventObj {.importc.} = object of UIEvent + changedTouches*, targetTouches*, touches*: seq[Touch] + Location* = ref LocationObj LocationObj {.importc.} = object of RootObj hash*: cstring @@ -845,12 +937,6 @@ type once*: bool passive*: bool - JFile* {.importc.} = ref object - lastModified*: int - name*: cstring - size*: int - `type`*: cstring - when defined(nodejs): # we provide a dummy DOM for nodejs for testing purposes proc len*(x: Node): int = x.childNodes.len @@ -1022,6 +1108,8 @@ proc getElementsByClassName*(e: Element, name: cstring): seq[Element] # FormElement "methods" proc reset*(f: FormElement) proc submit*(f: FormElement) +proc checkValidity*(e: FormElement): bool +proc reportValidity*(e: FormElement): bool # EmbedElement "methods" proc play*(e: EmbedElement) @@ -1072,7 +1160,16 @@ proc setData*(dt: DataTransfer, format: cstring, data: cstring) proc setDragImage*(dt: DataTransfer, img: Element, xOffset: int64, yOffset: int64) # DataTransferItem "methods" -proc getAsFile*(dti: DataTransferItem): JFile +proc getAsFile*(dti: DataTransferItem): File + +# InputElement "methods" +proc setSelectionRange*(e: InputElement, selectionStart: int, selectionEnd: int, selectionDirection: cstring = "none") +proc setRangeText*(e: InputElement, replacement: cstring, startindex: int = 0, endindex: int = 0, selectionMode: cstring = "preserve") +proc setCustomValidity*(e: InputElement, error: cstring) +proc checkValidity*(e: InputElement): bool + +# Blob "methods" +proc slice*(e: Blob, startindex: int = 0, endindex: int = e.size, contentType: cstring = "") {.pop.} @@ -1132,3 +1229,4 @@ proc inViewport*(el: Node): bool = proc scrollTop*(e: Node): int {.importcpp: "#.scrollTop", nodecl.} proc offsetHeight*(e: Node): int {.importcpp: "#.offsetHeight", nodecl.} proc offsetTop*(e: Node): int {.importcpp: "#.offsetTop", nodecl.} +proc offsetLeft*(e: Node): int {.importcpp: "#.offsetLeft", nodecl.} diff --git a/tests/domEventTests.nim b/tests/domEventTests.nim index 2db49c8..347d636 100644 --- a/tests/domEventTests.nim +++ b/tests/domEventTests.nim @@ -41,7 +41,7 @@ proc check(cond: bool, msg: string, warn: bool): bool = proc dragDivDragStart(ev: kdom.Event) = dragEventsCompleted[DragStart] = true - var dgev = ((DragEvent)ev) + var dgev = cast[DragEvent](ev) var dragDiv = document.getElementById("dragDiv") if dragDiv != nil: @@ -413,7 +413,7 @@ proc test3() = proc dragDivDrop(ev: kdom.Event) = dragEventsCompleted[Drop] = true - var dgev = ((DragEvent)ev) + var dgev = cast[DragEvent](ev) var dragDiv = document.getElementById("dragDiv") var data = $dgev.dataTransfer.getData("text/plain") var dt = dgev.dataTransfer @@ -495,7 +495,7 @@ proc dragDivDrop(ev: kdom.Event) = log "Test 2 completed successfully." test3() - dgev.preventDefault() + ev.preventDefault() return document.getElementById("dragDiv").style.visibility = "hidden" @@ -504,40 +504,35 @@ proc dragDivDrop(ev: kdom.Event) = test2ImageDrop = true testRunning[1] = false - dgev.preventDefault() + ev.preventDefault() proc dragDivDrag(ev: kdom.Event) = dragEventsCompleted[Drag] = true - var dgev = ((DragEvent)ev) - dgev.preventDefault() + ev.preventDefault() proc dragDivDragLeave(ev: kdom.Event) = dragEventsCompleted[DragLeave] = true - var dgev = ((DragEvent)ev) if testRunning[0]: log "[dragLeave]" - dgev.preventDefault() + ev.preventDefault() proc dragDivDragExit(ev: kdom.Event) = dragEventsCompleted[DragExit] = true - var dgev = ((DragEvent)ev) if testRunning[0]: log "[dragExit]" - dgev.preventDefault() + ev.preventDefault() proc dragDivDragEnd(ev: kdom.Event) = dragEventsCompleted[DragEnd] = true - var dgev = ((DragEvent)ev) if testRunning[0]: log "[dragEnd]" - dgev.preventDefault() + ev.preventDefault() proc dragDivDragEnter(ev: kdom.Event) = dragEventsCompleted[DragEnter] = true if testRunning[0]: log "[dragEnter]" - var dgev = ((DragEvent)ev) - dgev.preventDefault() + ev.preventDefault() proc initDragEvents() = log "Drag event initialization started."