about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2023-09-30 19:18:22 +0200
committerbptato <nincsnevem662@gmail.com>2023-09-30 19:18:22 +0200
commit1b20a3f8fae0f0eaa4f0b9979dc25d5bd04b9b10 (patch)
tree9cae5df0e9c1b6a378799473d76ba64d4e3f1f17 /src
parent31fbd611aa107cc023dcf1e1358f19ff58f14075 (diff)
downloadchawan-1b20a3f8fae0f0eaa4f0b9979dc25d5bd04b9b10.tar.gz
Improve implicit form submission
* Implement the "default button" part of the standard.
* If the submitter is the form, formmethod may be called on it. Check if
  this is the case in the function, and if yes, return the form's method.
Diffstat (limited to 'src')
-rw-r--r--src/html/dom.nim25
-rw-r--r--src/server/buffer.nim13
2 files changed, 26 insertions, 12 deletions
diff --git a/src/html/dom.nim b/src/html/dom.nim
index 0fac35e7..eec535ad 100644
--- a/src/html/dom.nim
+++ b/src/html/dom.nim
@@ -1819,24 +1819,29 @@ func enctype*(element: Element): FormEncodingType =
 
   return FORM_ENCODING_TYPE_URLENCODED
 
+func parseFormMethod(s: string): FormMethod =
+  return case s.toLowerAscii()
+  of "get": FORM_METHOD_GET
+  of "post": FORM_METHOD_POST
+  of "dialog": FORM_METHOD_DIALOG
+  else: FORM_METHOD_GET
+
 func formmethod*(element: Element): FormMethod =
+  if element.tagType == TAG_FORM:
+    # The standard says nothing about this, but this code path is reached
+    # on implicit form submission and other browsers seem to agree on this
+    # behavior.
+    return parseFormMethod(element.attr("method"))
+
   if element.isSubmitButton():
     if element.attrb("formmethod"):
-      return case element.attr("formmethod").tolower()
-      of "get": FORM_METHOD_GET
-      of "post": FORM_METHOD_POST
-      of "dialog": FORM_METHOD_DIALOG
-      else: FORM_METHOD_GET
+      return parseFormMethod(element.attr("formmethod"))
 
   if element.tagType in SupportedFormAssociatedElements:
     let element = FormAssociatedElement(element)
     if element.form != nil:
       if element.form.attrb("method"):
-        return case element.form.attr("method").tolower()
-        of "get": FORM_METHOD_GET
-        of "post": FORM_METHOD_POST
-        of "dialog": FORM_METHOD_DIALOG
-        else: FORM_METHOD_GET
+        return parseFormMethod(element.form.attr("method"))
 
   return FORM_METHOD_GET
 
diff --git a/src/server/buffer.nim b/src/server/buffer.nim
index 1e97a4bb..24dc7d3d 100644
--- a/src/server/buffer.nim
+++ b/src/server/buffer.nim
@@ -1200,8 +1200,17 @@ type ReadSuccessResult* = object
   repaint*: bool
 
 func implicitSubmit(input: HTMLInputElement): Option[Request] =
-  if input.form != nil and input.form.canSubmitImplicitly():
-    return submitForm(input.form, input.form)
+  let form = input.form
+  if form != nil and form.canSubmitImplicitly():
+    var defaultButton: Element
+    for element in form.elements:
+      if element.isSubmitButton():
+        defaultButton = element
+        break
+    if defaultButton != nil:
+      return submitForm(form, defaultButton)
+    else:
+      return submitForm(form, form)
 
 proc readSuccess*(buffer: Buffer, s: string): ReadSuccessResult {.proxy.} =
   if buffer.document.focus != nil: