diff --git a/compute/compute.js b/compute/compute.js index be99806d285..d4fa361b05b 100644 --- a/compute/compute.js +++ b/compute/compute.js @@ -126,29 +126,38 @@ steal('can/util', 'can/util/bind', 'can/util/batch', function (can, bind) { obEv, name; // Go through what needs to be observed. - for( name in newObserveSet ) { - - if( oldObserved[name] ) { - // After binding is set up, values - // in `oldObserved` will be unbound. So if a name - // has already be observed, remove from `oldObserved` - // to prevent this. - delete oldObserved[name]; - } else { - // If current name has not been observed, listen to it. - obEv = newObserveSet[name]; - obEv.obj.bind(obEv.event, onchanged); - } + bindNewSet(oldObserved, newObserveSet, onchanged); + unbindOldSet(oldObserved, onchanged); + + return info; + }; + // This will not be optimized. + var bindNewSet = function(oldObserved, newObserveSet, onchanged){ + for(var name in newObserveSet ) { + bindOrPreventUnbinding(oldObserved, newObserveSet, name, onchanged); } - - // Iterate through oldObserved, looking for observe/attributes - // that are no longer being bound and unbind them. - for ( name in oldObserved) { + }; + // This will be optimized. + var bindOrPreventUnbinding = function(oldObserved, newObserveSet, name, onchanged){ + if( oldObserved[name] ) { + // After binding is set up, values + // in `oldObserved` will be unbound. So if a name + // has already be observed, remove from `oldObserved` + // to prevent this. + delete oldObserved[name]; + } else { + // If current name has not been observed, listen to it. + obEv = newObserveSet[name]; + obEv.obj.bind(obEv.event, onchanged); + } + }; + // Iterate through oldObserved, looking for observe/attributes + // that are no longer being bound and unbind them. + var unbindOldSet = function(oldObserved, onchanged){ + for (var name in oldObserved) { obEv = oldObserved[name]; obEv.obj.unbind(obEv.event, onchanged); } - - return info; }; // ### updateOnChange @@ -257,7 +266,7 @@ steal('can/util', 'can/util/bind', 'can/util/batch', function (can, bind) { }, setCached = set, // Save arguments for cloning - args = can.makeArray(arguments), + args = [], // updater for when value is changed updater = function (newValue, oldValue, batchNum) { setCached(newValue); @@ -265,6 +274,13 @@ steal('can/util', 'can/util/bind', 'can/util/batch', function (can, bind) { }, // the form of the arguments form; + + + // convert arguments to args to make V8 Happy + for(var i = 0, arglen = arguments.length; i< arglen; i++){ + args[i] = arguments[i]; + } + computed = function (newVal) { // If the computed function is called with arguments, // a value should be set diff --git a/map/bubble.js b/map/bubble.js index f9892665f71..bedb9f58ad2 100644 --- a/map/bubble.js +++ b/map/bubble.js @@ -53,6 +53,9 @@ steal('can/util', function(can){ can.stopListening.call(parent, child, eventName); } }, + isBubbling: function(parent, eventName){ + return parent._bubbleBindings && parent._bubbleBindings[eventName]; + }, bind: function(parent, eventName) { if (!parent._init ) { var bubbleEvent = bubble.event(parent, eventName); diff --git a/map/map.js b/map/map.js index eb2b64f07f8..2183c44480d 100644 --- a/map/map.js +++ b/map/map.js @@ -300,17 +300,24 @@ steal('can/util', 'can/util/bind','./bubble.js', 'can/construct', 'can/util/batc target: ev.target }, [newVal, oldVal]); + + }, + // Trigger a change event. + _triggerChange: function (attr, how, newVal, oldVal) { + // so this change can bubble ... a bubbling change triggers the + // _changes trigger + if(bubble.isBubbling(this, "change")) { + can.batch.trigger(this, "change", [attr, how, newVal, oldVal]); + } else { + can.batch.trigger(this, attr, [newVal, oldVal]); + } + if(how === "remove" || how === "add") { can.batch.trigger(this, { - type: "__keys", - batchNum: ev.batchNum + type: "__keys" }); } }, - // Trigger a change event. - _triggerChange: function (attr, how, newVal, oldVal) { - can.batch.trigger(this, "change", arguments); - }, // Iterator that does not trigger live binding. _each: function (callback) { var data = this.__get(); @@ -384,8 +391,10 @@ steal('can/util', 'can/util/bind','./bubble.js', 'can/construct', 'can/util/batc // Reads a property from the `object`. _get: function (attr) { var value; + // Handles the case of a key having a `.` in its name - if (typeof attr === 'string' && !! ~attr.indexOf('.')) { + // Otherwise we have to dig deeper into the Map to get the value. + if( typeof attr === 'string' && !! ~attr.indexOf('.') ) { // Attempt to get the value value = this.__get(attr); // For keys with a `.` in them, value will be defined @@ -393,12 +402,13 @@ steal('can/util', 'can/util/bind','./bubble.js', 'can/construct', 'can/util/batc return value; } } - - // Otherwise we have to dig deeper into the Map to get the value. + // First, break up the attr (`"foo.bar"`) into parts like `["foo","bar"]`. var parts = can.Map.helpers.attrParts(attr), // Then get the value of the first attr name (`"foo"`). current = this.__get(parts.shift()); + + // If there are other attributes to read... return parts.length ? // and current has a value... @@ -475,7 +485,7 @@ steal('can/util', 'can/util/bind','./bubble.js', 'can/construct', 'can/util/batc if (value !== current) { // Check if we are adding this for the first time -- // if we are, we need to create an `add` event. - var changeType = this.__get() + var changeType = current !== undefined || this.__get() .hasOwnProperty(prop) ? "set" : "add"; // Set the value on `_data` and hook it up to send event. @@ -500,7 +510,7 @@ steal('can/util', 'can/util/bind','./bubble.js', 'can/construct', 'can/util/batc } // Add property directly for easy writing. // Check if its on the `prototype` so we don't overwrite methods like `attrs`. - if (!can.isFunction(this.constructor.prototype[prop]) && !this._computedBindings[prop] ) { + if (! typeof this.constructor.prototype[prop] === 'function' && !this._computedBindings[prop] ) { this[prop] = val; } }, diff --git a/map/test.html b/map/test.html index 01775986460..16ff9b68e4c 100644 --- a/map/test.html +++ b/map/test.html @@ -22,10 +22,13 @@
} QUnit.config.autostart = false; - steal("can/map/map_test.js", function() { - can.dev.logLevel = 3; - QUnit.start(); - }); + setTimeout(function(){ + steal("can/map/map_test.js", function() { + can.dev.logLevel = 3; + QUnit.start(); + }); + },300); +