Skip to content

Commit aead3d7

Browse files
committed
Use existing add/removeEventListener for elements
This makes it possible to use can-define with HTML elements so that both property events and DOM events can be listened to and fire correctly. This is done by using the can-event/lifecycle/lifecycle mixin, and passing it our existing addEventListener (where it exists), rather than using canEvent.addEventListener as lifecycle did before. Closes #145
1 parent 4fbb7eb commit aead3d7

File tree

3 files changed

+69
-68
lines changed

3 files changed

+69
-68
lines changed

can-define.js

+63-51
Original file line numberDiff line numberDiff line change
@@ -83,15 +83,9 @@ module.exports = define = ns.define = function(objPrototype, defines, baseDefine
8383
return data;
8484
});
8585

86-
// Add necessary event methods to this object.
87-
for (var prop in eventsProto) {
88-
Object.defineProperty(objPrototype, prop, {
89-
enumerable: false,
90-
value: eventsProto[prop],
91-
configurable: true,
92-
writable: true
93-
});
94-
}
86+
// Mixin the event methods
87+
define.mixinEvents(objPrototype);
88+
9589
// add so instance defs can be dynamically added
9690
Object.defineProperty(objPrototype,"_define",{
9791
enumerable: false,
@@ -280,7 +274,7 @@ make = {
280274
if (newVal !== current) {
281275
setData.call(this, newVal);
282276

283-
canEvent.dispatch.call(this, {
277+
canEvent.trigger.call(this, {
284278
type: prop,
285279
target: this
286280
}, [newVal, current]);
@@ -642,50 +636,12 @@ replaceWith = function(obj, prop, cb, writable) {
642636
eventsProto = assign({}, event);
643637
assign(eventsProto, {
644638
_eventSetup: function() {},
645-
_eventTeardown: function() {},
646-
addEventListener: function(eventName, handler) {
647-
648-
var computedBinding = this._computed && this._computed[eventName];
649-
if (computedBinding && computedBinding.compute) {
650-
if (!computedBinding.count) {
651-
computedBinding.count = 1;
652-
computedBinding.compute.addEventListener("change", computedBinding.handler);
653-
} else {
654-
computedBinding.count++;
655-
}
656-
657-
}
658-
659-
var baseAddEventListener = this.__proto__.addEventListener ||
660-
eventLifecycle.addAndSetup;
661-
662-
return baseAddEventListener.apply(this, arguments);
663-
},
664-
665-
// ### unbind
666-
// Stops listening to an event.
667-
// If this is the last listener of a computed property,
668-
// stop forwarding events of the computed property to this map.
669-
removeEventListener: function(eventName, handler) {
670-
var computedBinding = this._computed && this._computed[eventName];
671-
if (computedBinding) {
672-
if (computedBinding.count === 1) {
673-
computedBinding.count = 0;
674-
computedBinding.compute.removeEventListener("change", computedBinding.handler);
675-
} else {
676-
computedBinding.count--;
677-
}
678-
679-
}
680-
681-
return eventLifecycle.removeAndTeardown.apply(this, arguments);
682-
683-
}
639+
_eventTeardown: function() {}
684640
});
685-
eventsProto.on = eventsProto.bind = eventsProto.addEventListener;
686-
eventsProto.off = eventsProto.unbind = eventsProto.removeEventListener;
687641

688642
delete eventsProto.one;
643+
delete eventsProto.addEventListener;
644+
delete eventsProto.removeEventListener;
689645

690646
define.setup = function(props, sealed) {
691647
defineConfigurableAndNotEnumerable(this, "_cid");
@@ -721,6 +677,62 @@ define.setup = function(props, sealed) {
721677
};
722678
define.replaceWith = replaceWith;
723679
define.eventsProto = eventsProto;
680+
define.mixinEvents = function(objPrototype, makeEnumerable){
681+
// Add necessary event methods to this object.
682+
for (var prop in eventsProto) {
683+
Object.defineProperty(objPrototype, prop, {
684+
enumerable: !!makeEnumerable,
685+
value: eventsProto[prop],
686+
configurable: true,
687+
writable: true
688+
});
689+
}
690+
691+
var baseAddEventListener = objPrototype.addEventListener ||
692+
canEvent.addEventListener;
693+
var baseRemoveEventListener = objPrototype.removeEventListener ||
694+
canEvent.removeEventListener;
695+
696+
objPrototype.addEventListener = function(eventName, handler) {
697+
var computedBinding = this._computed && this._computed[eventName];
698+
if (computedBinding && computedBinding.compute) {
699+
if (!computedBinding.count) {
700+
computedBinding.count = 1;
701+
computedBinding.compute.addEventListener("change", computedBinding.handler);
702+
} else {
703+
computedBinding.count++;
704+
}
705+
}
706+
707+
eventLifecycle.addAndSetup
708+
709+
return baseAddEventListener.apply(this, arguments);
710+
};
711+
712+
// ### unbind
713+
// Stops listening to an event.
714+
// If this is the last listener of a computed property,
715+
// stop forwarding events of the computed property to this map.
716+
objPrototype.removeEventListener = function(eventName, handler) {
717+
var computedBinding = this._computed && this._computed[eventName];
718+
if (computedBinding) {
719+
if (computedBinding.count === 1) {
720+
computedBinding.count = 0;
721+
computedBinding.compute.removeEventListener("change", computedBinding.handler);
722+
} else {
723+
computedBinding.count--;
724+
}
725+
726+
}
727+
728+
return baseRemoveEventListener.apply(this, arguments);
729+
};
730+
731+
eventLifecycle(objPrototype);
732+
733+
objPrototype.on = objPrototype.bind = objPrototype.addEventListener;
734+
objPrototype.off = objPrototype.unbind = objPrototype.removeEventListener;
735+
};
724736
define.defineConfigurableAndNotEnumerable = defineConfigurableAndNotEnumerable;
725737
define.make = make;
726738
define.getDefinitionOrMethod = getDefinitionOrMethod;

list/list.js

+2-8
Original file line numberDiff line numberDiff line change
@@ -1056,14 +1056,8 @@ assign(DefineList.prototype, {
10561056

10571057

10581058
// Add necessary event methods to this object.
1059-
for (var prop in define.eventsProto) {
1060-
DefineList[prop] = define.eventsProto[prop];
1061-
Object.defineProperty(DefineList.prototype, prop, {
1062-
enumerable: false,
1063-
value: define.eventsProto[prop],
1064-
writable: true
1065-
});
1066-
}
1059+
define.mixinEvents(DefineList, true);
1060+
define.mixinEvents(DefineList.prototype);
10671061

10681062
Object.defineProperty(DefineList.prototype, "length", {
10691063
get: function() {

map/map.js

+4-9
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ var setProps = function(props, remove) {
5656
}
5757
else if( ("replace" in curVal) && isArray(newVal)) {
5858
curVal.replace(newVal);
59-
}
59+
}
6060
else if( ("set" in curVal) && (isPlainObject(newVal) || isArray(newVal))) {
6161
curVal.set(newVal, remove);
6262
}
@@ -259,14 +259,9 @@ var DefineMap = Construct.extend("DefineMap",{
259259
});
260260

261261
// Add necessary event methods to this object.
262-
for(var prop in define.eventsProto) {
263-
DefineMap[prop] = define.eventsProto[prop];
264-
Object.defineProperty(DefineMap.prototype, prop, {
265-
enumerable:false,
266-
value: define.eventsProto[prop],
267-
writable: true
268-
});
269-
}
262+
define.mixinEvents(DefineMap, true);
263+
define.mixinEvents(DefineMap.prototype);
264+
270265
types.DefineMap = DefineMap;
271266
types.DefaultMap = DefineMap;
272267

0 commit comments

Comments
 (0)