@@ -17,15 +17,16 @@ var JSONViewer = (function(document) {
1717 * @param {Object|Array } json Input value
1818 * @param {Number } [inputMaxLvl] Process only to max level, where 0..n, -1 unlimited
1919 * @param {Number } [inputColAt] Collapse at level, where 0..n, -1 unlimited
20+ * @param {Object } [inputState] Expand or collapse according to given state.
2021 */
21- JSONViewer . prototype . showJSON = function ( jsonValue , inputMaxLvl , inputColAt ) {
22+ JSONViewer . prototype . showJSON = function ( jsonValue , inputMaxLvl , inputColAt , inputState ) {
2223 // Process only to maxLvl, where 0..n, -1 unlimited
2324 var maxLvl = typeof inputMaxLvl === "number" ? inputMaxLvl : - 1 ; // max level
2425 // Collapse at level colAt, where 0..n, -1 unlimited
2526 var colAt = typeof inputColAt === "number" ? inputColAt : - 1 ; // collapse at
2627
2728 this . _dom_container . innerHTML = "" ;
28- walkJSONTree ( this . _dom_container , jsonValue , maxLvl , colAt , 0 ) ;
29+ walkJSONTree ( this . _dom_container , jsonValue , maxLvl , colAt , 0 , 'root' , inputState ) ;
2930 } ;
3031
3132 /**
@@ -37,6 +38,18 @@ var JSONViewer = (function(document) {
3738 return this . _dom_container ;
3839 } ;
3940
41+ /**
42+ * Get current expand/collapse state - this can be passed to showJSON to set initial state.
43+ * For each key, true == expanded and false == collapsed. For missing keys, colAt will apply.
44+ */
45+ JSONViewer . prototype . getState = function ( ) {
46+ var state = { } ;
47+ this . _dom_container . querySelectorAll ( 'a' ) . forEach ( function ( a ) {
48+ state [ a . getAttribute ( 'data-key' ) ] = ! a . classList . contains ( 'collapsed' )
49+ } )
50+ return state ;
51+ } ;
52+
4053 /**
4154 * Recursive walk for input value.
4255 *
@@ -46,12 +59,15 @@ var JSONViewer = (function(document) {
4659 * @param {Number } colAt Collapse at level, where 0..n, -1 unlimited
4760 * @param {Number } lvl Current level
4861 */
49- function walkJSONTree ( outputParent , value , maxLvl , colAt , lvl ) {
62+ function walkJSONTree ( outputParent , value , maxLvl , colAt , lvl , path , state ) {
5063 var isDate = Object_prototype_toString . call ( value ) === DatePrototypeAsString ;
5164 var realValue = ! isDate && typeof value === "object" && value !== null && "toJSON" in value ? value . toJSON ( ) : value ;
5265 if ( typeof realValue === "object" && realValue !== null && ! isDate ) {
5366 var isMaxLvl = maxLvl >= 0 && lvl >= maxLvl ;
5467 var isCollapse = colAt >= 0 && lvl >= colAt ;
68+ if ( state && state . hasOwnProperty ( path ) ) {
69+ isCollapse = ! state [ path ] ;
70+ }
5571
5672 var isArray = Array . isArray ( realValue ) ;
5773 var items = isArray ? realValue : Object . keys ( realValue ) ;
@@ -60,7 +76,7 @@ var JSONViewer = (function(document) {
6076 // root level
6177 var rootCount = _createItemsCount ( items . length ) ;
6278 // hide/show
63- var rootLink = _createLink ( isArray ? "[" : "{" ) ;
79+ var rootLink = _createLink ( isArray ? "[" : "{" , path ) ;
6480
6581 if ( items . length ) {
6682 rootLink . addEventListener ( "click" , function ( ) {
@@ -94,6 +110,7 @@ var JSONViewer = (function(document) {
94110
95111 items . forEach ( function ( key , ind ) {
96112 var item = isArray ? key : value [ key ] ;
113+ var itemPath = path + "." + ( isArray ? ind : key ) ;
97114 var li = document . createElement ( "li" ) ;
98115
99116 if ( typeof item === "object" ) {
@@ -114,7 +131,7 @@ var JSONViewer = (function(document) {
114131 else {
115132 // 1+ items
116133 var itemTitle = ( typeof key === "string" ? key + ": " : "" ) + ( itemIsArray ? "[" : "{" ) ;
117- var itemLink = _createLink ( itemTitle ) ;
134+ var itemLink = _createLink ( itemTitle , itemPath ) ;
118135 var itemsCount = _createItemsCount ( itemLen ) ;
119136
120137 // maxLvl - only text, no link
@@ -126,7 +143,7 @@ var JSONViewer = (function(document) {
126143 li . appendChild ( itemLink ) ;
127144 }
128145
129- walkJSONTree ( li , item , maxLvl , colAt , lvl + 1 ) ;
146+ walkJSONTree ( li , item , maxLvl , colAt , lvl + 1 , itemPath , state ) ;
130147 li . appendChild ( document . createTextNode ( itemIsArray ? "]" : "}" ) ) ;
131148
132149 var list = li . querySelector ( "ul" ) ;
@@ -140,8 +157,14 @@ var JSONViewer = (function(document) {
140157 itemLink . addEventListener ( "click" , itemLinkCb ) ;
141158
142159 // collapse lower level
143- if ( colAt >= 0 && lvl + 1 >= colAt ) {
144- itemLinkCb ( ) ;
160+ if ( state && state . hasOwnProperty ( itemPath ) ) {
161+ if ( ! state [ itemPath ] ) {
162+ itemLinkCb ( ) ;
163+ }
164+ } else {
165+ if ( colAt >= 0 && lvl + 1 >= colAt ) {
166+ itemLinkCb ( ) ;
167+ }
145168 }
146169 }
147170 }
@@ -154,7 +177,7 @@ var JSONViewer = (function(document) {
154177 }
155178
156179 // recursive
157- walkJSONTree ( li , item , maxLvl , colAt , lvl + 1 ) ;
180+ walkJSONTree ( li , item , maxLvl , colAt , lvl + 1 , itemPath , state ) ;
158181 }
159182
160183 // add comma to the end
@@ -244,11 +267,12 @@ var JSONViewer = (function(document) {
244267 * @param {String } title Link title
245268 * @return {Element }
246269 */
247- function _createLink ( title ) {
270+ function _createLink ( title , path ) {
248271 var linkEl = document . createElement ( "a" ) ;
249272 linkEl . classList . add ( "list-link" ) ;
250273 linkEl . href = "javascript:void(0)" ;
251274 linkEl . innerHTML = title || "" ;
275+ linkEl . setAttribute ( "data-key" , path ) ;
252276
253277 return linkEl ;
254278 } ;
0 commit comments