@@ -2037,9 +2037,10 @@ plots.didMarginChange = function(margin0, margin1) {
2037
2037
* keepall: keep data and src
2038
2038
* @param {String } output If you specify 'object', the result will not be stringified
2039
2039
* @param {Boolean } useDefaults If truthy, use _fullLayout and _fullData
2040
+ * @param {Boolean } includeConfig If truthy, include _context
2040
2041
* @returns {Object|String }
2041
2042
*/
2042
- plots . graphJson = function ( gd , dataonly , mode , output , useDefaults ) {
2043
+ plots . graphJson = function ( gd , dataonly , mode , output , useDefaults , includeConfig ) {
2043
2044
// if the defaults aren't supplied yet, we need to do that...
2044
2045
if ( ( useDefaults && dataonly && ! gd . _fullData ) ||
2045
2046
( useDefaults && ! dataonly && ! gd . _fullLayout ) ) {
@@ -2050,26 +2051,29 @@ plots.graphJson = function(gd, dataonly, mode, output, useDefaults) {
2050
2051
var layout = ( useDefaults ) ? gd . _fullLayout : gd . layout ;
2051
2052
var frames = ( gd . _transitionData || { } ) . _frames ;
2052
2053
2053
- function stripObj ( d ) {
2054
+ function stripObj ( d , keepFunction ) {
2054
2055
if ( typeof d === 'function' ) {
2055
- return null ;
2056
+ return keepFunction ? '_function_' : null ;
2056
2057
}
2057
2058
if ( Lib . isPlainObject ( d ) ) {
2058
2059
var o = { } ;
2059
- var v , src ;
2060
- for ( v in d ) {
2060
+ var src ;
2061
+ Object . keys ( d ) . sort ( ) . forEach ( function ( v ) {
2061
2062
// remove private elements and functions
2062
2063
// _ is for private, [ is a mistake ie [object Object]
2063
- if ( typeof d [ v ] === 'function' ||
2064
- [ '_' , '[' ] . indexOf ( v . charAt ( 0 ) ) !== - 1 ) {
2065
- continue ;
2064
+ if ( [ '_' , '[' ] . indexOf ( v . charAt ( 0 ) ) !== - 1 ) return ;
2065
+
2066
+ // if a function, add if necessary then move on
2067
+ if ( typeof d [ v ] === 'function' ) {
2068
+ if ( keepFunction ) o [ v ] = '_function' ;
2069
+ return ;
2066
2070
}
2067
2071
2068
2072
// look for src/data matches and remove the appropriate one
2069
2073
if ( mode === 'keepdata' ) {
2070
2074
// keepdata: remove all ...src tags
2071
2075
if ( v . substr ( v . length - 3 ) === 'src' ) {
2072
- continue ;
2076
+ return ;
2073
2077
}
2074
2078
} else if ( mode === 'keepstream' ) {
2075
2079
// keep sourced data if it's being streamed.
@@ -2078,26 +2082,26 @@ plots.graphJson = function(gd, dataonly, mode, output, useDefaults) {
2078
2082
src = d [ v + 'src' ] ;
2079
2083
if ( typeof src === 'string' && src . indexOf ( ':' ) > 0 ) {
2080
2084
if ( ! Lib . isPlainObject ( d . stream ) ) {
2081
- continue ;
2085
+ return ;
2082
2086
}
2083
2087
}
2084
2088
} else if ( mode !== 'keepall' ) {
2085
2089
// keepref: remove sourced data but only
2086
2090
// if the source tag is well-formed
2087
2091
src = d [ v + 'src' ] ;
2088
2092
if ( typeof src === 'string' && src . indexOf ( ':' ) > 0 ) {
2089
- continue ;
2093
+ return ;
2090
2094
}
2091
2095
}
2092
2096
2093
2097
// OK, we're including this... recurse into it
2094
- o [ v ] = stripObj ( d [ v ] ) ;
2095
- }
2098
+ o [ v ] = stripObj ( d [ v ] , keepFunction ) ;
2099
+ } ) ;
2096
2100
return o ;
2097
2101
}
2098
2102
2099
2103
if ( Array . isArray ( d ) ) {
2100
- return d . map ( stripObj ) ;
2104
+ return d . map ( function ( x ) { return stripObj ( x , keepFunction ) ; } ) ;
2101
2105
}
2102
2106
2103
2107
if ( Lib . isTypedArray ( d ) ) {
@@ -2126,6 +2130,8 @@ plots.graphJson = function(gd, dataonly, mode, output, useDefaults) {
2126
2130
2127
2131
if ( frames ) obj . frames = stripObj ( frames ) ;
2128
2132
2133
+ if ( includeConfig ) obj . config = stripObj ( gd . _context , true ) ;
2134
+
2129
2135
return ( output === 'object' ) ? obj : JSON . stringify ( obj ) ;
2130
2136
} ;
2131
2137
0 commit comments