Trapped-Frontend.st 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. Smalltalk current createPackage: 'Trapped-Frontend' properties: #{}!
  2. Widget subclass: #TrappedDumbView
  3. instanceVariableNames: ''
  4. package: 'Trapped-Frontend'!
  5. !TrappedDumbView commentStamp!
  6. I just read and show an actual path.!
  7. !TrappedDumbView methodsFor: 'rendering'!
  8. renderOn: html
  9. html root trapShow: #()
  10. ! !
  11. Object subclass: #TrappedModelWrapper
  12. instanceVariableNames: 'dispatcher payload'
  13. package: 'Trapped-Frontend'!
  14. !TrappedModelWrapper commentStamp!
  15. I am base class for model wrappers.
  16. I wrap a model which can be any object.
  17. My subclasses need to provide implementation for:
  18. read:do:
  19. modify:do:
  20. (optionally) name
  21. and must initialize:
  22. payload
  23. dispatcher!
  24. !TrappedModelWrapper methodsFor: 'accessing'!
  25. dispatcher
  26. ^dispatcher
  27. !
  28. dispatcher: aDispatcher
  29. dispatcher := aDispatcher
  30. !
  31. name
  32. ^ self class name
  33. !
  34. payload
  35. ^payload
  36. !
  37. payload: anObject
  38. payload := anObject.
  39. self dispatcher changed: #()
  40. ! !
  41. !TrappedModelWrapper methodsFor: 'action'!
  42. start
  43. Trapped current register: self name: self name
  44. !
  45. watch: path do: aBlock
  46. self dispatcher add: { true. path. [ self read: path do: aBlock ] }.
  47. self dispatcher dirty: true
  48. ! !
  49. !TrappedModelWrapper class methodsFor: 'action'!
  50. start
  51. ^self new start; yourself
  52. ! !
  53. Object subclass: #TrappedSingleton
  54. instanceVariableNames: ''
  55. package: 'Trapped-Frontend'!
  56. !TrappedSingleton methodsFor: 'action'!
  57. start
  58. ^ self subclassResponsibility
  59. ! !
  60. TrappedSingleton class instanceVariableNames: 'current'!
  61. !TrappedSingleton class methodsFor: 'accessing'!
  62. current
  63. ^ current ifNil: [ current := self new ]
  64. ! !
  65. !TrappedSingleton class methodsFor: 'action'!
  66. start
  67. self current start
  68. ! !
  69. TrappedSingleton subclass: #Trapped
  70. instanceVariableNames: 'registry'
  71. package: 'Trapped-Frontend'!
  72. !Trapped methodsFor: 'accessing'!
  73. byName: aString
  74. ^ registry at: aString
  75. !
  76. register: aFly name: aString
  77. registry at: aString put: aFly
  78. ! !
  79. !Trapped methodsFor: 'action'!
  80. start
  81. '[data-trap]' asJQuery each: [ :index :elem |
  82. | trap jq viewName modelName tokens path |
  83. jq := elem asJQuery.
  84. trap := jq attr: 'data-trap'.
  85. tokens := trap tokenize: ':'.
  86. tokens size = 1 ifTrue: [ tokens := { 'TrappedDumbView' }, tokens ].
  87. viewName := tokens first.
  88. tokens := (tokens second tokenize: ' ') select: [ :each | each notEmpty ].
  89. modelName := tokens first.
  90. path := Trapped parse: tokens allButFirst.
  91. { modelName }, path trapDescend: [(Smalltalk current at: viewName) new appendToJQuery: jq].
  92. ]
  93. ! !
  94. !Trapped methodsFor: 'initialization'!
  95. initialize
  96. super initialize.
  97. registry := #{}.
  98. ! !
  99. !Trapped class methodsFor: 'accessing'!
  100. parse: anArray
  101. ^anArray collect: [ :each |
  102. | asNum |
  103. <asNum = parseInt(each)>.
  104. asNum = asNum ifTrue: [ asNum ] ifFalse: [
  105. each first = '#' ifTrue: [ each allButFirst asSymbol ] ifFalse: [ each ]]]
  106. !
  107. path
  108. ^TrappedPathStack current elements
  109. ! !
  110. TrappedSingleton subclass: #TrappedPathStack
  111. instanceVariableNames: 'elements'
  112. package: 'Trapped-Frontend'!
  113. !TrappedPathStack methodsFor: 'accessing'!
  114. elements
  115. ^elements
  116. ! !
  117. !TrappedPathStack methodsFor: 'descending'!
  118. append: anArray
  119. elements := elements, anArray
  120. !
  121. with: anArray do: aBlock
  122. | old |
  123. old := elements.
  124. [ self append: anArray.
  125. aBlock value ] ensure: [ elements := old ]
  126. ! !
  127. !TrappedPathStack methodsFor: 'initialization'!
  128. initialize
  129. super initialize.
  130. elements := #().
  131. ! !
  132. !Array methodsFor: '*Trapped-Frontend'!
  133. trapDescend: aBlock
  134. TrappedPathStack current with: self do: aBlock
  135. ! !
  136. !Array methodsFor: '*Trapped-Frontend'!
  137. trapDescend: aBlock
  138. TrappedPathStack current with: self do: aBlock
  139. ! !
  140. !TagBrush methodsFor: '*Trapped-Frontend'!
  141. trap: path read: aBlock
  142. path trapDescend: [ | actual model |
  143. actual := Trapped path.
  144. model := Trapped current byName: actual first.
  145. model watch: actual allButFirst do: [ :data |
  146. actual trapDescend: [ self with: [ :html | aBlock value: data value: html ] ]
  147. ]
  148. ]
  149. !
  150. trap: path toggle: aBlock
  151. self trap: path toggle: aBlock ifNotPresent: [ self asJQuery empty; hide ]
  152. !
  153. trap: path toggle: aBlock ifNotPresent: anotherBlock
  154. | shown |
  155. shown := nil.
  156. self trap: path read: [ :data : html |
  157. shown = data notNil ifFalse: [
  158. shown := data notNil.
  159. shown ifTrue: [ self asJQuery empty; show ].
  160. (shown ifTrue: [aBlock] ifFalse: [anotherBlock]) value: data value: html.
  161. ]
  162. ]
  163. !
  164. trapShow: path
  165. self trapShow: path default: []
  166. !
  167. trapShow: path default: anObject
  168. self trap: path read: [ :model :html | html root empty; with: (model ifNil: [anObject]) ]
  169. ! !