123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 |
- Smalltalk createPackage: 'Web-Snippets'!
- (Smalltalk packageAt: '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
- ! !
- !CharacterArray methodsFor: '*Web-Snippets'!
- asSnippet
- ^ HTMLSnippet current snippetAt: self asString
- ! !
- !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
- ! !
|