/ * *
* Underscore mixins for deep objects
*
* Based on https : //gist.github.com/echong/3861963
* /
define (
[
'underscore'
] , function ( _ ) {
var arrays , basicObjects , deepClone , deepExtend , deepExtendCouple , isBasicObject , _ _slice =
[
] . slice ;
deepClone = function ( obj ) {
var func , isArr ;
if ( ! _ . isObject ( obj ) || _ . isFunction ( obj ) ) {
return obj ;
}
if ( obj instanceof Backbone . Collection || obj instanceof Backbone . Model ) {
return obj ;
}
if ( _ . isDate ( obj ) ) {
return new Date ( obj . getTime ( ) ) ;
}
if ( _ . isRegExp ( obj ) ) {
return new RegExp ( obj . source , obj . toString ( ) . replace ( /.*\// , '' ) ) ;
}
isArr = _ . isArray ( obj || _ . isArguments ( obj ) ) ;
func = function ( memo , value , key ) {
if ( isArr ) {
memo . push ( deepClone ( value ) ) ;
}
else {
memo [ key ] = deepClone ( value ) ;
}
return memo ;
} ;
return _ . reduce ( obj , func , isArr ?
[
] : { } ) ;
} ;
isBasicObject = function ( object ) {
if ( object == null ) {
return false ;
}
return ( object . prototype === { } . prototype || object . prototype === Object . prototype ) && _ . isObject ( object ) && ! _ . isArray ( object ) && ! _ . isFunction ( object ) && ! _ . isDate ( object ) && ! _ . isRegExp ( object ) && ! _ . isArguments ( object ) ;
} ;
basicObjects = function ( object ) {
return _ . filter ( _ . keys ( object ) , function ( key ) {
return isBasicObject ( object [ key ] ) ;
} ) ;
} ;
arrays = function ( object ) {
return _ . filter ( _ . keys ( object ) , function ( key ) {
return _ . isArray ( object [ key ] ) ;
} ) ;
} ;
deepExtendCouple = function ( destination , source , maxDepth ) {
var combine , recurse , sharedArrayKey , sharedArrayKeys , sharedObjectKey , sharedObjectKeys , _i , _j , _len , _len1 ;
if ( maxDepth == null ) {
maxDepth = 20 ;
}
if ( maxDepth <= 0 ) {
console . warn ( '_.deepExtend(): Maximum depth of recursion hit.' ) ;
return _ . extend ( destination , source ) ;
}
sharedObjectKeys = _ . intersection ( basicObjects ( destination ) , basicObjects ( source ) ) ;
recurse = function ( key ) {
return source [ key ] = deepExtendCouple ( destination [ key ] , source [ key ] , maxDepth - 1 ) ;
} ;
for ( _i = 0 , _len = sharedObjectKeys . length ; _i < _len ; _i ++ ) {
sharedObjectKey = sharedObjectKeys [ _i ] ;
recurse ( sharedObjectKey ) ;
}
sharedArrayKeys = _ . intersection ( arrays ( destination ) , arrays ( source ) ) ;
combine = function ( key ) {
return source [ key ] = _ . union ( destination [ key ] , source [ key ] ) ;
} ;
for ( _j = 0 , _len1 = sharedArrayKeys . length ; _j < _len1 ; _j ++ ) {
sharedArrayKey = sharedArrayKeys [ _j ] ;
combine ( sharedArrayKey ) ;
}
return _ . extend ( destination , source ) ;
} ;
deepExtend = function ( ) {
var finalObj , maxDepth , objects , _i ;
objects = 2 <= arguments . length ? _ _slice . call ( arguments , 0 , _i = arguments . length - 1 ) : ( _i = 0 ,
[
] ) , maxDepth = arguments [ _i ++ ] ;
if ( ! _ . isNumber ( maxDepth ) ) {
objects . push ( maxDepth ) ;
maxDepth = 20 ;
}
if ( objects . length <= 1 ) {
return objects [ 0 ] ;
}
if ( maxDepth <= 0 ) {
return _ . extend . apply ( this , objects ) ;
}
finalObj = objects . shift ( ) ;
while ( objects . length > 0 ) {
finalObj = deepExtendCouple ( finalObj , deepClone ( objects . shift ( ) ) , maxDepth ) ;
}
return finalObj ;
} ;
_ . mixin ( {
deepClone : deepClone ,
isBasicObject : isBasicObject ,
basicObjects : basicObjects ,
arrays : arrays ,
deepExtend : deepExtend
} ) ;
} ) ;