summaryrefslogtreecommitdiff
path: root/compojure-3.2/src/compojure/html/form_helpers.clj
blob: 9da2ef94ab9cfc4bec1041bbe12605e2a9723b3e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
;; Copyright (c) James Reeves. All rights reserved.
;; The use and distribution terms for this software are covered by the Eclipse
;; Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) which
;; can be found in the file epl-v10.html at the root of this distribution. By
;; using this software in any fashion, you are agreeing to be bound by the
;; terms of this license. You must not remove this notice, or any other, from
;; this software.

(ns compojure.html.form-helpers
  "Functions for generating HTML forms and input fields."
  (:use compojure.html.gen
        compojure.control
        compojure.str-utils
        clojure.contrib.def
        clojure.contrib.seq-utils))

;; Global parameters for easy default values

(defvar *params* {}
  "Parameter map var that form input field functions use to populate their
  default values.")

(defmacro with-params
  "Bind a map of params to *params*."
  [params & body]
  `(binding [*params* ~params]
    ~@body))

;; Form input fields

(defn- input-field
  "Creates a form input field."
  [type name value]
  (let [name  (str* name)
        attrs {:type type, :name name, :id name}
        attrs (if value
                (assoc attrs :value value)
                attrs)]
    [:input attrs]))

(defn hidden-field
  "Creates a hidden input field."
  ([name]       (hidden-field name (*params* name)))
  ([name value] (input-field "hidden" name value)))

(defn text-field
  "Creates a text input field."
  ([name]       (text-field name (*params* name)))
  ([name value] (input-field "text" name value)))

(defn password-field
  "Creates a password input field."
  [name]
  (input-field "password" name ""))

(defn check-box
  "Creates a check box."
  ([name]
    (check-box name (*params* name)))
  ([name checked?]
    (check-box name checked? "true"))
  ([name checked? value]
    [:input {:type    "checkbox"
             :name    (str* name)
             :id      (str* name)
             :value   value
             :checked checked?}]))

(defn radio-button
 "Creates a radio button."
 ([group]
    (radio-button group (*params* group)))
 ([group checked?]
    (radio-button group checked? "true"))
 ([group checked? value]
    [:input {:type    "radio"
             :name    (str* group)
             :id      (str* group "_" value)
             :value   value
             :checked checked?}]))

(defn select-options
  "Turn a collection into a set of option tags."
  ([options]
    (select-options options nil))
  ([options selected]
    (let [select (fn [opt attrs]
                   (if (and selected (= opt (str* selected)))
                     (merge attrs {:selected "selected"})
                     attrs))]
      (domap [opt options]
        (if (vector? opt)
          (let [text  (opt 0)
                value (str* (opt 1))]
            [:option (select value {:value value}) text])
          [:option (select opt {}) opt])))))

(defn drop-down
  "Creates a drop-down box using the 'select' tag."
  ([name options]
    (drop-down name options (*params* name)))
  ([name options selected]
    [:select {:name (str* name) :id (str* name)}
      (select-options options selected)]))

(defn text-area
  "Creates a text area element."
  ([name]
    (text-area name (*params* name)))
  ([name value]
    [:textarea {:name (str* name) :id (str* name)} value]))

(defn file-upload
  "Creates a file upload input."
  [name]
  [:input {:type "file", :name (str* name), :id (str* name)}])

(defn label
  "Create a label for an input field with the supplied name."
  [name text]
  [:label {:for (str* name)} text])

(defn submit-button
  "Create a submit button."
  [text]
  [:input {:type "submit" :value text}])

(defn reset-button
  "Create a form reset button."
  [text]
  [:input {:type "reset" :value text}])

(defn form-to
  "Create a form that points to a particular method and route.
  e.g. (form-to [:put \"/post\"]
         ...)"
  [[method action] & body]
  (let [method-str (upcase-name method)]
    (into []
      (concat
        (if (includes? [:get :post] method)
          [:form {:method method-str :action action}]
          [:form {:method "POST" :action action}
           (hidden-field "_method" method-str)])
        body))))

(decorate-with optional-attrs
  hidden-field
  text-field
  check-box
  drop-down
  text-area
  file-upload
  label
  submit-button
  reset-button
  form-to)

(defmacro decorate-fields
  "Wrap all input field functions in a decorator."
  [decorator & body]
  `(decorate-bind ~decorator
     [text-field
      password-field
      check-box
      drop-down
      text-area
      file-upload]
    (list ~@body)))