about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/css/cascade.nim12
-rw-r--r--src/html/dom.nim52
-rw-r--r--src/server/buffer.nim2
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: