Skip to content

Commit 96b8d4a

Browse files
author
Emmanouil Konstantinidis
committed
Use JSONView
1 parent eafe55e commit 96b8d4a

File tree

5 files changed

+374
-2
lines changed

5 files changed

+374
-2
lines changed

rest_framework_docs/static/rest_framework_docs/css/style.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.

rest_framework_docs/static/rest_framework_docs/js/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ $( document ).ready(function() {
2828
$('#responseStatusCode').addClass(statusCodeClass);
2929

3030
$('#responseStatusText').text(response.statusText.toLowerCase());
31-
$('#responseData').text(JSON.stringify(response.responseJSON, undefined, 2));
31+
$('#responseData').JSONView(response.responseJSON);
3232

3333
// console.log(response);
3434
// console.log(response.responseJSON);
Lines changed: 284 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,284 @@
1+
2+
/*!
3+
jQuery JSONView.
4+
Licensed under the MIT License.
5+
*/
6+
(function(jQuery) {
7+
var $, Collapser, JSONFormatter, JSONView;
8+
JSONFormatter = (function() {
9+
function JSONFormatter(options) {
10+
if (options == null) {
11+
options = {};
12+
}
13+
this.options = options;
14+
}
15+
16+
JSONFormatter.prototype.htmlEncode = function(html) {
17+
if (html !== null) {
18+
return html.toString().replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
19+
} else {
20+
return '';
21+
}
22+
};
23+
24+
JSONFormatter.prototype.jsString = function(s) {
25+
s = JSON.stringify(s).slice(1, -1);
26+
return this.htmlEncode(s);
27+
};
28+
29+
JSONFormatter.prototype.decorateWithSpan = function(value, className) {
30+
return "<span class=\"" + className + "\">" + (this.htmlEncode(value)) + "</span>";
31+
};
32+
33+
JSONFormatter.prototype.valueToHTML = function(value, level) {
34+
var valueType;
35+
if (level == null) {
36+
level = 0;
37+
}
38+
valueType = Object.prototype.toString.call(value).match(/\s(.+)]/)[1].toLowerCase();
39+
return this["" + valueType + "ToHTML"].call(this, value, level);
40+
};
41+
42+
JSONFormatter.prototype.nullToHTML = function(value) {
43+
return this.decorateWithSpan('null', 'null');
44+
};
45+
46+
JSONFormatter.prototype.numberToHTML = function(value) {
47+
return this.decorateWithSpan(value, 'num');
48+
};
49+
50+
JSONFormatter.prototype.stringToHTML = function(value) {
51+
var multilineClass, newLinePattern;
52+
if (/^(http|https|file):\/\/[^\s]+$/i.test(value)) {
53+
return "<a href=\"" + (this.htmlEncode(value)) + "\"><span class=\"q\">\"</span>" + (this.jsString(value)) + "<span class=\"q\">\"</span></a>";
54+
} else {
55+
multilineClass = '';
56+
value = this.jsString(value);
57+
if (this.options.nl2br) {
58+
newLinePattern = /([^>\\r\\n]?)(\\r\\n|\\n\\r|\\r|\\n)/g;
59+
if (newLinePattern.test(value)) {
60+
multilineClass = ' multiline';
61+
value = (value + '').replace(newLinePattern, '$1' + '<br />');
62+
}
63+
}
64+
return "<span class=\"string" + multilineClass + "\">\"" + value + "\"</span>";
65+
}
66+
};
67+
68+
JSONFormatter.prototype.booleanToHTML = function(value) {
69+
return this.decorateWithSpan(value, 'bool');
70+
};
71+
72+
JSONFormatter.prototype.arrayToHTML = function(array, level) {
73+
var collapsible, hasContents, index, numProps, output, value, _i, _len;
74+
if (level == null) {
75+
level = 0;
76+
}
77+
hasContents = false;
78+
output = '';
79+
numProps = array.length;
80+
for (index = _i = 0, _len = array.length; _i < _len; index = ++_i) {
81+
value = array[index];
82+
hasContents = true;
83+
output += '<li>' + this.valueToHTML(value, level + 1);
84+
if (numProps > 1) {
85+
output += ',';
86+
}
87+
output += '</li>';
88+
numProps--;
89+
}
90+
if (hasContents) {
91+
collapsible = level === 0 ? '' : ' collapsible';
92+
return "[<ul class=\"array level" + level + collapsible + "\">" + output + "</ul>]";
93+
} else {
94+
return '[ ]';
95+
}
96+
};
97+
98+
JSONFormatter.prototype.objectToHTML = function(object, level) {
99+
var collapsible, hasContents, key, numProps, output, prop, value;
100+
if (level == null) {
101+
level = 0;
102+
}
103+
hasContents = false;
104+
output = '';
105+
numProps = 0;
106+
for (prop in object) {
107+
numProps++;
108+
}
109+
for (prop in object) {
110+
value = object[prop];
111+
hasContents = true;
112+
key = this.options.escape ? this.jsString(prop) : prop;
113+
output += "<li><span class=\"prop\"><span class=\"q\">\"</span>" + key + "<span class=\"q\">\"</span></span>: " + (this.valueToHTML(value, level + 1));
114+
if (numProps > 1) {
115+
output += ',';
116+
}
117+
output += '</li>';
118+
numProps--;
119+
}
120+
if (hasContents) {
121+
collapsible = level === 0 ? '' : ' collapsible';
122+
return "{<ul class=\"obj level" + level + collapsible + "\">" + output + "</ul>}";
123+
} else {
124+
return '{ }';
125+
}
126+
};
127+
128+
JSONFormatter.prototype.jsonToHTML = function(json) {
129+
return "<div class=\"jsonview\">" + (this.valueToHTML(json)) + "</div>";
130+
};
131+
132+
return JSONFormatter;
133+
134+
})();
135+
(typeof module !== "undefined" && module !== null) && (module.exports = JSONFormatter);
136+
Collapser = (function() {
137+
function Collapser() {}
138+
139+
Collapser.bindEvent = function(item, options) {
140+
var collapser;
141+
collapser = document.createElement('div');
142+
collapser.className = 'collapser';
143+
collapser.innerHTML = options.collapsed ? '+' : '-';
144+
collapser.addEventListener('click', (function(_this) {
145+
return function(event) {
146+
return _this.toggle(event.target, options);
147+
};
148+
})(this));
149+
item.insertBefore(collapser, item.firstChild);
150+
if (options.collapsed) {
151+
return this.collapse(collapser);
152+
}
153+
};
154+
155+
Collapser.expand = function(collapser) {
156+
var ellipsis, target;
157+
target = this.collapseTarget(collapser);
158+
if (target.style.display === '') {
159+
return;
160+
}
161+
ellipsis = target.parentNode.getElementsByClassName('ellipsis')[0];
162+
target.parentNode.removeChild(ellipsis);
163+
target.style.display = '';
164+
return collapser.innerHTML = '-';
165+
};
166+
167+
Collapser.collapse = function(collapser) {
168+
var ellipsis, target;
169+
target = this.collapseTarget(collapser);
170+
if (target.style.display === 'none') {
171+
return;
172+
}
173+
target.style.display = 'none';
174+
ellipsis = document.createElement('span');
175+
ellipsis.className = 'ellipsis';
176+
ellipsis.innerHTML = ' &hellip; ';
177+
target.parentNode.insertBefore(ellipsis, target);
178+
return collapser.innerHTML = '+';
179+
};
180+
181+
Collapser.toggle = function(collapser, options) {
182+
var action, collapsers, target, _i, _len, _results;
183+
if (options == null) {
184+
options = {};
185+
}
186+
target = this.collapseTarget(collapser);
187+
action = target.style.display === 'none' ? 'expand' : 'collapse';
188+
if (options.recursive_collapser) {
189+
collapsers = collapser.parentNode.getElementsByClassName('collapser');
190+
_results = [];
191+
for (_i = 0, _len = collapsers.length; _i < _len; _i++) {
192+
collapser = collapsers[_i];
193+
_results.push(this[action](collapser));
194+
}
195+
return _results;
196+
} else {
197+
return this[action](collapser);
198+
}
199+
};
200+
201+
Collapser.collapseTarget = function(collapser) {
202+
var target, targets;
203+
targets = collapser.parentNode.getElementsByClassName('collapsible');
204+
if (!targets.length) {
205+
return;
206+
}
207+
return target = targets[0];
208+
};
209+
210+
return Collapser;
211+
212+
})();
213+
$ = jQuery;
214+
JSONView = {
215+
collapse: function(el) {
216+
if (el.innerHTML === '-') {
217+
return Collapser.collapse(el);
218+
}
219+
},
220+
expand: function(el) {
221+
if (el.innerHTML === '+') {
222+
return Collapser.expand(el);
223+
}
224+
},
225+
toggle: function(el) {
226+
return Collapser.toggle(el);
227+
}
228+
};
229+
return $.fn.JSONView = function() {
230+
var args, defaultOptions, formatter, json, method, options, outputDoc;
231+
args = arguments;
232+
if (JSONView[args[0]] != null) {
233+
method = args[0];
234+
return this.each(function() {
235+
var $this, level;
236+
$this = $(this);
237+
if (args[1] != null) {
238+
level = args[1];
239+
return $this.find(".jsonview .collapsible.level" + level).siblings('.collapser').each(function() {
240+
return JSONView[method](this);
241+
});
242+
} else {
243+
return $this.find('.jsonview > ul > li .collapsible').siblings('.collapser').each(function() {
244+
return JSONView[method](this);
245+
});
246+
}
247+
});
248+
} else {
249+
json = args[0];
250+
options = args[1] || {};
251+
defaultOptions = {
252+
collapsed: false,
253+
nl2br: false,
254+
recursive_collapser: false,
255+
escape: true
256+
};
257+
options = $.extend(defaultOptions, options);
258+
formatter = new JSONFormatter({
259+
nl2br: options.nl2br,
260+
escape: options.escape
261+
});
262+
if (Object.prototype.toString.call(json) === '[object String]') {
263+
json = JSON.parse(json);
264+
}
265+
outputDoc = formatter.jsonToHTML(json);
266+
return this.each(function() {
267+
var $this, item, items, _i, _len, _results;
268+
$this = $(this);
269+
$this.html(outputDoc);
270+
items = $this[0].getElementsByClassName('collapsible');
271+
_results = [];
272+
for (_i = 0, _len = items.length; _i < _len; _i++) {
273+
item = items[_i];
274+
if (item.parentNode.nodeName === 'LI') {
275+
_results.push(Collapser.bindEvent(item.parentNode, options));
276+
} else {
277+
_results.push(void 0);
278+
}
279+
}
280+
return _results;
281+
});
282+
}
283+
};
284+
})(jQuery);

rest_framework_docs/static/rest_framework_docs/less/style.less

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,93 @@ body {
190190
/* @end Modal API */
191191

192192

193+
/* @group jQuery / JSON View */
194+
195+
.jsonview {
196+
font-family: monospace;
197+
font-size: 1.1em;
198+
white-space: pre-wrap;
199+
}
200+
201+
.jsonview .prop {
202+
font-weight: bold;
203+
}
204+
205+
.jsonview .null {
206+
color: red;
207+
}
208+
209+
.jsonview .bool {
210+
color: blue;
211+
}
212+
213+
.jsonview .num {
214+
color: blue;
215+
}
216+
217+
.jsonview .string {
218+
color: green;
219+
white-space: pre-wrap;
220+
}
221+
222+
.jsonview .string.multiline {
223+
display: inline-block;
224+
vertical-align: text-top;
225+
}
226+
227+
.jsonview .collapser {
228+
position: absolute;
229+
left: -1em;
230+
cursor: pointer;
231+
}
232+
233+
.jsonview .collapsible {
234+
transition: height 1.2s;
235+
transition: width 1.2s;
236+
}
237+
238+
.jsonview .collapsible.collapsed {
239+
height: .8em;
240+
width: 1em;
241+
display: inline-block;
242+
overflow: hidden;
243+
margin: 0;
244+
}
245+
246+
.jsonview .collapsible.collapsed:before {
247+
content: "";
248+
width: 1em;
249+
margin-left: .2em;
250+
}
251+
252+
.jsonview .collapser.collapsed {
253+
transform: rotate(0deg);
254+
}
255+
256+
.jsonview .q {
257+
display: inline-block;
258+
width: 0px;
259+
color: transparent;
260+
}
261+
262+
.jsonview li {
263+
position: relative;
264+
}
265+
266+
.jsonview ul {
267+
list-style: none;
268+
margin: 0 0 0 2em;
269+
padding: 0;
270+
}
271+
272+
.jsonview h1 {
273+
font-size: 1.2em;
274+
}
275+
276+
/* @end jQuery / JSON View */
277+
278+
279+
193280
/* @group Github Ribbon - SVG */
194281

195282
.github-corner:hover .octo-arm {

rest_framework_docs/templates/rest_framework_docs/base.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ <h3>Document Web APIs made with <a href="http://www.django-rest-framework.org/"
7878
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
7979
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
8080
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js" integrity="sha256-KXn5puMvxCw+dAYznun+drMdG1IFl3agK0p/pqT9KAo= sha512-2e8qq0ETcfWRI4HJBzQiA3UoyFk6tbNyG+qSaIBZLyW9Xf3sWZHN/lxe9fTh1U45DpPf07yj94KsUHHWe4Yk1A==" crossorigin="anonymous"></script>
81+
<script type="text/javascript" src="{% static "rest_framework_docs/js/jsonview.js" %}"></script>
8182
<script type="text/javascript" src="{% static "rest_framework_docs/js/index.js" %}"></script>
8283
</body>
8384
</html>

0 commit comments

Comments
 (0)