| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 | 
							- Smalltalk createPackage: 'Web-Snippets'!
 
- (Smalltalk packageAt: 'Web-Snippets' ifAbsent: [ self error: 'Package not created: Web-Snippets' ]) imports: {'amber/jquery/Wrappers-JQuery'. 'amber_core/Platform-DOM'}!
 
- Object subclass: #HTMLSnippet
 
- 	instanceVariableNames: 'snippets'
 
- 	package: 'Web-Snippets'!
 
- !HTMLSnippet commentStamp!
 
- My sole instance is the registry of html snippets.
 
- `HTMLSnippet current` is the public singleton instance.
 
- On startup, it scans the document for any html elements
 
- with `'data-snippet="foo"'` attribute and takes them off the document,
 
- remembering them in the store under the specified name.
 
- It also install method #foo into HTMLCanvas dynamically.
 
- Every html snippet should mark a 'caret', a place where contents
 
- can be inserted, by 'data-snippet="*"' (a special name for caret).
 
- For example:
 
- `<li data-snippet='menuelement' class='...'><a data-snippet='*'></a></li>`
 
- defines a list element with a link inside; the link itself is marked as a caret.
 
- You can later issue
 
- `html menuelement href: '/foo'; with: 'A foo'`
 
- to insert the whole snippet and directly manipulate the caret, so it renders:
 
- `<li class='...'><a href='/foo'>A foo</a></li>`
 
- For a self-careting tags (not very useful, but you do not need to fill class etc.
 
- you can use
 
- `<div class='lots of classes' attr1='one' attr2='two' data-snippet='*bar'></div>`
 
- and in code later do:
 
- `html bar with: [ xxx ]`
 
- to render
 
- `<div class='lots of classes' attr1='one' attr2='two'>...added by xxx...</div>`!
 
- !HTMLSnippet methodsFor: 'accessing'!
 
- snippetAt: aString
 
- 	^ self snippets at: aString
 
- !
 
- snippets
 
- 	^ snippets ifNil: [ snippets := #{} ]
 
- ! !
 
- !HTMLSnippet methodsFor: 'initialization'!
 
- initializeFromJQuery: aJQuery
 
- 	"Finds and takes out all snippets out of aJQuery.
 
- 	Installs it into self."
 
- 	
 
- 	(self snippetsFromJQuery: aJQuery) do: [ :each |
 
- 		self installSnippetFromJQuery: each asJQuery ]
 
- ! !
 
- !HTMLSnippet methodsFor: 'method generation'!
 
- snippetAt: aString compile: anElement
 
- 	"Method generation for the snippet.
 
- 	The selector is aString, the method block uses anElement"
 
- 	
 
- 	ClassBuilder new
 
- 		installMethod: ([ :htmlReceiver | htmlReceiver snippet: anElement ]
 
- 			currySelf asCompiledMethod: aString)
 
- 		forClass: HTMLCanvas
 
- 		protocol: '**snippets'
 
- ! !
 
- !HTMLSnippet methodsFor: 'private'!
 
- snippetsFromJQuery: aJQuery
 
- 	^ (aJQuery find: '[data-snippet]') toArray
 
- ! !
 
- !HTMLSnippet methodsFor: 'snippet installation'!
 
- installSnippetFromJQuery: element
 
- 	| name |
 
- 	name := element attr: 'data-snippet'.
 
- 	name = '*' ifFalse: [
 
- 		('^\*' asRegexp test: name)
 
- 			ifTrue: [
 
- 				name := name allButFirst.
 
- 				element attr: 'data-snippet' put: '*' ]
 
- 			ifFalse: [
 
- 				element removeAttr: 'data-snippet' ].
 
- 		self snippetAt: name install: (element detach get: 0) ]
 
- !
 
- snippetAt: aString install: anElement
 
- 	self snippets at: aString put: anElement.
 
- 	self snippetAt: aString compile: anElement
 
- ! !
 
- HTMLSnippet class instanceVariableNames: 'current'!
 
- !HTMLSnippet class methodsFor: 'initialization'!
 
- ensureCurrent
 
- 	current ifNil: [
 
- 		current := super new
 
- 			initializeFromJQuery: document asJQuery;
 
- 			yourself ]
 
- !
 
- initialize
 
- 	super initialize.
 
- 	PlatformDom isFeasible ifTrue: [
 
- 		self ensureCurrent ]
 
- ! !
 
- !HTMLSnippet class methodsFor: 'instance creation'!
 
- current
 
- 	^ current
 
- !
 
- new
 
- 	self shouldNotImplement
 
- ! !
 
- !HTMLCanvas methodsFor: '*Web-Snippets'!
 
- snippet: anElement
 
- 	"Adds clone of anElement, finds [data-snippet=""*""] subelement
 
- 	and returns TagBrush as if that subelement was just added.
 
- 	
 
- 	Rarely needed to use directly, use `html foo` dynamically installed method
 
- 	for a snippet named foo."
 
- 	
 
- 	| clone caret |
 
- 	
 
- 	clone := anElement asJQuery clone.
 
- 	self with: (TagBrush fromJQuery: clone canvas: self).
 
- 	caret := clone find: '[data-snippet="*"]'.
 
- 	caret toArray ifEmpty: [ caret := clone ].
 
- 	^ TagBrush fromJQuery: (caret removeAttr: 'data-snippet') canvas: self
 
- ! !
 
- !String methodsFor: '*Web-Snippets'!
 
- asSnippet
 
- 	^ HTMLSnippet current snippetAt: self asString
 
- ! !
 
 
  |