3
3
* jsonTree: A dependency-free lightweight vanilla Javascript library to display JSON in an HTML unordered list.
4
4
**/
5
5
6
- var jsonTree = ( function ( ) {
6
+ class jsonTree {
7
7
/**
8
8
* json: URL for json file or a JSON object
9
9
* selector: the elements selector to apply the tree to
10
10
* depth: bool to add a "depth-#" class, can increase loading times
11
11
**/
12
- return {
13
- init : function ( json , selector , depth ) {
14
- classList ( ) ;
15
-
16
- // It's not a URL, so let's skip the XMLHttpRequest
17
- if ( typeof json === "object" ) {
18
- generateTree ( selector , json ) ;
19
- classify ( selector , depth ) ;
20
- } else {
21
- var request = new XMLHttpRequest ( ) ;
22
- request . open ( "GET" , json , true ) ;
23
- request . send ( ) ;
24
- request . addEventListener ( "load" , function ( ) {
25
- generateTree ( selector , JSON . parse ( request . responseText ) ) ;
26
- classify ( selector , depth ) ;
27
- } ) ;
28
- }
12
+ constructor ( json , selector , depth ) {
13
+ // It's not a URL, so let's skip the XMLHttpRequest
14
+ if ( typeof json === "object" ) {
15
+ this . generateTree ( selector , json ) ;
16
+ this . classify ( selector , depth ) ;
17
+ } else {
18
+ const request = new XMLHttpRequest ( ) ;
19
+ request . open ( "GET" , json , true ) ;
20
+ request . send ( ) ;
21
+ request . addEventListener ( "load" , ( ) => {
22
+ this . generateTree ( selector , JSON . parse ( request . responseText ) ) ;
23
+ this . classify ( selector , depth ) ;
24
+ } ) ;
29
25
}
30
26
}
31
27
32
- /* classList.js for old browsers */
33
- function classList ( ) {
34
- /*! @source http://purl.eligrey.com/github/classList.js/blob/master/classList.js */
35
- "document" in self && ( "classList" in document . createElement ( "_" ) && ( ! document . createElementNS || "classList" in document . createElementNS ( "http://www.w3.org/2000/svg" , "g" ) ) || function ( a ) { if ( "Element" in a ) { a = a . Element . prototype ; var h = Object , l = String . prototype . trim || function ( ) { return this . replace ( / ^ \s + | \s + $ / g, "" ) } , n = Array . prototype . indexOf || function ( c ) { for ( var b = 0 , k = this . length ; b < k ; b ++ ) if ( b in this && this [ b ] === c ) return b ; return - 1 } , f = function ( c , b ) { this . name = c ; this . code = DOMException [ c ] ; this . message = b } , e = function ( c ,
36
- b ) { if ( "" === b ) throw new f ( "SYNTAX_ERR" , "The token must not be empty." ) ; if ( / \s / . test ( b ) ) throw new f ( "INVALID_CHARACTER_ERR" , "The token must not contain space characters." ) ; return n . call ( c , b ) } , g = function ( c ) { var b = l . call ( c . getAttribute ( "class" ) || "" ) ; b = b ?b . split ( / \s + / ) :[ ] ; for ( var k = 0 , e = b . length ; k < e ; k ++ ) this . push ( b [ k ] ) ; this . _updateClassName = function ( ) { c . setAttribute ( "class" , this . toString ( ) ) } } , d = g . prototype = [ ] , m = function ( ) { return new g ( this ) } ; f . prototype = Error . prototype ; d . item = function ( c ) { return this [ c ] ||
37
- null } ; d . contains = function ( c ) { return ! ~ e ( this , c + "" ) } ; d . add = function ( ) { var c = arguments , b = 0 , k = c . length , d = ! 1 ; do { var a = c [ b ] + "" ; ~ e ( this , a ) && ( this . push ( a ) , d = ! 0 ) } while ( ++ b < k ) ; d && this . _updateClassName ( ) } ; d . remove = function ( ) { var c = arguments , b = 0 , d = c . length , a = ! 1 , f ; do { var g = c [ b ] + "" ; for ( f = e ( this , g ) ; ~ f ; ) this . splice ( f , 1 ) , a = ! 0 , f = e ( this , g ) } while ( ++ b < d ) ; a && this . _updateClassName ( ) } ; d . toggle = function ( c , b ) { var a = this . contains ( c ) , d = a ?! 0 !== b && "remove" :! 1 !== b && "add" ; if ( d ) this [ d ] ( c ) ; return ! 0 === b || ! 1 === b ?b :! a } ; d . replace = function ( c ,
38
- b ) { var a = e ( c + "" ) ; ~ a && ( this . splice ( a , 1 , b ) , this . _updateClassName ( ) ) } ; d . toString = function ( ) { return this . join ( " " ) } ; if ( h . defineProperty ) { d = { get :m , enumerable :! 0 , configurable :! 0 } ; try { h . defineProperty ( a , "classList" , d ) } catch ( c ) { if ( void 0 === c . number || - 2146823252 === c . number ) d . enumerable = ! 1 , h . defineProperty ( a , "classList" , d ) } } else h . prototype . __defineGetter__ && a . __defineGetter__ ( "classList" , m ) } } ( self ) , function ( ) { var a = document . createElement ( "_" ) ; a . classList . add ( "c1" , "c2" ) ; if ( ! a . classList . contains ( "c2" ) ) { var h =
39
- function ( a ) { var f = DOMTokenList . prototype [ a ] ; DOMTokenList . prototype [ a ] = function ( a ) { var e , d = arguments . length ; for ( e = 0 ; e < d ; e ++ ) a = arguments [ e ] , f . call ( this , a ) } } ; h ( "add" ) ; h ( "remove" ) } a . classList . toggle ( "c3" , ! 1 ) ; if ( a . classList . contains ( "c3" ) ) { var l = DOMTokenList . prototype . toggle ; DOMTokenList . prototype . toggle = function ( a , f ) { return 1 in arguments && ! this . contains ( a ) === ! f ?f :l . call ( this , a ) } } "replace" in document . createElement ( "_" ) . classList || ( DOMTokenList . prototype . replace = function ( a , f ) { var e = this . toString ( ) . split ( " " ) ,
40
- g = e . indexOf ( a + "" ) ; ~ g && ( e = e . slice ( g ) , this . remove . apply ( this , e ) , this . add ( f ) , this . add . apply ( this , e . slice ( 1 ) ) ) } ) ; a = null } ( ) ) ;
41
- }
42
-
43
28
/** Generate the DOM elements for the tree**/
44
- function generateTree ( selector , json ) {
45
- var element = document . querySelector ( selector ) ;
29
+ generateTree ( selector , json ) {
30
+ const element = document . querySelector ( selector ) ;
46
31
element . classList . add ( "jsonTree" ) ;
47
- element . innerHTML = json2html ( json ) ;
48
- top = document . querySelectorAll ( "# top") ;
49
- top . addEventListener ( "click" , function ( e ) {
32
+ element . innerHTML = this . json2html ( json ) ;
33
+ const top = document . querySelector ( "[data-id=\" top\"] ") ;
34
+ top . addEventListener ( "click" , ( e ) => {
50
35
e . preventDefault ( ) ;
51
36
if ( e . target && e . target . nodeName . toUpperCase ( ) === "LI" ) {
52
- if ( toArray ( e . target . childNodes ) . length > 1 ) {
53
- toggleClass ( e . target , "selected" ) ;
37
+ if ( Array . from ( e . target . childNodes ) . length > 1 ) {
38
+ this . toggleClass ( e . target , "selected" ) ;
54
39
}
55
40
}
56
41
} ) ;
57
42
}
58
43
59
- function classify ( selector , depth ) {
60
- applyClasses ( selector , "li" , "ul" , depth ) ;
61
- applyClasses ( selector , "ul" , "li" , depth ) ;
44
+ classify ( selector , depth ) {
45
+ this . applyClasses ( selector , "li" , "ul" , depth ) ;
46
+ this . applyClasses ( selector , "ul" , "li" , depth ) ;
62
47
}
63
48
64
49
/** Applies classes to the element, including "parent" and "depth-#" **/
65
- function applyClasses ( selector , parent , child , depth ) {
66
- var parents = toArray ( document . querySelectorAll ( selector + " " + parent ) ) ;
50
+ applyClasses ( selector , parent , child , depth ) {
51
+ const parents = Array . from ( document . querySelectorAll ( ` ${ selector } ${ parent } ` ) ) ;
67
52
parents . forEach ( function ( element ) {
68
- var filter = toArray ( element . children ) . filter ( function ( el ) { return el . tagName . toLowerCase ( ) === child . toLowerCase ( ) . toString ( ) ; } ) ;
69
- if ( filter . length > 0 ) { // It's a parent!
70
- element . classList . add ( "parent" ) ;
71
- element . style . cursor = "pointer" ;
72
- } else {
73
- element . style . cursor = "auto" ;
74
- }
53
+ const filter = Array . from ( element . children ) . filter ( ( el ) => el . tagName . toLowerCase ( ) === child . toLowerCase ( ) . toString ( ) ) ;
54
+ if ( filter . length > 0 ) { // It's a parent!
55
+ element . classList . add ( "parent" ) ;
56
+ element . style . cursor = "pointer" ;
57
+ } else {
58
+ element . style . cursor = "auto" ;
59
+ }
60
+
75
61
// The amount of parents, "#top" is assigned by json2html
76
62
if ( depth ) {
77
- var count = depth ( element ) ;
63
+ const count = depth ( element ) ;
78
64
element . classList . add ( "depth-" + count ) ;
79
65
}
80
66
} ) ;
81
67
}
82
68
83
69
/** Returns the amount of parents of an element **/
84
- function depth ( ele ) {
70
+ depth ( ele ) {
85
71
if ( ele . parentNode && ele . parentNode . getAttribute ( "data-id" ) === "top" ) {
86
72
return ele == null ? 0 : 1 + depth ( ele . parentNode ) ;
87
73
} else {
88
74
return 0 ;
89
75
}
90
76
}
91
77
92
- /** Converts HTMLCollection to array (for ease of use with functions like forEach) **/
93
- function toArray ( o ) {
94
- return Array . prototype . slice . call ( o ) ;
95
- }
96
-
97
78
/** Returns a JSON file in HTML tokens **/
98
- function json2html ( json ) {
99
- var i , html = "" ;
100
- json = htmlEscape ( JSON . stringify ( json ) ) ;
79
+ json2html ( json ) {
80
+ let i , html = "" ;
81
+ json = this . htmlEscape ( JSON . stringify ( json ) ) ;
101
82
json = JSON . parse ( json ) ;
102
83
html += "<ul data-id=\"top\">" ;
103
84
for ( i in json ) {
104
85
html += "<li>" + i + ": " ;
105
86
if ( typeof json [ i ] === "object" ) {
106
- html += json2html ( json [ i ] ) ;
87
+ html += this . json2html ( json [ i ] ) ;
107
88
}
108
89
else html += json [ i ] ;
109
90
html += "</li>" ;
@@ -113,8 +94,8 @@ var jsonTree = (function() {
113
94
}
114
95
115
96
/** To stop XSS attacks by using JSON with HTML nodes **/
116
- function htmlEscape ( str ) {
117
- var tagsToReplace = {
97
+ htmlEscape ( str ) {
98
+ const tagsToReplace = {
118
99
"&" : "&" ,
119
100
"<" : "<" ,
120
101
">" : ">"
@@ -125,10 +106,10 @@ var jsonTree = (function() {
125
106
}
126
107
127
108
/** Toggles an elements class **/
128
- function toggleClass ( el , className ) {
109
+ toggleClass ( el , className ) {
129
110
if ( el ) {
130
111
el . classList . toggle ( className ) ;
131
112
}
132
113
}
133
- } ) ( ) ;
114
+ }
134
115
0 commit comments