Web.st 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971
  1. Smalltalk createPackage: 'Web'!
  2. (Smalltalk packageAt: 'Web' ifAbsent: [ self error: 'Package not created: Web' ]) imports: {'amber/core/Platform-DOM'. 'amber/jquery/Wrappers-JQuery'}!
  3. Object subclass: #HTMLCanvas
  4. slots: {#root}
  5. package: 'Web'!
  6. !HTMLCanvas commentStamp!
  7. I am a canvas for building HTML.
  8. I provide the `#tag:` method to create a `TagBrush` (wrapping a DOM element) and convenience methods in the `tags` protocol.
  9. ## API
  10. My instances are used as the argument of the `#renderOn:` method of `Widget` objects.
  11. The `#with:` method is used to compose HTML, nesting tags. `#with:` can take a `TagBrush`, a `String`, a `BlockClosure` or a `Widget` as argument.
  12. ## Usage example:
  13. aCanvas a
  14. with: [ aCanvas span with: 'click me' ];
  15. onClick: [ window alert: 'clicked!!' ]!
  16. !HTMLCanvas methodsFor: 'accessing'!
  17. root
  18. ^ root ifNil: [ root := TagBrush fromString: 'div' canvas: self ]
  19. !
  20. root: aTagBrush
  21. self deprecatedAPI.
  22. root := aTagBrush
  23. ! !
  24. !HTMLCanvas methodsFor: 'adding'!
  25. entity: aString
  26. "Adds a character representing html entity, eg.
  27. html entity: 'copy'
  28. adds a copyright sign.
  29. If a name does not represent valid HTML entity, error is raised."
  30. | result |
  31. result := ('<span />' asJQuery html: '&', aString, ';') text.
  32. result size = 1 ifFalse: [ self error: 'Not an HTML entity: ', aString ].
  33. self with: result
  34. !
  35. root: aTagBrush do: aBlock
  36. | old |
  37. old := root.
  38. root := aTagBrush.
  39. aBlock value: self.
  40. root := old
  41. !
  42. with: anObject
  43. ^ self root with: anObject
  44. ! !
  45. !HTMLCanvas methodsFor: 'initialization'!
  46. initializeFromJQuery: aJQuery
  47. root := TagBrush fromJQuery: aJQuery canvas: self
  48. ! !
  49. !HTMLCanvas methodsFor: 'tags'!
  50. a
  51. ^ self tag: 'a'
  52. !
  53. abbr
  54. ^ self tag: 'abbr'
  55. !
  56. address
  57. ^ self tag: 'address'
  58. !
  59. area
  60. ^ self tag: 'area'
  61. !
  62. article
  63. ^ self tag: 'article'
  64. !
  65. aside
  66. ^ self tag: 'aside'
  67. !
  68. audio
  69. ^ self tag: 'audio'
  70. !
  71. base
  72. ^ self tag: 'base'
  73. !
  74. blockquote
  75. ^ self tag: 'blockquote'
  76. !
  77. body
  78. ^ self tag: 'body'
  79. !
  80. br
  81. ^ self tag: 'br'
  82. !
  83. button
  84. ^ self tag: 'button'
  85. !
  86. canvas
  87. ^ self tag: 'canvas'
  88. !
  89. caption
  90. ^ self tag: 'caption'
  91. !
  92. cite
  93. ^ self tag: 'cite'
  94. !
  95. code
  96. ^ self tag: 'code'
  97. !
  98. col
  99. ^ self tag: 'col'
  100. !
  101. colgroup
  102. ^ self tag: 'colgroup'
  103. !
  104. command
  105. ^ self tag: 'command'
  106. !
  107. datalist
  108. ^ self tag: 'datalist'
  109. !
  110. dd
  111. ^ self tag: 'dd'
  112. !
  113. del
  114. ^ self tag: 'del'
  115. !
  116. details
  117. ^ self tag: 'details'
  118. !
  119. div
  120. ^ self tag: 'div'
  121. !
  122. div: aBlock
  123. ^ self div with: aBlock
  124. !
  125. dl
  126. ^ self tag: 'dl'
  127. !
  128. dt
  129. ^ self tag: 'dt'
  130. !
  131. em
  132. ^ self tag: 'em'
  133. !
  134. embed
  135. ^ self tag: 'embed'
  136. !
  137. fieldset
  138. ^ self tag: 'fieldset'
  139. !
  140. figcaption
  141. ^ self tag: 'figcaption'
  142. !
  143. figure
  144. ^ self tag: 'figure'
  145. !
  146. footer
  147. ^ self tag: 'footer'
  148. !
  149. form
  150. ^ self tag: 'form'
  151. !
  152. h1
  153. ^ self tag: 'h1'
  154. !
  155. h1: anObject
  156. ^ self h1 with: anObject
  157. !
  158. h2
  159. ^ self tag: 'h2'
  160. !
  161. h2: anObject
  162. ^ self h2 with: anObject
  163. !
  164. h3
  165. ^ self tag: 'h3'
  166. !
  167. h3: anObject
  168. ^ self h3 with: anObject
  169. !
  170. h4
  171. ^ self tag: 'h4'
  172. !
  173. h4: anObject
  174. ^ self h4 with: anObject
  175. !
  176. h5
  177. ^ self tag: 'h5'
  178. !
  179. h5: anObject
  180. ^ self h5 with: anObject
  181. !
  182. h6
  183. ^ self tag: 'h6'
  184. !
  185. h6: anObject
  186. ^ self h6 with: anObject
  187. !
  188. head
  189. ^ self tag: 'head'
  190. !
  191. header
  192. ^ self tag: 'header'
  193. !
  194. hgroup
  195. ^ self tag: 'hgroup'
  196. !
  197. hr
  198. ^ self tag: 'hr'
  199. !
  200. html
  201. ^ self tag: 'html'
  202. !
  203. iframe
  204. ^ self tag: 'iframe'
  205. !
  206. iframe: aString
  207. ^ self iframe src: aString
  208. !
  209. img
  210. ^ self tag: 'img'
  211. !
  212. img: aString
  213. ^ self img src: aString
  214. !
  215. input
  216. ^ self tag: 'input'
  217. !
  218. label
  219. ^ self tag: 'label'
  220. !
  221. legend
  222. ^ self tag: 'legend'
  223. !
  224. li
  225. ^ self tag: 'li'
  226. !
  227. li: anObject
  228. ^ self li with: anObject
  229. !
  230. link
  231. ^ self tag: 'link'
  232. !
  233. map
  234. ^ self tag: 'map'
  235. !
  236. mark
  237. ^ self tag: 'mark'
  238. !
  239. menu
  240. ^ self tag: 'menu'
  241. !
  242. meta
  243. ^ self tag: 'meta'
  244. !
  245. nav
  246. ^ self tag: 'nav'
  247. !
  248. newTag: aString
  249. ^ TagBrush fromString: aString canvas: self
  250. !
  251. noscript
  252. ^ self tag: 'noscript'
  253. !
  254. object
  255. ^ self tag: 'object'
  256. !
  257. ol
  258. ^ self tag: 'ol'
  259. !
  260. ol: anObject
  261. ^ self ol with: anObject
  262. !
  263. optgroup
  264. ^ self tag: 'optgroup'
  265. !
  266. option
  267. ^ self tag: 'option'
  268. !
  269. output
  270. ^ self tag: 'output'
  271. !
  272. p
  273. ^ self tag: 'p'
  274. !
  275. p: anObject
  276. ^ self p with: anObject
  277. !
  278. param
  279. ^ self tag: 'param'
  280. !
  281. pre
  282. ^ self tag: 'pre'
  283. !
  284. progress
  285. ^ self tag: 'progress'
  286. !
  287. script
  288. ^ self tag: 'script'
  289. !
  290. section
  291. ^ self tag: 'section'
  292. !
  293. select
  294. ^ self tag: 'select'
  295. !
  296. small
  297. ^ self tag: 'small'
  298. !
  299. source
  300. ^ self tag: 'source'
  301. !
  302. span
  303. ^ self tag: 'span'
  304. !
  305. span: anObject
  306. ^ self span with: anObject
  307. !
  308. strong
  309. ^ self tag: 'strong'
  310. !
  311. strong: anObject
  312. ^ self strong with: anObject
  313. !
  314. style
  315. ^ self tag: 'style'
  316. !
  317. style: aString
  318. ^ self style with: aString; yourself
  319. !
  320. sub
  321. ^ self tag: 'sub'
  322. !
  323. summary
  324. ^ self tag: 'summary'
  325. !
  326. sup
  327. ^ self tag: 'sup'
  328. !
  329. table
  330. ^ self tag: 'table'
  331. !
  332. tag: aString
  333. ^ self root addBrush: (self newTag: aString)
  334. !
  335. tbody
  336. ^ self tag: 'tbody'
  337. !
  338. td
  339. ^ self tag: 'td'
  340. !
  341. textarea
  342. ^ self tag: 'textarea'
  343. !
  344. tfoot
  345. ^ self tag: 'tfoot'
  346. !
  347. th
  348. ^ self tag: 'th'
  349. !
  350. thead
  351. ^ self tag: 'thead'
  352. !
  353. time
  354. ^ self tag: 'time'
  355. !
  356. title
  357. ^ self tag: 'title'
  358. !
  359. tr
  360. ^ self tag: 'tr'
  361. !
  362. ul
  363. ^ self tag: 'ul'
  364. !
  365. ul: anObject
  366. ^ self ul with: anObject
  367. !
  368. video
  369. ^ self tag: 'video'
  370. ! !
  371. !HTMLCanvas class methodsFor: 'instance creation'!
  372. onJQuery: aJQuery
  373. ^ self basicNew
  374. initializeFromJQuery: aJQuery;
  375. initialize;
  376. yourself
  377. ! !
  378. Object subclass: #TagBrush
  379. slots: {#canvas. #element}
  380. package: 'Web'!
  381. !TagBrush commentStamp!
  382. I am a brush for building a single DOM element (which I hold onto).
  383. All tags but `<style>` are instances of me (see the `StyleBrush` class).
  384. ## API
  385. 1. Nesting
  386. Use `#with:` to nest tags. `#with:` can take aString, `TagBrush` instance, a `Widget` or block closure as parameter.
  387. Example: `aTag with: aString with: aCanvas div`
  388. 2. Events
  389. The `events` protocol contains all methods related to events (delegating event handling to jQuery).
  390. Example: `aTag onClick: [ window alert: 'clicked' ]`
  391. 3. Attributes
  392. The `attribute` protocol contains methods for attribute manipulation (delegating to jQuery too).
  393. Example: `aTag at: 'value' put: 'hello world'`
  394. 4. Raw access and jQuery
  395. The `#element` method can be used to access to JavaScript DOM element object.
  396. Example: `aTag element cssStyle`
  397. Use `#asJQuery` to access to the receiver converted into a jQuery object.
  398. Example: `aTag asJQuery css: 'color' value: 'red'`!
  399. !TagBrush methodsFor: 'accessing'!
  400. element
  401. ^ element
  402. ! !
  403. !TagBrush methodsFor: 'adding'!
  404. addBrush: aTagBrush
  405. self appendChild: aTagBrush asDomNode.
  406. ^ aTagBrush
  407. !
  408. append: anObject
  409. anObject appendToBrush: self
  410. !
  411. appendBlock: aBlock
  412. canvas root: self do: aBlock
  413. !
  414. appendChild: anElement
  415. element appendChild: anElement
  416. !
  417. appendString: aString
  418. self appendChild: aString asDomNode
  419. !
  420. appendToBrush: aTagBrush
  421. aTagBrush addBrush: self
  422. !
  423. contents: anObject
  424. self
  425. empty;
  426. append: anObject
  427. !
  428. empty
  429. self asJQuery empty
  430. !
  431. with: anObject
  432. self append: anObject
  433. ! !
  434. !TagBrush methodsFor: 'attributes'!
  435. accesskey: aString
  436. self at: 'accesskey' put: aString
  437. !
  438. action: aString
  439. self at: 'action' put: aString
  440. !
  441. align: aString
  442. self at: 'align' put: aString
  443. !
  444. alt: aString
  445. self at: 'alt' put: aString
  446. !
  447. at: aString
  448. ^ self at: aString ifAbsent: [ Collection new errorNotFound ]
  449. !
  450. at: aString ifAbsent: aBlock
  451. <inlineJS: 'return $self.element.hasAttribute(aString) ? $self.element.getAttribute(aString) : aBlock._value()'>
  452. !
  453. at: aString put: aValue
  454. <inlineJS: '$self.element.setAttribute(aString, aValue); return aValue'>
  455. !
  456. class: aString
  457. <inlineJS: '$self.element.className = aString'>
  458. !
  459. cols: aString
  460. self at: 'cols' put: aString
  461. !
  462. contenteditable: aString
  463. self at: 'contenteditable' put: aString
  464. !
  465. contextmenu: aString
  466. self at: 'contextmenu' put: aString
  467. !
  468. draggable: aString
  469. self at: 'draggable' put: aString
  470. !
  471. for: aString
  472. self at: 'for' put: aString
  473. !
  474. height: aString
  475. self at: 'height' put: aString
  476. !
  477. hidden
  478. self at: 'hidden' put: 'hidden'
  479. !
  480. href: aString
  481. self at: 'href' put: aString
  482. !
  483. id: aString
  484. self at: 'id' put: aString
  485. !
  486. media: aString
  487. self at: 'media' put: aString
  488. !
  489. method: aString
  490. self at: 'method' put: aString
  491. !
  492. name: aString
  493. self at: 'name' put: aString
  494. !
  495. placeholder: aString
  496. self at: 'placeholder' put: aString
  497. !
  498. rel: aString
  499. self at: 'rel' put: aString
  500. !
  501. removeAt: aString
  502. <inlineJS: '$self.element.removeAttribute(aString)'>
  503. !
  504. rows: aString
  505. self at: 'rows' put: aString
  506. !
  507. src: aString
  508. self at: 'src' put: aString
  509. !
  510. style: aString
  511. self at: 'style' put: aString
  512. !
  513. tabindex: aNumber
  514. self at: 'tabindex' put: aNumber
  515. !
  516. target: aString
  517. self at: 'target' put: aString
  518. !
  519. title: aString
  520. self at: 'title' put: aString
  521. !
  522. type: aString
  523. self at: 'type' put: aString
  524. !
  525. valign: aString
  526. self at: 'valign' put: aString
  527. !
  528. value: aString
  529. self at: 'value' put: aString
  530. !
  531. width: aString
  532. self at: 'width' put: aString
  533. ! !
  534. !TagBrush methodsFor: 'converting'!
  535. asDomNode
  536. ^ element
  537. !
  538. asJQuery
  539. ^ self asDomNode asJQuery
  540. !
  541. asJQueryInContext: aContext
  542. ^ self asDomNode asJQueryInContext: aContext
  543. ! !
  544. !TagBrush methodsFor: 'events'!
  545. onBlur: aBlock
  546. self onEvent: 'blur' do: aBlock
  547. !
  548. onChange: aBlock
  549. self onEvent: 'change' do: aBlock
  550. !
  551. onClick: aBlock
  552. self onEvent: 'click' do: aBlock
  553. !
  554. onDblClick: aBlock
  555. self onEvent: 'dblclick' do: aBlock
  556. !
  557. onEvent: aString do: aBlock
  558. self asJQuery bind: aString do: aBlock
  559. !
  560. onFocus: aBlock
  561. self onEvent: 'focus' do: aBlock
  562. !
  563. onFocusIn: aBlock
  564. self onEvent: 'focusin' do: aBlock
  565. !
  566. onFocusOut: aBlock
  567. self onEvent: 'focusout' do: aBlock
  568. !
  569. onHover: aBlock
  570. self onEvent: 'hover' do: aBlock
  571. !
  572. onKeyDown: aBlock
  573. self onEvent: 'keydown' do: aBlock
  574. !
  575. onKeyPress: aBlock
  576. self onEvent: 'keypress' do: aBlock
  577. !
  578. onKeyUp: aBlock
  579. self onEvent: 'keyup' do: aBlock
  580. !
  581. onMouseDown: aBlock
  582. self onEvent: 'mousedown' do: aBlock
  583. !
  584. onMouseEnter: aBlock
  585. self onEvent: 'mouseenter' do: aBlock
  586. !
  587. onMouseLeave: aBlock
  588. self onEvent: 'mouseleave' do: aBlock
  589. !
  590. onMouseMove: aBlock
  591. self onEvent: 'mousemove' do: aBlock
  592. !
  593. onMouseOut: aBlock
  594. self onEvent: 'mouseout' do: aBlock
  595. !
  596. onMouseOver: aBlock
  597. self onEvent: 'mouseover' do: aBlock
  598. !
  599. onMouseUp: aBlock
  600. self onEvent: 'mouseup' do: aBlock
  601. !
  602. onSelect: aBlock
  603. self onEvent: 'select' do: aBlock
  604. !
  605. onSubmit: aBlock
  606. self onEvent: 'submit' do: aBlock
  607. !
  608. onUnload: aBlock
  609. self onEvent: 'unload' do: aBlock
  610. ! !
  611. !TagBrush methodsFor: 'initialization'!
  612. initializeFromCssSelector: aString canvas: aCanvas
  613. element := document querySelector: aString.
  614. canvas := aCanvas
  615. !
  616. initializeFromJQuery: aJQuery canvas: aCanvas
  617. element := aJQuery get: 0.
  618. canvas := aCanvas
  619. !
  620. initializeFromString: aString canvas: aCanvas
  621. element := document createElement: aString.
  622. canvas := aCanvas
  623. ! !
  624. !TagBrush class methodsFor: 'instance creation'!
  625. fromCssSelector: aString
  626. ^ self fromCssSelector: aString canvas: HTMLCanvas new
  627. !
  628. fromCssSelector: aString canvas: aCanvas
  629. ^ self new
  630. initializeFromCssSelector: aString canvas: aCanvas;
  631. yourself
  632. !
  633. fromJQuery: aJQuery
  634. ^ self fromJQuery: aJQuery canvas: HTMLCanvas new
  635. !
  636. fromJQuery: aJQuery canvas: aCanvas
  637. ^ self new
  638. initializeFromJQuery: aJQuery canvas: aCanvas;
  639. yourself
  640. !
  641. fromString: aString
  642. ^ self fromString: aString canvas: HTMLCanvas new
  643. !
  644. fromString: aString canvas: aCanvas
  645. ^ self new
  646. initializeFromString: aString canvas: aCanvas;
  647. yourself
  648. ! !
  649. Object subclass: #Widget
  650. slots: {}
  651. package: 'Web'!
  652. !Widget commentStamp!
  653. I am a presenter building HTML. Subclasses are typically reusable components.
  654. ## API
  655. Use `#renderContentOn:` to build HTML. (See `HTMLCanvas` and `TagBrush` classes for more about building HTML).
  656. To add a widget to the page, the convenience method `#appendToJQuery:` is very useful.
  657. Exemple:
  658. Counter new appendToJQuery: 'body' asJQuery!
  659. !Widget methodsFor: 'adding'!
  660. appendToBrush: aTagBrush
  661. [ :html | self renderOn: html ] appendToBrush: aTagBrush
  662. !
  663. appendToJQuery: aJQuery
  664. self renderOn: (HTMLCanvas onJQuery: aJQuery)
  665. ! !
  666. !Widget methodsFor: 'rendering'!
  667. renderOn: html
  668. self
  669. ! !
  670. !Widget class methodsFor: 'accessing'!
  671. classTag
  672. "Returns a tag or general category for this class.
  673. Typically used to help tools do some reflection.
  674. Helios, for example, uses this to decide what icon the class should display."
  675. ^ 'widget'
  676. ! !
  677. !Association methodsFor: '*Web'!
  678. appendToBrush: aTagBrush
  679. aTagBrush at: self key put: self value
  680. ! !
  681. !BlockClosure methodsFor: '*Web'!
  682. appendToBrush: aTagBrush
  683. aTagBrush appendBlock: self
  684. !
  685. appendToJQuery: aJQuery
  686. self value: (HTMLCanvas onJQuery: aJQuery)
  687. ! !
  688. !Collection methodsFor: '*Web'!
  689. appendToBrush: aTagBrush
  690. self do: [ :each | aTagBrush append: each ]
  691. ! !
  692. !JSObjectProxy methodsFor: '*Web'!
  693. appendToBrush: aTagBrush
  694. (PlatformDom isDomNode: jsObject)
  695. ifTrue: [ aTagBrush appendChild: jsObject ]
  696. ifFalse: [ aTagBrush append: self asString ]
  697. ! !
  698. !Object methodsFor: '*Web'!
  699. appendToBrush: aTagBrush
  700. aTagBrush append: self asString
  701. !
  702. appendToJQuery: aJQuery
  703. aJQuery append: self asString
  704. ! !
  705. !String methodsFor: '*Web'!
  706. appendToBrush: aTagBrush
  707. aTagBrush appendString: self
  708. !
  709. appendToJQuery: aJQuery
  710. aJQuery append: self
  711. !
  712. asBrush
  713. ^ TagBrush fromCssSelector: self
  714. ! !