@ -107,24 +107,49 @@ exports.assignAllKeys = function (obj, value) {
/ * *
/ * *
* Fill an object with a possibly partially defined other object . Only copies values if the a object has an object requiring values .
* Copy property from b to a if property present in a .
* If property in b explicitly set to null , delete it if ` allowDeletion ` set .
*
* Internal helper routine , should not be exported . Not added to ` exports ` for that reason .
*
* @ param { object } a target object
* @ param { object } b source object
* @ param { string } prop name of property to copy to a
* @ param { boolean } allowDeletion if true , delete property in a if explicitly set to null in b
* @ private
* /
function copyOrDelete ( a , b , prop , allowDeletion ) {
var doDeletion = false ;
if ( allowDeletion === true ) {
doDeletion = ( b [ prop ] === null && a [ prop ] !== undefined ) ;
}
if ( doDeletion ) {
delete a [ prop ] ;
} else {
a [ prop ] = b [ prop ] ; // Remember, this is a reference copy!
}
}
/ * *
* Fill an object with a possibly partially defined other object .
*
* Only copies values for the properties already present in a .
* That means an object is not created on a property if only the b object has it .
* That means an object is not created on a property if only the b object has it .
*
* @ param { object } a
* @ param { object } a
* @ param { object } b
* @ param { object } b
* @ param { boolean } [ allowDeletion = false ]
* @ param { boolean } [ allowDeletion = false ] if true , delete properties in a that are explicitly set to null in b
* /
* /
exports . fillIfDefined = function ( a , b , allowDeletion = false ) {
exports . fillIfDefined = function ( a , b , allowDeletion = false ) {
// NOTE: iteration of properties of a
// NOTE: prototype properties iterated over as well
for ( var prop in a ) {
for ( var prop in a ) {
if ( b [ prop ] !== undefined ) {
if ( b [ prop ] !== undefined ) {
if ( typeof b [ prop ] !== 'object' ) {
if ( ( b [ prop ] === undefined || b [ prop ] === null ) && a [ prop ] !== undefined && allowDeletion === true ) {
delete a [ prop ] ;
}
else {
a [ prop ] = b [ prop ] ;
}
}
else {
if ( b [ prop ] === null || typeof b [ prop ] !== 'object' ) { // Note: typeof null === 'object'
copyOrDelete ( a , b , prop , allowDeletion ) ;
} else {
if ( typeof a [ prop ] === 'object' ) {
if ( typeof a [ prop ] === 'object' ) {
exports . fillIfDefined ( a [ prop ] , b [ prop ] , allowDeletion ) ;
exports . fillIfDefined ( a [ prop ] , b [ prop ] , allowDeletion ) ;
}
}
@ -134,24 +159,6 @@ exports.fillIfDefined = function (a, b, allowDeletion = false) {
} ;
} ;
/ * *
* Extend object a with the properties of object b or a series of objects
* Only properties with defined values are copied
* @ param { Object } a
* @ param { ... Object } b
* @ return { Object } a
* /
exports . protoExtend = function ( a , b ) { // eslint-disable-line no-unused-vars
for ( var i = 1 ; i < arguments . length ; i ++ ) {
var other = arguments [ i ] ;
for ( var prop in other ) {
a [ prop ] = other [ prop ] ;
}
}
return a ;
} ;
/ * *
/ * *
* Extend object a with the properties of object b or a series of objects
* Extend object a with the properties of object b or a series of objects
* Only properties with defined values are copied
* Only properties with defined values are copied
@ -197,118 +204,112 @@ exports.selectiveExtend = function (props, a, b) { // eslint-disable-line no-un
return a ;
return a ;
} ;
} ;
/ * *
/ * *
* Extend object a with selected properties of object b or a series of objects
* Only properties with defined values are copied
* @ param { Array . < string > } props
* @ param { Object } a
* @ param { Object } b
* @ param { boolean } [ allowDeletion = false ]
* @ return { Object } a
* Extend object a with selected properties of object b .
* Only properties with defined values are copied .
*
* * * Note : * * Previous version of this routine implied that multiple source objects
* could be used ; however , the implementation was * * wrong * * .
* Since multiple ( > 1 ) sources weren ' t used anywhere in the ` vis.js ` code ,
* this has been removed
*
* @ param { Array . < string > } props names of first - level properties to copy over
* @ param { object } a target object
* @ param { object } b source object
* @ param { boolean } [ allowDeletion = false ] if true , delete property in a if explicitly set to null in b
* @ returns { Object } a
* /
* /
exports . selectiveDeepExtend = function ( props , a , b , allowDeletion = false ) {
exports . selectiveDeepExtend = function ( props , a , b , allowDeletion = false ) {
// TODO: add support for Arrays to deepExtend
// TODO: add support for Arrays to deepExtend
if ( Array . isArray ( b ) ) {
if ( Array . isArray ( b ) ) {
throw new TypeError ( 'Arrays are not supported by deepExtend' ) ;
throw new TypeError ( 'Arrays are not supported by deepExtend' ) ;
}
}
for ( var i = 2 ; i < arguments . length ; i ++ ) {
var other = arguments [ i ] ;
for ( var p = 0 ; p < props . length ; p ++ ) {
var prop = props [ p ] ;
if ( other . hasOwnProperty ( prop ) ) {
if ( b [ prop ] && b [ prop ] . constructor === Object ) {
if ( a [ prop ] === undefined ) {
a [ prop ] = { } ;
}
if ( a [ prop ] . constructor === Object ) {
exports . deepExtend ( a [ prop ] , b [ prop ] , false , allowDeletion ) ;
}
else {
if ( ( b [ prop ] === null ) && a [ prop ] !== undefined && allowDeletion === true ) {
delete a [ prop ] ;
}
else {
a [ prop ] = b [ prop ] ;
}
}
} else if ( Array . isArray ( b [ prop ] ) ) {
throw new TypeError ( 'Arrays are not supported by deepExtend' ) ;
} else {
if ( ( b [ prop ] === null ) && a [ prop ] !== undefined && allowDeletion === true ) {
delete a [ prop ] ;
}
else {
a [ prop ] = b [ prop ] ;
}
}
for ( var p = 0 ; p < props . length ; p ++ ) {
var prop = props [ p ] ;
if ( b . hasOwnProperty ( prop ) ) {
if ( b [ prop ] && b [ prop ] . constructor === Object ) {
if ( a [ prop ] === undefined ) {
a [ prop ] = { } ;
}
if ( a [ prop ] . constructor === Object ) {
exports . deepExtend ( a [ prop ] , b [ prop ] , false , allowDeletion ) ;
}
else {
copyOrDelete ( a , b , prop , allowDeletion ) ;
}
} else if ( Array . isArray ( b [ prop ] ) ) {
throw new TypeError ( 'Arrays are not supported by deepExtend' ) ;
} else {
copyOrDelete ( a , b , prop , allowDeletion ) ;
}
}
}
}
}
}
return a ;
return a ;
} ;
} ;
/ * *
/ * *
* Extend object a with selected properties of object b or a series of objects
* Extend object ` a ` with properties of object ` b ` , ignoring properties which are explicitly specified
* to be excluded .
*
* The properties of ` b ` are considered for copying .
* Properties which are themselves objects are are also extended .
* Only properties with defined values are copied
* Only properties with defined values are copied
* @ param { Array . < string > } props
* @ param { Object } a
* @ param { Object } b
* @ param { boolean } [ allowDeletion = false ]
*
* @ param { Array . < string > } propsToExclude names of properties which should * not * be copied
* @ param { Object } a object to extend
* @ param { Object } b object to take properties from for extension
* @ param { boolean } [ allowDeletion = false ] if true , delete properties in a that are explicitly set to null in b
* @ return { Object } a
* @ return { Object } a
* /
* /
exports . selectiveNotDeepExtend = function ( props , a , b , allowDeletion = false ) {
exports . selectiveNotDeepExtend = function ( propsToExclude , a , b , allowDeletion = false ) {
// TODO: add support for Arrays to deepExtend
// TODO: add support for Arrays to deepExtend
// NOTE: array properties have an else-below; apparently, there is a problem here.
if ( Array . isArray ( b ) ) {
if ( Array . isArray ( b ) ) {
throw new TypeError ( 'Arrays are not supported by deepExtend' ) ;
throw new TypeError ( 'Arrays are not supported by deepExtend' ) ;
}
}
for ( var prop in b ) {
for ( var prop in b ) {
if ( b . hasOwnProperty ( prop ) ) {
if ( props . indexOf ( prop ) == - 1 ) {
if ( b [ prop ] && b [ prop ] . constructor === Object ) {
if ( a [ prop ] === undefined ) {
a [ prop ] = { } ;
}
if ( a [ prop ] . constructor === Object ) {
exports . deepExtend ( a [ prop ] , b [ prop ] ) ;
}
else {
if ( ( b [ prop ] === null ) && a [ prop ] !== undefined && allowDeletion === true ) {
delete a [ prop ] ;
}
else {
a [ prop ] = b [ prop ] ;
}
}
} else if ( Array . isArray ( b [ prop ] ) ) {
a [ prop ] = [ ] ;
for ( let i = 0 ; i < b [ prop ] . length ; i ++ ) {
a [ prop ] . push ( b [ prop ] [ i ] ) ;
}
} else {
if ( ( b [ prop ] === null ) && a [ prop ] !== undefined && allowDeletion === true ) {
delete a [ prop ] ;
}
else {
a [ prop ] = b [ prop ] ;
}
}
if ( ! b . hasOwnProperty ( prop ) ) continue ; // Handle local properties only
if ( propsToExclude . indexOf ( prop ) !== - 1 ) continue ; // In exclusion list, skip
if ( b [ prop ] && b [ prop ] . constructor === Object ) {
if ( a [ prop ] === undefined ) {
a [ prop ] = { } ;
}
if ( a [ prop ] . constructor === Object ) {
exports . deepExtend ( a [ prop ] , b [ prop ] ) ; // NOTE: allowDeletion not propagated!
}
else {
copyOrDelete ( a , b , prop , allowDeletion ) ;
}
} else if ( Array . isArray ( b [ prop ] ) ) {
a [ prop ] = [ ] ;
for ( let i = 0 ; i < b [ prop ] . length ; i ++ ) {
a [ prop ] . push ( b [ prop ] [ i ] ) ;
}
}
} else {
copyOrDelete ( a , b , prop , allowDeletion ) ;
}
}
}
}
return a ;
return a ;
} ;
} ;
/ * *
/ * *
* Deep extend an object a with the properties of object b
* Deep extend an object a with the properties of object b
*
* @ param { Object } a
* @ param { Object } a
* @ param { Object } b
* @ param { Object } b
* @ param { boolean } [ protoExtend ] -- > optional parameter . If true , the prototype values will also be extended .
* ( ie . the options objects that inherit from others will also get the inherited options )
* @ param { boolean } [ allowDeletion ] -- > optional parameter . If true , the values of fields that are null will be deleted
* @ param { boolean } [ protoExtend = false ] If true , the prototype values will also be extended .
* ( ie . the options objects that inherit from others will also get the inherited options )
* @ param { boolean } [ allowDeletion = false ] If true , the values of fields that are null will be deleted
* @ returns { Object }
* @ returns { Object }
* /
* /
exports . deepExtend = function ( a , b , protoExtend , allowDeletion ) {
exports . deepExtend = function ( a , b , protoExtend = false , allowDeletion = false ) {
for ( var prop in b ) {
for ( var prop in b ) {
if ( b . hasOwnProperty ( prop ) || protoExtend === true ) {
if ( b . hasOwnProperty ( prop ) || protoExtend === true ) {
if ( b [ prop ] && b [ prop ] . constructor === Object ) {
if ( b [ prop ] && b [ prop ] . constructor === Object ) {
@ -316,15 +317,10 @@ exports.deepExtend = function (a, b, protoExtend, allowDeletion) {
a [ prop ] = { } ;
a [ prop ] = { } ;
}
}
if ( a [ prop ] . constructor === Object ) {
if ( a [ prop ] . constructor === Object ) {
exports . deepExtend ( a [ prop ] , b [ prop ] , protoExtend ) ;
exports . deepExtend ( a [ prop ] , b [ prop ] , protoExtend ) ; // NOTE: allowDeletion not propagated!
}
}
else {
else {
if ( ( b [ prop ] === null ) && a [ prop ] !== undefined && allowDeletion === true ) {
delete a [ prop ] ;
}
else {
a [ prop ] = b [ prop ] ;
}
copyOrDelete ( a , b , prop , allowDeletion ) ;
}
}
} else if ( Array . isArray ( b [ prop ] ) ) {
} else if ( Array . isArray ( b [ prop ] ) ) {
a [ prop ] = [ ] ;
a [ prop ] = [ ] ;
@ -332,18 +328,14 @@ exports.deepExtend = function (a, b, protoExtend, allowDeletion) {
a [ prop ] . push ( b [ prop ] [ i ] ) ;
a [ prop ] . push ( b [ prop ] [ i ] ) ;
}
}
} else {
} else {
if ( ( b [ prop ] === null ) && a [ prop ] !== undefined && allowDeletion === true ) {
delete a [ prop ] ;
}
else {
a [ prop ] = b [ prop ] ;
}
copyOrDelete ( a , b , prop , allowDeletion ) ;
}
}
}
}
}
}
return a ;
return a ;
} ;
} ;
/ * *
/ * *
* Test whether all elements in two arrays are equal .
* Test whether all elements in two arrays are equal .
* @ param { Array } a
* @ param { Array } a