Smalltalk createPackage: 'DOMite'! (Smalltalk packageAt: 'DOMite' ifAbsent: [ self error: 'Package not created: DOMite' ]) imports: {'amber_core/Platform-DOM'}! ProtoStream subclass: #Domite instanceVariableNames: 'element reference' package: 'DOMite'! !Domite commentStamp! I am (hopefully thin) wrapper around the notion of "cursor in a page". I represent a DOM node _and_ a point where to insert new content into it. So I play both the role of a container that inserts as well as the role of an element being inserted. I inherit from `ProtoStream`. Creation API: - `Domite new` creates an insertion point at the bottom of `
`. - `Domite newStream` 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. - `Domite fromElement: aDomElement` wraps an element and set the cursor to its end. - `Domite newElement: 'div'` creates new `` element (and returns it wrapped as a Domite). CSS selector API: - `Domite at: aSelector` wraps an element found by `document.querySelector(aSelector)`. - `aDomite at: aSelector` wraps an element found by `element.querySelector(aSelector)`. - `Domite allAt: aSelector` return collection of wrapped results of `document.querySelectorAll(aSelector)`. - `aDomite allAt: aSelector` return collection of wrapped results of `element.querySelectorAll(aSelector)`. Manipulation API: - `aDomite << obj` inserts obj at the insertion point. - `aDomite resetContents` deletes contents of the wrapped element. - `aDomite cutUpTo: anotherDomite` removes contents between the two cursors (or up to the end of the receiver) and returns it collected in a wrapped DocumentFragment (IOW, you can `anotherPlace << theResult` to move the contents in the specified range). - `aDomite attrAt: aString` returns attribute of the wrapped element or nil. - `aDomite attrAt: aString put: anotherString` sets an attribute of the wrapped element. - `aDomite propAt: aString` returns JS property of the wrapped element or nil. - `aDomite propAt: aString put: anObject` sets JS property of the wrapped element. Cursor moving API: Take this sample HTML, where `[n]` are just markers, not real content: ```[2]Hello[1]world[3]
[5] footer ``` If `d` is a `Domite` representing `[1]`, then: - `d setToStart` would move `d` to be at `[2]`, - `d setToEnd` would move `d` to be at `[3]`, - `d setToBefore` would move `d` to be at `[4]`, and - `d setToAfter` would move `d` to be at `[5]`. It is not presumed one would use `setToXxx` to actually move around in a single instance. It is envisioned this API will be used mostly in combination with `copy`, like `afterMe := self copy setToAfter`. Event API: - `aDomite on: aString bind: [ :ev | ... ]` binds a block to process an event. - `aDomite off: aString unbind: aBlock` unbinds the block from processing an event. - `aDomite fire: aString [detail: anObject]` triggers a CustomEvent with specified type and, optionally, a detail object. - `aDomite fireEvent: anEvent` triggers existing DOM Event object! !Domite methodsFor: 'accessing'! allAt: aString ^ self class wrap: (PlatformDom toArray: (self element querySelectorAll: aString)) ! at: aString ^ self class fromElement: (self element querySelector: aString) ! attrAt: aString (element hasAttribute: aString) ifTrue: [ ^ element getAttribute: aString ] ifFalse: [ ^ nil ] ! attrAt: aString put: anotherString element setAttribute: aString to: anotherString ! element ^ element ! element: anObject element := anObject ! propAt: aString ^ element at: aString ! propAt: aString put: anObject ^ element at: aString put: anObject ! reference ^ reference ! reference: anObject reference := anObject ! ! !Domite methodsFor: 'comparing'! = aDomite ^ self class = aDomite class and: [ self element = aDomite element and: [ self reference = aDomite reference ]] ! ! !Domite methodsFor: 'converting'! asDomNode ^ element ! asJQuery ^ self asDomNode asJQuery ! ! !Domite methodsFor: 'deletion'! cutUpTo: aDomite