示例#1
0
testBoth('implementing sendEvent on object should invoke when deferring property change notifications ends', function(get, set) {
  var count = 0;
  var events = [];
  var obj = {
    sendEvent(eventName) {
      events.push(eventName);
    },
    foo: 'baz'
  };

  addObserver(obj, 'foo', function() { count++; });

  beginPropertyChanges(obj);
  set(obj, 'foo', 'BAZ');

  equal(count, 0, 'should have not invoked observer');
  equal(events.length, 1, 'should have invoked sendEvent for before');

  endPropertyChanges(obj);

  equal(count, 1, 'should have invoked observer');
  equal(events.length, 2, 'should have invoked sendEvent');
  equal(events[0], 'foo:before');
  equal(events[1], 'foo:change');
});
示例#2
0
  removeAt: function(start, len) {
    if ('number' === typeof start) {
      var content = get(this, 'content');
      var arrangedContent = get(this, 'arrangedContent');
      var indices = [];
      var i;

      if ((start < 0) || (start >= get(this, 'length'))) {
        throw new EmberError(OUT_OF_RANGE_EXCEPTION);
      }

      if (len === undefined) len = 1;

      // Get a list of indices in original content to remove
      for (i=start; i<start+len; i++) {
        // Use arrangedContent here so we avoid confusion with objects transformed by objectAtContent
        indices.push(content.indexOf(arrangedContent.objectAt(i)));
      }

      // Replace in reverse order since indices will change
      indices.sort(function(a,b) { return b - a; });

      beginPropertyChanges();
      for (i=0; i<indices.length; i++) {
        this._replace(indices[i], 1, EMPTY);
      }
      endPropertyChanges();
    }

    return this ;
  },
示例#3
0
QUnit.test("computed properties that depend on multiple properties should run only once per run loop", function() {
  var obj = { a: 'a', b: 'b', c: 'c' };
  var cpCount = 0;
  var obsCount = 0;

  defineProperty(obj, 'abc', computed(function(key) {
    cpCount++;
    return 'computed '+key;
  }).property('a', 'b', 'c'));

  get(obj, 'abc');

  cpCount = 0;

  addObserver(obj, 'abc', function() {
    obsCount++;
  });

  beginPropertyChanges();
  set(obj, 'a', 'aa');
  set(obj, 'b', 'bb');
  set(obj, 'c', 'cc');
  endPropertyChanges();

  get(obj, 'abc');

  equal(cpCount, 1, "The computed property is only invoked once");
  equal(obsCount, 1, "The observer is only invoked once");
});
 removeObjects: function(objects) {
   beginPropertyChanges(this);
   for (var i = objects.length - 1; i >= 0; i--) {
     this.removeObject(objects[i]);
   }
   endPropertyChanges(this);
   return this;
 }
示例#5
0
testBoth('deferring property change notifications', function(get, set) {
  var obj = { foo: 'foo' };
  var fooCount = 0;

  addObserver(obj, 'foo', function() { fooCount++; });

  beginPropertyChanges(obj);
  set(obj, 'foo', 'BIFF');
  set(obj, 'foo', 'BAZ');
  endPropertyChanges(obj);

  equal(fooCount, 1, 'foo should have fired once');
});
 run(function() {
   beginPropertyChanges();
   // here we trigger several changes
   //  A. D.priority 3 -> 6
   //    1. updated sorted from item property change
   //      a. remove D; reinsert D
   //      b. update filtered from sorted change
   //    2. update filtered from item property change
   //
   // If 1.b happens before 2 it should invalidate 2
   todos.objectAt(1).set('priority', 6);
   endPropertyChanges();
 });
示例#7
0
testBoth('deferring property change notifications will not defer before observers', function(get, set) {
  var obj = { foo: 'foo' };
  var fooCount = 0;

  _addBeforeObserver(obj, 'foo', function() { fooCount++; });

  beginPropertyChanges(obj);
  set(obj, 'foo', 'BIFF');
  equal(fooCount, 1, 'should fire before observer immediately');
  set(obj, 'foo', 'BAZ');
  endPropertyChanges(obj);

  equal(fooCount, 1, 'should not fire before observer twice');
});
示例#8
0
文件: each_proxy.js 项目: 5y/ember.js
  arrayWillChange: function(content, idx, removedCnt, addedCnt) {
    var keys = this._keys, key, lim;

    lim = removedCnt>0 ? idx+removedCnt : -1;
    beginPropertyChanges(this);

    for(key in keys) {
      if (!keys.hasOwnProperty(key)) { continue; }

      if (lim>0) { removeObserverForContentKey(content, key, this, idx, lim); }

      propertyWillChange(this, key);
    }

    propertyWillChange(this._content, '@each');
    endPropertyChanges(this);
  },
示例#9
0
testBoth('suspending observers should not defer change notifications during callback', function(get, set) {
  var obj = {};
  var target, otherTarget;

  target = {
    values: [],
    method() { this.values.push(get(obj, 'foo')); }
  };

  otherTarget = {
    values: [],
    method() { this.values.push(get(obj, 'foo')); }
  };

  addObserver(obj, 'foo', target, target.method);
  addObserver(obj, 'foo', otherTarget, otherTarget.method);

  function callback() {
    /*jshint validthis:true */
    equal(this, target);

    set(obj, 'foo', '2');

    return 'result';
  }

  set(obj, 'foo', '1');

  beginPropertyChanges();
  equal(_suspendObservers(obj, ['foo'], target, target.method, callback), 'result');
  endPropertyChanges();

  set(obj, 'foo', '3');

  deepEqual(target.values, ['1', '3'], 'should invoke');
  deepEqual(otherTarget.values, ['1', '2', '3'], 'should invoke');
});
示例#10
0
    @method addObject
    @param {Object} object The object to add to the enumerable.
    @return {Object} the passed object
  */
  addObject: null,

  /**
    Adds each object in the passed enumerable to the receiver.

    @method addObjects
    @param {Ember.Enumerable} objects the objects to add.
    @return {Object} receiver
  */
  addObjects(objects) {
    beginPropertyChanges(this);
    forEach(objects, function(obj) { this.addObject(obj); }, this);
    endPropertyChanges(this);
    return this;
  },

  /**
    __Required.__ You must implement this method to apply this mixin.

    Attempts to remove the passed object from the receiver collection if the
    object is present in the collection. If the object is not present,
    this method has no effect.

    If the passed object is of a type not supported by the receiver,
    then this method should raise an exception.
示例#11
0
 run(function() {
   beginPropertyChanges();
   obj.set('foo', 'quux');
   obj.destroy();
   endPropertyChanges();
 });
示例#12
0
    Begins a grouping of property changes.

    You can use this method to group property changes so that notifications
    will not be sent until the changes are finished. If you plan to make a
    large number of changes to an object at one time, you should call this
    method at the beginning of the changes to begin deferring change
    notifications. When you are done making changes, call
    `endPropertyChanges()` to deliver the deferred change notifications and end
    deferring.

    @method beginPropertyChanges
    @return {Ember.Observable}
    @private
  */
  beginPropertyChanges() {
    beginPropertyChanges();
    return this;
  },

  /**
    Ends a grouping of property changes.

    You can use this method to group property changes so that notifications
    will not be sent until the changes are finished. If you plan to make a
    large number of changes to an object at one time, you should call
    `beginPropertyChanges()` at the beginning of the changes to defer change
    notifications. When you are done making changes, call this method to
    deliver the deferred change notifications and end deferring.

    @method endPropertyChanges
    @return {Ember.Observable}
示例#13
0
 addObjects: function(objects) {
   beginPropertyChanges(this);
   forEach(objects, function(obj) { this.addObject(obj); }, this);
   endPropertyChanges(this);
   return this;
 },
示例#14
0
 run(() => {
   beginPropertyChanges();
   obj.set('foo', 'quux');
   obj.destroy();
   endPropertyChanges();
 });
示例#15
0
 beginPropertyChanges: function() {
   beginPropertyChanges();
   return this;
 },