Skip to content

Commit

Permalink
Added toggle and merge operations
Browse files Browse the repository at this point in the history
  • Loading branch information
Flamenco committed Dec 29, 2016
1 parent c76ea54 commit b8c3894
Show file tree
Hide file tree
Showing 4 changed files with 244 additions and 0 deletions.
33 changes: 33 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,39 @@ dotProp.delete(obj, 'foo.0.bar');
//=> {foo: [{}, 'white-unicorn', 'silver-unicorn']}
```

### toggle

Delete a value by a dot path.

```javascript
var obj = {foo: { bar: true } };

// toggle
dotProp.toggle(obj, 'foo.bar');
//=> {foo: { bar: false } }
```
### merge

Merge a value by a dot path.
> The target value must be an object, array, null, or undefined.
* If target is an object, Object.assign({}, target, param) is used.
* If target an array, target.concat(param) is used.
* If target is null or undefined, the value is simply set.

```javascript
var obj = {foo: { bar: {a:1, b:2 } };

// merge object
dotProp.merge(obj, 'foo.bar', {c:3} );
//=> {foo: { bar:{ a:1, b:2, c:3} } }

var arr = {foo: { bar: [1, 2] } };

// merge array
dotProp.merge(arr, 'foo.bar', [3, 4] );
//=> {foo: { bar:[1, 2, 3, 4 ] }
```
## License
[MIT](http://opensource.org/licenses/MIT)
40 changes: 40 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,46 @@ module.exports.delete = function(obj, prop) {
return deletePropImmutableRec(obj, prop, 0);
};

/**
* Toggles a value. The target value is evaluated using Boolean(currentValue). The result will always be a JSON boolean.
* Be careful with strings as target value, as "true" and "false" will toggle to false, but "0" will toggle to true.
* Here is what Javascript considers false: 0, -0, null, false, NaN, undefined, and the empty string ("")
* @param obj The object to evaluate.
* @param prop The path to the value.
*/
module.exports.toggle = function(obj, prop) {
var curVal = this.get(obj, prop);
return this.set(obj, prop, !Boolean(curVal));
};

/**
* Merges a value. The target value must be an object, array, null, or undefined.
* If target is an object, Object.assign({}, target, param) is used.
* If target an array, target.concat(param) is used.
* If target is null or undefined, the value is simply set.
* @param obj The object to evaluate.
* @param prop The path to the value.
*/
module.exports.merge = function(obj, prop, val) {
var curVal = this.get(obj, prop);
if (typeof curVal === 'object') {
if (Array.isArray(curVal)){
return this.set(obj, prop, curVal.concat(val));
} else if (curVal === null){
return this.set(obj, prop, val);
}
else {
var merged = Object.assign({}, curVal, val);
return this.set(obj, prop, merged);
}
} else if (typeof curVal === 'undefined'){
return this.set(obj, prop, val);
}
else {
return obj;
}
};

function getArrayIndex(head, obj) {
if (head === '$end') {
head = obj.length - 1;
Expand Down
138 changes: 138 additions & 0 deletions test/dot-prop-immutable-merge.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
var dotProp = require('..');

describe('dot-prop-immutable.merge.spec.js', function () {

var obj = {
a: 1,
b: {
x: 1,
y: 2
},
c: [1, 2],
d: null,
'b.x': 10
};

var arr = [1, {a: [1, 2]}];

var result;
describe('when have an object', () => {

describe('merge an object value into object', () => {

before(function () {
result = dotProp.merge(obj, 'b', {z: 3});
});

it('should merge prop', () => {
expect(result).to.eql({
a: 1,
b: {
x: 1,
y: 2,
z: 3
},
c: [1, 2],
d: null,
'b.x': 10
});
});

it('invariant', objInvariant);

});

describe('merge an array value into array', () => {

before(function () {
result = dotProp.merge(obj, 'c', [3, 4]);
});

it('should merge prop', () => {
expect(result).to.eql({
a: 1,
b: {
x: 1,
y: 2
},
c: [1, 2, 3, 4],
d: null,
'b.x': 10
});
});

it('invariant', objInvariant);

});

describe('merge an object value into null', () => {

before(function () {
result = dotProp.merge(obj, 'd', {foo: 'bar'});
});

it('should merge prop', () => {
expect(result).to.eql({
a: 1,
b: {
x: 1,
y: 2
},
c: [1, 2],
d: {foo: 'bar'},
'b.x': 10
});
});

it('invariant', objInvariant);

});

describe('merge an object value into undefined', () => {

before(function () {
result = dotProp.merge(obj, 'z', {foo: 'bar'});
});

it('should merge prop', () => {
expect(result).to.eql({
a: 1,
b: {
x: 1,
y: 2
},
c: [1, 2],
d: null,
z: {foo: 'bar'},
'b.x': 10
});
});

it('invariant', objInvariant);

});


});

function objInvariant() {
expect(obj).to.eql({
a: 1,
b: {
x: 1,
y: 2
},
c: [1, 2],
d: null,
'b.x': 10
});
}

function arrInvariant() {
expect(arr).to.eql(
[1, {a: [1, 2]}]
);
}
});


33 changes: 33 additions & 0 deletions test/dot-prop-immutable-toggle.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
var dotProp = require('..');

describe('dot-prop-immutable.toggle.spec.js', function () {

var arr = [1, {a: false}];

var result;
describe('when have an array', () => {

describe('toggle a value', () => {

before(function () {
result = dotProp.toggle(arr, '1.a');
});


it('should toggle prop', () => {
expect(result).to.eql(
[1, {a: true}]);
});

it('invariant', arrInvariant);
});
});

function arrInvariant() {
expect(arr).to.eql(
[1, {a: false}]
);
}
});


0 comments on commit b8c3894

Please sign in to comment.