1. The first step is to download both Twitter Bootstrap and jQuery. I installed versions 3.1.1 and 1.11.0 respectively. The download links are:
- Bootstrap: http://getbootstrap.com/getting-started/#download
- jQuery: http://jquery.com/download/
2. Extract the artifacts from the zip files and copy them to the "resources" directory under "webapp". Also, delete the old css file, style.css. Your directory structure should look like the image below, with the directories "css", "fonts", and "js" populated.
4. The reworked home.html page is show below.
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 | <!DOCTYPE html> < html xmlns = "http://www.w3.org/1999/xhtml" xmlns:th = "http://www.thymeleaf.org" > < head data-th-fragment = "header" > < meta charset = "utf-8" /> < meta http-equiv = "X-UA-Compatible" content = "IE=edge" /> < meta name = "viewport" content = "width=device-width, initial-scale=1" /> < title data-th-text = "#{strategy.list.page.title}" >Title</ title > <!-- Bootstrap --> < link type = "text/css" rel = "stylesheet" href = "../../resources/css/bootstrap-3.1.1.min.css" th:href = "@{/resources/css/bootstrap-3.1.1.min.css}" /> < title th:text = "#{user.page.title}" >Title</ title > <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries --> <!-- WARNING: Respond.js doesn't work if you view the page via file:// --> <!--[if lt IE 9]> <script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script> <script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script> <![endif]--> </ head > < body > < h1 data-th-text = "#{home.page.title}" >Title</ h1 > < p > < a href = "strategy/list.html" >Strategy list</ a > </ p > <!-- jQuery (necessary for Bootstrap's JavaScript plugins) --> < script type = "text/css" src = "../../resources/js/jquery-1.11.0.min.js" th:href = "@{/resources/js/jquery-1.11.0.min.js}" ></ script > <!-- Include all compiled plugins (below), or include individual files as needed --> < script type = "text/css" src = "../../resources/js/bootstrap-3.3.3.min.js" th:href = "@{/resources/js/bootstrap-3.3.3.min.js}" ></ script > </ body > </ html > |
5. The reworked strategy-list.html page is show below.
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 | <!DOCTYPE html> < html xmlns = "http://www.w3.org/1999/xhtml" xmlns:th = "http://www.thymeleaf.org" > < head data-th-fragment = "header" > < meta charset = "utf-8" /> < meta http-equiv = "X-UA-Compatible" content = "IE=edge" /> < meta name = "viewport" content = "width=device-width, initial-scale=1" /> < title data-th-text = "#{strategy.list.page.title}" >Title</ title > <!-- Bootstrap --> < link type = "text/css" rel = "stylesheet" href = "../../resources/css/bootstrap-3.1.1.min.css" th:href = "@{/resources/css/bootstrap-3.1.1.min.css}" /> < style > .no-border-on-me>thead>tr>th, .no-border-on-me>tbody>tr>th, .no-border-on-me>tfoot>tr>th, .no-border-on-me>thead>tr>td, .no-border-on-me>tbody>tr>td, .no-border-on-me>tfoot>tr>td { border-top-style: none; border-bottom-style: none; } </ style > <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries --> <!-- WARNING: Respond.js doesn't work if you view the page via file:// --> <!--[if lt IE 9]> <script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script> <script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script> <![endif]--> </ head > < body > < div class = "container-fluid" > < div class = "row" > < div class = "main" > < h3 data-th-text = "#{strategy.list.table.title}" >Configured Strategies</ h3 > < div class = "table responsive" > < table class = "table table-striped table-bordered table-hover" > < thead > < tr > < th class = "col-sm-1" data-th-text = "#{strategy.list.id.label}" >Id</ th > < th class = "col-sm-4" data-th-text = "#{strategy.list.type.label}" >Strategy Type</ th > < th class = "col-sm-4" data-th-text = "#{strategy.list.name.label}" >Strategy Name</ th > < th class = "col-sm-2" data-th-text = "#{strategy.list.actions.label}" >Action</ th > </ tr > </ thead > < tbody > < tr data-th-each = "strategy : ${strategies}" > < td data-th-text = "${strategy.id}" >1</ td > < td data-th-text = "${strategy.type}" >Iron Butterfly</ td > < td data-th-text = "${strategy.name}" >Triple Butter</ td > < td style = "text-align: center;" > < a href = "#" data-th-href = "@{/strategy/edit(id=${strategy.id})}" > < button type = "button" class = "btn btn-default btn-xs" > < span class = "glyphicon glyphicon-pencil" ></ span > Edit </ button ></ a > < a href = "#" data-th-href = "@{/strategy/delete(id=${strategy.id},phase=stage)}" > < button type = "button" class = "btn btn-default btn-xs" > < span class = "glyphicon glyphicon-trash" ></ span > Delete </ button ></ a > </ td > </ tr > < tr data-th-remove = "all" > < td >2</ td > < td >Iron Condor</ td > < td >High Prob Hedged</ td > < td style = "text-align: center;" > < a href = "#" > < button type = "button" class = "btn btn-default btn-xs" > < span class = "glyphicon glyphicon-pencil" ></ span > Edit </ button ></ a > < a href = "#" > < button type = "button" class = "btn btn-default btn-xs" > < span class = "glyphicon glyphicon-trash" ></ span > Delete </ button ></ a > </ td > </ tr > </ tbody > </ table > </ div > < form class = "form" action = "#" data-th-action = "@{/strategy/add}" data-th-object = "${strategyDTO}" method = "post" > < div class = "table responsive" > < table class = "no-border-on-me table " > < thead > < tr > < th class = "col-sm-1" ></ th > < th class = "col-sm-4" data-th-text = "#{strategy.list.type.label}" >Strategy Type</ th > < th class = "col-sm-4" data-th-text = "#{strategy.list.name.label}" >Strategy Name</ th > < th class = "col-sm-2" data-th-text = "#{strategy.list.actions.label}" >Action</ th > </ tr > </ thead > < tbody > < tr > < td >< input type = "text" hidden = "hidden" data-th-field = "*{id}" ></ input ></ td > < td >< input class = "form-control" type = "text" data-th-field = "*{type}" placeholder = "Type" ></ input ></ td > < td >< input class = "form-control" type = "text" data-th-field = "*{name}" placeholder = "Name" ></ input ></ td > < td > < button type = "submit" class = "btn btn-primary" data-th-text = "#{add.strategy.button.label}" >Add Strategy</ button > </ td > </ tr > </ tbody > </ table > </ div > </ form > </ div > <!-- END MAIN TAG --> </ div > <!-- END ROW TAG --> </ div > <!-- END CONTAINER TAG --> <!-- jQuery (necessary for Bootstrap's JavaScript plugins) --> < script type = "text/css" src = "../../resources/js/jquery-1.11.0.min.js" th:href = "@{/resources/js/jquery-1.11.0.min.js}" ></ script > <!-- Include all compiled plugins (below), or include individual files as needed --> < script type = "text/css" src = "../../resources/js/bootstrap-3.3.3.min.js" th:href = "@{/resources/js/bootstrap-3.3.3.min.js}" ></ script > </ body > </ html > |
In the tables you will notice the addition of glyphicons, to make button functionality more clear. You will also see the inclusion of div tags and liberal references to class attributes on many of the tags. These two items are responsible for the sizing and appearance of the page. In order to better understand how much space a given div occupied, I would add the following attribute inside the div tag in question: style="background:#888888;"
6. The reworked strategy-edit.html page is show below.
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 | <!DOCTYPE html> < html xmlns = "http://www.w3.org/1999/xhtml" xmlns:th = "http://www.thymeleaf.org" > < head data-th-fragment = "header" > < meta charset = "utf-8" /> < meta http-equiv = "X-UA-Compatible" content = "IE=edge" /> < meta name = "viewport" content = "width=device-width, initial-scale=1" /> < title data-th-text = "#{strategy.list.page.title}" >Title</ title > <!-- Bootstrap --> < link type = "text/css" rel = "stylesheet" href = "../../resources/css/bootstrap-3.1.1.min.css" th:href = "@{/resources/css/bootstrap-3.1.1.min.css}" /> < style > .no-border-on-me>thead>tr>th, .no-border-on-me>tbody>tr>th, .no-border-on-me>tfoot>tr>th, .no-border-on-me>thead>tr>td, .no-border-on-me>tbody>tr>td, .no-border-on-me>tfoot>tr>td { border-top-style: none; border-bottom-style: none; } </ style > <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries --> <!-- WARNING: Respond.js doesn't work if you view the page via file:// --> <!--[if lt IE 9]> <script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script> <script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script> <![endif]--> </ head > < body > < div class = "container-fluid" > < div class = "row" > < div class = "main" > < div class = "col-sm-3" ></ div > < div class = "col-sm-6" > < h3 data-th-text = "#{strategy.edit.head.title}" >Edit Strategy</ h3 > < form class = "form-horizontal" action = "#" data-th-action = "@{/strategy/edit}" data-th-object = "${strategyDTO}" method = "post" > < div class = "form-group" > < label class = "col-sm-4 control-label" data-th-text = "#{strategy.list.type.label}" >Strategy Type</ label > < div class = "col-sm-8" > < input type = "text" hidden = "hidden" data-th-value = "*{id}" data-th-field = "*{id}" ></ input > < input type = "text" class = "form-control" data-th-value = "*{type}" data-th-field = "*{type}" ></ input > </ div > </ div > < div class = "form-group" > < label class = "col-sm-4 control-label" data-th-text = "#{strategy.list.name.label}" >Strategy Name</ label > < div class = "col-sm-8" > < input type = "text" class = "form-control" data-th-value = "*{name}" data-th-field = "*{name}" ></ input > </ div > </ div > < div class = "form-group" > < div class = "col-sm-offset-4 col-sm-8" > < button type = "submit" class = "btn btn-primary" name = "action" value = "save" data-th-text = "#{update.button.label}" >Save</ button > < button type = "submit" class = "btn btn-default active" name = "action" value = "cancel" data-th-text = "#{cancel.button.label}" >Cancel</ button > </ div > </ div > </ form > </ div > < div class = "col-sm-3" ></ div > </ div > <!-- END MAIN TAG --> </ div > <!-- END ROW TAG --> </ div > <!-- END CONTAINER TAG --> <!-- jQuery (necessary for Bootstrap's JavaScript plugins) --> < script type = "text/css" src = "../../resources/js/jquery-1.11.0.min.js" th:href = "@{/resources/js/jquery-1.11.0.min.js}" ></ script > <!-- Include all compiled plugins (below), or include individual files as needed --> < script type = "text/css" src = "../../resources/js/bootstrap-3.3.3.min.js" th:href = "@{/resources/js/bootstrap-3.3.3.min.js}" ></ script > </ body > </ html > |
div class = container
div class = row
div class = main
... content here
div
div
div
The page above is no exception. Also notice the button class attribute values and the class attribute value of "form-group" in the page. The latter does exactly what it sounds like, grouping functionality within a form.
7. The reworked strategy-delete.html page is show below.
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 | <!DOCTYPE html> < html xmlns = "http://www.w3.org/1999/xhtml" xmlns:th = "http://www.thymeleaf.org" > < head data-th-fragment = "header" > < meta charset = "utf-8" /> < meta http-equiv = "X-UA-Compatible" content = "IE=edge" /> < meta name = "viewport" content = "width=device-width, initial-scale=1" /> < title data-th-text = "#{strategy.list.page.title}" >Title</ title > <!-- Bootstrap --> < link type = "text/css" rel = "stylesheet" href = "../../resources/css/bootstrap-3.1.1.min.css" th:href = "@{/resources/css/bootstrap-3.1.1.min.css}" /> < style > .no-border-on-me>thead>tr>th, .no-border-on-me>tbody>tr>th, .no-border-on-me>tfoot>tr>th, .no-border-on-me>thead>tr>td, .no-border-on-me>tbody>tr>td, .no-border-on-me>tfoot>tr>td { border-top-style: none; border-bottom-style: none; } </ style > <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries --> <!-- WARNING: Respond.js doesn't work if you view the page via file:// --> <!--[if lt IE 9]> <script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script> <script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script> <![endif]--> </ head > < body > < div class = "container-fluid" > < div class = "row" > < div class = "main" > < div class = "col-sm-3" ></ div > < div class = "col-sm-6" > < h3 data-th-text = "#{strategy.delete.head.title}" >Delete Strategy</ h3 > < form class = "form-horizontal" action = "#" method = "get" > < div class = "form-group" > < label class = "col-sm-4 control-label" data-th-text = "#{strategy.list.id.label}" >Strategy Id</ label > < div class = "col-sm-8" > < input type = "text" class = "form-control" data-th-field = "${strategyDTO.id}" disabled = "disabled" ></ input > </ div > </ div > < div class = "form-group" > < label class = "col-sm-4 control-label" data-th-text = "#{strategy.list.type.label}" >Strategy Type</ label > < div class = "col-sm-8" > < input type = "text" class = "form-control" data-th-field = "${strategyDTO.type}" disabled = "disabled" ></ input > </ div > </ div > < div class = "form-group" > < label class = "col-sm-4 control-label" data-th-text = "#{strategy.list.name.label}" >Strategy Name</ label > < div class = "col-sm-8" > < input type = "text" class = "form-control" data-th-field = "${strategyDTO.name}" disabled = "disabled" ></ input > </ div > </ div > </ form > < div class = "form-horizontal" > < div class = "form-group" > < label class = "col-sm-4 control-label" ></ label > < div class = "col-sm-8" > < a href = "#" data-th-href = "@{/strategy/delete(id=${strategyDTO.id},phase=confirm)}" > < button type = "button" class = "btn btn-primary" data-th-text = "#{delete.button.label}" >Delete</ button ></ a > < a href = "#" data-th-href = "@{/strategy/delete(id=${strategyDTO.id},phase=cancel)}" > < button type = "button" class = "btn btn-default active" data-th-text = "#{cancel.button.label}" >Cancel</ button ></ a > </ div > </ div > </ div > </ div > < div class = "col-sm-3" ></ div > </ div > <!-- END MAIN TAG --> </ div > <!-- END ROW TAG --> </ div > <!-- END CONTAINER TAG --> <!-- jQuery (necessary for Bootstrap's JavaScript plugins) --> < script type = "text/css" src = "../../resources/js/jquery-1.11.0.min.js" th:href = "@{/resources/js/jquery-1.11.0.min.js}" ></ script > <!-- Include all compiled plugins (below), or include individual files as needed --> < script type = "text/css" src = "../../resources/js/bootstrap-3.3.3.min.js" th:href = "@{/resources/js/bootstrap-3.3.3.min.js}" ></ script > </ body > </ html > |
The other item to note is how a button was used with the "a href=..." tag/attribute. In order to maintain a consistent look-and-feel, the following button class attributes were used:
- class="btn btn-primary"
- class="btn btn-default active"
8. Now, let's take a look at our new pages, starting with the new home.html page.
9. Here is our new strategy-list.html page.
10. And our strategy-edit.html page.
11. And finally our strategy-delete.html page.
In future posts we will look at input validation, modal dialogues, navigation/themes/Thymeleaf templates, integrating Spring Security, JPA/connection pooling, and unit testing. I changed this list slightly after working on this exercise. After these steps are complete, we should be ready to start building out the trading system core.
Code at GitHub: https://github.com/dtr-trading/spring-ex05
1 comment:
Hi:
Nice tutorial!
Can you show your servlet-context file??
I have this:
and a folder called css as you show in your tutorial but styles are not applied on my html file :(
Thanks!
Post a Comment