Skip to content

Commit 7f19df2

Browse files
author
Martynas Žilinskas
committed
Fixed collapsible area.
1 parent f279805 commit 7f19df2

File tree

7 files changed

+85
-24
lines changed

7 files changed

+85
-24
lines changed

assets/json-view.css

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

index.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/array.tsx

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export interface Props {
66
json: any;
77
level: number;
88
spaces: number;
9+
clickId: number;
910
}
1011

1112
export interface State {
@@ -17,8 +18,20 @@ export default class JsonArray extends React.Component<Props, State> {
1718
Collapsed: false
1819
};
1920

21+
componentWillMount() {
22+
if (this.props.clickId != null) {
23+
Formatter.RegisterClickCallback(this.props.clickId, () => {
24+
this.toggleCollapse();
25+
});
26+
}
27+
}
28+
2029
// TODO: Fix any.
21-
private toggleCollapse: React.EventHandler<React.MouseEvent<any>> = (event) => {
30+
private onClick: React.EventHandler<React.MouseEvent<any>> = (event) => {
31+
this.toggleCollapse();
32+
}
33+
34+
private toggleCollapse() {
2235
this.setState((state) => {
2336
state.Collapsed = !state.Collapsed;
2437
return state;
@@ -30,11 +43,11 @@ export default class JsonArray extends React.Component<Props, State> {
3043
let countLoop = arr.length;
3144

3245
for (let item in arr) {
33-
let content = Formatter.valueToHtml(arr[item], this.props.spaces, this.props.level);
46+
let innerContent = Formatter.valueToHtml(arr[item], this.props.spaces, this.props.level);
3447
countLoop--;
3548
items.push(<div key={'array-item-' + item}>
3649
{Helpers.generateSpace(this.props.level * this.props.spaces + this.props.spaces)}
37-
{content}
50+
{innerContent.content}
3851
{countLoop !== 0 ? ',' : ''}
3952
</div>);
4053
}
@@ -56,9 +69,9 @@ export default class JsonArray extends React.Component<Props, State> {
5669
}
5770

5871
return <span className="array">
59-
<span className="brackets-start" onClick={this.toggleCollapse}>{'['}</span>
72+
<span className="brackets collapsible" onClick={this.onClick}>{'['}</span>
6073
{content}
61-
<span className="brackets">{Helpers.generateSpace(bracketSpaces)}{']'}</span>
74+
<span className="brackets collapsible" onClick={this.onClick}>{Helpers.generateSpace(bracketSpaces)}{']'}</span>
6275
</span>
6376
}
6477
return <span className="array">{'[ ]'}</span>;

src/assets/json-view.scss

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
.json-view {
22
font-family: monospace;
33

4-
.brackets-start {
4+
.collapsible {
55
cursor: pointer;
6-
padding: 10px;
7-
margin: -10px;
86

97
&:hover {
108
color: red;

src/formatter.tsx

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,41 @@ import * as React from 'react';
22
import JsonObject from './object';
33
import JsonArray from './array';
44

5-
export default class Formatter {
5+
export interface InnerContent {
6+
content: JSX.Element;
7+
collapsible: boolean;
8+
onClickHandler?: Function;
9+
}
10+
11+
export class Formatter {
612
static URL_PATTERN = /^(http|https):\/\/[^\s]+$/;
13+
private uniqueId: number = 0;
14+
private callbacks: Array<Function> = [];
715

8-
static valueToHtml(value: any, spaces: number, level: number = -1) {
16+
valueToHtml(value: any, spaces: number, level: number = -1): InnerContent {
917
let valueType = typeof value;
10-
let output: JSX.Element | undefined = undefined;
18+
let output: JSX.Element | undefined;
19+
let id = this.uniqueId;
1120
level++;
1221

1322
if (value == null) {
1423
output = <span className="null">null</span>;
1524
} else if (value && value.constructor === Array) {
16-
output = <span className="array"><JsonArray json={value} spaces={spaces} level={level} /></span>;
25+
this.uniqueId++;
26+
27+
return {
28+
content: <span className="array"><JsonArray json={value} spaces={spaces} level={level} clickId={id} /></span>,
29+
collapsible: true,
30+
onClickHandler: () => { this.callbacks[id](); }
31+
}
1732
} else if (valueType === 'object') {
18-
output = <span className="object"><JsonObject json={value} spaces={spaces} level={level} /></span>;
33+
this.uniqueId++;
34+
35+
return {
36+
content: <span className="object"><JsonObject json={value} spaces={spaces} level={level} clickId={id} /></span>,
37+
collapsible: true,
38+
onClickHandler: () => { this.callbacks[id](); }
39+
}
1940
} else if (valueType === 'number') {
2041
output = <span className="number">{value}</span>;
2142
} else if (valueType === 'string') {
@@ -31,6 +52,17 @@ export default class Formatter {
3152
} else if (valueType === 'boolean') {
3253
output = <span className="boolean">{value.toString()}</span>;
3354
}
34-
return output as JSX.Element;
55+
56+
return {
57+
content: output as JSX.Element,
58+
collapsible: false
59+
};
60+
}
61+
62+
RegisterClickCallback(id: number, cb: Function) {
63+
this.callbacks[id] = cb;
3564
}
36-
}
65+
}
66+
67+
let formatter = new Formatter();
68+
export default formatter;

src/json-view.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export default class JsonView extends React.Component<Props, State> {
1616

1717
render() {
1818
return <div className="json-view">
19-
{Formatter.valueToHtml(this.props.json, this.props.spaces as number)}
19+
{Formatter.valueToHtml(this.props.json, this.props.spaces as number).content}
2020
</div>;
2121
}
2222
}

src/object.tsx

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export interface Props {
66
json: any;
77
level: number;
88
spaces: number;
9+
clickId: number;
910
}
1011

1112
export interface State {
@@ -17,8 +18,20 @@ export default class JsonObject extends React.Component<Props, State> {
1718
Collapsed: false
1819
};
1920

21+
componentWillMount() {
22+
if (this.props.clickId != null) {
23+
Formatter.RegisterClickCallback(this.props.clickId, () => {
24+
this.toggleCollapse();
25+
});
26+
}
27+
}
28+
2029
// TODO: Fix any.
21-
private toggleCollapse: React.EventHandler<React.MouseEvent<any>> = (event) => {
30+
private onClick: React.EventHandler<React.MouseEvent<any>> = (event) => {
31+
this.toggleCollapse();
32+
}
33+
34+
private toggleCollapse() {
2235
this.setState((state) => {
2336
state.Collapsed = !state.Collapsed;
2437
return state;
@@ -31,12 +44,17 @@ export default class JsonObject extends React.Component<Props, State> {
3144

3245
for (let item in obj) {
3346
let name = Helpers.htmlEncode(item);
34-
let content = Formatter.valueToHtml(obj[item], this.props.spaces, this.props.level);
47+
let innerContent = Formatter.valueToHtml(obj[item], this.props.spaces, this.props.level);
48+
let collapsibleClassName = (innerContent.collapsible ? 'collapsible' : '');
3549
countLoop--;
3650
items.push(<div key={'object-item-' + item}>
3751
{Helpers.generateSpace(this.props.level * this.props.spaces + this.props.spaces)}
38-
<span className="key">{`"${name}"`}</span>:
39-
{content}
52+
<span className={`key ${collapsibleClassName}`} onClick={() => {
53+
if (innerContent.collapsible && innerContent.onClickHandler != null) {
54+
innerContent.onClickHandler();
55+
}
56+
} }>{`"${name}"`}</span>:
57+
{innerContent.content}
4058
{countLoop !== 0 ? ',' : ''}
4159
</div>);
4260
}
@@ -60,9 +78,9 @@ export default class JsonObject extends React.Component<Props, State> {
6078
}
6179

6280
return <span className={`object ${collapserClassName}`}>
63-
<span className="brackets-start" onClick={this.toggleCollapse}>{'{'}</span>
81+
<span className="brackets collapsible" onClick={this.onClick}>{'{'}</span>
6482
{content}
65-
<span className="brackets">{Helpers.generateSpace(bracketSpaces)}{'}'}</span>
83+
<span className="brackets collapsible" onClick={this.onClick}>{Helpers.generateSpace(bracketSpaces)}{'}'}</span>
6684
</span>
6785
}
6886
return <span className="object">{'{ }'}</span>;

0 commit comments

Comments
 (0)