Improved splitter: can now completely hide the panels. Added highlighting of the splitter.

This commit is contained in:
josdejong 2013-03-07 22:35:06 +01:00
parent 89e7b6e76e
commit 430a2ce5a4
9 changed files with 234 additions and 57 deletions

View File

@ -144,28 +144,65 @@ span.header-light {
#contents { #contents {
width: 100%; width: 100%;
height: 100%; height: 100%;
overflow: hidden; overflow: hidden;
} }
#jsonformatter, #jsoneditor { #jsonformatter, #jsoneditor {
float: left;
height: 100%; height: 100%;
width: 400px; width: 400px;
padding: 15px;
-moz-box-sizing: border-box; -moz-box-sizing: border-box;
-webkit-box-sizing: border-box; -webkit-box-sizing: border-box;
box-sizing: border-box; box-sizing: border-box;
} }
#jsonformatter {
float: left;
padding: 15px 0 15px 15px;
}
#jsoneditor {
float: left;
padding: 15px 15px 15px 0;
}
#splitter { #splitter {
text-align: center;
float: left; float: left;
height: 100%; height: 100%;
padding: 15px;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
#splitter #buttons {
margin: 0 0 15px 0;
}
#splitter #toEditor {
margin: 40px 0 0 0 ;
}
#splitter #toJSON {
margin: 20px 0 0 0 ;
}
#splitter #drag {
font-size: 32px;
color: lightgray;
border-radius: 3px;
min-width: 24px;
cursor: col-resize; cursor: col-resize;
} }
#splitter #drag:hover,
#splitter #drag.active {
color: gray;
background-color: #f5f5f5;
}
#footer { #footer {
width: 100%; width: 100%;
height: 23px; height: 23px;
@ -195,7 +232,8 @@ a.footer:hover {
} }
#ad { #ad {
float: left; float: right;
right: 15px;
padding: 15px 0 15px 0; padding: 15px 0 15px 0;
position: relative; position: relative;
} }

View File

@ -38,7 +38,7 @@ var app = {};
/** /**
* Get the JSON from the formatter and load it in the editor * Get the JSON from the formatter and load it in the editor
*/ */
app.formatterToEditor = function() { app.JSONToEditor = function() {
try { try {
editor.set(formatter.get()); editor.set(formatter.get());
} }
@ -50,7 +50,7 @@ app.formatterToEditor = function() {
/** /**
* Get the JSON from the editor and load it into the formatter * Get the JSON from the editor and load it into the formatter
*/ */
app.editorToFormatter = function () { app.editorToJSON = function () {
try { try {
formatter.set(editor.get()); formatter.set(editor.get());
} }
@ -121,42 +121,26 @@ app.load = function() {
// TODO: automatically synchronize data of formatter and editor? (editor should keep its state though) // TODO: automatically synchronize data of formatter and editor? (editor should keep its state though)
// splitter // splitter
var domSplitter = document.getElementById('splitter');
app.splitter = new Splitter({ app.splitter = new Splitter({
container: domSplitter, container: document.getElementById('drag'),
change: function () { change: function () {
app.resize(); app.resize();
} }
}); });
// button Formatter-to-Editor // button JSON-to-Editor
domSplitter.appendChild(document.createElement('br')); var toEditor = document.getElementById('toEditor');
domSplitter.appendChild(document.createElement('br')); toEditor.onclick = function () {
domSplitter.appendChild(document.createElement('br'));
var toForm = document.createElement('button');
toForm.id = 'toForm';
toForm.title = 'JSON to Editor';
toForm.className = 'convert';
toForm.innerHTML = '<div class="convert-right"></div>';
toForm.onclick = function () {
this.focus(); this.focus();
app.formatterToEditor(); app.JSONToEditor();
}; };
domSplitter.appendChild(toForm);
// button Editor-to-Formatter // button Editor-to-Editor
domSplitter.appendChild(document.createElement('br')); var toJSON = document.getElementById('toJSON');
domSplitter.appendChild(document.createElement('br'));
var toJSON = document.createElement('button');
toJSON.id = 'toJSON';
toJSON.title = 'Editor to JSON';
toJSON.className = 'convert';
toJSON.innerHTML = '<div class="convert-left"></div>';
toJSON.onclick = function () { toJSON.onclick = function () {
this.focus(); this.focus();
app.editorToFormatter(); app.editorToJSON();
}; };
domSplitter.appendChild(toJSON);
// web page resize handler // web page resize handler
jsoneditor.util.addEventListener(window, 'resize', app.resize); jsoneditor.util.addEventListener(window, 'resize', app.resize);
@ -263,11 +247,11 @@ app.openUrl = function (url) {
app.saveFile = function () { app.saveFile = function () {
// first synchronize the editors and formatters contents // first synchronize the editors and formatters contents
if (app.lastChanged == editor) { if (app.lastChanged == editor) {
app.editorToFormatter(); app.editorToJSON();
} }
/* TODO: also sync from formatter to editor? will clear the history ... /* TODO: also sync from formatter to editor? will clear the history ...
if (app.lastChanged == formatter) { if (app.lastChanged == formatter) {
app.formatterToEditor(); app.JSONToEditor();
} }
*/ */
app.lastChanged = undefined; app.lastChanged = undefined;
@ -296,37 +280,75 @@ app.resize = function() {
var domEditor = document.getElementById('jsoneditor'); var domEditor = document.getElementById('jsoneditor');
var domFormatter = document.getElementById('jsonformatter'); var domFormatter = document.getElementById('jsonformatter');
var domSplitter = document.getElementById('splitter'); var domSplitter = document.getElementById('splitter');
var domSplitterButtons = document.getElementById('buttons');
var domSplitterDrag = document.getElementById('drag');
var domAd = document.getElementById('ad'); var domAd = document.getElementById('ad');
var width = window.innerWidth || document.body.offsetWidth || document.documentElement.offsetWidth; var margin = 15;
var height = window.innerHeight || document.body.offsetHeight || document.documentElement.offsetHeight; var width = (window.innerWidth || document.body.offsetWidth ||
document.documentElement.offsetWidth);
var adWidth = domAd ? domAd.clientWidth : 0; var adWidth = domAd ? domAd.clientWidth : 0;
var splitterWidth = domSplitter.clientWidth;
if (adWidth) { if (adWidth) {
width -= (adWidth + 15); // Not so nice, +15 here for the margin width -= (adWidth + margin);
} }
if (app.splitter) { if (app.splitter) {
var splitterLeft = width * app.splitter.getValue(); app.splitter.setWidth(width);
// calculate horizontal splitter position
var value = app.splitter.getValue();
var showFormatter = (value > 0);
var showEditor = (value < 1);
var showButtons = showFormatter && showEditor;
domSplitterButtons.style.display = showButtons ? '' : 'none';
var splitterWidth = domSplitter.clientWidth;
var splitterLeft;
if (!showFormatter) {
// formatter not visible
splitterLeft = 0;
domSplitterDrag.innerHTML = '&rsaquo;';
domSplitterDrag.title = 'Drag right to show the code editor';
}
else if (!showEditor) {
// editor not visible
splitterLeft = width * value - splitterWidth;
domSplitterDrag.innerHTML = '&lsaquo;';
domSplitterDrag.title = 'Drag left to show the tree editor';
}
else {
// both editor and formatter visible
splitterLeft = width * value - splitterWidth / 2;
domSplitterDrag.innerHTML = '&#8942;';
domSplitterDrag.title = 'Drag left or right to change the width of the panels';
}
// resize formatter // resize formatter
domFormatter.style.width = Math.round(splitterLeft) + 'px'; domFormatter.style.display = (value == 0) ? 'none' : '';
domFormatter.style.width = Math.max(Math.round(splitterLeft), 0) + 'px';
formatter.resize(); formatter.resize();
// resize the splitter
domSplitterDrag.style.height = (domSplitter.clientHeight -
domSplitterButtons.clientHeight - 2 * margin -
(showButtons ? margin : 0)) + 'px';
domSplitterDrag.style.lineHeight = domSplitterDrag.style.height;
// resize editor // resize editor
// the width has a -1 to prevent the width from being just half a pixel // the width has a -1 to prevent the width from being just half a pixel
// wider than the window, causing the content elements to wrap... // wider than the window, causing the content elements to wrap...
domEditor.style.display = (value == 1) ? 'none' : '';
domEditor.style.left = Math.round(splitterLeft + splitterWidth) + 'px'; domEditor.style.left = Math.round(splitterLeft + splitterWidth) + 'px';
domEditor.style.width = Math.round(width - splitterLeft - splitterWidth - 1) + 'px'; domEditor.style.width = Math.max(Math.round(width - splitterLeft - splitterWidth - 2), 0) + 'px';
} }
// align main menu with ads // align main menu with ads
if (domMenu) { if (domMenu) {
if (adWidth) { if (adWidth) {
domMenu.style.right = (15 + (adWidth + 15)) + 'px'; domMenu.style.right = (margin + (adWidth + margin)) + 'px';
} }
else { else {
domMenu.style.right = 15 + 'px'; domMenu.style.right = margin + 'px';
} }
} }
}; };

View File

@ -1,4 +1,4 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <!DOCTYPE HTML>
<html> <html>
<head> <head>
@ -37,7 +37,7 @@
Copyright (C) 2011-2013 Jos de Jong, http://jsoneditoronline.org Copyright (C) 2011-2013 Jos de Jong, http://jsoneditoronline.org
@author Jos de Jong, <wjosdejong@gmail.com> @author Jos de Jong, <wjosdejong@gmail.com>
@date 2013-03-04 @date 2013-03-07
--> -->
<meta name="description" content="JSON Editor Online is a web-based tool to view, edit, and format JSON. It shows your data side by side in a clear, editable treeview and in formatted plain text."> <meta name="description" content="JSON Editor Online is a web-based tool to view, edit, and format JSON. It shows your data side by side in a clear, editable treeview and in formatted plain text.">
@ -125,7 +125,22 @@
<div id="contents"> <div id="contents">
<div id="jsonformatter"></div> <div id="jsonformatter"></div>
<div id="splitter"></div> <div id="splitter">
<div id="buttons">
<div>
<button id="toEditor" class="convert" title="JSON to Editor">
<div class="convert-right"></div>
</button>
</div>
<div>
<button id="toJSON" class="convert" title="Editor to JSON">
<div class="convert-left"></div>
</button>
</div>
</div>
<div id="drag">
</div>
</div>
<div id="jsoneditor"></div> <div id="jsoneditor"></div>

View File

@ -108,7 +108,8 @@ color: red\
color: #BF78CC\ color: #BF78CC\
}\ }\
.ace-jso .ace_invalid {\ .ace-jso .ace_invalid {\
background-color: #FF002A\ color: #FFFFFF;\
background-color: #FF002A;\
}\ }\
.ace-jso .ace_fold {\ .ace-jso .ace_fold {\
background-color: #AF956F;\ background-color: #AF956F;\

View File

@ -59,6 +59,7 @@ Notify.prototype.showMessage = function (params) {
frame.style.left = (windowWidth - width) / 2 + 'px'; frame.style.left = (windowWidth - width) / 2 + 'px';
frame.style.width = width + 'px'; frame.style.width = width + 'px';
frame.style.top = top + 'px'; frame.style.top = top + 'px';
frame.style.zIndex = '999';
document.body.appendChild(frame); document.body.appendChild(frame);
this.dom.frame = frame; this.dom.frame = frame;
} }

View File

@ -21,6 +21,8 @@ function Splitter (params) {
}); });
this.container = params.container; this.container = params.container;
this.width = 1;
this.value = 0.5;
this.onChange = (params.change) ? params.change : function () {}; this.onChange = (params.change) ? params.change : function () {};
this.params = {}; this.params = {};
} }
@ -36,6 +38,7 @@ Splitter.prototype.onMouseDown = function (event) {
if (!leftButtonDown) { if (!leftButtonDown) {
return; return;
} }
jsoneditor.util.addClassName(this.container, 'active');
if (!this.params.mousedown) { if (!this.params.mousedown) {
this.params.mousedown = true; this.params.mousedown = true;
@ -59,12 +62,10 @@ Splitter.prototype.onMouseDown = function (event) {
* @private * @private
*/ */
Splitter.prototype.onMouseMove = function (event) { Splitter.prototype.onMouseMove = function (event) {
var width = (window.innerWidth || document.body.offsetWidth ||
document.documentElement.offsetWidth);
var diff = event.screenX - this.params.screenX; var diff = event.screenX - this.params.screenX;
var value = this.params.value + diff / width; // TODO: width does not work correct when ad is visible
var value = this.params.value + diff / this.width;
value = this.setValue(value); value = this.setValue(value);
this.onChange(value); this.onChange(value);
@ -78,16 +79,39 @@ Splitter.prototype.onMouseMove = function (event) {
* @private * @private
*/ */
Splitter.prototype.onMouseUp = function (event) { Splitter.prototype.onMouseUp = function (event) {
jsoneditor.util.removeClassName(this.container, 'active');
if (this.params.mousedown) { if (this.params.mousedown) {
jsoneditor.util.removeEventListener(document, 'mousemove', this.params.mousemove); jsoneditor.util.removeEventListener(document, 'mousemove', this.params.mousemove);
jsoneditor.util.removeEventListener(document, 'mouseup', this.params.mouseup); jsoneditor.util.removeEventListener(document, 'mouseup', this.params.mouseup);
this.params.mousemove = undefined; this.params.mousemove = undefined;
this.params.mouseup = undefined; this.params.mouseup = undefined;
this.params.mousedown = false; this.params.mousedown = false;
var value = this.getValue();
if (value == this.params.value) {
// value is unchanged
if (value == 0) {
value = this.setValue(0.2);
this.onChange(value);
}
if (value == 1) {
value = this.setValue(0.8);
this.onChange(value);
}
}
} }
jsoneditor.util.preventDefault(event); jsoneditor.util.preventDefault(event);
}; };
/**
* Set the window width for the splitter
* @param {Number} width
*/
Splitter.prototype.setWidth = function (width) {
this.width = width;
};
/** /**
* Set a value for the splitter (UI is not adjusted) * Set a value for the splitter (UI is not adjusted)
* @param {Number} value A number between 0.1 and 0.9 * @param {Number} value A number between 0.1 and 0.9
@ -96,10 +120,10 @@ Splitter.prototype.onMouseUp = function (event) {
Splitter.prototype.setValue = function (value) { Splitter.prototype.setValue = function (value) {
value = Number(value); value = Number(value);
if (value < 0.1) { if (value < 0.1) {
value = 0.1; value = 0;
} }
if (value > 0.9) { if (value > 0.9) {
value = 0.9; value = 1;
} }
this.value = value; this.value = value;

View File

@ -1,4 +1,4 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <!DOCTYPE HTML>
<html> <html>
<head> <head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"> <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
@ -36,7 +36,7 @@
Copyright (C) 2011-2013 Jos de Jong, http://jsoneditoronline.org Copyright (C) 2011-2013 Jos de Jong, http://jsoneditoronline.org
@author Jos de Jong, <wjosdejong@gmail.com> @author Jos de Jong, <wjosdejong@gmail.com>
@date 2013-03-04 @date 2013-03-07
--> -->
<meta name="description" content="JSON Editor Online is a web-based tool to view, edit, and format JSON. It shows your data side by side in a clear, editable treeview and in formatted plain text."> <meta name="description" content="JSON Editor Online is a web-based tool to view, edit, and format JSON. It shows your data side by side in a clear, editable treeview and in formatted plain text.">
@ -155,7 +155,22 @@
<div id="contents"> <div id="contents">
<div id="jsonformatter"></div> <div id="jsonformatter"></div>
<div id="splitter"></div> <div id="splitter">
<div id="buttons">
<div>
<button id="toEditor" class="convert" title="JSON to Editor">
<div class="convert-right"></div>
</button>
</div>
<div>
<button id="toJSON" class="convert" title="Editor to JSON">
<div class="convert-left"></div>
</button>
</div>
</div>
<div id="drag">
</div>
</div>
<div id="jsoneditor"></div> <div id="jsoneditor"></div>

View File

@ -5,8 +5,9 @@ http://jsoneditoronline.org
## <not yet released>, version 2.1.0 ## <not yet released>, version 2.1.0
- Implemented code editor Ace instead of the plain text JSON editor. Ace - Replaced the plain text editor with code editor Ace, which brings in syntax
provides syntax highlighting and code inspection. highlighting and code inspection.
- Improved the splitter between the two panels. Panels can be hided.
## 2013-02-26, version 2.0.2 ## 2013-02-26, version 2.0.2

60
test/test_ace.html Normal file
View File

@ -0,0 +1,60 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Test Ace</title>
<script src="../app/web/lib/ace/ace.js" type="text/javascript" charset="utf-8"></script>
<script src="../app/web/lib/ace/mode-json.js" type="text/javascript" charset="utf-8"></script>
<script src="../app/web/lib/ace/theme-textmate.js" type="text/javascript" charset="utf-8"></script>
<script src="../app/web/lib/ace/theme-jso.js" type="text/javascript" charset="utf-8"></script>
<style type="text/css" media="screen">
html, body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
#editor {
border: 1px solid gray;
width: 50%;
height: 75%;
}
</style>
</head>
<body>
<h1>Test Ace</h1>
<div id="editor"></div>
<script>
var editor = ace.edit('editor');
editor.setTheme("ace/theme/jso");
editor.setShowPrintMargin(false);
editor.setFontSize(13);
editor.getSession().setMode('ace/mode/json');
editor.getSession().setUseSoftTabs(true);
editor.getSession().setUseWrapMode(true);
var json = {
"array": [
1,
2,
3
],
"boolean": true,
"null": null,
"number": 123,
"object": {
"a": "b",
"c": "d",
"e": "f"
},
"string": "Hello World"
};
editor.setValue(JSON.stringify(json, null, 4), -1);
</script>
</body>
</html>