Skip to content

Commit e31626a

Browse files
author
Sergii.Kliuchnyk
committed
comparators:
1 parent e32299f commit e31626a

File tree

6 files changed

+142
-4
lines changed

6 files changed

+142
-4
lines changed

README.md

+28
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,34 @@ Property name with unique value in it array. Default value is `id`. If your arra
140140

141141
Hash where key is path to array and value is id property. Path examples: `users.list`, `user.list.1.friends`, `users.list.*.friends`
142142

143+
## `comparators: [[Class, function (oldValue, newValue, options)], ...]`
144+
145+
Array of comparators to handle comparison of objects which do not have own properties. For example instead of `user.name` you have `user.getName()` or you need to compare `Date` objects or you just know quick way to compare large objects like by `id` property and you do not need full list of changes of those objects. First value of comparator should be some class and second is function which should return `true` if objects are equal and `false` if they not. In `options` will be `oldPath` and `newPath`.
146+
```javascript
147+
var now = new Date();
148+
var prevHour = new Date();
149+
prevHour.setHours(-1);
150+
151+
var changes = diff(
152+
{
153+
createdAt: now
154+
},
155+
{
156+
createdAt: prevHour
157+
},
158+
{
159+
comparators: [
160+
[Date, function(oldValue, newValue, options) {
161+
options.oldPath; // ['createdAt']
162+
options.newPath; // ['createdAt']
163+
164+
return oldValue.toString() === newValue.toString();
165+
}]
166+
]
167+
}
168+
);
169+
```
170+
143171
## `callback: function (event)`
144172

145173
Function which will be called for each event. If callback is passed then lib will not create array of all changes.

bower.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "simple-diff",
33
"main": "simple-diff.js",
4-
"version": "1.4.0",
4+
"version": "1.5.0",
55
"homepage": "https://github.com/redexp/simple-diff",
66
"authors": [
77
"Sergii Kliuchnyk <sergiikliuchnyk@gmail.com>"

package.json

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "simple-diff",
3-
"version": "1.4.0",
3+
"version": "1.5.0",
44
"description": "simple diff for object and arrays with options",
55
"main": "simple-diff.js",
66
"scripts": {
@@ -25,6 +25,8 @@
2525
"gulp-rename": "^1.2.2",
2626
"gulp-replace": "^0.5.4",
2727
"gulp-uglify": "^1.5.4",
28-
"mocha": "^2.5.3"
28+
"mocha": "^2.5.3",
29+
"sinon": "^1.17.7",
30+
"sinon-chai": "^2.8.0"
2931
}
3032
}

simple-diff.js

+24
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
callback = ops.callback || function (item) {
2929
changes.push(item);
3030
},
31+
comparators = ops.comparators || [],
3132
i, len, prop, id;
3233

3334
if (!isObject(oldObj) || !isObject(newObj)) {
@@ -180,6 +181,29 @@
180181
}
181182
}
182183
else {
184+
if (comparators.length > 0) {
185+
for (i = 0, len = comparators.length; i < len; i++) {
186+
if (oldObj instanceof comparators[i][0] === false && newObj instanceof comparators[i][0] === false) continue;
187+
188+
var objEqual = comparators[i][1](oldObj, newObj, {
189+
oldPath: oldPath,
190+
newPath: newPath
191+
});
192+
193+
if (!objEqual) {
194+
callback({
195+
oldPath: oldPath,
196+
newPath: newPath,
197+
type: CHANGE_EVENT,
198+
oldValue: oldObj,
199+
newValue: newObj
200+
});
201+
}
202+
203+
return changes;
204+
}
205+
}
206+
183207
for (prop in oldObj) {
184208
if (!oldObj.hasOwnProperty(prop)) continue;
185209

simple-diff.min.js

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/test.js

+84
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
var expect = require('chai').expect,
2+
sinon = require('sinon'),
23
diff = require('../simple-diff'),
34
undefined;
45

6+
require('chai').use(require('sinon-chai'));
7+
58
describe('diff', function () {
69
it('should find changes in objects', function () {
710
var changes = diff(
@@ -550,4 +553,85 @@ describe('diff', function () {
550553
}
551554
]);
552555
});
556+
557+
it('should handle comparators: [] to compare custom class objects', function () {
558+
var cb = sinon.spy(function (a, b, ops) {
559+
expect(a).to.be.instanceOf(Date);
560+
expect(b).to.be.instanceOf(Date);
561+
562+
expect(ops).to.deep.equal({
563+
oldPath: ['prop', 'date'],
564+
newPath: ['prop', 'date']
565+
});
566+
567+
return a.toString() === b.toString();
568+
});
569+
570+
var changes = diff(
571+
{
572+
prop: {
573+
test1: {},
574+
test2: [{}],
575+
date: new Date()
576+
}
577+
},
578+
{
579+
prop: {
580+
test1: {},
581+
test2: [{}],
582+
date: new Date()
583+
}
584+
},
585+
{
586+
comparators: [
587+
[Date, cb]
588+
]
589+
}
590+
);
591+
592+
expect(changes).to.deep.equal([]);
593+
expect(cb).to.have.callCount(1);
594+
595+
var nowDate = new Date();
596+
var prevDate = new Date();
597+
prevDate.setHours(-1);
598+
599+
changes = diff(
600+
{
601+
prop: {
602+
test1: 1,
603+
date: nowDate
604+
}
605+
},
606+
{
607+
prop: {
608+
test1: 2,
609+
date: prevDate
610+
}
611+
},
612+
{
613+
comparators: [
614+
[Date, cb]
615+
]
616+
}
617+
);
618+
619+
expect(cb).to.have.callCount(2);
620+
expect(changes).to.deep.equal([
621+
{
622+
oldPath: ['prop', 'test1'],
623+
newPath: ['prop', 'test1'],
624+
type: 'change',
625+
oldValue: 1,
626+
newValue: 2
627+
},
628+
{
629+
oldPath: ['prop', 'date'],
630+
newPath: ['prop', 'date'],
631+
type: 'change',
632+
oldValue: nowDate,
633+
newValue: prevDate
634+
}
635+
]);
636+
});
553637
});

0 commit comments

Comments
 (0)