footer.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. // +build js
  2. package views
  3. import (
  4. "fmt"
  5. "strings"
  6. "github.com/soroushjp/humble"
  7. "github.com/soroushjp/humble/view"
  8. "honnef.co/go/js/dom"
  9. )
  10. type Footer struct {
  11. humble.Identifier
  12. TodoViews *[]*Todo
  13. }
  14. func (f *Footer) RenderHTML() string {
  15. return fmt.Sprintf(`
  16. <span id="todo-count">
  17. <strong>%d</strong> items left
  18. </span>
  19. <ul id="filters">
  20. <li>
  21. <a href="#/">All</a>
  22. </li>
  23. <li>
  24. <a href="#/active">Active</a>
  25. </li>
  26. <li>
  27. <a href="#/completed">Completed</a>
  28. </li>
  29. </ul>
  30. <button id="clear-completed">Clear completed (%d)</button>`, f.countRemaining(), f.countCompleted())
  31. }
  32. func (f *Footer) OuterTag() string {
  33. return "div"
  34. }
  35. func (f *Footer) OnLoad() error {
  36. // Set some things in the DOM which may have changed
  37. // after an update.
  38. if err := f.setSelected(); err != nil {
  39. return err
  40. }
  41. if f.countCompleted() == 0 {
  42. f.hideClearCompleted()
  43. } else {
  44. f.showClearCompleted()
  45. }
  46. // Add listeners
  47. if err := view.AddListener(f, "button#clear-completed", "click", f.clearCompleted); err != nil {
  48. return err
  49. }
  50. return nil
  51. }
  52. func (f *Footer) countRemaining() int {
  53. count := 0
  54. if f.TodoViews == nil {
  55. return 0
  56. }
  57. for _, todoView := range *f.TodoViews {
  58. if !todoView.Model.IsCompleted {
  59. count++
  60. }
  61. }
  62. return count
  63. }
  64. func (f *Footer) countCompleted() int {
  65. count := 0
  66. if f.TodoViews == nil {
  67. return 0
  68. }
  69. for _, todoView := range *f.TodoViews {
  70. if todoView.Model.IsCompleted {
  71. count++
  72. }
  73. }
  74. return count
  75. }
  76. func (f *Footer) setSelected() error {
  77. hash := dom.GetWindow().Location().Hash
  78. links, err := view.QuerySelectorAll(f, "#filters li a")
  79. if err != nil {
  80. return err
  81. }
  82. for _, linkEl := range links {
  83. if linkEl.GetAttribute("href") == hash {
  84. linkEl.SetAttribute("class", linkEl.GetAttribute("class")+" selected")
  85. } else {
  86. oldClass := linkEl.GetAttribute("class")
  87. newClass := strings.Replace(oldClass, "selected", "", 1)
  88. linkEl.SetAttribute("class", newClass)
  89. }
  90. }
  91. return nil
  92. }
  93. func (f *Footer) clearCompleted(dom.Event) {
  94. f.hideClearCompleted()
  95. if f.TodoViews == nil {
  96. return
  97. }
  98. todosToRemove := []*Todo{}
  99. for _, todoView := range *(f.TodoViews) {
  100. if todoView.Model.IsCompleted {
  101. todosToRemove = append(todosToRemove, todoView)
  102. }
  103. }
  104. for _, todoView := range todosToRemove {
  105. todoView.remove()
  106. }
  107. }
  108. func (f *Footer) showClearCompleted() {
  109. clrCompletedEl, err := view.QuerySelector(f, "button#clear-completed")
  110. if err != nil {
  111. panic(err)
  112. }
  113. clrCompletedEl.SetAttribute("style", "display: block;")
  114. }
  115. func (f *Footer) hideClearCompleted() {
  116. clrCompletedEl, err := view.QuerySelector(f, "button#clear-completed")
  117. if err != nil {
  118. panic(err)
  119. }
  120. clrCompletedEl.SetAttribute("style", "display: none;")
  121. }