Canvas.st 14 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007
  1. Smalltalk current createPackage: 'Canvas' properties: #{}!
  2. Object subclass: #HTMLCanvas
  3. instanceVariableNames: 'root'
  4. package: 'Canvas'!
  5. !HTMLCanvas methodsFor: 'accessing'!
  6. root
  7. ^root
  8. !
  9. root: aTagBrush
  10. root := aTagBrush
  11. ! !
  12. !HTMLCanvas methodsFor: 'adding'!
  13. with: anObject
  14. ^self root with: anObject
  15. ! !
  16. !HTMLCanvas methodsFor: 'initialization'!
  17. initialize
  18. super initialize.
  19. root ifNil: [root := TagBrush fromString: 'div' canvas: self]
  20. !
  21. initializeFromJQuery: aJQuery
  22. root := TagBrush fromJQuery: aJQuery canvas: self
  23. ! !
  24. !HTMLCanvas methodsFor: 'tags'!
  25. a
  26. ^self tag: 'a'
  27. !
  28. abbr
  29. ^self tag: 'abbr'
  30. !
  31. address
  32. ^self tag: 'address'
  33. !
  34. area
  35. ^self tag: 'area'
  36. !
  37. article
  38. ^self tag: 'article'
  39. !
  40. aside
  41. ^self tag: 'aside'
  42. !
  43. audio
  44. ^self tag: 'audio'
  45. !
  46. base
  47. ^self tag: 'base'
  48. !
  49. blockquote
  50. ^self tag: 'blockquote'
  51. !
  52. body
  53. ^self tag: 'body'
  54. !
  55. br
  56. ^self tag: 'br'
  57. !
  58. button
  59. ^self tag: 'button'
  60. !
  61. canvas
  62. ^self tag: 'canvas'
  63. !
  64. caption
  65. ^self tag: 'caption'
  66. !
  67. cite
  68. ^self tag: 'cite'
  69. !
  70. code
  71. ^self tag: 'code'
  72. !
  73. col
  74. ^self tag: 'col'
  75. !
  76. colgroup
  77. ^self tag: 'colgroup'
  78. !
  79. command
  80. ^self tag: 'command'
  81. !
  82. datalist
  83. ^self tag: 'datalist'
  84. !
  85. dd
  86. ^self tag: 'dd'
  87. !
  88. del
  89. ^self tag: 'del'
  90. !
  91. details
  92. ^self tag: 'details'
  93. !
  94. div
  95. ^self tag: 'div'
  96. !
  97. div: aBlock
  98. ^self div with: aBlock
  99. !
  100. dl
  101. ^self tag: 'dl'
  102. !
  103. dt
  104. ^self tag: 'dt'
  105. !
  106. em
  107. ^self tag: 'em'
  108. !
  109. embed
  110. ^self tag: 'embed'
  111. !
  112. fieldset
  113. ^self tag: 'fieldset'
  114. !
  115. figcaption
  116. ^self tag: 'figcaption'
  117. !
  118. figure
  119. ^self tag: 'figure'
  120. !
  121. footer
  122. ^self tag: 'footer'
  123. !
  124. form
  125. ^self tag: 'form'
  126. !
  127. h1
  128. ^self tag: 'h1'
  129. !
  130. h1: anObject
  131. ^self h1 with: anObject
  132. !
  133. h2
  134. ^self tag: 'h2'
  135. !
  136. h2: anObject
  137. ^ self h2 with: anObject
  138. !
  139. h3
  140. ^self tag: 'h3'
  141. !
  142. h3: anObject
  143. ^self h3 with: anObject
  144. !
  145. h4
  146. ^self tag: 'h4'
  147. !
  148. h4: anObject
  149. ^self h4 with: anObject
  150. !
  151. h5
  152. ^self tag: 'h5'
  153. !
  154. h5: anObject
  155. ^self h5 with: anObject
  156. !
  157. h6
  158. ^self tag: 'h6'
  159. !
  160. h6: anObject
  161. ^self h6 with: anObject
  162. !
  163. head
  164. ^self tag: 'head'
  165. !
  166. header
  167. ^self tag: 'header'
  168. !
  169. hgroup
  170. ^self tag: 'hgroup'
  171. !
  172. hr
  173. ^self tag: 'hr'
  174. !
  175. html
  176. ^self tag: 'html'
  177. !
  178. iframe
  179. ^self tag: 'iframe'
  180. !
  181. iframe: aString
  182. ^self iframe src: aString
  183. !
  184. img
  185. ^self tag: 'img'
  186. !
  187. img: aString
  188. ^self img src: aString
  189. !
  190. input
  191. ^self tag: 'input'
  192. !
  193. label
  194. ^self tag: 'label'
  195. !
  196. legend
  197. ^self tag: 'legend'
  198. !
  199. li
  200. ^self tag: 'li'
  201. !
  202. li: anObject
  203. ^self li with: anObject
  204. !
  205. link
  206. ^self tag: 'link'
  207. !
  208. map
  209. ^self tag: 'map'
  210. !
  211. mark
  212. ^self tag: 'mark'
  213. !
  214. menu
  215. ^self tag: 'menu'
  216. !
  217. meta
  218. ^self tag: 'meta'
  219. !
  220. nav
  221. ^self tag: 'nav'
  222. !
  223. newTag: aString
  224. ^TagBrush fromString: aString canvas: self
  225. !
  226. noscript
  227. ^self tag: 'noscript'
  228. !
  229. object
  230. ^self tag: 'object'
  231. !
  232. ol
  233. ^self tag: 'ol'
  234. !
  235. ol: anObject
  236. ^self ol with: anObject
  237. !
  238. optgroup
  239. ^self tag: 'optgroup'
  240. !
  241. option
  242. ^self tag: 'option'
  243. !
  244. output
  245. ^self tag: 'output'
  246. !
  247. p
  248. ^self tag: 'p'
  249. !
  250. p: anObject
  251. ^self p with: anObject
  252. !
  253. param
  254. ^self tag: 'param'
  255. !
  256. pre
  257. ^self tag: 'pre'
  258. !
  259. progress
  260. ^self tag: 'progress'
  261. !
  262. script
  263. ^self tag: 'script'
  264. !
  265. section
  266. ^self tag: 'section'
  267. !
  268. select
  269. ^self tag: 'select'
  270. !
  271. small
  272. ^self tag: 'small'
  273. !
  274. source
  275. ^self tag: 'source'
  276. !
  277. span
  278. ^self tag: 'span'
  279. !
  280. span: anObject
  281. ^self span with: anObject
  282. !
  283. strong
  284. ^self tag: 'strong'
  285. !
  286. strong: anObject
  287. ^self strong with: anObject
  288. !
  289. style
  290. ^ root addBrush: (StyleTag canvas: self)
  291. !
  292. style: aString
  293. ^ self style with: aString; yourself
  294. !
  295. sub
  296. ^self tag: 'sub'
  297. !
  298. summary
  299. ^self tag: 'summary'
  300. !
  301. sup
  302. ^self tag: 'sup'
  303. !
  304. table
  305. ^self tag: 'table'
  306. !
  307. tag: aString
  308. ^root addBrush: (self newTag: aString)
  309. !
  310. tbody
  311. ^self tag: 'tbody'
  312. !
  313. td
  314. ^self tag: 'td'
  315. !
  316. textarea
  317. ^self tag: 'textarea'
  318. !
  319. tfoot
  320. ^self tag: 'tfoot'
  321. !
  322. th
  323. ^self tag: 'th'
  324. !
  325. thead
  326. ^self tag: 'thead'
  327. !
  328. time
  329. ^self tag: 'time'
  330. !
  331. title
  332. ^self tag: 'title'
  333. !
  334. tr
  335. ^self tag: 'tr'
  336. !
  337. ul
  338. ^self tag: 'ul'
  339. !
  340. ul: anObject
  341. ^self ul with: anObject
  342. !
  343. video
  344. ^self tag: 'video'
  345. ! !
  346. !HTMLCanvas class methodsFor: 'instance creation'!
  347. browserVersion
  348. ^(jQuery at: #browser) version
  349. !
  350. isMSIE
  351. ^((jQuery at: #browser) at: #msie) notNil
  352. !
  353. isMozilla
  354. ^((jQuery at: #browser) at: #mozilla) notNil
  355. !
  356. isOpera
  357. ^((jQuery at: #browser) at: #opera) notNil
  358. !
  359. isWebkit
  360. ^((jQuery at: #browser) at: #webkit) notNil
  361. !
  362. onJQuery: aJQuery
  363. ^self basicNew
  364. initializeFromJQuery: aJQuery;
  365. initialize;
  366. yourself
  367. ! !
  368. Object subclass: #HtmlSnippet
  369. instanceVariableNames: 'snippets'
  370. package: 'Canvas'!
  371. !HtmlSnippet commentStamp!
  372. HtmlSnippet instance is the registry of html snippets.
  373. HtmlSnippet current is the public singleton instance.
  374. At the beginning, it scans the document for any html elements
  375. with 'data-snippet="foo"' attribute and takes them off the document,
  376. remembering them in the store under the specified name.
  377. It also install method #foo into HTMLCanvas dynamically.
  378. Every html snippet should mark a 'caret', a place where contents
  379. can be inserted, by 'data-snippet="*"' (a special name for caret).
  380. For example:
  381. <li data-snippet='menuelement' class='...'><a data-snippet='*'></a></li>
  382. defines a list element with a link inside; the link itself is marked as a caret.
  383. You can later issue
  384. html menuelement href: '/foo'; with: 'A foo'
  385. to insert the whole snippet and directly manipulate the caret, so it renders:
  386. <li class='...'><a href='/foo'>A foo</a></li>
  387. For a self-careting tags (not very useful, but you do not need to fill class etc.
  388. you can use
  389. <div class='lots of classes' attr1='one' attr2='two' data-snippet='*bar'></div>
  390. and in code later do:
  391. html bar with: [ xxx ]
  392. to render
  393. <div class='lots of classes' attr1='one' attr2='two'>...added by xxx...</div>!
  394. !HtmlSnippet methodsFor: 'accessing'!
  395. at: aString
  396. ^ snippets at: aString
  397. !
  398. at: aString ifAbsent: aBlock
  399. ^ snippets at: aString ifAbsent: aBlock
  400. !
  401. snippets
  402. ^snippets ifNil: [ snippets := #{} ]
  403. ! !
  404. !HtmlSnippet methodsFor: 'snippet installation'!
  405. addSnippet: anAssociation
  406. | snippet |
  407. self snippets add: anAssociation.
  408. snippet := anAssociation value.
  409. ClassBuilder new
  410. installMethod: ([ :htmlReceiver | htmlReceiver snippet: snippet ] currySelf asCompiledMethod: anAssociation key)
  411. forClass: HTMLCanvas
  412. category: '**snippets'
  413. !
  414. loadFromJQuery: aJQuery
  415. "Finds and takes out all snippets out of aJQuery.
  416. Installs it into self."
  417. (aJQuery find: '[data-snippet]') toArray do: [ :each |
  418. | jq name |
  419. jq := each asJQuery.
  420. name := jq attr: 'data-snippet'.
  421. name = '*' ifFalse: [
  422. ('^\*' asRegexp test: name) ifTrue: [ name := name allButFirst. jq attr: 'data-snippet' put: '*' ]
  423. ifFalse: [ jq removeAttr: 'data-snippet' ].
  424. self addSnippet: name -> (jq detach get: 0) ]]
  425. ! !
  426. HtmlSnippet class instanceVariableNames: 'current'!
  427. !HtmlSnippet class methodsFor: 'initialization'!
  428. initialize
  429. super initialize.
  430. self current loadFromJQuery: document asJQuery
  431. ! !
  432. !HtmlSnippet class methodsFor: 'instance creation'!
  433. current
  434. ^ current ifNil: [ current := self new ]
  435. ! !
  436. Object subclass: #TagBrush
  437. instanceVariableNames: 'canvas element'
  438. package: 'Canvas'!
  439. !TagBrush methodsFor: 'accessing'!
  440. element
  441. ^element
  442. ! !
  443. !TagBrush methodsFor: 'adding'!
  444. addBrush: aTagBrush
  445. self appendChild: aTagBrush element.
  446. ^aTagBrush
  447. !
  448. append: anObject
  449. anObject appendToBrush: self
  450. !
  451. appendBlock: aBlock
  452. | root |
  453. root := canvas root.
  454. canvas root: self.
  455. aBlock value: canvas.
  456. canvas root: root
  457. !
  458. appendChild: anElement
  459. "In IE7 and IE8 appendChild fails on several node types. So we need to check"
  460. <var element=self['@element'];
  461. if (null == element.canHaveChildren || element.canHaveChildren) {
  462. element.appendChild(anElement);
  463. } else {
  464. element.text = String(element.text) + anElement.innerHTML;
  465. } >
  466. !
  467. appendString: aString
  468. self appendChild: (self createTextNodeFor: aString)
  469. !
  470. appendToBrush: aTagBrush
  471. aTagBrush addBrush: self
  472. !
  473. contents: anObject
  474. self
  475. empty;
  476. append: anObject
  477. !
  478. empty
  479. self asJQuery empty
  480. !
  481. with: anObject
  482. self append: anObject
  483. ! !
  484. !TagBrush methodsFor: 'attributes'!
  485. accesskey: aString
  486. self at: 'accesskey' put: aString
  487. !
  488. action: aString
  489. self at: 'action' put: aString
  490. !
  491. align: aString
  492. self at: 'align' put: aString
  493. !
  494. alt: aString
  495. self at: 'alt' put: aString
  496. !
  497. at: aString put: aValue
  498. <self['@element'].setAttribute(aString, aValue)>
  499. !
  500. class: aString
  501. <self['@element'].className = aString>
  502. !
  503. cols: aString
  504. self at: 'cols' put: aString
  505. !
  506. contenteditable: aString
  507. self at: 'contenteditable' put: aString
  508. !
  509. contextmenu: aString
  510. self at: 'contextmenu' put: aString
  511. !
  512. draggable: aString
  513. self at: 'draggable' put: aString
  514. !
  515. for: aString
  516. self at: 'for' put: aString
  517. !
  518. height: aString
  519. self at: 'height' put: aString
  520. !
  521. hidden
  522. self at: 'hidden' put: 'hidden'
  523. !
  524. href: aString
  525. self at: 'href' put: aString
  526. !
  527. id: aString
  528. self at: 'id' put: aString
  529. !
  530. media: aString
  531. self at: 'media' put: aString
  532. !
  533. method: aString
  534. self at: 'method' put: aString
  535. !
  536. name: aString
  537. self at: 'name' put: aString
  538. !
  539. placeholder: aString
  540. self at: 'placeholder' put: aString
  541. !
  542. rel: aString
  543. self at: 'rel' put: aString
  544. !
  545. removeAt: aString
  546. <self['@element'].removeAttribute(aString)>
  547. !
  548. rows: aString
  549. self at: 'rows' put: aString
  550. !
  551. src: aString
  552. self at: 'src' put: aString
  553. !
  554. style: aString
  555. self at: 'style' put: aString
  556. !
  557. tabindex: aNumber
  558. self at: 'tabindex' put: aNumber
  559. !
  560. target: aString
  561. self at: 'target' put: aString
  562. !
  563. title: aString
  564. self at: 'title' put: aString
  565. !
  566. type: aString
  567. self at: 'type' put: aString
  568. !
  569. valign: aString
  570. self at: 'valign' put: aString
  571. !
  572. value: aString
  573. self at: 'value' put: aString
  574. !
  575. width: aString
  576. self at: 'width' put: aString
  577. ! !
  578. !TagBrush methodsFor: 'converting'!
  579. asJQuery
  580. ^window jQuery: self element
  581. ! !
  582. !TagBrush methodsFor: 'events'!
  583. onBlur: aBlock
  584. self asJQuery bind: 'blur' do: aBlock
  585. !
  586. onChange: aBlock
  587. self asJQuery bind: 'change' do: aBlock
  588. !
  589. onClick: aBlock
  590. self asJQuery bind: 'click' do: aBlock
  591. !
  592. onDblClick: aBlock
  593. self asJQuery bind: 'dblclick' do: aBlock
  594. !
  595. onFocus: aBlock
  596. self asJQuery bind: 'focus' do: aBlock
  597. !
  598. onFocusIn: aBlock
  599. self asJQuery bind: 'focusin' do: aBlock
  600. !
  601. onFocusOut: aBlock
  602. self asJQuery bind: 'focusout' do: aBlock
  603. !
  604. onHover: aBlock
  605. self asJQuery bind: 'hover' do: aBlock
  606. !
  607. onKeyDown: aBlock
  608. self asJQuery bind: 'keydown' do: aBlock
  609. !
  610. onKeyPress: aBlock
  611. self asJQuery bind: 'keypress' do: aBlock
  612. !
  613. onKeyUp: aBlock
  614. self asJQuery bind: 'keyup' do: aBlock
  615. !
  616. onMouseDown: aBlock
  617. self asJQuery bind: 'mousedown' do: aBlock
  618. !
  619. onMouseEnter: aBlock
  620. self asJQuery bind: 'mouseenter' do: aBlock
  621. !
  622. onMouseLeave: aBlock
  623. self asJQuery bind: 'mouseleave' do: aBlock
  624. !
  625. onMouseMove: aBlock
  626. self asJQuery bind: 'mousemove' do: aBlock
  627. !
  628. onMouseOut: aBlock
  629. self asJQuery bind: 'mouseout' do: aBlock
  630. !
  631. onMouseOver: aBlock
  632. self asJQuery bind: 'mouseover' do: aBlock
  633. !
  634. onMouseUp: aBlock
  635. self asJQuery bind: 'mouseup' do: aBlock
  636. !
  637. onSelect: aBlock
  638. self asJQuery bind: 'select' do: aBlock
  639. !
  640. onSubmit: aBlock
  641. self asJQuery bind: 'submit' do: aBlock
  642. !
  643. onUnload: aBlock
  644. self asJQuery bind: 'unload' do: aBlock
  645. ! !
  646. !TagBrush methodsFor: 'initialization'!
  647. initializeFromJQuery: aJQuery canvas: aCanvas
  648. element := aJQuery get: 0.
  649. canvas := aCanvas
  650. !
  651. initializeFromString: aString canvas: aCanvas
  652. element := self createElementFor: aString.
  653. canvas := aCanvas
  654. ! !
  655. !TagBrush methodsFor: 'private'!
  656. createElementFor: aString
  657. <return document.createElement(String(aString))>
  658. !
  659. createTextNodeFor: aString
  660. <return document.createTextNode(String(aString))>
  661. ! !
  662. !TagBrush class methodsFor: 'instance creation'!
  663. fromJQuery: aJQuery canvas: aCanvas
  664. ^self new
  665. initializeFromJQuery: aJQuery canvas: aCanvas;
  666. yourself
  667. !
  668. fromString: aString canvas: aCanvas
  669. ^self new
  670. initializeFromString: aString canvas: aCanvas;
  671. yourself
  672. ! !
  673. TagBrush subclass: #StyleTag
  674. instanceVariableNames: 'canvas element'
  675. package: 'Canvas'!
  676. !StyleTag commentStamp!
  677. I'm a <style> tag use to inline CSS or load a stylesheet.
  678. For inlining handle IE compatibility problems.!
  679. !StyleTag methodsFor: 'adding'!
  680. with: aString
  681. HTMLCanvas isMSIE
  682. ifTrue: [self element styleSheet cssText: aString ]
  683. ifFalse: [super with: aString ].
  684. ! !
  685. !StyleTag class methodsFor: 'instance creation'!
  686. canvas: aCanvas
  687. ^self new
  688. initializeFromString: 'style' canvas: aCanvas;
  689. yourself
  690. ! !
  691. Object subclass: #Widget
  692. instanceVariableNames: ''
  693. package: 'Canvas'!
  694. !Widget methodsFor: 'adding'!
  695. appendToBrush: aTagBrush
  696. self appendToJQuery: aTagBrush asJQuery
  697. !
  698. appendToJQuery: aJQuery
  699. self renderOn: (HTMLCanvas onJQuery: aJQuery)
  700. ! !
  701. !Widget methodsFor: 'rendering'!
  702. renderOn: html
  703. self
  704. ! !
  705. !Object methodsFor: '*Canvas'!
  706. appendToBrush: aTagBrush
  707. aTagBrush append: self asString
  708. !
  709. appendToJQuery: aJQuery
  710. aJQuery append: self asString
  711. ! !
  712. !BlockClosure methodsFor: '*Canvas'!
  713. appendToBrush: aTagBrush
  714. aTagBrush appendBlock: self
  715. !
  716. appendToJQuery: aJQuery
  717. self value: (HTMLCanvas onJQuery: aJQuery)
  718. ! !
  719. !CharacterArray methodsFor: '*Canvas'!
  720. asSnippet
  721. ^ HtmlSnippet current at: self asString
  722. ! !
  723. !String methodsFor: '*Canvas'!
  724. appendToBrush: aTagBrush
  725. aTagBrush appendString: self
  726. !
  727. appendToJQuery: aJQuery
  728. aJQuery append: self
  729. !
  730. asJQuery
  731. <return jQuery(String(self))>
  732. ! !
  733. !HTMLCanvas methodsFor: '*Canvas'!
  734. snippet: anElement
  735. "Adds clone of anElement, finds [data-snippet=""*""] subelement
  736. and returns TagBrush as if that subelement was just added.
  737. Rarely needed to use directly, use `html foo` dynamically installed method
  738. for a snippet named foo."
  739. | clone caret |
  740. clone := anElement asJQuery clone.
  741. self with: (TagBrush fromJQuery: clone canvas: self).
  742. caret := clone find: '[data-snippet="*"]'.
  743. caret toArray isEmpty ifTrue: [ caret := clone ].
  744. ^TagBrush fromJQuery: (caret removeAttr: 'data-snippet') canvas: self
  745. ! !
  746. !JSObjectProxy methodsFor: '*Canvas'!
  747. asJQuery
  748. <return jQuery(self['@jsObject'])>
  749. ! !