Trapped-Frontend.st 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  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 on: path hook: [ self read: path do: aBlock ]
  47. ! !
  48. !TrappedModelWrapper class methodsFor: 'action'!
  49. start
  50. ^self new start; yourself
  51. ! !
  52. Object subclass: #TrappedSingleton
  53. instanceVariableNames: ''
  54. package: 'Trapped-Frontend'!
  55. !TrappedSingleton methodsFor: 'action'!
  56. start
  57. ^ self subclassResponsibility
  58. ! !
  59. TrappedSingleton class instanceVariableNames: 'current'!
  60. !TrappedSingleton class methodsFor: 'accessing'!
  61. current
  62. ^ current ifNil: [ current := self new ]
  63. ! !
  64. !TrappedSingleton class methodsFor: 'action'!
  65. start
  66. self current start
  67. ! !
  68. TrappedSingleton subclass: #Trapped
  69. instanceVariableNames: 'registry'
  70. package: 'Trapped-Frontend'!
  71. !Trapped methodsFor: 'accessing'!
  72. byName: aString
  73. ^ registry at: aString
  74. !
  75. register: aFly name: aString
  76. registry at: aString put: aFly
  77. ! !
  78. !Trapped methodsFor: 'action'!
  79. start
  80. '[data-trap]' asJQuery each: [ :index :elem |
  81. | trap jq viewName modelName tokens path |
  82. jq := elem asJQuery.
  83. trap := jq attr: 'data-trap'.
  84. tokens := trap tokenize: ':'.
  85. tokens size = 1 ifTrue: [ tokens := { 'TrappedDumbView' }, tokens ].
  86. viewName := tokens first.
  87. tokens := (tokens second tokenize: ' ') select: [ :each | each notEmpty ].
  88. modelName := tokens first.
  89. path := Trapped parse: tokens allButFirst.
  90. { modelName }, path trapDescend: [(Smalltalk current at: viewName) new appendToJQuery: jq].
  91. ]
  92. ! !
  93. !Trapped methodsFor: 'initialization'!
  94. initialize
  95. super initialize.
  96. registry := #{}.
  97. ! !
  98. !Trapped class methodsFor: 'accessing'!
  99. parse: anArray
  100. ^anArray collect: [ :each |
  101. | asNum |
  102. <asNum = parseInt(each)>.
  103. asNum = asNum ifTrue: [ asNum ] ifFalse: [
  104. each first = '#' ifTrue: [ each allButFirst asSymbol ] ifFalse: [ each ]]]
  105. !
  106. path
  107. ^TrappedPathStack current elements
  108. ! !
  109. TrappedSingleton subclass: #TrappedPathStack
  110. instanceVariableNames: 'elements'
  111. package: 'Trapped-Frontend'!
  112. !TrappedPathStack methodsFor: 'accessing'!
  113. elements
  114. ^elements
  115. ! !
  116. !TrappedPathStack methodsFor: 'descending'!
  117. append: anArray
  118. elements := elements, anArray
  119. !
  120. with: anArray do: aBlock
  121. | old |
  122. old := elements.
  123. [ self append: anArray.
  124. aBlock value ] ensure: [ elements := old ]
  125. ! !
  126. !TrappedPathStack methodsFor: 'initialization'!
  127. initialize
  128. super initialize.
  129. elements := #().
  130. ! !
  131. !Array methodsFor: '*Trapped-Frontend'!
  132. trapDescend: aBlock
  133. TrappedPathStack current with: self do: aBlock
  134. ! !
  135. !Array methodsFor: '*Trapped-Frontend'!
  136. trapDescend: aBlock
  137. TrappedPathStack current with: self do: aBlock
  138. ! !
  139. !TagBrush methodsFor: '*Trapped-Frontend'!
  140. trap: path read: aBlock
  141. path trapDescend: [ | actual model |
  142. actual := Trapped path.
  143. model := Trapped current byName: actual first.
  144. model watch: actual allButFirst do: [ :data |
  145. (self asJQuery closest: 'html') toArray isEmpty ifTrue: [ TrappedUnwatch signal ].
  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 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. self asJQuery empty; show.
  160. (shown ifTrue: [aBlock] ifFalse: [anotherBlock]) value: data value: html.
  161. ]
  162. ]
  163. !
  164. trapIter: path tag: aSymbol do: aBlock
  165. self trap: path read: [ :model :html |
  166. html root empty.
  167. model ifNotNil: [ model withIndexDo: [ :item :i |
  168. (html perform: aSymbol) trap: {i} read: aBlock
  169. ]]
  170. ]
  171. !
  172. trapShow: path
  173. self trapShow: path default: []
  174. !
  175. trapShow: path default: anObject
  176. self trap: path read: [ :model | self empty; with: (model ifNil: [anObject]) ]
  177. ! !