{"_id":"pop-observe","_rev":"48556","name":"pop-observe","description":"Property, range, map, and set content change observers for arrays, objects, and other instances.","dist-tags":{"latest":"2.0.2"},"maintainers":[{"name":"kriskowal","email":""}],"time":{"modified":"2021-06-03T10:14:54.000Z","created":"2015-03-05T16:47:28.245Z","2.0.2":"2015-03-08T08:00:56.309Z","2.0.1":"2015-03-07T21:59:56.446Z","2.0.0":"2015-03-07T21:53:33.884Z","1.1.0":"2015-03-06T16:43:29.781Z","1.0.0":"2015-03-05T16:47:28.245Z"},"users":{},"author":{"name":"Kris Kowal","email":"kris@cixar.com"},"repository":{"type":"git","url":"https://github.com/kriskowal/pop-observe.git"},"versions":{"2.0.2":{"name":"pop-observe","version":"2.0.2","description":"Property, range, map, and set content change observers for arrays, objects, and other instances.","main":"index.js","directories":{"test":"test"},"scripts":{"test":"jasminum test"},"repository":{"type":"git","url":"https://github.com/kriskowal/pop-observe.git"},"keywords":["observable","observe","observers","polymorphic","pop","change","object","array","map","set","range"],"author":{"name":"Kris Kowal","email":"kris@cixar.com"},"license":"MIT","bugs":{"url":"https://github.com/kriskowal/pop-observe/issues"},"homepage":"https://github.com/kriskowal/pop-observe","devDependencies":{"jasminum":"^2.0.6","sinon":"^1.12.2"},"dependencies":{"pop-equals":"^1.0.0","pop-has":"^1.0.0","pop-swap":"^1.0.0"},"gitHead":"54bd0e46b78db9c9b19dec764c2f09673ad4fee8","_id":"pop-observe@2.0.2","_shasum":"5acb5ac6f24c7c6ffab2c32151b0adb740eef363","_from":".","_npmVersion":"1.4.21","_npmUser":{"name":"kriskowal","email":"kris.kowal@cixar.com"},"maintainers":[{"name":"kriskowal","email":""}],"dist":{"shasum":"5acb5ac6f24c7c6ffab2c32151b0adb740eef363","size":17369,"noattachment":false,"key":"/pop-observe/-/pop-observe-2.0.2.tgz","tarball":"http://registry.cnpm.dingdandao.com/pop-observe/download/pop-observe-2.0.2.tgz"},"publish_time":1425801656309,"_cnpm_publish_time":1425801656309,"_hasShrinkwrap":false},"2.0.1":{"name":"pop-observe","version":"2.0.1","description":"Property, range, map, and set content change observers for arrays, objects, and other instances.","main":"index.js","directories":{"test":"test"},"scripts":{"test":"jasminum test"},"repository":{"type":"git","url":"https://github.com/kriskowal/pop-observe.git"},"keywords":["observable","observe","observers","polymorphic","pop","change","object","array","map","set","range"],"author":{"name":"Kris Kowal","email":"kris@cixar.com"},"license":"MIT","bugs":{"url":"https://github.com/kriskowal/pop-observe/issues"},"homepage":"https://github.com/kriskowal/pop-observe","devDependencies":{"jasminum":"^2.0.6","sinon":"^1.12.2"},"dependencies":{"pop-equals":"^1.0.0","pop-has":"^1.0.0","pop-swap":"^1.0.0"},"gitHead":"036ff2c6a57b1a873c4ced3cf578b6fe9b1eb5cc","_id":"pop-observe@2.0.1","_shasum":"cea4e10cdc27c62f89d7d97c6e9ae8e0891c5609","_from":".","_npmVersion":"1.4.21","_npmUser":{"name":"kriskowal","email":"kris.kowal@cixar.com"},"maintainers":[{"name":"kriskowal","email":""}],"dist":{"shasum":"cea4e10cdc27c62f89d7d97c6e9ae8e0891c5609","size":17359,"noattachment":false,"key":"/pop-observe/-/pop-observe-2.0.1.tgz","tarball":"http://registry.cnpm.dingdandao.com/pop-observe/download/pop-observe-2.0.1.tgz"},"publish_time":1425765596446,"_cnpm_publish_time":1425765596446,"_hasShrinkwrap":false},"2.0.0":{"name":"pop-observe","version":"2.0.0","description":"Property, range, map, and set content change observers for arrays, objects, and other instances.","main":"index.js","directories":{"test":"test"},"scripts":{"test":"jasminum test"},"repository":{"type":"git","url":"https://github.com/kriskowal/pop-observe.git"},"keywords":["observable","observe","observers","polymorphic","pop","change","object","array","map","set","range"],"author":{"name":"Kris Kowal","email":"kris@cixar.com"},"license":"MIT","bugs":{"url":"https://github.com/kriskowal/pop-observe/issues"},"homepage":"https://github.com/kriskowal/pop-observe","devDependencies":{"jasminum":"^2.0.6","sinon":"^1.12.2"},"dependencies":{"pop-equals":"^1.0.0","pop-has":"^1.0.0","pop-swap":"^1.0.0"},"gitHead":"23b2783b84f106d4f9f609460f383d9310c99f40","_id":"pop-observe@2.0.0","_shasum":"4bf817969df9d3b8667b17d1c903b3648d4336cf","_from":".","_npmVersion":"1.4.21","_npmUser":{"name":"kriskowal","email":"kris.kowal@cixar.com"},"maintainers":[{"name":"kriskowal","email":""}],"dist":{"shasum":"4bf817969df9d3b8667b17d1c903b3648d4336cf","size":17318,"noattachment":false,"key":"/pop-observe/-/pop-observe-2.0.0.tgz","tarball":"http://registry.cnpm.dingdandao.com/pop-observe/download/pop-observe-2.0.0.tgz"},"publish_time":1425765213884,"_cnpm_publish_time":1425765213884,"_hasShrinkwrap":false},"1.1.0":{"name":"pop-observe","version":"1.1.0","description":"Property, range, map, and set content change observers for arrays, objects, and other instances.","main":"index.js","directories":{"test":"test"},"scripts":{"test":"jasminum test"},"repository":{"type":"git","url":"https://github.com/kriskowal/pop-observe.git"},"keywords":["observable","observe","observers","polymorphic","pop","change","object","array","map","set","range"],"author":{"name":"Kris Kowal","email":"kris@cixar.com"},"license":"MIT","bugs":{"url":"https://github.com/kriskowal/pop-observe/issues"},"homepage":"https://github.com/kriskowal/pop-observe","devDependencies":{"jasminum":"^2.0.6","sinon":"^1.12.2"},"dependencies":{"pop-equals":"^1.0.0","pop-has":"^1.0.0","pop-swap":"^1.0.0"},"gitHead":"d81c6c4f96567b0fd986012f2e5b0283c8f76955","_id":"pop-observe@1.1.0","_shasum":"75f5978f5a785a54b6f739344ddd0df92a93ce03","_from":".","_npmVersion":"1.4.21","_npmUser":{"name":"kriskowal","email":"kris.kowal@cixar.com"},"maintainers":[{"name":"kriskowal","email":""}],"dist":{"shasum":"75f5978f5a785a54b6f739344ddd0df92a93ce03","size":16915,"noattachment":false,"key":"/pop-observe/-/pop-observe-1.1.0.tgz","tarball":"http://registry.cnpm.dingdandao.com/pop-observe/download/pop-observe-1.1.0.tgz"},"publish_time":1425660209781,"_cnpm_publish_time":1425660209781,"_hasShrinkwrap":false},"1.0.0":{"name":"pop-observe","version":"1.0.0","description":"Property, range, map, and set content change observers for arrays, objects, and other instances.","main":"index.js","directories":{"test":"test"},"scripts":{"test":"jasminum test"},"repository":{"type":"git","url":"https://github.com/kriskowal/pop-observe.git"},"keywords":["observable","observe","observers","polymorphic","pop","change","object","array","map","set","range"],"author":{"name":"Kris Kowal","email":"kris@cixar.com"},"license":"MIT","bugs":{"url":"https://github.com/kriskowal/pop-observe/issues"},"homepage":"https://github.com/kriskowal/pop-observe","devDependencies":{"jasminum":"^2.0.6","sinon":"^1.12.2"},"dependencies":{"pop-equals":"^1.0.0","pop-has":"^1.0.0","pop-swap":"^1.0.0"},"gitHead":"84e8d7f9dcf897365c3712a9278ed8f0762be0d8","_id":"pop-observe@1.0.0","_shasum":"254d5fe8426879f13aef99ee668a86fd6df67f7b","_from":".","_npmVersion":"1.4.21","_npmUser":{"name":"kriskowal","email":"kris.kowal@cixar.com"},"maintainers":[{"name":"kriskowal","email":""}],"dist":{"shasum":"254d5fe8426879f13aef99ee668a86fd6df67f7b","size":15763,"noattachment":false,"key":"/pop-observe/-/pop-observe-1.0.0.tgz","tarball":"http://registry.cnpm.dingdandao.com/pop-observe/download/pop-observe-1.0.0.tgz"},"publish_time":1425574048245,"_cnpm_publish_time":1425574048245,"_hasShrinkwrap":false}},"readme":"\n# Observable content changes\n\nThis JavaScript package, suitable for browsers and Node.js, provides a system\nfor synchronously observing content changes to arrays, objects, and other\ninstances.\nThese observers have a common, composable style, expose their internal state for\ndebugging, and reuse state tracking objects to reduce garbage collection.\n\n-   Changes can be captured before or after they are made.\n-   The last argument of a change notification is the object observed, so a\n    single handler can service multiple objects.\n-   Handler methods can return a child observer object, which will be implicitly\n    cancelled before the next change, so observers can be stacked.\n-   Does not alter the Array base type, but promotes array instances to an\n    ObservableArray when they are observed.\n\n## Installation\n\n```\nnpm install --save pop-observe@2\n```\n\n## Examples\n\nObserving the length of an array.\n\n```js\nvar array = [];\nvar observer = O.observePropertyChange(array, \"length\", function (length) {\n    expect(length).toBe(1);\n});\narray.push(10);\nobserver.cancel();\n```\n\nObserving a property of an ordinary object.\n\n```js\nvar object = {weight: 10};\nvar observer = O.observePropertyChange(object, \"weight\", function (weight) {\n    expect(weight).toBe(20);\n});\nobject.weight = 20;\nobserver.cancel();\n```\n\nObserving values at indexes.\n\n```js\nvar array = [];\nvar change;\nvar handler = {\n    handlePropertyChange: function (plus, minus, index, object) {\n        change = {\n            plus: plus,\n            minus: minus,\n            index: index,\n            object: object\n        };\n    }\n};\nvar observer0 = O.observePropertyChange(array, 0, handler);\nvar observer1 = O.observePropertyChange(array, 1, handler);\nvar observer2 = O.observePropertyChange(array, 2, handler);\n\narray.set(0, 10);\nexpect(change).toEqual({plus: 10, minus: undefined, index: 0, object: array});\n\narray.set(0, 20);\nexpect(change).toEqual({plus: 20, minus: 10, index: 0, object: array});\n\narray.set(1, 20);\nexpect(change).toEqual({plus: 20, minus: undefined, index: 1, object: array});\n```\n\nMirroring arrays.\n\n```js\nvar O = require(\"pop-observe\");\nvar swap = require(\"pop-swap\");\nvar array = [];\nvar mirror = [];\nvar observer = O.observeRangeChange(array, function (plus, minus, index) {\n    swap(mirror, index, minus.length, plus);\n});\narray.push(1, 2, 3);\narray.shift();\narray.pop();\nexpect(mirror).toEqual([2]);\nobserver.cancel();\n```\n\nTracking an array with a plain object.\n\n```js\nvar O = require(\"pop-observe\");\nvar array = [];\nvar object = {};\nvar observer = O.observeMapChange(array, function (plus, minus, index, type) {\n    if (type === \"delete\") {\n        delete object[index];\n    } else { // type === \"create\" || type === \"update\"\n        object[index] = plus;\n    }\n});\narray.push(1, 2, 3);\nexpect(object).toEqual({0: 1, 1: 2, 2: 3});\n\narray.splice(1, 1);\nexpect(object).toEqual({0: 1, 1: 3});\n```\n\nObserving a property of a property.\nNote that the cancel method gets rid of observers on a.b and b.c.\nNote that the b.c observer gets canceled every time b changes.\n\n```js\nvar O = require(\"pop-observe\");\nvar a = {b: {c: 10}};\nvar value;\nvar observer = O.observePropertyChange(a, \"b\", function (b) {\n    value = b.c;\n    return O.observePropertyChange(b, \"c\", function (c) {\n        value = c;\n    });\n});\n\na.b = {c: 20};\nexpect(value).toBe(20);\n\na.b.c = 30;\nexpect(value).toBe(30);\n\nobserver.cancel();\n```\n\n## Change notification arguments\n\n-   Property change observers dispatch (plus, minus, name, object) change\n    notifications when the value of a specific, named property changes.\n    Each observer sees the old value (minus), new value (plus), property name\n    (name), and the object (object) such that a single property change handler\n    can service multiple observers.\n    Observing a property of an ordinary object replaces that property with a\n    getter and setter.\n-   Range change observers dispatch (plus, minus, index, object) change\n    notifications when ordered values are removed (captured in a minus array),\n    then added (captured in the plus array), at a particular index.\n    Each handler also receives the object observed, so a single handler can\n    service multiple observers.\n-   Map change observers dispatch (plus, minus, key, object) change\n    notifications when the value for a specific key in a map has changed.\n  \n## Behavior on Arrays\n\n-   This library does not alter plain JavaScript arrays or the Array prototype.\n-   Observing an array transforms that array into an ObservableArray either by\n    subverting its prototype or adding properties directly to the instance.\n    Observable arrays have additional [swap][] and set methods.\n-   Observing any property change on an array transforms that array into an\n    observable array and property changes are dispatched for the \"length\" or any\n    value by its index.\n-   Observing range changes on an array transforms that array into an observable\n    array and all of its methods produce these change notifications.\n-   Observing any map change on an array transforms the array into an observable\n    array and map changes are dispatched for changes to the value at the given\n    index.\n\n[swap]: https://github.com/kriskowal/pop-swap\n\n## Custom types\n\nArbitrary constructors can mix in or inherit the ObservableObject type to\nsupport the observable interface directly and do not need to provide any further\nsupport.\n\n```js\nvar inherits = require(\"util\").inherits;\nvar ObservableObject = require(\"pop-observe/observable-object\");\nfunction Custom() {}\ninherits(Custom, ObservableObject);\n```\n\nArbitrary constructors can mix in or inherit the ObservableRangeChange type and\nmust explicitly dispatch change notifications when range change observers are\nactive.\n\n```js\nvar inherits = require(\"util\").inherits;\nvar ObservableRange = require(\"pop-observe/observable-range\");\nfunction Custom() {}\ninherits(Custom, ObservableRange);\nCustomer.prototype.unshift = function unshift(value) {\n    if (this.dispatchesRangeChanges) {\n        this.dispatchRangeWillChange([value], [], 0);\n    }\n    // actual work\n    if (this.dispatchesRangeChanges) {\n        this.dispatchRangeChange([value], [], 0);\n    }\n};\n```\n\nThis library does not provide any map implementations but provides the\nObservableMap for any to inherit or mix in.\n\n```js\nvar inherits = require(\"util\").inherits;\nvar ObservableMap = require(\"pop-observe/observable-map\");\nfunction Custom() {}\ninherits(Custom, ObservableMap);\nCustomer.prototype.delete = function delete(key) {\n    var old = this.get(key);\n    if (!old) {\n        return;\n    }\n    if (this.dispatchesMapChanges) {\n        this.dispatchMapWillChange(\"delete\", key, undefined, old);\n    }\n    // actual work\n    if (this.dispatchesMapChanges) {\n        this.dispatchMapChange(\"delete\", key, undefined, old);\n    }\n};\n```\n\nAll of thse can be mixed by copying the properties from their prototypes.\n\n```js\nvar ObservableObject = require(\"pop-observe/observable-object\");\n// Your favorite property copying idiom here\nvar owns = Object.prototype.hasOwnProperty;\nfor (var name in ObservableObject.prototype) {\n    if (owns.call(ObservableObject.prototype, name)) {\n        Customer.prototype[name] = ObservableObject.prototype[name];\n    }\n}\n```\n\n## Interface\n\nEach type of observer provides before and after methods for observation and\nmanual dispatch.\nFor properties, manual dispatch is necessary when a property is hidden behind a\ngetter and a setter *if* the value as returned by the getter changes without the\nsetter ever being invoked.\nArrays require manual dispatch only if the value at a given index changes\nwithout invoking an array mutation method.\nFor this reason, observable arrays have a `set(index, value)` method.\nAll ranged and map collections must implement manual dispatch when their\n`dispatchesRangeChanges` or `dispatchesMapChanges` properties are true.\n\nObject property change observers\n\n-   observePropertyChange(object, handler, note, capture) -> Observer\n-   observePropertyWillChange(object, handler, note) -> Observer\n-   dispatchPropertyChange(object, name, plus, minus, capture)\n-   dispatchPropertyWillChange(object, name, plus, minus)\n\n-   makePropertyObservable(object, name)\n-   preventPropertyObserver(object, name)\n\nRange change observers\n\n-   observeRangeChange(object, handler, note, capture) -> Observer\n-   observeRangeWillChange(object, handler, note) -> Observer\n-   dispatchRangeChange(object, plus, minus, index, capture)\n-   dispatchRangeWillChange(object, plus, minus, index)\n\nMap change observers\n\n-   observeMapChange(object, handler, note, capture) -> Observer\n-   observeMapWillChange(object, handler, note) -> Observer\n-   dispatchMapChange(object, type, key, plus, minus, capture)\n-   dispatchMapWillChange(object, type, key, plus, minus)\n\nObserver objects in general\n\n-   Observer.prototype.cancel();\n\n## Handlers\n\nHandlers may be raw functions, or objects with one or more handler methods.\nObservers for different kinds of changes and before and after changes call\ndifferent methods of the handler object based on their availability at the time\nthat the observer is created.\nFor example, `observePropertyWillChange(array, \"length\", handler)` will create a\nproperty observer that will delegate to the\n`handler.handleLengthPropertyWillChange(plus, minus, key, object)` method, or\njust that generic `handler.handlePropertyWillChange(plus, minus, key, object)`\nmethod if the specific method does not exist.\n\n-   observable object, property observers (plus, minus, key, object)\n    -   after change\n        -   specific: handleProperty*Name*Change\n        -   general: handlePropertyChange\n    -   before change\n        -   specific: handleProperty*Name*WillChange\n        -   general: handlePropertyWillChange\n\nRange changes do not operate on a given property name, but the\n`observeRangeChange(handler, name, note, capture)` method allows you to give the\nrange change a name, for example, the name of the array observed on a given\nobject.\n\n```js\nvar handler = {\n    handleValuesRangeChange: function (plus, minus, index, object) {\n        // ...\n    }\n};\nvar observer = repetition.values.observeRangeChange(handler, \"values\");\n// ...\nrepetition.values.push(10);\n// ...\nobserver.cancel();\n```\n\n-   observable range (plus, minus, index, object)\n    -   after change\n        -   specific: handle*Name*RangeChange\n        -   general: handleRangeChange\n    -   before change\n        -   specific: handle*Name*RangeWillChange\n        -   general: handleRangeWillChange\n\nLikewise, `observeMapChange(handler, name, note, capture)` accepts a name for a\nspecific handler method.\n\n-   observable map (plus, minus, key, object)\n    -   after change\n        -   specific: handle*Name*MapChange\n        -   general: handleMapChange\n    -   before change\n        -   specific: handle*Name*MapWillChange\n        -   general: handleMapWillChange\n\n## Observers\n\nObservers are re-usable objects that capture the state of the observer.\nMost importantly, they provide the `cancel` method, which disables the observer\nand returns it to a free list for the observer methods to re-use.\nThey are suitable for run-time inspection of the state of the observer.\n\nThey also carry an informational `note` property, if the caller of the observe\nmethod provided one.\nThis is intended for use by third parties to provide additional debugging\ninformation about an observer, for example, where the observer came from.\n\n-   PropertyChangeObserver\n    -   object\n    -   propertyName\n    -   observers\n    -   handler\n    -   handlerMethodName\n    -   childObserver\n    -   note\n    -   capture\n    -   value\n-   RangeChangeObserver\n    -   object\n    -   name\n    -   observers\n    -   handler\n    -   handlerMethodName\n    -   childObserver\n    -   note\n    -   capture\n-   MapChangeObserver\n    -   object\n    -   name\n    -   observers\n    -   handler\n    -   handlerMethodName\n    -   childObserver\n    -   note\n    -   capture\n\n## Implementing observability\n\nThe `pop-observe/observable-object`, `pop-observe/observable-range`, and\n`pop-observe/observable-map` modules export mixable or prototypically\ninheritable constructors.\nObjects that inherit the observable interface must then dispatch change and will\nchange notifications if they are being observed, in all of their methods that\nchange their content.\n\n-   ObservableObject.observePropertyChange(object, handler, note, capture)\n-   ObservableObject.observePropertyWillChange(object, handler, note)\n-   ObservableObject.dispatchPropertyChange(object, name, plus, minus, capture)\n-   ObservableObject.dispatchPropertyWillChange(object, name, plus, minus)\n-   ObservableObject.getPropertyChangeObservers(object, name, capture)\n-   ObservableObject.getPropertyWillChangeObservers(object, name)\n-   ObservableObject.makePropertyObservable(object, name)\n-   ObservableObject.preventPropertyObserver(object, name)\n\n-   ObservableObject.prototype.observePropertyChange(handler, note, capture)\n-   ObservableObject.prototype.observePropertyWillChange(handler, note)\n-   ObservableObject.prototype.dispatchPropertyChange(name, plus, minus, capture)\n-   ObservableObject.prototype.dispatchPropertyWillChange(name, plus, minus)\n-   ObservableObject.prototype.getPropertyChangeObservers(name, capture)\n-   ObservableObject.prototype.getPropertyWillChangeObservers(name)\n-   ObservableObject.prototype.makePropertyObservable(name)\n-   ObservableObject.prototype.preventPropertyObserver(name)\n\n-   ObservableRange.prototype.observeRangeChange(handler, name, note, capture)\n-   ObservableRange.prototype.observeRangeWillChange(handler, name, note)\n-   ObservableRange.prototype.dispatchRangeChange(handler, name, note, capture)\n-   ObservableRange.prototype.dispatchRangeWillChange(handler, name, note)\n-   ObservableRange.prototype.makeRangeChangesObservable()\n\n-   ObservableMap.prototype.observeMapChange(handler, name, note, capture)\n-   ObservableMap.prototype.observeMapWillChange(handler, name, note)\n-   ObservableMap.prototype.dispatchMapChange(type, key, plus, minus, capture)\n-   ObservableMap.prototype.dispatchMapWillChange(type, key, plus, minus)\n-   ObservableMap.prototype.makeMapChangesObservable()\n\n\n## Copyright and License\n\nCopyright (c) 2015 Motorola Mobility, Montage Studio, Kristopher Michael Kowal,\nand contributors.\nAll rights reserved.\nBSD 3-Clause license.\n\n","_attachments":{},"homepage":"https://github.com/kriskowal/pop-observe","bugs":{"url":"https://github.com/kriskowal/pop-observe/issues"},"license":"MIT"}