code: explicitly call init in some named constructors
[nit.git] / lib / html / bootstrap.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 # HTML templates for Bootstrap components.
16 #
17 # See http://getbootstrap.com/components/
18 module bootstrap
19
20 import template
21
22 # Bootstrap component abstraction.
23 #
24 # Mainly used to factoryze CSS treatments.
25 # Can be used in the future to handle generic stuff like attributes or escaping.
26 #
27 # TODO merge with html::HTMTag without init conflict?
28 # HTMLTag requires the main init to pass a tagname,
29 # this was so much verbose here.
30 abstract class BSComponent
31 super Template
32
33 # CSS classes to add on this element.
34 var css_classes = new Array[String]
35
36 # Render `self` css clases as a `class` attribute.
37 fun render_css_classes: String do
38 if css_classes.is_empty then return ""
39 return " class=\"{css_classes.join(" ")}\""
40 end
41 end
42
43 # A `<a>` tag.
44 #
45 # Not really a Bootstrap component but used in other components
46 # that it required its own abstraction.
47 #
48 # Example:
49 # ~~~
50 # var lnk = new Link("http://nitlanguage.org", "Nit")
51 # assert lnk.write_to_string == "<a href=\"http://nitlanguage.org\">Nit</a>"
52 # ~~~
53 #
54 # Creates a link with a title attribute:
55 # ~~~
56 # lnk = new Link.with_title("http://nitlanguage.org", "Nit", "Nit homepage")
57 # assert lnk.write_to_string == "<a href=\"http://nitlanguage.org\" title=\"Nit homepage\">Nit</a>"
58 # ~~~
59 class Link
60 super BSComponent
61
62 # URL pointed by this link.
63 var href: String is writable
64
65 # Displayed text.
66 var text: Writable is writable
67
68 # Optional title.
69 var title: nullable String is noinit, writable
70
71 # Creates a link with a `title` attribute.
72 init with_title(href: String, text: Writable, title: nullable String) do
73 init(href, text)
74 self.title = title
75 end
76
77 redef fun rendering do
78 add "<a{render_css_classes} href=\"{href}\""
79 if title != null then add " title=\"{title.write_to_string}\""
80 add ">{text}</a>"
81 end
82 end
83
84 # A `<h1>` to `<h6>` tag.
85 #
86 # Not really a Bootstrap component but used in other components
87 # that it required its own abstraction.
88 #
89 # Example:
90 # ~~~
91 # var h1 = new Header(1, "Title")
92 # assert h1.write_to_string == "<h1>Title</h1>"
93 # ~~~
94 #
95 # With subtext:
96 # ~~~
97 # var h6 = new Header.with_subtext(6, "Title", "with subtext")
98 # assert h6.write_to_string == "<h6>Title<small>with subtext</small></h6>"
99 # ~~~
100 class Header
101 super BSComponent
102
103 # Header level between 1 and 6.
104 var level: Int
105
106 # Displayed text.
107 var text: Writable
108
109 # Optional subtext.
110 var subtext: nullable Writable is noinit, writable
111
112 # Creates a link with a `title` attribute.
113 init with_subtext(level: Int, text: Writable, subtext: String) do
114 init(level, text)
115 self.subtext = subtext
116 end
117
118 redef fun rendering do
119 add "<h{level}{render_css_classes}>{text.write_to_string}"
120 if subtext != null then add "<small>{subtext.write_to_string}</small>"
121 add "</h{level}>"
122 end
123 end
124
125 # An abstract HTML list.
126 #
127 # Many Bootstrap components are built around a HTML list.
128 #
129 # Used to factorize behavior between OrderedList and UnorderedList.
130 abstract class HTMLList
131 super BSComponent
132
133 # A list contains `<li>` tags as children.
134 #
135 # See ListItem.
136 var items = new Array[ListItem]
137
138 # Adds a new ListItem to `self`.
139 fun add_li(item: ListItem) do items.add item
140
141 # Does `self` contains no items?
142 fun is_empty: Bool do return items.is_empty
143 end
144
145 # A `<ol>` list tag.
146 #
147 # Example:
148 #
149 # ~~~
150 # var lst = new OrderedList
151 # lst.add_li(new ListItem("foo"))
152 # lst.add_li(new ListItem("bar"))
153 # lst.add_li(new ListItem("baz"))
154 #
155 # assert lst.write_to_string == """
156 # <ol>
157 # <li>foo</li>
158 # <li>bar</li>
159 # <li>baz</li>
160 # </ol>
161 # """
162 # ~~~
163 class OrderedList
164 super HTMLList
165
166 redef fun rendering do
167 addn "<ol{render_css_classes}>"
168 for item in items do add item
169 addn "</ol>"
170 end
171 end
172
173 # A `<ul>` list tag.
174 #
175 # Example:
176 #
177 # ~~~
178 # var lst = new UnorderedList
179 # lst.add_li(new ListItem("foo"))
180 # lst.add_li(new ListItem("bar"))
181 # lst.add_li(new ListItem("baz"))
182 #
183 # assert lst.write_to_string == """
184 # <ul>
185 # <li>foo</li>
186 # <li>bar</li>
187 # <li>baz</li>
188 # </ul>
189 # """
190 # ~~~
191 class UnorderedList
192 super HTMLList
193
194 redef fun rendering do
195 addn "<ul{render_css_classes}>"
196 for item in items do add item
197 addn "</ul>"
198 end
199 end
200
201 # A `<li>` tag.
202 class ListItem
203 super BSComponent
204
205 # Content to display in this list item.
206 var text: Writable is writable
207
208 redef fun rendering do addn "<li{render_css_classes}>{text.write_to_string}</li>"
209 end
210
211 # A Boostrap icon.
212 #
213 # See http://getbootstrap.com/components/#glyphicons
214 #
215 # Example:
216 #
217 # ~~~
218 # var icon = new BSIcon("star")
219 # assert icon.write_to_string == "<span class=\"glyphicon glyphicon-star\" aria-hidden=\"true\"></span>"
220 # ~~~
221 class BSIcon
222 super BSComponent
223
224 # Glyphicon name to display.
225 #
226 # See full list at http://getbootstrap.com/components/#glyphicons.
227 var icon: String
228
229 init do css_classes.add "glyphicon glyphicon-{icon}"
230
231 redef fun rendering do
232 add "<span{render_css_classes} aria-hidden=\"true\"></span>"
233 end
234 end
235
236 # A Bootstrap breadcrumbs component.
237 #
238 # See http://getbootstrap.com/components/#breadcrumbs
239 #
240 # Example:
241 #
242 # ~~~
243 # var bc = new BSBreadCrumbs
244 # bc.add_li(new ListItem("foo"))
245 # bc.add_li(new ListItem("bar"))
246 # bc.add_li(new ListItem("baz"))
247 #
248 # assert bc.write_to_string == """
249 # <ol class=\"breadcrumbs\">
250 # <li>foo</li>
251 # <li>bar</li>
252 # <li class=\"active\">baz</li>
253 # </ol>
254 # """
255 # ~~~
256 class BSBreadCrumbs
257 super OrderedList
258
259 init do css_classes.add "breadcrumbs"
260
261 redef fun rendering do
262 items.last.css_classes.add "active"
263 super
264 end
265 end
266
267 # A Bootstrap label component.
268 #
269 # See http://getbootstrap.com/components/#labels
270 #
271 # Example:
272 #
273 # ~~~
274 # var lbl = new BSLabel("danger", "Danger!")
275 # assert lbl.write_to_string == "<span class=\"label label-danger\">Danger!</span>"
276 # ~~~
277 class BSLabel
278 super BSComponent
279
280 # Class used to change the color of the label.
281 #
282 # Can be one of `default`, `primary`, `success`, `info`, `warning` or `danger`.
283 var color: String
284
285 # Text to display in the label.
286 var text: Writable
287
288 init do css_classes.add "label label-{color}"
289
290 redef fun rendering do
291 add "<span{render_css_classes}>{text.write_to_string}</span>"
292 end
293 end
294
295 # A Bootstrap badge component.
296 #
297 # See http://getbootstrap.com/components/#badges
298 #
299 # Example:
300 #
301 # ~~~
302 # var b = new BSBadge("42 messages")
303 # assert b.write_to_string == "<span class=\"badge\">42 messages</span>"
304 # ~~~
305 class BSBadge
306 super BSComponent
307
308 # Text to display in the label.
309 var text: Writable
310
311 init do css_classes.add "badge"
312
313 redef fun rendering do
314 add "<span{render_css_classes}>{text.write_to_string}</span>"
315 end
316 end
317
318 # A Bootstrap page header component.
319 #
320 # See http://getbootstrap.com/components/#page-header
321 #
322 # Example:
323 #
324 # ~~~
325 # var h = new BSPageHeader("Welcome")
326 # assert h.write_to_string == """
327 # <div class=\"page-header\">
328 # Welcome
329 # </div>
330 # """
331 # ~~~
332 class BSPageHeader
333 super BSComponent
334
335 # Text to display as title.
336 var text: Writable
337
338 init do css_classes.add "page-header"
339
340 redef fun rendering do
341 addn "<div{render_css_classes}>"
342 addn text.write_to_string
343 addn "</div>"
344 end
345 end
346
347 # A Bootstrap alert component.
348 #
349 # See http://getbootstrap.com/components/#alerts
350 #
351 # Example:
352 #
353 # ~~~
354 # var alert = new BSAlert("danger", "Danger!")
355 # assert alert.write_to_string == """
356 # <div class="alert alert-danger">
357 # Danger!
358 # </div>
359 # """
360 # ~~~
361 class BSAlert
362 super BSComponent
363
364 # Class used to change the color of the alert.
365 #
366 # Can be one of `primary`, `success`, `info`, `warning` or `danger`.
367 var color: String
368
369 # Text to display in the alert.
370 var text: Writable
371
372 # Can the alert be dismissed by clicking the close button?
373 #
374 # See http://getbootstrap.com/components/#alerts-dismissible
375 #
376 # Default is `false`.
377 var is_dismissible = false
378
379 init do css_classes.add "alert alert-{color}"
380
381 redef fun rendering do
382 addn "<div{render_css_classes}>"
383 if is_dismissible then
384 add "<button type=\"button\" class=\"close\" data-dismiss=\"alert\""
385 add "aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span>"
386 addn "</button>"
387 end
388 addn text.write_to_string
389 addn "</div>"
390 end
391 end
392
393 # A Bootstrap panel component.
394 #
395 # See http://getbootstrap.com/components/#panels
396 #
397 # Example:
398 #
399 # ~~~
400 # var p = new BSPanel("default", "Panel content")
401 #
402 # assert p.write_to_string == """
403 # <div class="panel panel-default">
404 # <div class="panel-body">
405 # Panel content
406 # </div>
407 # </div>
408 # """
409 # ~~~
410 #
411 # Panel with heading:
412 #
413 # ~~~
414 # p = new BSPanel("danger", "Panel content")
415 # p.heading = "Panel heading"
416 #
417 # assert p.write_to_string == """
418 # <div class="panel panel-danger">
419 # <div class="panel-heading">
420 # Panel heading
421 # </div>
422 # <div class="panel-body">
423 # Panel content
424 # </div>
425 # </div>
426 # """
427 # ~~~
428 class BSPanel
429 super BSComponent
430
431 # Panel color.
432 #
433 # Can be one of `default`, `primary`, `success`, `info`, `warning` or `danger`.
434 var color: String
435
436 # Panel header if any.
437 var heading: nullable Writable is noinit, writable
438
439 # Body to display in the panel.
440 var body: Writable
441
442 # Panel footer is any.
443 var footer: nullable Writable is noinit, writable
444
445 init do css_classes.add "panel panel-{color}"
446
447 redef fun rendering do
448 addn "<div{render_css_classes}>"
449 if heading != null then
450 addn "<div class=\"panel-heading\">"
451 addn heading.write_to_string
452 addn "</div>"
453 end
454 addn "<div class=\"panel-body\">"
455 addn body.write_to_string
456 addn "</div>"
457 if footer != null then
458 addn "<div class=\"panel-footer\">"
459 addn footer.write_to_string
460 addn "</div>"
461 end
462 addn "</div>"
463 end
464 end