implement attributes on Y.Text
This commit is contained in:
parent
e1f0324840
commit
0aca7bbefa
@ -21,6 +21,10 @@ import {
|
|||||||
iterateDeletedStructs,
|
iterateDeletedStructs,
|
||||||
iterateStructs,
|
iterateStructs,
|
||||||
findMarker,
|
findMarker,
|
||||||
|
typeMapDelete,
|
||||||
|
typeMapSet,
|
||||||
|
typeMapGet,
|
||||||
|
typeMapGetAll,
|
||||||
updateMarkerChanges,
|
updateMarkerChanges,
|
||||||
ArraySearchMarker, AbstractUpdateDecoder, AbstractUpdateEncoder, ID, Doc, Item, Snapshot, Transaction // eslint-disable-line
|
ArraySearchMarker, AbstractUpdateDecoder, AbstractUpdateEncoder, ID, Doc, Item, Snapshot, Transaction // eslint-disable-line
|
||||||
} from '../internals.js'
|
} from '../internals.js'
|
||||||
@ -512,13 +516,32 @@ export class YTextEvent extends YEvent {
|
|||||||
/**
|
/**
|
||||||
* @param {YText} ytext
|
* @param {YText} ytext
|
||||||
* @param {Transaction} transaction
|
* @param {Transaction} transaction
|
||||||
|
* @param {Set<any>} subs The keys that changed
|
||||||
*/
|
*/
|
||||||
constructor (ytext, transaction) {
|
constructor (ytext, transaction, subs) {
|
||||||
super(ytext, transaction)
|
super(ytext, transaction)
|
||||||
/**
|
/**
|
||||||
* @type {Array<DeltaItem>|null}
|
* @type {Array<DeltaItem>|null}
|
||||||
*/
|
*/
|
||||||
this._delta = null
|
this._delta = null
|
||||||
|
/**
|
||||||
|
* Whether the children changed.
|
||||||
|
* @type {Boolean}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
this.childListChanged = false
|
||||||
|
/**
|
||||||
|
* Set of all changed attributes.
|
||||||
|
* @type {Set<string>}
|
||||||
|
*/
|
||||||
|
this.keysChanged = new Set()
|
||||||
|
subs.forEach((sub) => {
|
||||||
|
if (sub === null) {
|
||||||
|
this.childListChanged = true
|
||||||
|
} else {
|
||||||
|
this.keysChanged.add(sub)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -779,7 +802,7 @@ export class YText extends AbstractType {
|
|||||||
*/
|
*/
|
||||||
_callObserver (transaction, parentSubs) {
|
_callObserver (transaction, parentSubs) {
|
||||||
super._callObserver(transaction, parentSubs)
|
super._callObserver(transaction, parentSubs)
|
||||||
const event = new YTextEvent(this, transaction)
|
const event = new YTextEvent(this, transaction, parentSubs)
|
||||||
const doc = transaction.doc
|
const doc = transaction.doc
|
||||||
// If a remote change happened, we try to cleanup potential formatting duplicates.
|
// If a remote change happened, we try to cleanup potential formatting duplicates.
|
||||||
if (!transaction.local) {
|
if (!transaction.local) {
|
||||||
@ -1111,6 +1134,74 @@ export class YText extends AbstractType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes an attribute.
|
||||||
|
*
|
||||||
|
* @note Xml-Text nodes don't have attributes. You can use this feature to assign properties to complete text-blocks.
|
||||||
|
*
|
||||||
|
* @param {String} attributeName The attribute name that is to be removed.
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
removeAttribute (attributeName) {
|
||||||
|
if (this.doc !== null) {
|
||||||
|
transact(this.doc, transaction => {
|
||||||
|
typeMapDelete(transaction, this, attributeName)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
/** @type {Array<function>} */ (this._pending).push(() => this.removeAttribute(attributeName))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets or updates an attribute.
|
||||||
|
*
|
||||||
|
* @note Xml-Text nodes don't have attributes. You can use this feature to assign properties to complete text-blocks.
|
||||||
|
*
|
||||||
|
* @param {String} attributeName The attribute name that is to be set.
|
||||||
|
* @param {any} attributeValue The attribute value that is to be set.
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
setAttribute (attributeName, attributeValue) {
|
||||||
|
if (this.doc !== null) {
|
||||||
|
transact(this.doc, transaction => {
|
||||||
|
typeMapSet(transaction, this, attributeName, attributeValue)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
/** @type {Array<function>} */ (this._pending).push(() => this.setAttribute(attributeName, attributeValue))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an attribute value that belongs to the attribute name.
|
||||||
|
*
|
||||||
|
* @note Xml-Text nodes don't have attributes. You can use this feature to assign properties to complete text-blocks.
|
||||||
|
*
|
||||||
|
* @param {String} attributeName The attribute name that identifies the
|
||||||
|
* queried value.
|
||||||
|
* @return {any} The queried attribute value.
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
getAttribute (attributeName) {
|
||||||
|
return /** @type {any} */ (typeMapGet(this, attributeName))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all attribute name/value pairs in a JSON Object.
|
||||||
|
*
|
||||||
|
* @note Xml-Text nodes don't have attributes. You can use this feature to assign properties to complete text-blocks.
|
||||||
|
*
|
||||||
|
* @param {Snapshot} [snapshot]
|
||||||
|
* @return {Object<string, any>} A JSON Object that describes the attributes.
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
getAttributes (snapshot) {
|
||||||
|
return typeMapGetAll(this)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {AbstractUpdateEncoder} encoder
|
* @param {AbstractUpdateEncoder} encoder
|
||||||
*/
|
*/
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
YEvent,
|
YEvent,
|
||||||
YXmlElement, YXmlFragment, Transaction // eslint-disable-line
|
YXmlText, YXmlElement, YXmlFragment, Transaction // eslint-disable-line
|
||||||
} from '../internals.js'
|
} from '../internals.js'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -9,7 +9,7 @@ import {
|
|||||||
*/
|
*/
|
||||||
export class YXmlEvent extends YEvent {
|
export class YXmlEvent extends YEvent {
|
||||||
/**
|
/**
|
||||||
* @param {YXmlElement|YXmlFragment} target The target on which the event is created.
|
* @param {YXmlElement|YXmlText|YXmlFragment} target The target on which the event is created.
|
||||||
* @param {Set<string|null>} subs The set of changed attributes. `null` is included if the
|
* @param {Set<string|null>} subs The set of changed attributes. `null` is included if the
|
||||||
* child list changed.
|
* child list changed.
|
||||||
* @param {Transaction} transaction The transaction instance with wich the
|
* @param {Transaction} transaction The transaction instance with wich the
|
||||||
@ -25,7 +25,7 @@ export class YXmlEvent extends YEvent {
|
|||||||
this.childListChanged = false
|
this.childListChanged = false
|
||||||
/**
|
/**
|
||||||
* Set of all changed attributes.
|
* Set of all changed attributes.
|
||||||
* @type {Set<string|null>}
|
* @type {Set<string>}
|
||||||
*/
|
*/
|
||||||
this.attributesChanged = new Set()
|
this.attributesChanged = new Set()
|
||||||
subs.forEach((sub) => {
|
subs.forEach((sub) => {
|
||||||
|
@ -73,3 +73,17 @@ export const testTreewalker = tc => {
|
|||||||
t.assert(xml0.querySelector('p') === paragraph1, 'querySelector found paragraph1')
|
t.assert(xml0.querySelector('p') === paragraph1, 'querySelector found paragraph1')
|
||||||
compare(users)
|
compare(users)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {t.TestCase} tc
|
||||||
|
*/
|
||||||
|
export const testYtextAttributes = tc => {
|
||||||
|
const ydoc = new Y.Doc()
|
||||||
|
const ytext = /** @type {Y.XmlText} */ (ydoc.get('', Y.XmlText))
|
||||||
|
ytext.observe(event => {
|
||||||
|
t.compare(event.changes.keys.get('test'), { action: 'add', oldValue: undefined })
|
||||||
|
})
|
||||||
|
ytext.setAttribute('test', 42)
|
||||||
|
t.compare(ytext.getAttribute('test'), 42)
|
||||||
|
t.compare(ytext.getAttributes(), { test: 42 })
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user