| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914 | Smalltalk createPackage: 'Web'!(Smalltalk packageAt: 'Web' ifAbsent: [ self error: 'Package not created: Web' ]) imports: {'amber/core/Platform-DOM'. 'amber/web/Web-JQuery'}!Object subclass: #HTMLCanvas	slots: {#root}	package: 'Web'!!HTMLCanvas commentStamp!I am a canvas for building HTML.I provide the `#tag:` method to create a `TagBrush` (wrapping a DOM element) and convenience methods in the `tags` protocol.## APIMy instances are used as the argument of the `#renderOn:` method of `Widget` objects.The `#with:` method is used to compose HTML, nesting tags. `#with:` can take a `TagBrush`, a `String`, a `BlockClosure` or a `Widget` as argument.## Usage example:    aCanvas a         with: [ aCanvas span with: 'click me' ];        onClick: [ window alert: 'clicked!!' ]!!HTMLCanvas methodsFor: 'accessing'!root	^ root ifNil: [ root := TagBrush fromString: 'div' canvas: self ]!root: aTagBrush	self deprecatedAPI.	root := aTagBrush! !!HTMLCanvas methodsFor: 'adding'!entity: aString	"Adds a character representing html entity, eg.	html entity: 'copy'	adds a copyright sign.	If a name does not represent valid HTML entity, error is raised."	| result |	result := (TagBrush fromString: 'span') asDomNode innerHTML: '&', aString, ';'; textContent.	result size = 1 ifFalse: [ self error: 'Not an HTML entity: ', aString ].	self with: result!root: aTagBrush do: aBlock	| old |	old := root.	root := aTagBrush.	aBlock value: self.	root := old!with: anObject	^ self root with: anObject! !!HTMLCanvas methodsFor: 'tags'!a	^ self tag: 'a'!abbr	^ self tag: 'abbr'!address	^ self tag: 'address'!area	^ self tag: 'area'!article	^ self tag: 'article'!aside	^ self tag: 'aside'!audio	^ self tag: 'audio'!base	^ self tag: 'base'!blockquote	^ self tag: 'blockquote'!body	^ self tag: 'body'!br	^ self tag: 'br'!button	^ self tag: 'button'!canvas	^ self tag: 'canvas'!caption	^ self tag: 'caption'!cite	^ self tag: 'cite'!code	^ self tag: 'code'!col	^ self tag: 'col'!colgroup	^ self tag: 'colgroup'!command	^ self tag: 'command'!datalist	^ self tag: 'datalist'!dd	^ self tag: 'dd'!del	^ self tag: 'del'!details	^ self tag: 'details'!div	^ self tag: 'div'!div: aBlock	^ self div with: aBlock!dl	^ self tag: 'dl'!dt	^ self tag: 'dt'!em	^ self tag: 'em'!embed	^ self tag: 'embed'!fieldset	^ self tag: 'fieldset'!figcaption	^ self tag: 'figcaption'!figure	^ self tag: 'figure'!footer	^ self tag: 'footer'!form	^ self tag: 'form'!h1	^ self tag: 'h1'!h1: anObject	^ self h1 with: anObject!h2	^ self tag: 'h2'!h2: anObject	^ self h2 with: anObject!h3	^ self tag: 'h3'!h3: anObject	^ self h3 with: anObject!h4	^ self tag: 'h4'!h4: anObject	^ self h4 with: anObject!h5	^ self tag: 'h5'!h5: anObject	^ self h5 with: anObject!h6	^ self tag: 'h6'!h6: anObject	^ self h6 with: anObject!head	^ self tag: 'head'!header	^ self tag: 'header'!hgroup	^ self tag: 'hgroup'!hr	^ self tag: 'hr'!html	^ self tag: 'html'!iframe	^ self tag: 'iframe'!iframe: aString	^ self iframe src: aString!img	^ self tag: 'img'!img: aString	^ self img src: aString!input	^ self tag: 'input'!label	^ self tag: 'label'!legend	^ self tag: 'legend'!li	^ self tag: 'li'!li: anObject	^ self li with: anObject!link	^ self tag: 'link'!map	^ self tag: 'map'!mark	^ self tag: 'mark'!menu	^ self tag: 'menu'!meta	^ self tag: 'meta'!nav	^ self tag: 'nav'!newTag: aString	^ TagBrush fromString: aString canvas: self!noscript	^ self tag: 'noscript'!object	^ self tag: 'object'!ol	^ self tag: 'ol'!ol: anObject	^ self ol with: anObject!optgroup	^ self tag: 'optgroup'!option	^ self tag: 'option'!output	^ self tag: 'output'!p	^ self tag: 'p'!p: anObject	^ self p with: anObject!param	^ self tag: 'param'!pre	^ self tag: 'pre'!progress	^ self tag: 'progress'!script	^ self tag: 'script'!section	^ self tag: 'section'!select	^ self tag: 'select'!small	^ self tag: 'small'!source	^ self tag: 'source'!span	^ self tag: 'span'!span: anObject	^ self span with: anObject!strong	^ self tag: 'strong'!strong: anObject	^ self strong with: anObject!style	^ self tag: 'style'!style: aString	^ self style with: aString; yourself!sub	^ self tag: 'sub'!summary	^ self tag: 'summary'!sup	^ self tag: 'sup'!table	^ self tag: 'table'!tag: aString	^ self root addBrush: (self newTag: aString)!tbody	^ self tag: 'tbody'!td	^ self tag: 'td'!textarea	^ self tag: 'textarea'!tfoot	^ self tag: 'tfoot'!th	^ self tag: 'th'!thead	^ self tag: 'thead'!time	^ self tag: 'time'!title	^ self tag: 'title'!tr	^ self tag: 'tr'!ul	^ self tag: 'ul'!ul: anObject	^ self ul with: anObject!video	^ self tag: 'video'! !Object subclass: #TagBrush	slots: {#canvas. #element}	package: 'Web'!!TagBrush commentStamp!I am a brush for building a single DOM element (which I hold onto).## API1. Nesting    Use `#with:` to nest tags. `#with:` can take aString, `TagBrush` instance, a `Widget` or block closure as parameter.    Example: `aTag with: aString with: aCanvas div`2. Events    The `events` protocol contains all methods related to events (delegating event handling to jQuery).    Example: `aTag onClick: [ window alert: 'clicked' ]`3. Attributes    The `attribute` protocol contains methods for attribute manipulation.    Example: `aTag at: 'value' put: 'hello world'`4. Raw access and jQuery    The `#asDomNode` method can be used to access to JavaScript DOM element object.    Example: `aTag asDomNode cssStyle`    Use `#asJQuery` to access to the receiver converted into a jQuery object.    Example: `aTag asJQuery css: 'color' value: 'red'`!!TagBrush methodsFor: 'accessing'!element	^ element! !!TagBrush methodsFor: 'adding'!addBrush: aTagBrush	self appendChild: aTagBrush asDomNode.	^ aTagBrush!append: anObject	anObject appendToBrush: self!appendBlock: aBlock	canvas root: self do: aBlock!appendChild: anElement	element appendChild: anElement!appendString: aString	self appendChild: aString asDomNode!appendToBrush: aTagBrush	aTagBrush addBrush: self!contents: anObject	self	empty;	append: anObject!empty<inlineJS: '	var element = $self.element, child;	while (child = element.firstChild) element.removeChild(child);'>!with: anObject	self append: anObject! !!TagBrush methodsFor: 'attributes'!accesskey: aString	self at: 'accesskey' put: aString!action: aString	self at: 'action' put: aString!align: aString	self at: 'align' put: aString!alt: aString	self at: 'alt' put: aString!at: aString	^ self at: aString ifAbsent: [ Collection new errorNotFound ]!at: aString ifAbsent: aBlock	<inlineJS: 'return $self.element.hasAttribute(aString) ? $self.element.getAttribute(aString) : aBlock._value()'>!at: aString put: aValue	<inlineJS: '$self.element.setAttribute(aString, aValue); return aValue'>!class: aString	<inlineJS: '$self.element.className = aString'>!cols: aString	self at: 'cols' put: aString!contenteditable: aString	self at: 'contenteditable' put: aString!contextmenu: aString	self at: 'contextmenu' put: aString!draggable: aString	self at: 'draggable' put: aString!for: aString	self at: 'for' put: aString!height: aString	self at: 'height' put: aString!hidden	self at: 'hidden' put: 'hidden'!href: aString	self at: 'href' put: aString!id: aString	self at: 'id' put: aString!media: aString	self at: 'media' put: aString!method: aString	self at: 'method' put: aString!name: aString	self at: 'name' put: aString!placeholder: aString	self at: 'placeholder' put: aString!rel: aString	self at: 'rel' put: aString!removeAt: aString	<inlineJS: '$self.element.removeAttribute(aString)'>!rows: aString	self at: 'rows' put: aString!src: aString	self at: 'src' put: aString!style: aString	self at: 'style' put: aString!tabindex: aNumber	self at: 'tabindex' put: aNumber!target: aString	self at: 'target' put: aString!title: aString	self at: 'title' put: aString!type: aString	self at: 'type' put: aString!valign: aString	self at: 'valign' put: aString!value: aString	self at: 'value' put: aString!width: aString	self at: 'width' put: aString! !!TagBrush methodsFor: 'converting'!asDomNode	^ element! !!TagBrush methodsFor: 'events'!onBlur: aBlock	self onEvent: 'blur' do: aBlock!onChange: aBlock	self onEvent: 'change' do: aBlock!onClick: aBlock	self onEvent: 'click' do: aBlock!onDblClick: aBlock	self onEvent: 'dblclick' do: aBlock!onEvent: aString do: aBlock	self asDomNode addEventListener: aString block: aBlock useCapture: false!onFocus: aBlock	self onEvent: 'focus' do: aBlock!onFocusIn: aBlock	self onEvent: 'focusin' do: aBlock!onFocusOut: aBlock	self onEvent: 'focusout' do: aBlock!onKeyDown: aBlock	self onEvent: 'keydown' do: aBlock!onKeyPress: aBlock	self onEvent: 'keypress' do: aBlock!onKeyUp: aBlock	self onEvent: 'keyup' do: aBlock!onMouseDown: aBlock	self onEvent: 'mousedown' do: aBlock!onMouseEnter: aBlock	self onEvent: 'mouseenter' do: aBlock!onMouseLeave: aBlock	self onEvent: 'mouseleave' do: aBlock!onMouseMove: aBlock	self onEvent: 'mousemove' do: aBlock!onMouseOut: aBlock	self onEvent: 'mouseout' do: aBlock!onMouseOver: aBlock	self onEvent: 'mouseover' do: aBlock!onMouseUp: aBlock	self onEvent: 'mouseup' do: aBlock!onSelect: aBlock	self onEvent: 'select' do: aBlock!onSubmit: aBlock	self onEvent: 'submit' do: aBlock!onUnload: aBlock	self onEvent: 'unload' do: aBlock! !!TagBrush methodsFor: 'initialization'!initializeFromCssSelector: aString canvas: aCanvas	element := document querySelector: aString.	canvas := aCanvas!initializeFromString: aString canvas: aCanvas	element := document createElement: aString.	canvas := aCanvas! !!TagBrush class methodsFor: 'instance creation'!fromCssSelector: aString	^ self fromCssSelector: aString canvas: HTMLCanvas new!fromCssSelector: aString canvas: aCanvas	^ self new		initializeFromCssSelector: aString canvas: aCanvas;		yourself!fromString: aString	^ self fromString: aString canvas: HTMLCanvas new!fromString: aString canvas: aCanvas	^ self new	initializeFromString: aString canvas: aCanvas;	yourself! !Object subclass: #Widget	slots: {}	package: 'Web'!!Widget commentStamp!I am a presenter building HTML. Subclasses are typically reusable components.## APIUse `#renderOn:` to build HTML. (See `HTMLCanvas` and `TagBrush` classes for more about building HTML).To add a widget to the page, the convenience method `#appendToBrush:` is very useful.Exemple:     Counter new appendToBrush: 'body' asBrush!!Widget methodsFor: 'adding'!appendToBrush: aTagBrush	[ :html | self renderOn: html ] appendToBrush: aTagBrush! !!Widget methodsFor: 'rendering'!renderOn: html	self! !!Widget class methodsFor: 'accessing'!classTag	"Returns a tag or general category for this class.	Typically used to help tools do some reflection.	Helios, for example, uses this to decide what icon the class should display."		^ 'widget'! !!Association methodsFor: '*Web'!appendToBrush: aTagBrush	aTagBrush at: self key put: self value! !!BlockClosure methodsFor: '*Web'!appendToBrush: aTagBrush	aTagBrush appendBlock: self! !!Collection methodsFor: '*Web'!appendToBrush: aTagBrush	self do: [ :each | aTagBrush append: each ]! !!JSObjectProxy methodsFor: '*Web'!appendToBrush: aTagBrush	(PlatformDom isDomNode: jsObject)		ifTrue: [ aTagBrush appendChild: jsObject ]		ifFalse: [ aTagBrush append: self asString ]! !!Object methodsFor: '*Web'!appendToBrush: aTagBrush	aTagBrush append: self asString! !!String methodsFor: '*Web'!appendToBrush: aTagBrush	aTagBrush appendString: self!asBrush	^ TagBrush fromCssSelector: self! !
 |