bee_api 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/bin/bee_api +84 -0
- data/lib/mdpreview.rb +80 -0
- data/lib/mdpreview/translator.rb +60 -0
- data/lib/mdpreview/version.rb +3 -0
- data/test/mdptest.rb +100 -0
- data/vendor/HISTORY.md +237 -0
- data/vendor/Jakefile.js +316 -0
- data/vendor/LICENSE +176 -0
- data/vendor/NOTICE +17 -0
- data/vendor/README.md +102 -0
- data/vendor/app/chrome/documentation.txt +12 -0
- data/vendor/app/chrome/manifest.json +24 -0
- data/vendor/app/web/ajax.js +43 -0
- data/vendor/app/web/app.css +292 -0
- data/vendor/app/web/app.js +377 -0
- data/vendor/app/web/beta/index.html +17 -0
- data/vendor/app/web/datapolicy.txt +48 -0
- data/vendor/app/web/doc/doc.css +60 -0
- data/vendor/app/web/doc/img/actions_menu.png +0 -0
- data/vendor/app/web/doc/img/button_actions_menu.png +0 -0
- data/vendor/app/web/doc/img/button_dragarea.png +0 -0
- data/vendor/app/web/doc/img/jsoneditor.png +0 -0
- data/vendor/app/web/doc/img/jsonformatter.png +0 -0
- data/vendor/app/web/doc/img/main_menu.png +0 -0
- data/vendor/app/web/doc/img/splitter.png +0 -0
- data/vendor/app/web/doc/index.html +201 -0
- data/vendor/app/web/favicon.ico +0 -0
- data/vendor/app/web/fileretriever.css +54 -0
- data/vendor/app/web/fileretriever.js +567 -0
- data/vendor/app/web/fileretriever.php +120 -0
- data/vendor/app/web/googlea47c4a0b36d11021.html +1 -0
- data/vendor/app/web/hash.js +133 -0
- data/vendor/app/web/img/description.txt +20 -0
- data/vendor/app/web/img/header_background.png +0 -0
- data/vendor/app/web/img/icon_128.png +0 -0
- data/vendor/app/web/img/icon_16.png +0 -0
- data/vendor/app/web/img/icon_gray.svg +151 -0
- data/vendor/app/web/img/icon_gray_16.svg +150 -0
- data/vendor/app/web/img/icon_orange.svg +151 -0
- data/vendor/app/web/img/logo.png +0 -0
- data/vendor/app/web/img/logo.xcf +0 -0
- data/vendor/app/web/img/logo_app.png +0 -0
- data/vendor/app/web/img/logo_app.xcf +0 -0
- data/vendor/app/web/index.html +191 -0
- data/vendor/app/web/notify.js +150 -0
- data/vendor/app/web/queryparams.js +71 -0
- data/vendor/app/web/robots.txt +0 -0
- data/vendor/app/web/splitter.js +179 -0
- data/vendor/app/web/test.html +224 -0
- data/vendor/component.json +33 -0
- data/vendor/docs/api.md +188 -0
- data/vendor/docs/usage.md +137 -0
- data/vendor/examples/01_basic_usage.html +45 -0
- data/vendor/examples/02_viewer.html +38 -0
- data/vendor/examples/03_switch_mode.html +98 -0
- data/vendor/examples/cur.file +1 -0
- data/vendor/examples/jquery.js +2 -0
- data/vendor/examples/meta.js +1 -0
- data/vendor/examples/requirejs_demo/requirejs_demo.html +19 -0
- data/vendor/examples/requirejs_demo/scripts/main.js +25 -0
- data/vendor/examples/requirejs_demo/scripts/require.js +35 -0
- data/vendor/img/jsoneditor-icons.png +0 -0
- data/vendor/jsoneditor-min.css +1 -0
- data/vendor/jsoneditor-min.js +34 -0
- data/vendor/jsoneditor.css +597 -0
- data/vendor/jsoneditor.js +6069 -0
- data/vendor/jsoneditor/css/contextmenu.css +219 -0
- data/vendor/jsoneditor/css/img/description.txt +13 -0
- data/vendor/jsoneditor/css/img/export.sh +16 -0
- data/vendor/jsoneditor/css/img/jsoneditor-icons.png +0 -0
- data/vendor/jsoneditor/css/img/jsoneditor-icons.svg +861 -0
- data/vendor/jsoneditor/css/jsoneditor.css +220 -0
- data/vendor/jsoneditor/css/menu.css +81 -0
- data/vendor/jsoneditor/css/searchbox.css +73 -0
- data/vendor/jsoneditor/js/appendnode.js +211 -0
- data/vendor/jsoneditor/js/contextmenu.js +440 -0
- data/vendor/jsoneditor/js/header.js +32 -0
- data/vendor/jsoneditor/js/highlighter.js +82 -0
- data/vendor/jsoneditor/js/history.js +218 -0
- data/vendor/jsoneditor/js/jsoneditor.js +206 -0
- data/vendor/jsoneditor/js/module.js +50 -0
- data/vendor/jsoneditor/js/node.js +2864 -0
- data/vendor/jsoneditor/js/searchbox.js +288 -0
- data/vendor/jsoneditor/js/texteditor.js +311 -0
- data/vendor/jsoneditor/js/treeeditor.js +770 -0
- data/vendor/jsoneditor/js/util.js +582 -0
- data/vendor/lib/ace/ace.js +11 -0
- data/vendor/lib/ace/mode-json.js +1 -0
- data/vendor/lib/ace/theme-jsoneditor.js +144 -0
- data/vendor/lib/ace/theme-textmate.js +163 -0
- data/vendor/lib/ace/worker-json.js +1 -0
- data/vendor/lib/jsonlint/README.md +62 -0
- data/vendor/lib/jsonlint/jsonlint.js +432 -0
- data/vendor/misc/screenshots/actionsmenu_640x400.png +0 -0
- data/vendor/misc/screenshots/codeeditor_640x400.png +0 -0
- data/vendor/misc/screenshots/description.json +17 -0
- data/vendor/misc/screenshots/jsoneditoronline.png +0 -0
- data/vendor/misc/screenshots/jsoneditoronline_640x400.png +0 -0
- data/vendor/misc/screenshots/search_640x400.png +0 -0
- data/vendor/misc/screenshots/small_tile.xcf +0 -0
- data/vendor/misc/screenshots/small_tile_440x280.png +0 -0
- data/vendor/misc/todo.txt +101 -0
- data/vendor/package.json +28 -0
- data/vendor/test/couchdbeditor.html +100 -0
- data/vendor/test/largefile.json +12605 -0
- data/vendor/test/test_ace.html +60 -0
- data/vendor/test/test_editable_div.html +449 -0
- metadata +154 -0
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @constructor SearchBox
|
|
3
|
+
* Create a search box in given HTML container
|
|
4
|
+
* @param {JSONEditor} editor The JSON Editor to attach to
|
|
5
|
+
* @param {Element} container HTML container element of where to
|
|
6
|
+
* create the search box
|
|
7
|
+
*/
|
|
8
|
+
function SearchBox (editor, container) {
|
|
9
|
+
var searchBox = this;
|
|
10
|
+
|
|
11
|
+
this.editor = editor;
|
|
12
|
+
this.timeout = undefined;
|
|
13
|
+
this.delay = 200; // ms
|
|
14
|
+
this.lastText = undefined;
|
|
15
|
+
|
|
16
|
+
this.dom = {};
|
|
17
|
+
this.dom.container = container;
|
|
18
|
+
|
|
19
|
+
var table = document.createElement('table');
|
|
20
|
+
this.dom.table = table;
|
|
21
|
+
table.className = 'search';
|
|
22
|
+
container.appendChild(table);
|
|
23
|
+
var tbody = document.createElement('tbody');
|
|
24
|
+
this.dom.tbody = tbody;
|
|
25
|
+
table.appendChild(tbody);
|
|
26
|
+
var tr = document.createElement('tr');
|
|
27
|
+
tbody.appendChild(tr);
|
|
28
|
+
|
|
29
|
+
var td = document.createElement('td');
|
|
30
|
+
tr.appendChild(td);
|
|
31
|
+
var results = document.createElement('div');
|
|
32
|
+
this.dom.results = results;
|
|
33
|
+
results.className = 'results';
|
|
34
|
+
td.appendChild(results);
|
|
35
|
+
|
|
36
|
+
td = document.createElement('td');
|
|
37
|
+
tr.appendChild(td);
|
|
38
|
+
var divInput = document.createElement('div');
|
|
39
|
+
this.dom.input = divInput;
|
|
40
|
+
divInput.className = 'frame';
|
|
41
|
+
divInput.title = 'Search fields and values';
|
|
42
|
+
td.appendChild(divInput);
|
|
43
|
+
|
|
44
|
+
// table to contain the text input and search button
|
|
45
|
+
var tableInput = document.createElement('table');
|
|
46
|
+
divInput.appendChild(tableInput);
|
|
47
|
+
var tbodySearch = document.createElement('tbody');
|
|
48
|
+
tableInput.appendChild(tbodySearch);
|
|
49
|
+
tr = document.createElement('tr');
|
|
50
|
+
tbodySearch.appendChild(tr);
|
|
51
|
+
|
|
52
|
+
var refreshSearch = document.createElement('button');
|
|
53
|
+
refreshSearch.className = 'refresh';
|
|
54
|
+
td = document.createElement('td');
|
|
55
|
+
td.appendChild(refreshSearch);
|
|
56
|
+
tr.appendChild(td);
|
|
57
|
+
|
|
58
|
+
var search = document.createElement('input');
|
|
59
|
+
this.dom.search = search;
|
|
60
|
+
search.oninput = function (event) {
|
|
61
|
+
searchBox._onDelayedSearch(event);
|
|
62
|
+
};
|
|
63
|
+
search.onchange = function (event) { // For IE 8
|
|
64
|
+
searchBox._onSearch(event);
|
|
65
|
+
};
|
|
66
|
+
search.onkeydown = function (event) {
|
|
67
|
+
searchBox._onKeyDown(event);
|
|
68
|
+
};
|
|
69
|
+
search.onkeyup = function (event) {
|
|
70
|
+
searchBox._onKeyUp(event);
|
|
71
|
+
};
|
|
72
|
+
refreshSearch.onclick = function (event) {
|
|
73
|
+
search.select();
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
// TODO: ESC in FF restores the last input, is a FF bug, https://bugzilla.mozilla.org/show_bug.cgi?id=598819
|
|
77
|
+
td = document.createElement('td');
|
|
78
|
+
td.appendChild(search);
|
|
79
|
+
tr.appendChild(td);
|
|
80
|
+
|
|
81
|
+
var searchNext = document.createElement('button');
|
|
82
|
+
searchNext.title = 'Next result (Enter)';
|
|
83
|
+
searchNext.className = 'next';
|
|
84
|
+
searchNext.onclick = function () {
|
|
85
|
+
searchBox.next();
|
|
86
|
+
};
|
|
87
|
+
td = document.createElement('td');
|
|
88
|
+
td.appendChild(searchNext);
|
|
89
|
+
tr.appendChild(td);
|
|
90
|
+
|
|
91
|
+
var searchPrevious = document.createElement('button');
|
|
92
|
+
searchPrevious.title = 'Previous result (Shift+Enter)';
|
|
93
|
+
searchPrevious.className = 'previous';
|
|
94
|
+
searchPrevious.onclick = function () {
|
|
95
|
+
searchBox.previous();
|
|
96
|
+
};
|
|
97
|
+
td = document.createElement('td');
|
|
98
|
+
td.appendChild(searchPrevious);
|
|
99
|
+
tr.appendChild(td);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Go to the next search result
|
|
104
|
+
* @param {boolean} [focus] If true, focus will be set to the next result
|
|
105
|
+
* focus is false by default.
|
|
106
|
+
*/
|
|
107
|
+
SearchBox.prototype.next = function(focus) {
|
|
108
|
+
if (this.results != undefined) {
|
|
109
|
+
var index = (this.resultIndex != undefined) ? this.resultIndex + 1 : 0;
|
|
110
|
+
if (index > this.results.length - 1) {
|
|
111
|
+
index = 0;
|
|
112
|
+
}
|
|
113
|
+
this._setActiveResult(index, focus);
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Go to the prevous search result
|
|
119
|
+
* @param {boolean} [focus] If true, focus will be set to the next result
|
|
120
|
+
* focus is false by default.
|
|
121
|
+
*/
|
|
122
|
+
SearchBox.prototype.previous = function(focus) {
|
|
123
|
+
if (this.results != undefined) {
|
|
124
|
+
var max = this.results.length - 1;
|
|
125
|
+
var index = (this.resultIndex != undefined) ? this.resultIndex - 1 : max;
|
|
126
|
+
if (index < 0) {
|
|
127
|
+
index = max;
|
|
128
|
+
}
|
|
129
|
+
this._setActiveResult(index, focus);
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Set new value for the current active result
|
|
135
|
+
* @param {Number} index
|
|
136
|
+
* @param {boolean} [focus] If true, focus will be set to the next result.
|
|
137
|
+
* focus is false by default.
|
|
138
|
+
* @private
|
|
139
|
+
*/
|
|
140
|
+
SearchBox.prototype._setActiveResult = function(index, focus) {
|
|
141
|
+
// de-activate current active result
|
|
142
|
+
if (this.activeResult) {
|
|
143
|
+
var prevNode = this.activeResult.node;
|
|
144
|
+
var prevElem = this.activeResult.elem;
|
|
145
|
+
if (prevElem == 'field') {
|
|
146
|
+
delete prevNode.searchFieldActive;
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
delete prevNode.searchValueActive;
|
|
150
|
+
}
|
|
151
|
+
prevNode.updateDom();
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if (!this.results || !this.results[index]) {
|
|
155
|
+
// out of range, set to undefined
|
|
156
|
+
this.resultIndex = undefined;
|
|
157
|
+
this.activeResult = undefined;
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
this.resultIndex = index;
|
|
162
|
+
|
|
163
|
+
// set new node active
|
|
164
|
+
var node = this.results[this.resultIndex].node;
|
|
165
|
+
var elem = this.results[this.resultIndex].elem;
|
|
166
|
+
if (elem == 'field') {
|
|
167
|
+
node.searchFieldActive = true;
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
node.searchValueActive = true;
|
|
171
|
+
}
|
|
172
|
+
this.activeResult = this.results[this.resultIndex];
|
|
173
|
+
node.updateDom();
|
|
174
|
+
|
|
175
|
+
// TODO: not so nice that the focus is only set after the animation is finished
|
|
176
|
+
node.scrollTo(function () {
|
|
177
|
+
if (focus) {
|
|
178
|
+
node.focus(elem);
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Cancel any running onDelayedSearch.
|
|
185
|
+
* @private
|
|
186
|
+
*/
|
|
187
|
+
SearchBox.prototype._clearDelay = function() {
|
|
188
|
+
if (this.timeout != undefined) {
|
|
189
|
+
clearTimeout(this.timeout);
|
|
190
|
+
delete this.timeout;
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Start a timer to execute a search after a short delay.
|
|
196
|
+
* Used for reducing the number of searches while typing.
|
|
197
|
+
* @param {Event} event
|
|
198
|
+
* @private
|
|
199
|
+
*/
|
|
200
|
+
SearchBox.prototype._onDelayedSearch = function (event) {
|
|
201
|
+
// execute the search after a short delay (reduces the number of
|
|
202
|
+
// search actions while typing in the search text box)
|
|
203
|
+
this._clearDelay();
|
|
204
|
+
var searchBox = this;
|
|
205
|
+
this.timeout = setTimeout(function (event) {
|
|
206
|
+
searchBox._onSearch(event);
|
|
207
|
+
},
|
|
208
|
+
this.delay);
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Handle onSearch event
|
|
213
|
+
* @param {Event} event
|
|
214
|
+
* @param {boolean} [forceSearch] If true, search will be executed again even
|
|
215
|
+
* when the search text is not changed.
|
|
216
|
+
* Default is false.
|
|
217
|
+
* @private
|
|
218
|
+
*/
|
|
219
|
+
SearchBox.prototype._onSearch = function (event, forceSearch) {
|
|
220
|
+
this._clearDelay();
|
|
221
|
+
|
|
222
|
+
var value = this.dom.search.value;
|
|
223
|
+
var text = (value.length > 0) ? value : undefined;
|
|
224
|
+
if (text != this.lastText || forceSearch) {
|
|
225
|
+
// only search again when changed
|
|
226
|
+
this.lastText = text;
|
|
227
|
+
this.results = this.editor.search(text);
|
|
228
|
+
this._setActiveResult(undefined);
|
|
229
|
+
|
|
230
|
+
// display search results
|
|
231
|
+
if (text != undefined) {
|
|
232
|
+
var resultCount = this.results.length;
|
|
233
|
+
switch (resultCount) {
|
|
234
|
+
case 0: this.dom.results.innerHTML = 'no results'; break;
|
|
235
|
+
case 1: this.dom.results.innerHTML = '1 result'; break;
|
|
236
|
+
default: this.dom.results.innerHTML = resultCount + ' results'; break;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
else {
|
|
240
|
+
this.dom.results.innerHTML = '';
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
};
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Handle onKeyDown event in the input box
|
|
247
|
+
* @param {Event} event
|
|
248
|
+
* @private
|
|
249
|
+
*/
|
|
250
|
+
SearchBox.prototype._onKeyDown = function (event) {
|
|
251
|
+
event = event || window.event;
|
|
252
|
+
var keynum = event.which || event.keyCode;
|
|
253
|
+
if (keynum == 27) { // ESC
|
|
254
|
+
this.dom.search.value = ''; // clear search
|
|
255
|
+
this._onSearch(event);
|
|
256
|
+
util.preventDefault(event);
|
|
257
|
+
util.stopPropagation(event);
|
|
258
|
+
}
|
|
259
|
+
else if (keynum == 13) { // Enter
|
|
260
|
+
if (event.ctrlKey) {
|
|
261
|
+
// force to search again
|
|
262
|
+
this._onSearch(event, true);
|
|
263
|
+
}
|
|
264
|
+
else if (event.shiftKey) {
|
|
265
|
+
// move to the previous search result
|
|
266
|
+
this.previous();
|
|
267
|
+
}
|
|
268
|
+
else {
|
|
269
|
+
// move to the next search result
|
|
270
|
+
this.next();
|
|
271
|
+
}
|
|
272
|
+
util.preventDefault(event);
|
|
273
|
+
util.stopPropagation(event);
|
|
274
|
+
}
|
|
275
|
+
};
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* Handle onKeyUp event in the input box
|
|
279
|
+
* @param {Event} event
|
|
280
|
+
* @private
|
|
281
|
+
*/
|
|
282
|
+
SearchBox.prototype._onKeyUp = function (event) {
|
|
283
|
+
event = event || window.event;
|
|
284
|
+
var keynum = event.which || event.keyCode;
|
|
285
|
+
if (keynum != 27 && keynum != 13) { // !show and !Enter
|
|
286
|
+
this._onDelayedSearch(event); // For IE 8
|
|
287
|
+
}
|
|
288
|
+
};
|
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Create a TextEditor and attach it to given container
|
|
3
|
+
* @constructor TextEditor
|
|
4
|
+
* @param {Element} container
|
|
5
|
+
* @param {Object} [options] Object with options. available options:
|
|
6
|
+
* {String} mode Available values:
|
|
7
|
+
* "text" (default)
|
|
8
|
+
* or "code".
|
|
9
|
+
* {Number} indentation Number of indentation
|
|
10
|
+
* spaces. 4 by default.
|
|
11
|
+
* {function} change Callback method
|
|
12
|
+
* triggered on change
|
|
13
|
+
* @param {JSON | String} [json] initial contents of the formatter
|
|
14
|
+
*/
|
|
15
|
+
function TextEditor(container, options, json) {
|
|
16
|
+
if (!(this instanceof TextEditor)) {
|
|
17
|
+
throw new Error('TextEditor constructor called without "new".');
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
this._create(container, options, json);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Create a TextEditor and attach it to given container
|
|
25
|
+
* @constructor TextEditor
|
|
26
|
+
* @param {Element} container
|
|
27
|
+
* @param {Object} [options] See description in constructor
|
|
28
|
+
* @param {JSON | String} [json] initial contents of the formatter
|
|
29
|
+
* @private
|
|
30
|
+
*/
|
|
31
|
+
TextEditor.prototype._create = function (container, options, json) {
|
|
32
|
+
// check availability of JSON parser (not available in IE7 and older)
|
|
33
|
+
if (typeof(JSON) == 'undefined') {
|
|
34
|
+
throw new Error('Your browser does not support JSON. \n\n' +
|
|
35
|
+
'Please install the newest version of your browser.\n' +
|
|
36
|
+
'(all modern browsers support JSON).');
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// read options
|
|
40
|
+
options = options || {};
|
|
41
|
+
if (options.indentation) {
|
|
42
|
+
this.indentation = Number(options.indentation);
|
|
43
|
+
}
|
|
44
|
+
this.options = options;
|
|
45
|
+
this.mode = (options.mode == 'code') ? 'code' : 'text';
|
|
46
|
+
if (this.mode == 'code') {
|
|
47
|
+
// verify whether Ace editor is available and supported
|
|
48
|
+
if (typeof ace === 'undefined') {
|
|
49
|
+
this.mode = 'text';
|
|
50
|
+
util.log('WARNING: Cannot load code editor, Ace library not loaded. ' +
|
|
51
|
+
'Falling back to plain text editor');
|
|
52
|
+
}
|
|
53
|
+
if (util.getInternetExplorerVersion() == 8) {
|
|
54
|
+
this.mode = 'text';
|
|
55
|
+
util.log('WARNING: Cannot load code editor, Ace is not supported on IE8. ' +
|
|
56
|
+
'Falling back to plain text editor');
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
var me = this;
|
|
61
|
+
this.container = container;
|
|
62
|
+
this.editor = undefined; // ace code editor
|
|
63
|
+
this.textarea = undefined; // plain text editor (fallback when Ace is not available)
|
|
64
|
+
this.indentation = 4; // number of spaces
|
|
65
|
+
|
|
66
|
+
this.width = container.clientWidth;
|
|
67
|
+
this.height = container.clientHeight;
|
|
68
|
+
|
|
69
|
+
this.frame = document.createElement('div');
|
|
70
|
+
this.frame.className = 'jsoneditor';
|
|
71
|
+
this.frame.onclick = function (event) {
|
|
72
|
+
// prevent default submit action when TextEditor is located inside a form
|
|
73
|
+
util.preventDefault(event);
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
// create menu
|
|
77
|
+
this.menu = document.createElement('div');
|
|
78
|
+
this.menu.className = 'menu';
|
|
79
|
+
this.frame.appendChild(this.menu);
|
|
80
|
+
|
|
81
|
+
// create format button
|
|
82
|
+
var buttonFormat = document.createElement('button');
|
|
83
|
+
//buttonFormat.innerHTML = 'Format';
|
|
84
|
+
buttonFormat.className = 'format';
|
|
85
|
+
buttonFormat.title = 'Format JSON data, with proper indentation and line feeds';
|
|
86
|
+
//buttonFormat.className = 'jsoneditor-button';
|
|
87
|
+
this.menu.appendChild(buttonFormat);
|
|
88
|
+
buttonFormat.onclick = function () {
|
|
89
|
+
try {
|
|
90
|
+
me.format();
|
|
91
|
+
}
|
|
92
|
+
catch (err) {
|
|
93
|
+
me._onError(err);
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
// create compact button
|
|
98
|
+
var buttonCompact = document.createElement('button');
|
|
99
|
+
//buttonCompact.innerHTML = 'Compact';
|
|
100
|
+
buttonCompact.className = 'compact';
|
|
101
|
+
buttonCompact.title = 'Compact JSON data, remove all whitespaces';
|
|
102
|
+
//buttonCompact.className = 'jsoneditor-button';
|
|
103
|
+
this.menu.appendChild(buttonCompact);
|
|
104
|
+
buttonCompact.onclick = function () {
|
|
105
|
+
try {
|
|
106
|
+
me.compact();
|
|
107
|
+
}
|
|
108
|
+
catch (err) {
|
|
109
|
+
me._onError(err);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
this.content = document.createElement('div');
|
|
115
|
+
this.content.className = 'outer';
|
|
116
|
+
this.frame.appendChild(this.content);
|
|
117
|
+
|
|
118
|
+
this.container.appendChild(this.frame);
|
|
119
|
+
|
|
120
|
+
if (this.mode == 'code') {
|
|
121
|
+
this.editorDom = document.createElement('div');
|
|
122
|
+
this.editorDom.style.height = '100%'; // TODO: move to css
|
|
123
|
+
this.editorDom.style.width = '100%'; // TODO: move to css
|
|
124
|
+
this.content.appendChild(this.editorDom);
|
|
125
|
+
|
|
126
|
+
var editor = ace.edit(this.editorDom);
|
|
127
|
+
editor.setTheme('ace/theme/jsoneditor');
|
|
128
|
+
editor.setShowPrintMargin(false);
|
|
129
|
+
editor.setFontSize(13);
|
|
130
|
+
editor.getSession().setMode('ace/mode/json');
|
|
131
|
+
editor.getSession().setUseSoftTabs(true);
|
|
132
|
+
editor.getSession().setUseWrapMode(true);
|
|
133
|
+
this.editor = editor;
|
|
134
|
+
|
|
135
|
+
var poweredBy = document.createElement('a');
|
|
136
|
+
poweredBy.appendChild(document.createTextNode('powered by ace'));
|
|
137
|
+
poweredBy.href = 'http://ace.ajax.org';
|
|
138
|
+
poweredBy.target = '_blank';
|
|
139
|
+
poweredBy.className = 'poweredBy';
|
|
140
|
+
poweredBy.onclick = function () {
|
|
141
|
+
// TODO: this anchor falls below the margin of the content,
|
|
142
|
+
// therefore the normal a.href does not work. We use a click event
|
|
143
|
+
// for now, but this should be fixed.
|
|
144
|
+
window.open(poweredBy.href, poweredBy.target);
|
|
145
|
+
};
|
|
146
|
+
this.menu.appendChild(poweredBy);
|
|
147
|
+
|
|
148
|
+
if (options.change) {
|
|
149
|
+
// register onchange event
|
|
150
|
+
editor.on('change', function () {
|
|
151
|
+
options.change();
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
// load a plain text textarea
|
|
157
|
+
var textarea = document.createElement('textarea');
|
|
158
|
+
textarea.className = 'content';
|
|
159
|
+
textarea.spellcheck = false;
|
|
160
|
+
this.content.appendChild(textarea);
|
|
161
|
+
this.textarea = textarea;
|
|
162
|
+
|
|
163
|
+
if (options.change) {
|
|
164
|
+
// register onchange event
|
|
165
|
+
if (this.textarea.oninput === null) {
|
|
166
|
+
this.textarea.oninput = function () {
|
|
167
|
+
options.change();
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
// oninput is undefined. For IE8-
|
|
172
|
+
this.textarea.onchange = function () {
|
|
173
|
+
options.change();
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// load initial json object or string
|
|
180
|
+
if (typeof(json) == 'string') {
|
|
181
|
+
this.setText(json);
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
this.set(json);
|
|
185
|
+
}
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Detach the editor from the DOM
|
|
190
|
+
* @private
|
|
191
|
+
*/
|
|
192
|
+
TextEditor.prototype._delete = function () {
|
|
193
|
+
if (this.frame && this.container && this.frame.parentNode == this.container) {
|
|
194
|
+
this.container.removeChild(this.frame);
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Throw an error. If an error callback is configured in options.error, this
|
|
200
|
+
* callback will be invoked. Else, a regular error is thrown.
|
|
201
|
+
* @param {Error} err
|
|
202
|
+
* @private
|
|
203
|
+
*/
|
|
204
|
+
TextEditor.prototype._onError = function(err) {
|
|
205
|
+
// TODO: onError is deprecated since version 2.2.0. cleanup some day
|
|
206
|
+
if (typeof this.onError === 'function') {
|
|
207
|
+
util.log('WARNING: JSONEditor.onError is deprecated. ' +
|
|
208
|
+
'Use options.error instead.');
|
|
209
|
+
this.onError(err);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
if (typeof this.options.error === 'function') {
|
|
213
|
+
this.options.error(err);
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
throw err;
|
|
217
|
+
}
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Compact the code in the formatter
|
|
222
|
+
*/
|
|
223
|
+
TextEditor.prototype.compact = function () {
|
|
224
|
+
var json = util.parse(this.getText());
|
|
225
|
+
this.setText(JSON.stringify(json));
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Format the code in the formatter
|
|
230
|
+
*/
|
|
231
|
+
TextEditor.prototype.format = function () {
|
|
232
|
+
var json = util.parse(this.getText());
|
|
233
|
+
this.setText(JSON.stringify(json, null, this.indentation));
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Set focus to the formatter
|
|
238
|
+
*/
|
|
239
|
+
TextEditor.prototype.focus = function () {
|
|
240
|
+
if (this.textarea) {
|
|
241
|
+
this.textarea.focus();
|
|
242
|
+
}
|
|
243
|
+
if (this.editor) {
|
|
244
|
+
this.editor.focus();
|
|
245
|
+
}
|
|
246
|
+
};
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Resize the formatter
|
|
250
|
+
*/
|
|
251
|
+
TextEditor.prototype.resize = function () {
|
|
252
|
+
if (this.editor) {
|
|
253
|
+
var force = false;
|
|
254
|
+
this.editor.resize(force);
|
|
255
|
+
}
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Set json data in the formatter
|
|
260
|
+
* @param {Object} json
|
|
261
|
+
*/
|
|
262
|
+
TextEditor.prototype.set = function(json) {
|
|
263
|
+
this.setText(JSON.stringify(json, null, this.indentation));
|
|
264
|
+
};
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Get json data from the formatter
|
|
268
|
+
* @return {Object} json
|
|
269
|
+
*/
|
|
270
|
+
TextEditor.prototype.get = function() {
|
|
271
|
+
return util.parse(this.getText());
|
|
272
|
+
};
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Get the text contents of the TextEditor
|
|
276
|
+
* @return {String} jsonText
|
|
277
|
+
*/
|
|
278
|
+
TextEditor.prototype.getText = function() {
|
|
279
|
+
if (this.textarea) {
|
|
280
|
+
return this.textarea.value;
|
|
281
|
+
}
|
|
282
|
+
if (this.editor) {
|
|
283
|
+
return this.editor.getValue();
|
|
284
|
+
}
|
|
285
|
+
return '';
|
|
286
|
+
};
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Set the text contents of the TextEditor
|
|
290
|
+
* @param {String} jsonText
|
|
291
|
+
*/
|
|
292
|
+
TextEditor.prototype.setText = function(jsonText) {
|
|
293
|
+
if (this.textarea) {
|
|
294
|
+
this.textarea.value = jsonText;
|
|
295
|
+
}
|
|
296
|
+
if (this.editor) {
|
|
297
|
+
this.editor.setValue(jsonText, -1);
|
|
298
|
+
}
|
|
299
|
+
};
|
|
300
|
+
|
|
301
|
+
// register modes at the JSONEditor
|
|
302
|
+
JSONEditor.modes.text = {
|
|
303
|
+
editor: TextEditor,
|
|
304
|
+
data: 'text',
|
|
305
|
+
load: TextEditor.prototype.format
|
|
306
|
+
};
|
|
307
|
+
JSONEditor.modes.code = {
|
|
308
|
+
editor: TextEditor,
|
|
309
|
+
data: 'text',
|
|
310
|
+
load: TextEditor.prototype.format
|
|
311
|
+
};
|