Merge: gamnit: new services and a lot of bug fixes and performance improvements
[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] is optional
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("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 autoinit(href, text, title, css_classes)
62
63 # URL pointed by this link.
64 var href: String is writable
65
66 # Displayed text.
67 var text: Writable is writable
68
69 # Optional title.
70 var title: nullable String = null is optional, writable
71
72 redef fun rendering do
73 add "<a{render_css_classes} href=\"{href}\""
74 var title = self.title
75 if title != null then add " title=\"{title.write_to_string}\""
76 add ">{text}</a>"
77 end
78 end
79
80 # A `<h1>` to `<h6>` tag.
81 #
82 # Not really a Bootstrap component but used in other components
83 # that it required its own abstraction.
84 #
85 # Example:
86 # ~~~
87 # var h1 = new Header(1, "Title")
88 # assert h1.write_to_string == "<h1>Title</h1>"
89 # ~~~
90 #
91 # With subtext:
92 # ~~~
93 # var h6 = new Header(6, "Title", "with subtext")
94 # assert h6.write_to_string == "<h6>Title<small>with subtext</small></h6>"
95 # ~~~
96 class Header
97 super BSComponent
98 autoinit(level, text, subtext, id, css_classes)
99
100 # Header level between 1 and 6.
101 var level: Int
102
103 # Displayed text.
104 var text: Writable
105
106 # Optional subtext.
107 var subtext: nullable Writable = null is optional, writable
108
109 # Optional id.
110 var id: nullable String = null is optional, writable
111
112 redef fun rendering do
113 add "<h{level}{render_css_classes}>{text.write_to_string}"
114 var subtext = self.subtext
115 if subtext != null then add "<small>{subtext.write_to_string}</small>"
116 add "</h{level}>"
117 end
118 end
119
120 # An abstract HTML list.
121 #
122 # Many Bootstrap components are built around a HTML list.
123 #
124 # Used to factorize behavior between OrderedList and UnorderedList.
125 abstract class HTMLList
126 super BSComponent
127 autoinit(items, css_classes)
128
129 # A list contains `<li>` tags as children.
130 #
131 # See ListItem.
132 var items = new Array[ListItem] is optional
133
134 # Adds a new ListItem to `self`.
135 fun add_li(item: ListItem) do items.add item
136
137 # Does `self` contains no items?
138 fun is_empty: Bool do return items.is_empty
139 end
140
141 # A `<ol>` list tag.
142 #
143 # Example:
144 #
145 # ~~~
146 # var lst = new OrderedList
147 # lst.add_li(new ListItem("foo"))
148 # lst.add_li(new ListItem("bar"))
149 # lst.add_li(new ListItem("baz"))
150 #
151 # assert lst.write_to_string == """
152 # <ol>
153 # <li>foo</li>
154 # <li>bar</li>
155 # <li>baz</li>
156 # </ol>
157 # """
158 # ~~~
159 class OrderedList
160 super HTMLList
161
162 redef fun rendering do
163 addn "<ol{render_css_classes}>"
164 for item in items do add item
165 addn "</ol>"
166 end
167 end
168
169 # A `<ul>` list tag.
170 #
171 # Example:
172 #
173 # ~~~
174 # var lst = new UnorderedList
175 # lst.add_li(new ListItem("foo"))
176 # lst.add_li(new ListItem("bar"))
177 # lst.add_li(new ListItem("baz"))
178 #
179 # assert lst.write_to_string == """
180 # <ul>
181 # <li>foo</li>
182 # <li>bar</li>
183 # <li>baz</li>
184 # </ul>
185 # """
186 # ~~~
187 class UnorderedList
188 super HTMLList
189
190 redef fun rendering do
191 addn "<ul{render_css_classes}>"
192 for item in items do add item
193 addn "</ul>"
194 end
195 end
196
197 # A `<li>` tag.
198 class ListItem
199 super BSComponent
200 autoinit(text, css_classes)
201
202 # Content to display in this list item.
203 var text: Writable is writable
204
205 redef fun rendering do addn "<li{render_css_classes}>{text.write_to_string}</li>"
206 end
207
208 # A Boostrap icon.
209 #
210 # See http://getbootstrap.com/components/#glyphicons
211 #
212 # Example:
213 #
214 # ~~~
215 # var icon = new BSIcon("star")
216 # assert icon.write_to_string == "<span class=\"glyphicon glyphicon-star\" aria-hidden=\"true\"></span>"
217 # ~~~
218 class BSIcon
219 super BSComponent
220 autoinit(icon, css_classes)
221
222 # Glyphicon name to display.
223 #
224 # See full list at http://getbootstrap.com/components/#glyphicons.
225 var icon: String
226
227 init do css_classes.add "glyphicon glyphicon-{icon}"
228
229 redef fun rendering do
230 add "<span{render_css_classes} aria-hidden=\"true\"></span>"
231 end
232 end
233
234 # A Bootstrap breadcrumbs component.
235 #
236 # See http://getbootstrap.com/components/#breadcrumbs
237 #
238 # Example:
239 #
240 # ~~~
241 # var bc = new BSBreadCrumbs
242 # bc.add_li(new ListItem("foo"))
243 # bc.add_li(new ListItem("bar"))
244 # bc.add_li(new ListItem("baz"))
245 #
246 # assert bc.write_to_string == """
247 # <ol class=\"breadcrumbs\">
248 # <li>foo</li>
249 # <li>bar</li>
250 # <li class=\"active\">baz</li>
251 # </ol>
252 # """
253 # ~~~
254 class BSBreadCrumbs
255 super OrderedList
256
257 init do css_classes.add "breadcrumbs"
258
259 redef fun rendering do
260 items.last.css_classes.add "active"
261 super
262 end
263 end
264
265 # A Bootstrap label component.
266 #
267 # See http://getbootstrap.com/components/#labels
268 #
269 # Example:
270 #
271 # ~~~
272 # var lbl = new BSLabel("danger", "Danger!")
273 # assert lbl.write_to_string == "<span class=\"label label-danger\">Danger!</span>"
274 # ~~~
275 class BSLabel
276 super BSComponent
277 autoinit(color, text, css_classes)
278
279 # Class used to change the color of the label.
280 #
281 # Can be one of `default`, `primary`, `success`, `info`, `warning` or `danger`.
282 var color: String
283
284 # Text to display in the label.
285 var text: Writable
286
287 init do css_classes.add "label label-{color}"
288
289 redef fun rendering do
290 add "<span{render_css_classes}>{text.write_to_string}</span>"
291 end
292 end
293
294 # A Bootstrap badge component.
295 #
296 # See http://getbootstrap.com/components/#badges
297 #
298 # Example:
299 #
300 # ~~~
301 # var b = new BSBadge("42 messages")
302 # assert b.write_to_string == "<span class=\"badge\">42 messages</span>"
303 # ~~~
304 class BSBadge
305 super BSComponent
306 autoinit(text, css_classes)
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 autoinit(text, css_classes)
335
336 # Text to display as title.
337 var text: Writable
338
339 init do css_classes.add "page-header"
340
341 redef fun rendering do
342 addn "<div{render_css_classes}>"
343 addn text.write_to_string
344 addn "</div>"
345 end
346 end
347
348 # A Bootstrap alert component.
349 #
350 # See http://getbootstrap.com/components/#alerts
351 #
352 # Example:
353 #
354 # ~~~
355 # var alert = new BSAlert("danger", "Danger!")
356 # assert alert.write_to_string == """
357 # <div class="alert alert-danger">
358 # Danger!
359 # </div>
360 # """
361 # ~~~
362 class BSAlert
363 super BSComponent
364 autoinit(color, text, is_dismissible, css_classes)
365
366 # Class used to change the color of the alert.
367 #
368 # Can be one of `primary`, `success`, `info`, `warning` or `danger`.
369 var color: String
370
371 # Text to display in the alert.
372 var text: Writable
373
374 # Can the alert be dismissed by clicking the close button?
375 #
376 # See http://getbootstrap.com/components/#alerts-dismissible
377 #
378 # Default is `false`.
379 var is_dismissible = false is optional, writable
380
381 init do css_classes.add "alert alert-{color}"
382
383 redef fun rendering do
384 addn "<div{render_css_classes}>"
385 if is_dismissible then
386 add "<button type=\"button\" class=\"close\" data-dismiss=\"alert\""
387 add "aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span>"
388 addn "</button>"
389 end
390 addn text.write_to_string
391 addn "</div>"
392 end
393 end
394
395 # A Bootstrap panel component.
396 #
397 # See http://getbootstrap.com/components/#panels
398 #
399 # Example:
400 #
401 # ~~~
402 # var p = new BSPanel("default", body = "Panel content")
403 #
404 # assert p.write_to_string == """
405 # <div class="panel panel-default">
406 # <div class="panel-body">
407 # Panel content
408 # </div>
409 # </div>
410 # """
411 # ~~~
412 #
413 # Panel with heading:
414 #
415 # ~~~
416 # p = new BSPanel("danger", heading = "Panel heading", body = "Panel content")
417 #
418 # assert p.write_to_string == """
419 # <div class="panel panel-danger">
420 # <div class="panel-heading">
421 # Panel heading
422 # </div>
423 # <div class="panel-body">
424 # Panel content
425 # </div>
426 # </div>
427 # """
428 # ~~~
429 class BSPanel
430 super BSComponent
431 autoinit(color, heading, body, footer, css_classes)
432
433 # Panel color.
434 #
435 # Can be one of `default`, `primary`, `success`, `info`, `warning` or `danger`.
436 var color: String is writable
437
438 # Panel header if any.
439 var heading: nullable Writable = null is optional, writable
440
441 # Body to display in the panel.
442 var body: nullable Writable = null is optional, writable
443
444 # Panel footer is any.
445 var footer: nullable Writable = null is optional, writable
446
447 init do css_classes.add "panel panel-{color}"
448
449 redef fun rendering do
450 addn "<div{render_css_classes}>"
451 var heading = self.heading
452 if heading != null then
453 addn "<div class=\"panel-heading\">"
454 addn heading.write_to_string
455 addn "</div>"
456 end
457 var body = self.body
458 if body != null then
459 addn "<div class=\"panel-body\">"
460 addn body.write_to_string
461 addn "</div>"
462 end
463 var footer = self.footer
464 if footer != null then
465 addn "<div class=\"panel-footer\">"
466 addn footer.write_to_string
467 addn "</div>"
468 end
469 addn "</div>"
470 end
471 end