implemented observePath, fixed some inconsistencies
This commit is contained in:
parent
c95dae3c33
commit
1ace3e3120
@ -14,16 +14,11 @@ Y({
|
|||||||
window.yconfig = yconfig
|
window.yconfig = yconfig
|
||||||
var textarea = document.getElementById('textfield')
|
var textarea = document.getElementById('textfield')
|
||||||
var contenteditable = document.getElementById('contenteditable')
|
var contenteditable = document.getElementById('contenteditable')
|
||||||
yconfig.root.observe(function (events) {
|
yconfig.root.observePath(['text'], function (text) {
|
||||||
for (var e in events) {
|
if (text != null) {
|
||||||
var event = events[e]
|
text.bind(textarea)
|
||||||
if (event.name === 'text' && (event.type === 'add' || event.type === 'update')) {
|
text.bind(contenteditable)
|
||||||
event.object.get(event.name).then(function (text) { // eslint-disable-line
|
window.ytext = text
|
||||||
text.bind(textarea)
|
|
||||||
text.bind(contenteditable)
|
|
||||||
window.ytext = text
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
yconfig.root.set('text', Y.TextBind)
|
yconfig.root.set('text', Y.TextBind)
|
||||||
|
@ -81,6 +81,7 @@ class AbstractTransaction {
|
|||||||
/*
|
/*
|
||||||
Get a type based on the id of its model.
|
Get a type based on the id of its model.
|
||||||
If it does not exist yes, create it.
|
If it does not exist yes, create it.
|
||||||
|
TODO: delete type from store.initializedTypes[id] when corresponding id was deleted!
|
||||||
*/
|
*/
|
||||||
* getType (id) {
|
* getType (id) {
|
||||||
var sid = JSON.stringify(id)
|
var sid = JSON.stringify(id)
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
/* global createUsers, wait, Y, compareAllUsers, getRandomNumber, applyRandomTransactions, async, garbageCollectAllUsers, describeManyTimes */
|
/* global createUsers, wait, Y, compareAllUsers, getRandomNumber, applyRandomTransactions, async, garbageCollectAllUsers, describeManyTimes */
|
||||||
/* eslint-env browser,jasmine */
|
/* eslint-env browser,jasmine */
|
||||||
|
|
||||||
var numberOfYArrayTests = 1000
|
var numberOfYArrayTests = 200
|
||||||
var repeatArrayTests = 5
|
var repeatArrayTests = 1
|
||||||
|
|
||||||
describe('Array Type', function () {
|
describe('Array Type', function () {
|
||||||
var y1, y2, y3, yconfig1, yconfig2, yconfig3, flushAll
|
var y1, y2, y3, yconfig1, yconfig2, yconfig3, flushAll
|
||||||
|
@ -3,12 +3,12 @@
|
|||||||
|
|
||||||
;(function () {
|
;(function () {
|
||||||
class YMap {
|
class YMap {
|
||||||
constructor (os, model) {
|
constructor (os, model, contents, opContents) {
|
||||||
this._model = model.id
|
this._model = model.id
|
||||||
this.os = os
|
this.os = os
|
||||||
this.map = Y.utils.copyObject(model.map)
|
this.map = Y.utils.copyObject(model.map)
|
||||||
this.contents = {}
|
this.contents = contents
|
||||||
this.opContents = {}
|
this.opContents = opContents
|
||||||
this.eventHandler = new Y.utils.EventHandler(ops => {
|
this.eventHandler = new Y.utils.EventHandler(ops => {
|
||||||
var userEvents = []
|
var userEvents = []
|
||||||
for (var i in ops) {
|
for (var i in ops) {
|
||||||
@ -84,12 +84,11 @@
|
|||||||
// return property.
|
// return property.
|
||||||
// if property does not exist, return null
|
// if property does not exist, return null
|
||||||
// if property is a type, return a promise
|
// if property is a type, return a promise
|
||||||
|
if (key == null) {
|
||||||
|
throw new Error('You must specify key!')
|
||||||
|
}
|
||||||
if (this.opContents[key] == null) {
|
if (this.opContents[key] == null) {
|
||||||
if (key == null) {
|
return this.contents[key]
|
||||||
return Y.utils.copyObject(this.contents)
|
|
||||||
} else {
|
|
||||||
return this.contents[key]
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
var oid = this.opContents[key]
|
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) {
|
delete (key) {
|
||||||
var right = this.map[key]
|
var right = this.map[key]
|
||||||
if (right != null) {
|
if (right != null) {
|
||||||
@ -161,10 +173,48 @@
|
|||||||
unobserve (f) {
|
unobserve (f) {
|
||||||
this.eventHandler.removeEventListener(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) {
|
observePath (path, f) {
|
||||||
var self = this
|
var self = this
|
||||||
if (path.length === 0) {
|
function observeProperty (events) {
|
||||||
this.observe(f)
|
// 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 () {
|
return Promise.resolve(function () {
|
||||||
self.unobserve(f)
|
self.unobserve(f)
|
||||||
})
|
})
|
||||||
@ -173,14 +223,15 @@
|
|||||||
var resetObserverPath = function () {
|
var resetObserverPath = function () {
|
||||||
var promise = self.get(path[0])
|
var promise = self.get(path[0])
|
||||||
if (!promise instanceof Promise) {
|
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)
|
promise = self.set(path[0], Y.Map)
|
||||||
}
|
}
|
||||||
return promise.then(function (map) {
|
return promise.then(function (map) {
|
||||||
return map.observePath(path.slice(1), f)
|
return map.observePath(path.slice(1), f)
|
||||||
}).then(function (_deleteChildObservers) {
|
}).then(function (_deleteChildObservers) {
|
||||||
|
// update deleteChildObservers
|
||||||
deleteChildObservers = _deleteChildObservers
|
deleteChildObservers = _deleteChildObservers
|
||||||
return Promise.resolve()
|
return Promise.resolve() // Promise does not return anything
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
var observer = function (events) {
|
var observer = function (events) {
|
||||||
@ -191,11 +242,14 @@
|
|||||||
if (event.type === 'add' || event.type === 'update') {
|
if (event.type === 'add' || event.type === 'update') {
|
||||||
resetObserverPath()
|
resetObserverPath()
|
||||||
}
|
}
|
||||||
|
// TODO: what about the delete events?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.observe(observer)
|
self.observe(observer)
|
||||||
return resetObserverPath().then(
|
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 () {
|
Promise.resolve(function () {
|
||||||
deleteChildObservers()
|
deleteChildObservers()
|
||||||
self.unobserve(observer)
|
self.unobserve(observer)
|
||||||
@ -223,8 +277,19 @@
|
|||||||
yield* this.applyCreatedOperations([model])
|
yield* this.applyCreatedOperations([model])
|
||||||
return modelid
|
return modelid
|
||||||
},
|
},
|
||||||
initType: function * YMapInitializer (os, model) { // eslint-disable-line
|
initType: function * YMapInitializer (os, model) {
|
||||||
return new YMap(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 */
|
/* eslint-env browser,jasmine */
|
||||||
|
|
||||||
var numberOfYMapTests = 100
|
var numberOfYMapTests = 100
|
||||||
var repeatMapTeasts = 10
|
var repeatMapTeasts = 1
|
||||||
|
|
||||||
describe('Map Type', function () {
|
describe('Map Type', function () {
|
||||||
var y1, y2, y3, y4, flushAll
|
var y1, y2, y3, y4, flushAll
|
||||||
@ -117,6 +117,18 @@ describe('Map Type', function () {
|
|||||||
}
|
}
|
||||||
done()
|
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) {
|
it('throws add & update & delete events (with type and primitive content)', async(function * (done) {
|
||||||
var event
|
var event
|
||||||
yield flushAll()
|
yield flushAll()
|
||||||
@ -170,7 +182,7 @@ describe('Map Type', function () {
|
|||||||
function compareMapValues (maps) {
|
function compareMapValues (maps) {
|
||||||
var firstMap
|
var firstMap
|
||||||
for (var map of maps) {
|
for (var map of maps) {
|
||||||
var val = map.get()
|
var val = map.getPrimitive()
|
||||||
if (firstMap == null) {
|
if (firstMap == null) {
|
||||||
firstMap = val
|
firstMap = val
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user