Trapped-Processors.st 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559
  1. Smalltalk current createPackage: 'Trapped-Processors'!
  2. TrappedDataExpectingProcessor subclass: #TrappedProcessorAttribute
  3. instanceVariableNames: 'attrName'
  4. package: 'Trapped-Processors'!
  5. !TrappedProcessorAttribute commentStamp!
  6. I set the data into an attribute speciried when creating me.
  7. No observing and sending back, atm.!
  8. !TrappedProcessorAttribute methodsFor: 'accessing'!
  9. attrName: aString
  10. attrName := aString
  11. ! !
  12. !TrappedProcessorAttribute methodsFor: 'data transformation'!
  13. toView: aDataCarrier
  14. aDataCarrier toTargetAttr: attrName
  15. ! !
  16. !TrappedProcessorAttribute class methodsFor: 'instance creation'!
  17. new: aString
  18. ^self new
  19. attrName: aString;
  20. yourself
  21. ! !
  22. TrappedDataExpectingProcessor subclass: #TrappedProcessorDataAdhoc
  23. instanceVariableNames: 'toViewBlock'
  24. package: 'Trapped-Processors'!
  25. !TrappedProcessorDataAdhoc commentStamp!
  26. I put data into target via contents: in toView:!
  27. !TrappedProcessorDataAdhoc methodsFor: 'accessing'!
  28. toViewBlock: aBlock
  29. toViewBlock := aBlock
  30. ! !
  31. !TrappedProcessorDataAdhoc methodsFor: 'data transformation'!
  32. toView: aDataCarrier
  33. toViewBlock value: aDataCarrier
  34. ! !
  35. !TrappedProcessorDataAdhoc class methodsFor: 'instance creation'!
  36. newToView: aBlock
  37. ^self new
  38. toViewBlock: aBlock;
  39. yourself
  40. ! !
  41. TrappedProcessor subclass: #TrappedProcessorDescend
  42. instanceVariableNames: ''
  43. package: 'Trapped-Processors'!
  44. !TrappedProcessorDescend commentStamp!
  45. I intepret data-trap in descendants of my brush.!
  46. !TrappedProcessorDescend methodsFor: 'data transformation'!
  47. toView: aDataCarrier
  48. Trapped current injectToChildren: aDataCarrier target element
  49. ! !
  50. TrappedProcessor subclass: #TrappedProcessorGuardBase
  51. instanceVariableNames: 'guardPath'
  52. package: 'Trapped-Processors'!
  53. !TrappedProcessorGuardBase commentStamp!
  54. I serve as base class for brush-guarding processors.
  55. I cover instantiation and subclasses have to provide
  56. implementation of toVIew: that react appropriately to guard releasing.!
  57. !TrappedProcessorGuardBase methodsFor: 'accessing'!
  58. guardPath: anArray
  59. guardPath := anArray
  60. ! !
  61. !TrappedProcessorGuardBase methodsFor: 'data transformation'!
  62. toModel: aDataCarrier
  63. "stop"
  64. !
  65. toView: aDataCarrier
  66. self subclassResponsibility
  67. ! !
  68. !TrappedProcessorGuardBase class methodsFor: 'instance creation'!
  69. new: anArray
  70. ^ self new
  71. guardPath: anArray;
  72. yourself
  73. ! !
  74. TrappedProcessorGuardBase subclass: #TrappedProcessorGuardProc
  75. instanceVariableNames: ''
  76. package: 'Trapped-Processors'!
  77. !TrappedProcessorGuardProc commentStamp!
  78. I am used to guard contents filling process of the brush I am installed on.
  79. I observe guard expression in the model,
  80. and when it changes to nil or false, I delete the brush contents;
  81. on the other hand, when it changes to non-nil and non-false,
  82. I run the rest on the chain, which should be one-time
  83. that sets up the contents,!
  84. !TrappedProcessorGuardProc methodsFor: 'data transformation'!
  85. toView: aDataCarrier
  86. | frozen xon |
  87. frozen := aDataCarrier copy.
  88. xon := frozen xontent.
  89. frozen target trapGuard: guardPath contents: [ :html | frozen copy target: html root; xontent: xon; proceed ]
  90. ! !
  91. TrappedProcessorGuardBase subclass: #TrappedProcessorGuardXon
  92. instanceVariableNames: ''
  93. package: 'Trapped-Processors'!
  94. !TrappedProcessorGuardXon commentStamp!
  95. I am used to guard contents of the brush I am installed on.
  96. I save the brush contents, then I observe guard expression in the model,
  97. and when it changes to nil or false, I delete the brush contents;
  98. on the other hand, when it changes to non-nil and non-false,
  99. I restore it from remembered state and interpret all contained
  100. data-trap attributes inside.!
  101. !TrappedProcessorGuardXon methodsFor: 'data transformation'!
  102. toView: aDataCarrier
  103. | frozen xon |
  104. frozen := aDataCarrier copy.
  105. xon := frozen xontent.
  106. frozen target trapGuard: guardPath contents: [ :html |
  107. | worker |
  108. worker := frozen copy.
  109. worker target: html root.
  110. worker xontent: xon.
  111. worker target asJQuery append: (Trapped current cloneAndInject: (worker xontent get: 0)) ]
  112. ! !
  113. TrappedDataExpectingProcessor subclass: #TrappedProcessorInputChecked
  114. instanceVariableNames: ''
  115. package: 'Trapped-Processors'!
  116. !TrappedProcessorInputChecked commentStamp!
  117. I bind to checkbox checked state.!
  118. !TrappedProcessorInputChecked methodsFor: 'data transformation'!
  119. toView: aDataCarrier
  120. aDataCarrier toTargetProp: 'checked'
  121. ! !
  122. !TrappedProcessorInputChecked methodsFor: 'installation'!
  123. installToView: aDataCarrier toModel: anotherDataCarrier
  124. | brush |
  125. brush := aDataCarrier target.
  126. brush onChange: [ anotherDataCarrier copy value: (brush asJQuery prop: 'checked'); proceed ]
  127. ! !
  128. TrappedDataExpectingProcessor subclass: #TrappedProcessorInputValue
  129. instanceVariableNames: ''
  130. package: 'Trapped-Processors'!
  131. !TrappedProcessorInputValue commentStamp!
  132. I bind to input value.!
  133. !TrappedProcessorInputValue methodsFor: 'data transformation'!
  134. toView: aDataCarrier
  135. aDataCarrier toTargetValue
  136. ! !
  137. !TrappedProcessorInputValue methodsFor: 'installation'!
  138. installToView: aDataCarrier toModel: anotherDataCarrier
  139. | brush |
  140. brush := aDataCarrier target.
  141. brush onChange: [ anotherDataCarrier copy value: brush asJQuery val; proceed ]
  142. ! !
  143. TrappedProcessor subclass: #TrappedProcessorLoopBase
  144. instanceVariableNames: ''
  145. package: 'Trapped-Processors'!
  146. !TrappedProcessorLoopBase commentStamp!
  147. I serve as base class for looping processors.
  148. I cover instantiation and subclasses have to provide
  149. implementation of toVIew: that loops appropriately.!
  150. !TrappedProcessorLoopBase methodsFor: 'data transformation'!
  151. toModel: aDataCarrier
  152. "stop"
  153. !
  154. toView: aDataCarrier
  155. self subclassResponsibility
  156. ! !
  157. TrappedProcessorLoopBase subclass: #TrappedProcessorLoopProcZ
  158. instanceVariableNames: ''
  159. package: 'Trapped-Processors'!
  160. !TrappedProcessorLoopProcZ commentStamp!
  161. I am used to loop over data and repeat the contents filling process
  162. of the brush I am installed on.
  163. I observe the data in the model,
  164. and when it changes, I loop over it
  165. and run the rest of the processing chain
  166. for each element, putting the result _after_ my brush.
  167. My brush itself should be as least visible as possible,
  168. as it only serve as a position flag (use for example
  169. noscript, ins or del).!
  170. !TrappedProcessorLoopProcZ methodsFor: 'data transformation'!
  171. toView: aDataCarrier
  172. | frozen xon |
  173. frozen := aDataCarrier copy.
  174. xon := frozen xontent.
  175. frozen target trapIter: #() after: [ :html | frozen copy target: html root; xontent: xon; proceed ]
  176. ! !
  177. TrappedProcessorLoopBase subclass: #TrappedProcessorLoopXonZ
  178. instanceVariableNames: ''
  179. package: 'Trapped-Processors'!
  180. !TrappedProcessorLoopXonZ commentStamp!
  181. I am used to loop over data and repeat the contents
  182. of the brush I am installed on.
  183. I save the brush contents, then I observe the data in the model,
  184. and when it changes, I loop over it
  185. and restore the contents from remembered state
  186. and interpret all contained data-trap attributes inside
  187. for each element, putting the result _after_ my brush.
  188. My brush itself should be as least visible as possible,
  189. as it only serve as a position flag (use for example
  190. noscript, ins or del).!
  191. !TrappedProcessorLoopXonZ methodsFor: 'data transformation'!
  192. toView: aDataCarrier
  193. | frozen xon |
  194. frozen := aDataCarrier copy.
  195. xon := frozen xontent.
  196. frozen target trapIter: #() after: [ :html |
  197. | worker |
  198. worker := frozen copy.
  199. worker target: html root.
  200. worker xontent: xon.
  201. worker target asJQuery append: (Trapped current cloneAndInject: (worker xontent get: 0)) ]
  202. ! !
  203. TrappedProcessor subclass: #TrappedProcessorReplace
  204. instanceVariableNames: 'left right'
  205. package: 'Trapped-Processors'!
  206. !TrappedProcessorReplace commentStamp!
  207. I convert data to string representation and do a regex replace.
  208. I get two parameters, in toView:, first is replaced with second,
  209. and in toModel:, the second is replaced with first.
  210. I remove leading '^' and ending '$' from the string used as replacement,
  211. so it safe to replace ^to with ^To, for example.!
  212. !TrappedProcessorReplace methodsFor: 'accessing'!
  213. left: aString
  214. left := aString
  215. !
  216. right: aString
  217. right := aString
  218. ! !
  219. !TrappedProcessorReplace methodsFor: 'data transformation'!
  220. toModel: aDataCarrier
  221. | replacement old |
  222. replacement := (left replace: '^\^' with: '') replace: '\$$' with: ''.
  223. old := aDataCarrier value asString.
  224. aDataCarrier
  225. value: (old replace: right with: replacement) whenDifferentFrom: old;
  226. proceed
  227. !
  228. toView: aDataCarrier
  229. | replacement old |
  230. replacement := (right replace: '^\^' with: '') replace: '\$$' with: ''.
  231. old := aDataCarrier value asString.
  232. aDataCarrier
  233. value: (old replace: left with: replacement) whenDifferentFrom: old;
  234. proceed
  235. ! !
  236. !TrappedProcessorReplace class methodsFor: 'instance creation'!
  237. new: aString with: anotherString
  238. ^ self new
  239. left: aString asString;
  240. right: anotherString asString;
  241. yourself
  242. ! !
  243. TrappedProcessor subclass: #TrappedProcessorSignal
  244. instanceVariableNames: 'selector'
  245. package: 'Trapped-Processors'!
  246. !TrappedProcessorSignal commentStamp!
  247. Instead of writing data directly to model,
  248. I instead modify it by sending a message specified when instantiating me.!
  249. !TrappedProcessorSignal methodsFor: 'accessing'!
  250. selector: aString
  251. selector := aString
  252. ! !
  253. !TrappedProcessorSignal methodsFor: 'data transformation'!
  254. toModel: aDataCarrier
  255. aDataCarrier modifyTargetByPerforming: selector
  256. !
  257. toView: aDataCarrier
  258. "stop"
  259. ! !
  260. !TrappedProcessorSignal class methodsFor: 'instance creation'!
  261. new: aString
  262. ^self new
  263. selector: aString;
  264. yourself
  265. ! !
  266. TrappedDataExpectingProcessor subclass: #TrappedProcessorToBlackboard
  267. instanceVariableNames: ''
  268. package: 'Trapped-Processors'!
  269. !TrappedProcessorToBlackboard commentStamp!
  270. I save the data to blackboard in toModel:, to position specified by path.!
  271. !TrappedProcessorToBlackboard methodsFor: 'data transformation'!
  272. toModel: aDataCarrier
  273. aDataCarrier target modify: [ aDataCarrier value ]
  274. ! !
  275. TrappedProcessor subclass: #TrappedProcessorUriComponentDecode
  276. instanceVariableNames: ''
  277. package: 'Trapped-Processors'!
  278. !TrappedProcessorUriComponentDecode commentStamp!
  279. I uriComponentDecode in toView:
  280. and encode in toModel:!
  281. !TrappedProcessorUriComponentDecode methodsFor: 'data transformation'!
  282. toModel: aDataCarrier
  283. aDataCarrier
  284. value: aDataCarrier value uriComponentEncoded;
  285. proceed
  286. !
  287. toView: aDataCarrier
  288. aDataCarrier
  289. value: aDataCarrier value uriComponentDecoded;
  290. proceed
  291. ! !
  292. TrappedProcessor subclass: #TrappedProcessorUriComponentEncode
  293. instanceVariableNames: ''
  294. package: 'Trapped-Processors'!
  295. !TrappedProcessorUriComponentEncode commentStamp!
  296. I uriComponentEncode in toView:
  297. and decode in toModel:!
  298. !TrappedProcessorUriComponentEncode methodsFor: 'data transformation'!
  299. toModel: aDataCarrier
  300. aDataCarrier
  301. value: aDataCarrier value uriComponentDecoded;
  302. proceed
  303. !
  304. toView: aDataCarrier
  305. aDataCarrier
  306. value: aDataCarrier value uriComponentEncoded;
  307. proceed
  308. ! !
  309. TrappedProcessor subclass: #TrappedProcessorWhenClicked
  310. instanceVariableNames: ''
  311. package: 'Trapped-Processors'!
  312. !TrappedProcessorWhenClicked commentStamp!
  313. I bind to an element and send true to blackboard when clicked.!
  314. !TrappedProcessorWhenClicked methodsFor: 'installation'!
  315. installToView: aDataCarrier toModel: anotherDataCarrier
  316. aDataCarrier target onClick: [ anotherDataCarrier copy proceed. false ]
  317. ! !
  318. TrappedProcessor subclass: #TrappedProcessorWhenSubmitted
  319. instanceVariableNames: ''
  320. package: 'Trapped-Processors'!
  321. !TrappedProcessorWhenSubmitted commentStamp!
  322. I bind to a form and send true to blackboard when submitted.!
  323. !TrappedProcessorWhenSubmitted methodsFor: 'installation'!
  324. installToView: aDataCarrier toModel: anotherDataCarrier
  325. aDataCarrier target onSubmit: [ anotherDataCarrier copy proceed. false ]
  326. ! !
  327. TrappedProcessor subclass: #TrappedProcessorWidget
  328. instanceVariableNames: 'viewName'
  329. package: 'Trapped-Processors'!
  330. !TrappedProcessorWidget commentStamp!
  331. I insert a widget instance of the class specified when creating me.!
  332. !TrappedProcessorWidget methodsFor: 'accessing'!
  333. viewName: aString
  334. viewName := aString
  335. ! !
  336. !TrappedProcessorWidget methodsFor: 'data transformation'!
  337. toView: aDataCarrier
  338. aDataCarrier target with: (Smalltalk current at: viewName) new
  339. ! !
  340. !TrappedProcessorWidget class methodsFor: 'instance creation'!
  341. new: aString
  342. ^self new
  343. viewName: aString;
  344. yourself
  345. ! !
  346. !TrappedDataCarrier methodsFor: '*Trapped-Processors'!
  347. modifyTarget
  348. self target modify: [ self value ]
  349. !
  350. modifyTargetByPerforming: aString
  351. self target modify: [ :m | m perform: aString ]
  352. !
  353. primitive: anObject
  354. <return anObject === nil ? null : anObject.valueOf()>
  355. !
  356. toTargetAttr: aString
  357. self falseAsNilValue
  358. ifNil: [ self target removeAt: aString ]
  359. ifNotNil: [ :bvalue |
  360. | value |
  361. value := self primitive: bvalue.
  362. self target at: aString put: (value = true ifTrue: [ aString ] ifFalse: [ value ]) ]
  363. !
  364. toTargetContents
  365. self target contents: (self primitive: self value)
  366. !
  367. toTargetProp: aString
  368. self target element at: aString put: (self primitive: self value)
  369. !
  370. toTargetValue
  371. self target asJQuery val: (self primitive: self value)
  372. !
  373. xontent
  374. ^self target asJQuery xontent
  375. !
  376. xontent: anObject
  377. self target asJQuery xontent: 'set' data: anObject
  378. ! !
  379. !TrappedProcessor class methodsFor: '*Trapped-Processors'!
  380. attr: aString
  381. ^TrappedProcessorAttribute new: aString
  382. !
  383. dataToView: aBlock
  384. ^TrappedProcessorDataAdhoc newToView: aBlock
  385. !
  386. deuric
  387. ^TrappedProcessorUriComponentDecode new
  388. !
  389. guardProc: anArray
  390. ^TrappedProcessorGuardProc new: anArray
  391. !
  392. guardXon: anArray
  393. ^TrappedProcessorGuardXon new: anArray
  394. !
  395. inputChecked
  396. ^TrappedProcessorInputChecked new
  397. !
  398. inputValue
  399. ^TrappedProcessorInputValue new
  400. !
  401. loopProcZ
  402. ^TrappedProcessorLoopProcZ new
  403. !
  404. loopXonZ
  405. ^TrappedProcessorLoopXonZ new
  406. !
  407. path
  408. ^TrappedProcessorDescend new
  409. !
  410. replace: aString with: anotherString
  411. ^TrappedProcessorReplace new: aString with: anotherString
  412. !
  413. signal: aString
  414. ^TrappedProcessorSignal new: aString
  415. !
  416. toBlackboard
  417. ^TrappedProcessorToBlackboard new
  418. !
  419. uric
  420. ^TrappedProcessorUriComponentEncode new
  421. !
  422. whenClicked
  423. ^TrappedProcessorWhenClicked new
  424. !
  425. whenSubmitted
  426. ^TrappedProcessorWhenSubmitted new
  427. !
  428. widget: aString
  429. ^TrappedProcessorWidget new: aString
  430. ! !