Smalltalk current createPackage: 'Trapped-Processors'!
TrappedDataExpectingProcessor subclass: #TrappedProcessorDataAdhoc
	instanceVariableNames: 'toViewBlock'
	package: 'Trapped-Processors'!
!TrappedProcessorDataAdhoc commentStamp!
I put data into target via contents: in toView:!

!TrappedProcessorDataAdhoc methodsFor: 'accessing'!

toViewBlock: aBlock
	toViewBlock := aBlock
! !

!TrappedProcessorDataAdhoc methodsFor: 'data transformation'!

toView: aDataCarrier
	toViewBlock value: aDataCarrier
! !

!TrappedProcessorDataAdhoc class methodsFor: 'instance creation'!

newToView: aBlock
	^self new
		toViewBlock: aBlock;
		yourself
! !

TrappedProcessor subclass: #TrappedProcessorDescend
	instanceVariableNames: ''
	package: 'Trapped-Processors'!
!TrappedProcessorDescend commentStamp!
I intepret data-trap in descendants of my brush.!

!TrappedProcessorDescend methodsFor: 'data transformation'!

toView: aDataCarrier
	Trapped current injectToJQuery: aDataCarrier target asJQuery children
! !

TrappedProcessor subclass: #TrappedProcessorGuardBase
	instanceVariableNames: 'guardPath'
	package: 'Trapped-Processors'!
!TrappedProcessorGuardBase commentStamp!
I serve as base class for brush-guarding processors.

I cover instantiation and subclasses have to provide
implementation of toVIew: that react appropriately to guard releasing.!

!TrappedProcessorGuardBase methodsFor: 'accessing'!

guardPath: anArray
	guardPath := anArray
! !

!TrappedProcessorGuardBase methodsFor: 'data transformation'!

toModel: aDataCarrier
	"stop"
!

toView: aDataCarrier
	self subclassResponsibility
! !

!TrappedProcessorGuardBase class methodsFor: 'instance creation'!

new: anArray
	^ self new
		guardPath: anArray;
		yourself
! !

TrappedProcessorGuardBase subclass: #TrappedProcessorGuardContents
	instanceVariableNames: ''
	package: 'Trapped-Processors'!
!TrappedProcessorGuardContents commentStamp!
I am used to guard contents of the brush I am installed on.

I save the brush contents, then I observe guard expression in the model,
and when it changes to nil or false, I delete the brush contents;
on the other hand, when it changes to non-nil and non-false,
I restore it from remembered state and interpret all contained
data-trap attributes inside.!

!TrappedProcessorGuardContents methodsFor: 'data transformation'!

toView: aDataCarrier
	| frozen contents |
	frozen := aDataCarrier copy.
	contents := frozen target asJQuery contents detach.
	frozen target trapGuard: guardPath contents: [ :html |
		html root asJQuery append: contents.
		Trapped current injectToJQuery: html root asJQuery ]
! !

TrappedProcessorGuardBase subclass: #TrappedProcessorGuardProc
	instanceVariableNames: ''
	package: 'Trapped-Processors'!
!TrappedProcessorGuardProc commentStamp!
I am used to guard contents filling process of the brush I am installed on.

I observe guard expression in the model,
and when it changes to nil or false, I delete the brush contents;
on the other hand, when it changes to non-nil and non-false,
I run the rest on the chain, which should be one-time
that sets up the contents,!

!TrappedProcessorGuardProc methodsFor: 'data transformation'!

toView: aDataCarrier
	| frozen |
	frozen := aDataCarrier copy.
	frozen target trapGuard: guardPath contents: [ frozen copy proceed ]
! !

TrappedDataExpectingProcessor subclass: #TrappedProcessorInputChecked
	instanceVariableNames: ''
	package: 'Trapped-Processors'!
!TrappedProcessorInputChecked commentStamp!
I bind to checkbox checked attribute.!

!TrappedProcessorInputChecked methodsFor: 'data transformation'!

toView: aDataCarrier
	aDataCarrier toTargetAttr: 'checked'
! !

!TrappedProcessorInputChecked methodsFor: 'installation'!

installToView: aDataCarrier toModel: anotherDataCarrier
	| brush |
	brush := aDataCarrier target.
	brush onChange: [ anotherDataCarrier copy value: (brush asJQuery attr: 'checked') notNil; proceed ]
! !

TrappedDataExpectingProcessor subclass: #TrappedProcessorInputValue
	instanceVariableNames: ''
	package: 'Trapped-Processors'!
!TrappedProcessorInputValue commentStamp!
I bind to input value.!

!TrappedProcessorInputValue methodsFor: 'data transformation'!

toView: aDataCarrier
	aDataCarrier toTargetValue
! !

!TrappedProcessorInputValue methodsFor: 'installation'!

installToView: aDataCarrier toModel: anotherDataCarrier
	| brush |
	brush := aDataCarrier target.
	brush onChange: [ anotherDataCarrier copy value: brush asJQuery val; proceed ]
! !

TrappedProcessor subclass: #TrappedProcessorLoopBase
	instanceVariableNames: ''
	package: 'Trapped-Processors'!
!TrappedProcessorLoopBase commentStamp!
I serve as base class for looping processors.

I cover instantiation and subclasses have to provide
implementation of toVIew: that loops appropriately.!

!TrappedProcessorLoopBase methodsFor: 'data transformation'!

toModel: aDataCarrier
	"stop"
!

toView: aDataCarrier
	self subclassResponsibility
! !

TrappedProcessorLoopBase subclass: #TrappedProcessorLoopContents
	instanceVariableNames: ''
	package: 'Trapped-Processors'!
!TrappedProcessorLoopContents commentStamp!
I am used to loop over data and repeat the contents
of the brush I am installed on.

I save the brush contents, then I observe the data in the model,
and when it changes, I loop over it
and restore the contents from remembered state
and interpret all contained data-trap attributes inside
for each element, putting the result _after_ my brush.

My brush itself should be as least visible as possible,
as it only serve as a position flag (use for example
noscript, ins or del).!

!TrappedProcessorLoopContents methodsFor: 'data transformation'!

toView: aDataCarrier
	| frozen contents |
	frozen := aDataCarrier copy.
	contents := frozen target asJQuery contents detach.
	frozen target trapIter: #() after: [ :html |
		html root asJQuery append: contents clone.
		Trapped current injectToJQuery: html root asJQuery ]
! !

TrappedProcessorLoopBase subclass: #TrappedProcessorLoopProc
	instanceVariableNames: ''
	package: 'Trapped-Processors'!
!TrappedProcessorLoopProc commentStamp!
I am used to loop over data and repeat the contents filling process
of the brush I am installed on.

I observe the data in the model,
and when it changes, I loop over it
and run the rest of the processing chain
for each element, putting the result _after_ my brush.

My brush itself should be as least visible as possible,
as it only serve as a position flag (use for example
noscript, ins or del).!

!TrappedProcessorLoopProc methodsFor: 'data transformation'!

toView: aDataCarrier
	| frozen |
	frozen := aDataCarrier copy.
	frozen target trapIter: #() after: [ :html | frozen copy target: html root; proceed ]
! !

TrappedProcessor subclass: #TrappedProcessorSignal
	instanceVariableNames: 'selector'
	package: 'Trapped-Processors'!
!TrappedProcessorSignal commentStamp!
Instead of writing data directly to model,
I instead modify it by sending a message specified when instantiating me.!

!TrappedProcessorSignal methodsFor: 'accessing'!

selector: aString
	selector := aString
! !

!TrappedProcessorSignal methodsFor: 'data transformation'!

toModel: aDataCarrier
	aDataCarrier modifyTargetByPerforming: selector
!

toView: aDataCarrier
	"stop"
! !

!TrappedProcessorSignal class methodsFor: 'instance creation'!

new: aString
	^self new
		selector: aString;
		yourself
! !

TrappedProcessor subclass: #TrappedProcessorWhenClicked
	instanceVariableNames: ''
	package: 'Trapped-Processors'!
!TrappedProcessorWhenClicked commentStamp!
I bind to an element and send true to blackboard when clicked.!

!TrappedProcessorWhenClicked methodsFor: 'installation'!

installToView: aDataCarrier toModel: anotherDataCarrier
	aDataCarrier target onClick: [ anotherDataCarrier copy proceed. false ]
! !

TrappedProcessor subclass: #TrappedProcessorWhenSubmitted
	instanceVariableNames: ''
	package: 'Trapped-Processors'!
!TrappedProcessorWhenSubmitted commentStamp!
I bind to a form and send true to blackboard when submitted.!

!TrappedProcessorWhenSubmitted methodsFor: 'installation'!

installToView: aDataCarrier toModel: anotherDataCarrier
	aDataCarrier target onSubmit: [ anotherDataCarrier copy proceed. false ]
! !

TrappedProcessor subclass: #TrappedProcessorWidget
	instanceVariableNames: 'viewName'
	package: 'Trapped-Processors'!
!TrappedProcessorWidget commentStamp!
I insert a widget instance of the class specified when creating me.!

!TrappedProcessorWidget methodsFor: 'accessing'!

viewName: aString
	viewName := aString
! !

!TrappedProcessorWidget methodsFor: 'data transformation'!

toView: aDataCarrier
	aDataCarrier target with: (Smalltalk current at: viewName) new
! !

!TrappedProcessorWidget class methodsFor: 'instance creation'!

new: aString
	^self new
		viewName: aString;
		yourself
! !

!TrappedDataCarrier methodsFor: '*Trapped-Processors'!

modifyTarget
	self target modify: [ self value ]
!

modifyTargetByPerforming: aString
	self target modify: [ :m | m perform: aString ]
!

toTargetAttr: aString
	self target asJQuery attr: aString put: (self value ifNotNil: [ :o | o value ] ifNil: [[]])
!

toTargetContents
	self target contents: self value
!

toTargetValue
	self target asJQuery val: (self value ifNotNil: [ :o | o value ] ifNil: [[]])
! !

!TrappedProcessor class methodsFor: '*Trapped-Processors'!

dataToView: aBlock
	^TrappedProcessorDataAdhoc newToView: aBlock
!

guardContents: anArray
	^TrappedProcessorGuardContents new: anArray
!

guardProc: anArray
	^TrappedProcessorGuardProc new: anArray
!

inputChecked
	^TrappedProcessorInputChecked new
!

inputValue
	^TrappedProcessorInputValue new
!

loopContents
	^TrappedProcessorLoopContents new
!

loopProc
	^TrappedProcessorLoopProc new
!

path
	^TrappedProcessorDescend new
!

signal: aString
	^TrappedProcessorSignal new: aString
!

whenClicked
	^TrappedProcessorWhenClicked new
!

whenSubmitted
	^TrappedProcessorWhenSubmitted new
!

widget: aString
	^TrappedProcessorWidget new: aString
! !