Trapped-Processors.st 14 KB

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