implemented observePath, fixed some inconsistencies
This commit is contained in:
parent
c95dae3c33
commit
1ace3e3120
@ -14,16 +14,11 @@ Y({
|
||||
window.yconfig = yconfig
|
||||
var textarea = document.getElementById('textfield')
|
||||
var contenteditable = document.getElementById('contenteditable')
|
||||
yconfig.root.observe(function (events) {
|
||||
for (var e in events) {
|
||||
var event = events[e]
|
||||
if (event.name === 'text' && (event.type === 'add' || event.type === 'update')) {
|
||||
event.object.get(event.name).then(function (text) { // eslint-disable-line
|
||||
yconfig.root.observePath(['text'], function (text) {
|
||||
if (text != null) {
|
||||
text.bind(textarea)
|
||||
text.bind(contenteditable)
|
||||
window.ytext = text
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
yconfig.root.set('text', Y.TextBind)
|
||||
|
@ -81,6 +81,7 @@ class AbstractTransaction {
|
||||
/*
|
||||
Get a type based on the id of its model.
|
||||
If it does not exist yes, create it.
|
||||
TODO: delete type from store.initializedTypes[id] when corresponding id was deleted!
|
||||
*/
|
||||
* getType (id) {
|
||||
var sid = JSON.stringify(id)
|
||||
|
@ -1,8 +1,8 @@
|
||||
/* global createUsers, wait, Y, compareAllUsers, getRandomNumber, applyRandomTransactions, async, garbageCollectAllUsers, describeManyTimes */
|
||||
/* eslint-env browser,jasmine */
|
||||
|
||||
var numberOfYArrayTests = 1000
|
||||
var repeatArrayTests = 5
|
||||
var numberOfYArrayTests = 200
|
||||
var repeatArrayTests = 1
|
||||
|
||||
describe('Array Type', function () {
|
||||
var y1, y2, y3, yconfig1, yconfig2, yconfig3, flushAll
|
||||
|
@ -3,12 +3,12 @@
|
||||
|
||||
;(function () {
|
||||
class YMap {
|
||||
constructor (os, model) {
|
||||
constructor (os, model, contents, opContents) {
|
||||
this._model = model.id
|
||||
this.os = os
|
||||
this.map = Y.utils.copyObject(model.map)
|
||||
this.contents = {}
|
||||
this.opContents = {}
|
||||
this.contents = contents
|
||||
this.opContents = opContents
|
||||
this.eventHandler = new Y.utils.EventHandler(ops => {
|
||||
var userEvents = []
|
||||
for (var i in ops) {
|
||||
@ -84,12 +84,11 @@
|
||||
// return property.
|
||||
// if property does not exist, return null
|
||||
// if property is a type, return a promise
|
||||
if (this.opContents[key] == null) {
|
||||
if (key == null) {
|
||||
return Y.utils.copyObject(this.contents)
|
||||
} else {
|
||||
return this.contents[key]
|
||||
throw new Error('You must specify key!')
|
||||
}
|
||||
if (this.opContents[key] == null) {
|
||||
return this.contents[key]
|
||||
} else {
|
||||
return new Promise((resolve) => {
|
||||
var oid = this.opContents[key]
|
||||
@ -99,6 +98,19 @@
|
||||
})
|
||||
}
|
||||
}
|
||||
/*
|
||||
If there is a primitive (not a custom type), then return it.
|
||||
Returns all primitive values, if propertyName is specified!
|
||||
Note: modifying the return value could result in inconsistencies!
|
||||
-- so make sure to copy it first!
|
||||
*/
|
||||
getPrimitive (key) {
|
||||
if (key == null) {
|
||||
return Y.utils.copyObject(this.contents)
|
||||
} else {
|
||||
return this.contents[key]
|
||||
}
|
||||
}
|
||||
delete (key) {
|
||||
var right = this.map[key]
|
||||
if (right != null) {
|
||||
@ -161,10 +173,48 @@
|
||||
unobserve (f) {
|
||||
this.eventHandler.removeEventListener(f)
|
||||
}
|
||||
/*
|
||||
Observe a path.
|
||||
|
||||
E.g.
|
||||
```
|
||||
o.set('textarea', Y.TextBind)
|
||||
o.observePath(['textarea'], function(t){
|
||||
// is called whenever textarea is replaced
|
||||
t.bind(textarea)
|
||||
})
|
||||
|
||||
returns a Promise that contains a function that removes the observer from the path.
|
||||
*/
|
||||
observePath (path, f) {
|
||||
var self = this
|
||||
if (path.length === 0) {
|
||||
this.observe(f)
|
||||
function observeProperty (events) {
|
||||
// call f whenever path changes
|
||||
for (var i = 0; i < events.length; i++) {
|
||||
var event = events[i]
|
||||
if (event.name === propertyName) {
|
||||
// call this also for delete events!
|
||||
var property = self.get(propertyName)
|
||||
if (property instanceof Promise) {
|
||||
property.then(f)
|
||||
} else {
|
||||
f(property)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (path.length < 1) {
|
||||
throw new Error('Path must contain at least one element!')
|
||||
} else if (path.length === 1) {
|
||||
var propertyName = path[0]
|
||||
var property = self.get(propertyName)
|
||||
if (property instanceof Promise) {
|
||||
property.then(f)
|
||||
} else {
|
||||
f(property)
|
||||
}
|
||||
this.observe(observeProperty)
|
||||
return Promise.resolve(function () {
|
||||
self.unobserve(f)
|
||||
})
|
||||
@ -173,14 +223,15 @@
|
||||
var resetObserverPath = function () {
|
||||
var promise = self.get(path[0])
|
||||
if (!promise instanceof Promise) {
|
||||
// its either not defined or a premitive value
|
||||
// its either not defined or a primitive value
|
||||
promise = self.set(path[0], Y.Map)
|
||||
}
|
||||
return promise.then(function (map) {
|
||||
return map.observePath(path.slice(1), f)
|
||||
}).then(function (_deleteChildObservers) {
|
||||
// update deleteChildObservers
|
||||
deleteChildObservers = _deleteChildObservers
|
||||
return Promise.resolve()
|
||||
return Promise.resolve() // Promise does not return anything
|
||||
})
|
||||
}
|
||||
var observer = function (events) {
|
||||
@ -191,11 +242,14 @@
|
||||
if (event.type === 'add' || event.type === 'update') {
|
||||
resetObserverPath()
|
||||
}
|
||||
// TODO: what about the delete events?
|
||||
}
|
||||
}
|
||||
}
|
||||
self.observe(observer)
|
||||
return resetObserverPath().then(
|
||||
// this promise contains a function that deletes all the child observers
|
||||
// and how to unobserve the observe from this object
|
||||
Promise.resolve(function () {
|
||||
deleteChildObservers()
|
||||
self.unobserve(observer)
|
||||
@ -223,8 +277,19 @@
|
||||
yield* this.applyCreatedOperations([model])
|
||||
return modelid
|
||||
},
|
||||
initType: function * YMapInitializer (os, model) { // eslint-disable-line
|
||||
return new YMap(os, model)
|
||||
initType: function * YMapInitializer (os, model) {
|
||||
var contents = {}
|
||||
var opContents = {}
|
||||
var map = model.map
|
||||
for (var name in map) {
|
||||
var op = yield* this.getOperation(map[name])
|
||||
if (op.opContent != null) {
|
||||
opContents[name] = op.opContent
|
||||
} else {
|
||||
contents[name] = op.content
|
||||
}
|
||||
}
|
||||
return new YMap(os, model, contents, opContents)
|
||||
}
|
||||
})
|
||||
})()
|
||||
|
@ -2,7 +2,7 @@
|
||||
/* eslint-env browser,jasmine */
|
||||
|
||||
var numberOfYMapTests = 100
|
||||
var repeatMapTeasts = 10
|
||||
var repeatMapTeasts = 1
|
||||
|
||||
describe('Map Type', function () {
|
||||
var y1, y2, y3, y4, flushAll
|
||||
@ -117,6 +117,18 @@ describe('Map Type', function () {
|
||||
}
|
||||
done()
|
||||
}))
|
||||
it('observePath properties', async(function * (done) {
|
||||
y1.observePath(['map'], function (map) {
|
||||
if (map != null) {
|
||||
map.set('yay', 4)
|
||||
}
|
||||
})
|
||||
yield y2.set('map', Y.Map)
|
||||
yield flushAll()
|
||||
var map = yield y3.get('map')
|
||||
expect(map.get('yay')).toEqual(4)
|
||||
done()
|
||||
}))
|
||||
it('throws add & update & delete events (with type and primitive content)', async(function * (done) {
|
||||
var event
|
||||
yield flushAll()
|
||||
@ -170,7 +182,7 @@ describe('Map Type', function () {
|
||||
function compareMapValues (maps) {
|
||||
var firstMap
|
||||
for (var map of maps) {
|
||||
var val = map.get()
|
||||
var val = map.getPrimitive()
|
||||
if (firstMap == null) {
|
||||
firstMap = val
|
||||
} else {
|
||||
|
Loading…
x
Reference in New Issue
Block a user