diff options
author | bptato <nincsnevem662@gmail.com> | 2025-01-27 19:34:27 +0100 |
---|---|---|
committer | bptato <nincsnevem662@gmail.com> | 2025-01-27 19:34:27 +0100 |
commit | f18645b2d36fde7dc0328ec3b8263be0a764286b (patch) | |
tree | 3a31bec2dd987ffee0879fdc3601c23b1b625e38 /src | |
parent | 583ee83e6e89fd74a1abc442eabb0ab4c8bbbf86 (diff) | |
download | chawan-f18645b2d36fde7dc0328ec3b8263be0a764286b.tar.gz |
cascade: reuse input value when possible
Diffstat (limited to 'src')
-rw-r--r-- | src/css/cascade.nim | 12 | ||||
-rw-r--r-- | src/html/dom.nim | 52 | ||||
-rw-r--r-- | src/server/buffer.nim | 2 |
3 files changed, 39 insertions, 27 deletions
diff --git a/src/css/cascade.nim b/src/css/cascade.nim index 20575f0d..57491938 100644 --- a/src/css/cascade.nim +++ b/src/css/cascade.nim @@ -413,11 +413,6 @@ when defined(debug): of stReplacement: return "#replacement" -# Defined here so it isn't accidentally used in dom. -#TODO it may be better to do it in dom anyway, so we can cache it... -func newCharacterData*(data: sink string): CharacterData = - return CharacterData(data: data) - template computed*(styledNode: StyledNode): CSSValues = styledNode.element.computedMap[styledNode.pseudo] @@ -453,10 +448,9 @@ iterator children*(styledNode: StyledNode): StyledNode {.closure.} = yield initStyledPseudo(parent, peBefore) case parent.tagType of TAG_INPUT: - #TODO cache (just put value in a CharacterData) - let s = HTMLInputElement(parent).inputString() - if s.len > 0: - yield initStyledText(parent, s) + let cdata = HTMLInputElement(parent).inputString() + if cdata != nil and cdata.data.len != 0: + yield initStyledText(parent, cdata) of TAG_TEXTAREA: #TODO cache (do the same as with input, and add borders in render) yield initStyledText(parent, HTMLTextAreaElement(parent).textAreaString()) diff --git a/src/html/dom.nim b/src/html/dom.nim index eef93341..f3ade44d 100644 --- a/src/html/dom.nim +++ b/src/html/dom.nim @@ -308,7 +308,7 @@ type HTMLInputElement* = ref object of FormAssociatedElement inputType* {.jsget: "type".}: InputType - value* {.jsget.}: string + internalValue: CharacterData internalChecked {.jsget: "checked".}: bool files* {.jsget.}: seq[WebFile] xcoord*: int @@ -2627,6 +2627,9 @@ func serializeFragment*(node: Node): string = result = "" result.serializeFragment(node) +func newCharacterData*(data: sink string = ""): CharacterData = + return CharacterData(data: data) + # Element proc hash(element: Element): Hash = return hash(cast[pointer](element)) @@ -3002,8 +3005,20 @@ func length(this: HTMLFormElement): int {.jsfget.} = func jsForm(this: HTMLInputElement): HTMLFormElement {.jsfget: "form".} = return this.form -proc setValue*(this: HTMLInputElement; value: string) {.jsfset: "value".} = - this.value = value +func value*(this: HTMLInputElement): lent string = + if this.internalValue == nil: + this.internalValue = newCharacterData() + return this.internalValue.data + +func jsValue(ctx: JSContext; this: HTMLInputElement): JSValue + {.jsfget: "value".} = + #TODO wat + return ctx.toJS(this.value) + +proc `value=`*(this: HTMLInputElement; value: sink string) {.jsfset: "value".} = + if this.internalValue == nil: + this.internalValue = CharacterData() + this.internalValue.data = value this.invalidate() proc setType(this: HTMLInputElement; s: string) {.jsfset: "type".} = @@ -3024,32 +3039,35 @@ proc setChecked*(input: HTMLInputElement; b: bool) {.jsfset: "checked".} = input.invalidate() input.internalChecked = b -func inputString*(input: HTMLInputElement): string = +func inputString*(input: HTMLInputElement): CharacterData = case input.inputType of itCheckbox, itRadio: if input.checked: - "*" - else: - " " + return newCharacterData("*") + return newCharacterData(" ") of itSearch, itText, itEmail, itURL, itTel: - input.value.padToWidth(int(input.attrulgz(satSize).get(20))) + if input.value.len == 20: + return input.internalValue + return CharacterData( + data: input.value.padToWidth(int(input.attrulgz(satSize).get(20))) + ) of itPassword: - '*'.repeat(input.value.len).padToWidth(int(input.attrulgz(satSize).get(20))) + let n = int(input.attrulgz(satSize).get(20)) + return newCharacterData('*'.repeat(input.value.len).padToWidth(n)) of itReset: if input.attrb(satValue): - input.value - else: - "RESET" + return input.internalValue + return newCharacterData("RESET") of itSubmit, itButton: if input.attrb(satValue): - input.value - else: - "SUBMIT" + return input.internalValue + return newCharacterData("SUBMIT") of itFile: #TODO multiple files? let s = if input.files.len > 0: input.files[0].name else: "" - s.padToWidth(int(input.attrulgz(satSize).get(20))) - else: input.value + return newCharacterData(s.padToWidth(int(input.attrulgz(satSize).get(20)))) + else: + return input.internalValue # <label> func control*(label: HTMLLabelElement): FormAssociatedElement {.jsfget.} = diff --git a/src/server/buffer.nim b/src/server/buffer.nim index 42ca60d7..7c66a3ac 100644 --- a/src/server/buffer.nim +++ b/src/server/buffer.nim @@ -1363,7 +1363,7 @@ proc readSuccess*(buffer: Buffer; s: string; hasFd: bool): Request {.proxy.} = input.files = @[newWebFile(s, fd)] input.invalidate() else: - input.setValue(s) + input.value = s buffer.maybeReshape() return buffer.implicitSubmit(input) of TAG_TEXTAREA: |