diff options
Diffstat (limited to 'node_modules/montage/core/event')
-rwxr-xr-x | node_modules/montage/core/event/binding.js | 93 | ||||
-rwxr-xr-x | node_modules/montage/core/event/event-manager.js | 15 | ||||
-rwxr-xr-x | node_modules/montage/core/event/mutable-event.js | 5 |
3 files changed, 65 insertions, 48 deletions
diff --git a/node_modules/montage/core/event/binding.js b/node_modules/montage/core/event/binding.js index 0ce154a1..7a15e5b9 100755 --- a/node_modules/montage/core/event/binding.js +++ b/node_modules/montage/core/event/binding.js | |||
@@ -88,10 +88,19 @@ Object.defineProperty(ChangeEventDispatchingArray, "splice", { | |||
88 | removedMembers = this._splice.apply(this, arguments); | 88 | removedMembers = this._splice.apply(this, arguments); |
89 | removedCount = removedMembers.length; | 89 | removedCount = removedMembers.length; |
90 | 90 | ||
91 | // I stopped caring about whether or not this splice could be considered an ADDITION or REMOVAL | 91 | netChange = addedCount - removedCount; |
92 | // all splices result in a modification now; we could change this if we want to | 92 | |
93 | // Find the most accurate propertyChange type for this splice, | ||
94 | // For the most part it's considered a modification unless the length of the array was modified | ||
95 | // if only to not bother notifying listeners for changes of the length of this array | ||
93 | changeType = ChangeTypes.MODIFICATION; | 96 | changeType = ChangeTypes.MODIFICATION; |
94 | 97 | ||
98 | if (netChange > 0) { | ||
99 | changeType = ChangeTypes.ADDITION; | ||
100 | } else if (netChange < 0) { | ||
101 | changeType = ChangeTypes.REMOVAL; | ||
102 | } | ||
103 | |||
95 | if (this.dispatchChangeEvent) { | 104 | if (this.dispatchChangeEvent) { |
96 | changeEvent = new ChangeEventConstructor(); | 105 | changeEvent = new ChangeEventConstructor(); |
97 | changeEvent.minus = removedMembers; | 106 | changeEvent.minus = removedMembers; |
@@ -103,8 +112,6 @@ Object.defineProperty(ChangeEventDispatchingArray, "splice", { | |||
103 | 112 | ||
104 | if (this.dispatchChangeAtIndexEvent) { | 113 | if (this.dispatchChangeAtIndexEvent) { |
105 | 114 | ||
106 | netChange = addedCount - removedCount; | ||
107 | |||
108 | if (typeof howMany === "undefined") { | 115 | if (typeof howMany === "undefined") { |
109 | // no howMany argument given: remove all elements after index? | 116 | // no howMany argument given: remove all elements after index? |
110 | // TODO this may only be in some implementations | 117 | // TODO this may only be in some implementations |
@@ -498,7 +505,7 @@ var PropertyChangeBindingListener = exports.PropertyChangeBindingListener = Obje | |||
498 | localPrevValue = event.minus, | 505 | localPrevValue = event.minus, |
499 | localTarget = event.target, | 506 | localTarget = event.target, |
500 | type = event.type, | 507 | type = event.type, |
501 | changeType = event.propertyChange, //MODIFICATION is 1, ADDITION 2, REMOVAL 3, | 508 | changeType = event.propertyChange, |
502 | localPropertyName = event.propertyName, | 509 | localPropertyName = event.propertyName, |
503 | boundObjectValue, | 510 | boundObjectValue, |
504 | sourceObjectValue, | 511 | sourceObjectValue, |
@@ -508,7 +515,12 @@ var PropertyChangeBindingListener = exports.PropertyChangeBindingListener = Obje | |||
508 | baseType, | 515 | baseType, |
509 | bindingDescriptor, | 516 | bindingDescriptor, |
510 | bindingOrigin = this.bindingOrigin, | 517 | bindingOrigin = this.bindingOrigin, |
511 | leftOriginated; | 518 | leftOriginated, |
519 | changeOriginPropertyPath = null, | ||
520 | exploredPath, | ||
521 | remainingPath, | ||
522 | i, | ||
523 | localPrevValueCount; | ||
512 | 524 | ||
513 | if (target !== bindingOrigin) { | 525 | if (target !== bindingOrigin) { |
514 | //the left and the right are different objects; easy enough | 526 | //the left and the right are different objects; easy enough |
@@ -617,51 +629,46 @@ var PropertyChangeBindingListener = exports.PropertyChangeBindingListener = Obje | |||
617 | event.plus = localNewValue; | 629 | event.plus = localNewValue; |
618 | event.target = localTarget; | 630 | event.target = localTarget; |
619 | 631 | ||
632 | if (localPrevValue) { | ||
620 | 633 | ||
621 | // Now we know that we handled a particular type of change event | 634 | // Determine where along the property path the change originated from so we know how to build the path |
622 | // Depending on what happened we may need to remove listeners from a broken propertyPath or | 635 | // to stop observing on things that were removed |
623 | // install listeners along the modified (or deeper) propertyPath | 636 | //TODO extract this into a "obj.getPathOfObjectAlongPropertyPath" method or something with proper tests |
624 | 637 | exploredPath = ""; | |
625 | // MODIFICATION 1 | 638 | this.target.getProperty(this.targetPropertyPath, null, null, function(value, currentPathComponent, result) { |
626 | if (changeType === 1) { | ||
627 | |||
628 | if (localPrevValue) { | ||
629 | // TODO remove all the listeners from the localPrev object as far to tne end of the path as possible | ||
630 | // localPrevValue.removeEventListener(baseType, this, this.useCapture); | ||
631 | } | ||
632 | |||
633 | if (localNewValue) { | ||
634 | // TODO this may be less efficient than we could be, but frankly I don't know how to tell where | ||
635 | // in the path you are by the time you get here, so I'm not sure how to install just the part | ||
636 | // we need, plus addEventListener seems to use the targetPropertyPath from the listener | ||
637 | // regardless of what you pass in fro the eventType. | ||
638 | this.target.addEventListener(baseType + "@" + this.targetPropertyPath, this, this.useCapture); | ||
639 | } | ||
640 | 639 | ||
641 | } | 640 | if (changeOriginPropertyPath) { |
642 | //ADDITION 2, REMOVAL 3, typically on collections | 641 | return; |
642 | } | ||
643 | 643 | ||
644 | //TODO looks like we end up wanting to do the sam thing in both cases right now, I think the TODO in the | 644 | exploredPath += "." + currentPathComponent; |
645 | // modification explains why a bit. | ||
646 | else { | ||
647 | 645 | ||
648 | if (localPrevValue) { | 646 | if (result === event.target) { |
647 | changeOriginPropertyPath = exploredPath.replace(/^\./, ""); | ||
648 | } | ||
649 | }); | ||
649 | 650 | ||
650 | // TODO how do we know the nextPathComponent, we need to know the rest of the path after each | 651 | if (changeOriginPropertyPath) { |
651 | // entry in the localPrevValue array | 652 | remainingPath = this.targetPropertyPath.replace(new RegExp("^" + changeOriginPropertyPath + "\.?"), ""); |
652 | // for (var i = 0; i < localPrevValue.length; i++) { | 653 | } else { |
653 | localPrevValue.removeEventListener(nextPathComponent ? baseType + "@" + nextPathComponent : baseType, this, this.useCapture); | 654 | remainingPath = this.targetPropertyPath; |
654 | // } | ||
655 | } | 655 | } |
656 | 656 | ||
657 | if (localNewValue) { | 657 | // NOTE this check works around Safari not having a removeEventListener on its CanvasPixelArray |
658 | this.target.addEventListener(baseType + "@" + this.targetPropertyPath, this, this.useCapture); | 658 | // TODO investigate if this is an appropriate fix or not |
659 | } else if (event._event.plus) { | 659 | if (typeof localPrevValue.removeEventListener === "function") { |
660 | this.target.addEventListener(baseType + "@" + this.targetPropertyPath, this, this.useCapture); | 660 | localPrevValue.removeEventListener(baseType + "@" + remainingPath, this, this.useCapture); |
661 | } | 661 | } |
662 | } | ||
662 | 663 | ||
663 | 664 | if (localNewValue) { | |
665 | // Reinstall listeners along the entire propertyPath from the target | ||
666 | this.target.addEventListener(baseType + "@" + this.targetPropertyPath, this, this.useCapture); | ||
667 | } else if (event._event.plus) { | ||
668 | // TODO removing this causes no spec failures; looks suspicious | ||
669 | this.target.addEventListener(baseType + "@" + this.targetPropertyPath, this, this.useCapture); | ||
664 | } | 670 | } |
671 | |||
665 | } | 672 | } |
666 | targetPropertyPath = null; | 673 | targetPropertyPath = null; |
667 | target = null; | 674 | target = null; |
@@ -964,7 +971,7 @@ Object.defineProperty(Object.prototype, "addEventListener", { | |||
964 | anEvent.initCustomEvent("change@" + setter.property, true, false, null); | 971 | anEvent.initCustomEvent("change@" + setter.property, true, false, null); |
965 | anEvent.minus = prevValue; | 972 | anEvent.minus = prevValue; |
966 | anEvent.plus = acceptedValue; | 973 | anEvent.plus = acceptedValue; |
967 | anEvent.propertyChange = 1;//MODIFICATION, ADDITION, REMOVAL | 974 | anEvent.propertyChange = ChangeTypes.MODIFICATION; |
968 | anEvent.propertyName = setter.property; | 975 | anEvent.propertyName = setter.property; |
969 | this.dispatchEvent(anEvent); | 976 | this.dispatchEvent(anEvent); |
970 | } | 977 | } |
@@ -1041,7 +1048,7 @@ Object.defineProperty(Object.prototype, "addEventListener", { | |||
1041 | anEvent.initCustomEvent("change@" + setter.property, true, false, null); | 1048 | anEvent.initCustomEvent("change@" + setter.property, true, false, null); |
1042 | anEvent.minus = prevValue; | 1049 | anEvent.minus = prevValue; |
1043 | anEvent.plus = acceptedValue; | 1050 | anEvent.plus = acceptedValue; |
1044 | anEvent.propertyChange = 1;//MODIFICATION, ADDITION, REMOVAL | 1051 | anEvent.propertyChange = ChangeTypes.MODIFICATION; |
1045 | anEvent.propertyName = setter.property; | 1052 | anEvent.propertyName = setter.property; |
1046 | this.dispatchEvent(anEvent); | 1053 | this.dispatchEvent(anEvent); |
1047 | } | 1054 | } |
diff --git a/node_modules/montage/core/event/event-manager.js b/node_modules/montage/core/event/event-manager.js index abc441c8..4adc3926 100755 --- a/node_modules/montage/core/event/event-manager.js +++ b/node_modules/montage/core/event/event-manager.js | |||
@@ -24,6 +24,9 @@ var Montage = require("montage").Montage, | |||
24 | Deserializer = require("core/deserializer").Deserializer, | 24 | Deserializer = require("core/deserializer").Deserializer, |
25 | defaultEventManager; | 25 | defaultEventManager; |
26 | 26 | ||
27 | // XXX Does not presently function server-side | ||
28 | if (typeof window !== "undefined") { // client-side | ||
29 | |||
27 | /* This is to handle browsers that have TouchEvents but don't have the global constructor function Touch */ | 30 | /* This is to handle browsers that have TouchEvents but don't have the global constructor function Touch */ |
28 | //if(TouchEvent && typeof window.Touch === "undefined") { | 31 | //if(TouchEvent && typeof window.Touch === "undefined") { |
29 | // HACK: The commented expression fails because Chrome on the desktop also has TouchEvent and in the code we're either registering touch events OR mouse events on most components. | 32 | // HACK: The commented expression fails because Chrome on the desktop also has TouchEvent and in the code we're either registering touch events OR mouse events on most components. |
@@ -91,12 +94,12 @@ var EventListenerDescriptor = Montage.create(Montage, { | |||
91 | serializable: true, | 94 | serializable: true, |
92 | value: null | 95 | value: null |
93 | }, | 96 | }, |
94 | 97 | ||
95 | listener: { | 98 | listener: { |
96 | serializable: "reference", | 99 | serializable: "reference", |
97 | value: null | 100 | value: null |
98 | }, | 101 | }, |
99 | 102 | ||
100 | capture: { |