DOMite.st 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. Smalltalk createPackage: 'DOMite'!
  2. Object subclass: #Domite
  3. instanceVariableNames: 'element reference'
  4. package: 'DOMite'!
  5. !Domite commentStamp!
  6. I am (hopefully thin) wrapper around the notion of "cursor in a page".
  7. I represent a DOM node _and_ a point where
  8. to insert new content into it.
  9. So I play both the role of a container that inserts
  10. as well as the role of an element being inserted.
  11. Creation API:
  12. - `Domite new` creates an insertion point at the bottom of `<body>`.
  13. - `Domite open` is unique way to create pieces of content. It creates an instance "floating in thin air" (wrapper around DOM DocumentFragment) that can be filled with any contents and then inserted in a page.
  14. - `Domite fromElement: aDomElement` wraps an element and set the cursor to its end.
  15. Manipulation API:
  16. - `aDomite insertDomite:` and `aDomite insertString:` insert either a Domite or a text content at the insertion point.
  17. - `aDomite clearHere` deletes contents of the wrapped element.
  18. Cursor moving API:
  19. Take this sample HTML, where `[n]` are just markers, not real content:
  20. ```
  21. <body>
  22. <h1>header</h1>
  23. [4]<p>[2]Hello[1]world[3]</p>[5]
  24. <small>footer</small>
  25. </body>
  26. ```
  27. If `d` is a `Domite` representing `[1]`, then:
  28. - `d seekHereStart` would move `d` to be at `[2]`,
  29. - `d seekHereEnd` would move `d` to be at `[3]`,
  30. - `d seekBeforeHere` would move `d` to be at `[4]`, and
  31. - `d seekAfterHere` would move `d` to be at `[5]`.
  32. It is not presumed one would use `seekXxx`
  33. to actually move around in a single instance.
  34. It is envisioned this API will be used mostly
  35. in combination with `copy`, like
  36. `afterMe := self copy seekAfterHere`.!
  37. !Domite methodsFor: 'accessing'!
  38. attrAt: aString
  39. (element hasAttribute: aString)
  40. ifTrue: [ ^ element getAttribute: aString ]
  41. ifFalse: [ ^ nil ]
  42. !
  43. attrAt: aString put: anotherString
  44. element setAttribute: aString to: anotherString
  45. !
  46. element
  47. ^ element
  48. !
  49. element: anObject
  50. element := anObject
  51. !
  52. propAt: aString
  53. ^ element at: aString
  54. !
  55. propAt: aString put: anObject
  56. ^ element at: aString put: anObject
  57. !
  58. reference
  59. ^ reference
  60. !
  61. reference: anObject
  62. reference := anObject
  63. ! !
  64. !Domite methodsFor: 'deletion'!
  65. clearHere
  66. <
  67. var element = self['@element'], child;
  68. while (child = element.firstChild) element.removeChild(child);
  69. self['@reference'] = null;
  70. >
  71. ! !
  72. !Domite methodsFor: 'events'!
  73. off: aString unbind: aBlock
  74. self removeEventListener: aString block: aBlock useCapture: false
  75. !
  76. on: aString bind: aBlock
  77. self addEventListener: aString block: aBlock useCapture: false
  78. ! !
  79. !Domite methodsFor: 'initialization'!
  80. initialize
  81. super initialize.
  82. element := document body.
  83. reference := nil asJSON
  84. ! !
  85. !Domite methodsFor: 'insertion'!
  86. insertDomite: aDomite
  87. self insertElement: aDomite element
  88. !
  89. insertElement: aDomElement
  90. self element
  91. insertBefore: aDomElement
  92. reference: self reference
  93. !
  94. insertString: aString
  95. self insertElement: (
  96. document createTextNode: aString asString )
  97. ! !
  98. !Domite methodsFor: 'navigation'!
  99. seekAfterHere
  100. self
  101. reference: self element nextSibling;
  102. element: self element parentNode
  103. !
  104. seekBeforeHere
  105. self
  106. reference: self element;
  107. element: self element parentNode
  108. !
  109. seekHereEnd
  110. self reference: nil asJSON "null"
  111. !
  112. seekHereStart
  113. self reference: self element firstChild
  114. ! !
  115. !Domite methodsFor: 'testing'!
  116. canSeekOutOfHere
  117. ^ self element parentNode notNil
  118. !
  119. isInvalid
  120. ^ self element isNil
  121. ! !
  122. !Domite class methodsFor: 'instance creation'!
  123. fromElement: aDomElement
  124. ^ self new
  125. element: aDomElement;
  126. yourself
  127. !
  128. fromElement: aDomElement cursorBefore: anotherDomElement
  129. ^ self new
  130. element: aDomElement;
  131. referenceElement: anotherDomElement;
  132. yourself
  133. !
  134. fromSelector: aString
  135. ^ self fromElement: (document querySelector: aString)
  136. !
  137. newElement: aString
  138. ^ self fromElement: (document createElement: aString)
  139. !
  140. open
  141. ^ self fromElement: document createDocumentFragment
  142. ! !