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]
 | 
					 | 
				
			||||||
      if (event.name === 'text' && (event.type === 'add' || event.type === 'update')) {
 | 
					 | 
				
			||||||
        event.object.get(event.name).then(function (text) { // eslint-disable-line
 | 
					 | 
				
			||||||
      text.bind(textarea)
 | 
					      text.bind(textarea)
 | 
				
			||||||
      text.bind(contenteditable)
 | 
					      text.bind(contenteditable)
 | 
				
			||||||
      window.ytext = text
 | 
					      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 (this.opContents[key] == null) {
 | 
					 | 
				
			||||||
      if (key == null) {
 | 
					      if (key == null) {
 | 
				
			||||||
          return Y.utils.copyObject(this.contents)
 | 
					        throw new Error('You must specify key!')
 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
          return this.contents[key]
 | 
					 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					      if (this.opContents[key] == null) {
 | 
				
			||||||
 | 
					        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